Al navegar por el código que he escrito, me encontré con la siguiente construcción que me hizo pensar. A primera vista, parece lo suficientemente limpio. Sí, en el código real, el getLocation()
método tiene un nombre un poco más específico que describe mejor exactamente qué ubicación se obtiene.
service.setLocation(this.configuration.getLocation().toString());
En este caso, service
es una variable de instancia de un tipo conocido, declarada dentro del método. this.configuration
proviene de ser pasado al constructor de la clase, y es una instancia de una clase que implementa una interfaz específica (que exige un getLocation()
método público ). Por lo tanto, this.configuration.getLocation()
se conoce el tipo de retorno de la expresión ; específicamente en este caso, es un java.net.URL
, mientras que service.setLocation()
quiere un String
. Dado que los dos tipos String y URL no son directamente compatibles, se requiere algún tipo de conversión para ajustar la clavija cuadrada en el agujero redondo.
Sin embargo , de acuerdo con la Ley de Demeter como se cita en código limpio , un método de f en la clase C sólo debe llamar a métodos en C , los objetos creados por o pasado como argumentos a f , y objetos celebrada en variables de instancia de C . Cualquier cosa más allá de eso (la final toString()
en mi caso particular anterior, a menos que considere un objeto temporal creado como resultado de la invocación del método en sí, en cuyo caso toda la Ley parece ser discutible) no está permitido.
¿Existe un razonamiento válido por el cual una llamada como la anterior, dadas las restricciones enumeradas, debe ser desalentada o incluso rechazada? ¿O solo estoy siendo demasiado quisquilloso?
Si tuviera que implementar un método URLToString()
que simplemente llama toString()
a un URL
objeto (como el devuelto por getLocation()
) pasado como parámetro y devuelve el resultado, podría ajustar la getLocation()
llamada para lograr exactamente el mismo resultado; efectivamente, solo movería la conversión un paso hacia afuera. ¿Eso de alguna manera lo haría aceptable? (Me parece , intuitivamente, que no debería hacer ninguna diferencia de ninguna manera, ya que todo lo que hace es mover un poco las cosas. Sin embargo, siguiendo la letra de la Ley de Deméter como se citó, sería aceptable, ya que yo entonces estaría operando directamente en un parámetro a una función).
¿Habría alguna diferencia si se tratara de algo un poco más exótico que recurrir toString()
a un tipo estándar?
Al responder, tenga en cuenta que alterar el comportamiento o la API del tipo de la service
variable no es práctico. Además, en aras de la discusión, digamos que alterar el tipo de retorno de getLocation()
tampoco es práctico.
fuente
La ley de Demeter es una directriz de diseño, no una ley a seguir religiosamente.
Si cree que sus clases están lo suficientemente desacopladas, no hay nada de malo en la línea,
this.configuration.getLocation()
especialmente si, como usted dice, no es práctico cambiar otras partes de la API.Estoy bastante seguro de que el cliente estará perfectamente feliz incluso si hace la Ley de Demeter en pedazos, siempre que entregue lo que quiere y a tiempo. Lo cual no es una excusa para crear un mal software, sino un recordatorio para ser pragmático al desarrollar software.
fuente
this.configuration
es una variable de instancia de un tipo de interfaz conocida, llamar a un método definido por esa interfaz parece estar bien incluso de acuerdo con una interpretación estricta. Sí, sé que es una guía, al igual que KISS, SOLID, YAGNI, etc. Hay muy pocas o ninguna "ley" (en el sentido legal) en el desarrollo de software en general.Lo único que se me ocurre al no escribir código como este es ¿qué pasa si
this.configuration.getLocation()
devuelve nulo? Depende de su código circundante y del público objetivo que usa este código. Pero como dice Marco, la ley de Demeter es una regla general, es bueno seguirla, pero no te rompas la espalda innecesariamente.fuente
this.configuration.getLocation()
devuelve nulo, entonces (a) lo más probable es que nunca hubiéramos llegado tan lejos, o (b) algo catastrófico ha sucedido en el ínterin, en cuyo caso me gustaría que el código fallara. Entonces, si bien este es definitivamente un punto válido en general, en este caso particular es bastante seguro decir que no se aplica. Además, todo esto y mucho más es un controlador de excepción diseñado específicamente para lidiar con ese tipo de fallas inesperadas.Seguir estrictamente la Ley de Demeter significaría que debe implementar un método en el objeto de configuración como:
pero personalmente no me molestaría porque esta es una situación tan pequeña, y de todos modos tus manos están un poco atadas debido a la API que no puedes cambiar. Las reglas de programación son sobre lo que debe hacer cuando tiene una opción, pero a veces no tiene otra opción.
fuente