Tengo el siguiente código:
public void moveCameraTo(Location location){
moveCameraTo(location.getLatitude(), location.getLongitude());
}
public void moveCameraTo(double latitude, double longitude){
LatLng latLng = new LatLng(latitude, longitude);
moveCameraTo(latLng);
}
public void moveCameraTo(LatLng latLng){
GoogleMap googleMap = getGoogleMap();
cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, INITIAL_MAP_ZOOM_LEVEL);
googleMap.moveCamera(cameraUpdate);
}
Creo que de esta manera elimino la responsabilidad de saber qué es un LatLng
en otra clase, por ejemplo.
Y no necesita preparar los datos antes de llamar a la función.
¿Qué piensas?
¿Este enfoque tiene un nombre? ¿Es realmente una mala práctica?
design
design-patterns
clean-code
code-smell
bad-code
Tlaloc-ES
fuente
fuente
LatLng
a los clientes de estaCamera
clase, entonces probablemente no quieramoveCameraTo(LatLng)
serlopublic
.moveCameraToLocation
ymoveCameraTo
/moveCameraToCoords
. Definitivamente no querría pasar Location / lat / long todos con los mismos nombres.Respuestas:
Está utilizando la función de sobrecarga de métodos de sus idiomas para ofrecer a la persona que llama formas alternativas de resolver la dependencia de los métodos de la información posicional. Luego está delegando a otro método para resolver el trabajo restante de actualización de la cámara.
El olor del código aquí sería si sigues extendiendo la cadena de métodos que llaman métodos. El método de toma de ubicación llama al método de toma doble que llama al método de toma de latLng que finalmente llama a algo que sabe cómo actualizar la cámara.
Las cadenas largas son tan fuertes como su eslabón más débil. Cada extensión de la cadena aumenta la huella de código que tiene que funcionar o esto se rompe.
Es un diseño mucho mejor si cada método toma el camino más corto posible para resolver el problema que se le ha presentado. Eso no significa que cada uno debe saber cómo actualizar la cámara. Cada uno debe traducir su tipo de parámetro de posición a un tipo uniforme que se pueda pasar a algo que sepa cómo actualizar la cámara cuando se presente este tipo.
Hazlo de esa manera y puedes eliminar uno sin romper la mitad de todo lo demás.
Considerar:
Esto hace que lidiar con el problema de la latitud y la longitud
LatLng
. El costo es que difunde el conocimiento deLatLng
alrededor. Eso puede parecer costoso, pero en mi experiencia es una alternativa preferible a la obsesión primitiva, que es lo que evita establecer un objeto de parámetro .Si
Location
es refactorizable peroLatLng
no lo es, considere resolver esto agregando una fábrica aLocation
:Esto también evita muy bien la obsesión primitiva.
fuente
LatLng
uLocation
objetos. Puede mostrar la relación entre los dos conNew LatLng(Location)
oLocation.toLatLng()
si necesita pasar de uno a otro.No hay nada particularmente malo con su solución.
Pero mi preferencia personal sería que esos métodos no sean tan útiles. Y simplemente complique la interfaz de cualquier objeto del que formen parte.
El
void moveCameraTo(double latitude, double longitude)
realmente no simplifica el código, ya que no veo ningún problema simplemente llamandomoveCameraTo(new LatLng(latitude, longitude));
en su lugar. Este método también huele a obsesión primitiva.El
void moveCameraTo(Location location)
podría resolverse mejor probando elLocation.ToLatLng()
método y llamandomoveCameraTo(location.ToLatLng())
.si esto fuera C # y si tales métodos fueran realmente necesarios, los preferiría como métodos de extensión en lugar de métodos de instancia. El uso de métodos de extensión se volvería realmente obvio si intentara abstraer y probar esta instancia de forma unitaria. Como sería mucho más fácil simplemente falsificar un método único en lugar de múltiples sobrecargas con conversiones simples.
No veo ninguna razón por la que esto sea un problema. Siempre que su código haga referencia a la clase que contiene
void moveCameraTo(LatLng latLng)
, aún depende indirectamente de ellaLatLng
. Incluso si esa clase nunca se instancia directamente.No entiendo lo que quieres decir. Si significa crear una nueva instancia o transformar clases de una a otra, no veo ningún problema con eso.
Pensando en ello, creo que lo que digo también es compatible con el diseño de API de .NET. Históricamente, muchas clases .NET siguieron su enfoque de tener muchas sobrecargas con diferentes parámetros y conversiones simples dentro. Pero eso fue antes de que existieran los métodos de extensión. Las clases .NET más modernas son más livianas en sus propias API y si hay algún método con sobrecarga de parámetros, se proporcionan como métodos de extensión. Un ejemplo más antiguo es NLog ILogger que tiene docenas de sobrecargas para escribir en el registro. Compare eso con las nuevas Microsoft.Extensions.Logging.ILogger que tiene un total de 3 métodos (y solo 1 si cuenta el registro en sí). Pero hay muchos ayudantes y varias parametrizaciones como métodos de extensión .
Creo que esta respuesta muestra que algunos idiomas tendrían herramientas para hacer un diseño como este más agradable. No conozco mucho Java, así que no estoy seguro de si habría algún equivalente. Pero incluso usar métodos estáticos simples podría ser una opción.
fuente
moveCameraTo(new LatLng(latitude, longitude));
en ningún lugar del proyecto, pero creo que es más claro el uso directo de moveCametaTo (latLng), es como un archivo en Java, puede pasar la ruta como una cadena, o como una clase de rutaNo estoy seguro de cuál es el nombre correcto para esto, si tiene uno, pero es una buena práctica. Expone múltiples sobrecargas, lo que permite que la clase que llama determine qué conjunto de parámetros desea usar. Como usted dice, otra clase puede no saber qué es un
LatLng
objeto, pero podría saberloLocation
.Hacer que un método llame al otro también es clave, ya que no desea código duplicado en esos métodos. Como lo ha hecho, elija un método para que sea el que haga el trabajo y haga que los otros métodos lo llamen (directa o indirectamente)
fuente
Si te importa usar algún tipo de método, es solo una función de sobrecarga de métodos, es bueno.
Pero no se elimina la responsabilidad de saber qué es un LatLng . Porque te estás inicializando
LatLng latLng = new LatLng(latitude, longitude)
. Esto es totalmente dependiente deLatLng
. (Para comprender por qué la inicialización es un problema de dependencia, puede verificar la inyección de dependencia ) Crear un método sobrecargado solo ayuda a los clientes que no les importaLatLng
. Si quiere decir esto, también es bueno, pero no creo que sea un enfoque. Son solo muchos métodos de servicio para clientes.Entonces, hay dos opciones para diseñar su arquitectura:
Me escapo lo más posible al crear métodos que necesitan tipos primitivos como parámetros (Opción 1). Porque si su negocio cambia muchas veces y necesita reproducir los parámetros del método, es realmente difícil cambiar e implementar todas las funciones de la persona que llama.
En lugar de esto, use interfaces (inyección de dependencia). Si cree que es costoso y lleva más tiempo, utilice las clases y proporcione sus métodos de extensión del asignador (Opción 2).
fuente