Según la ley de Demeter, ¿se le permite a una clase devolver a uno de sus miembros?
Si, ciertamente lo es.
Veamos los puntos principales :
- Cada unidad debe tener un conocimiento limitado sobre otras unidades: solo unidades "estrechamente" relacionadas con la unidad actual.
- Cada unidad solo debe hablar con sus amigos; No hables con extraños.
- Solo habla con tus amigos inmediatos.
Los tres te dejan haciendo una pregunta: ¿Quién es un amigo?
Al decidir qué devolver, la Ley de Demeter o el principio de menor conocimiento (LoD) no dicta que se defienda contra los codificadores que insisten en violarlo. Dicta que no obliga a los codificadores a violarlo.
Confundirlos es exactamente la razón por la que muchos piensan que un setter siempre debe volver vacío. No. Debe permitir una forma de realizar consultas (captadores) que no cambien el estado del sistema. Esa es la separación de consulta de comando básica .
¿Esto significa que eres libre de profundizar en una base de código que encadena lo que quieras? No. Encadena solo lo que estaba destinado a ser encadenado. De lo contrario, la cadena podría cambiar y de repente tus cosas se rompen. Esto es lo que se entiende por amigos.
Se pueden diseñar cadenas largas para. Las interfaces fluidas, iDSL, gran parte de Java8 y el buen StringBuilder están diseñados para permitirte construir cadenas largas. No violan LoD porque todo en la cadena está destinado a trabajar juntos y prometió seguir trabajando juntos. Usted viola el demeter cuando encadena cosas que nunca han oído hablar el uno del otro. Los amigos son aquellos que prometieron mantener su cadena funcionando. Amigos de amigos no lo hicieron.
Además de las clases que se designaron específicamente para devolver objetos, como las clases de fábrica y de constructor, ¿está bien que un método devuelva un objeto, por ejemplo, un objeto en poder de una de las propiedades de la clase o violaría la ley de demeter (1) ?
Esto solo crea una oportunidad para violar el demeter. Esto no es una violación. Esto ni siquiera es necesariamente malo.
Y si viola la ley de demeter, ¿importaría si el objeto devuelto es un objeto inmutable que representa un dato y no contiene nada más que captadores para estos datos (2)?
Inmutable es bueno pero irrelevante aquí. Llegar a las cosas a través de una cadena más larga no lo hace mejor. Lo que lo hace mejor es separar la obtención del uso. Si está utilizando, solicite lo que necesita como parámetro. No vayas a buscarlo profundizando en los captadores de extraños.
En pseudocódigo:
Sospecho que la ley de Demeter prohíbe un patrón como el anterior. ¿Qué puedo hacer para garantizar que se pueda llamar a doSomethingElse () sin violar la ley (3)?
Antes de hablar, x.doSomethingElse(a)
entiendo que básicamente has escrito
b.getA().doSomething()
Ahora, LoD no es un ejercicio de conteo de puntos . Pero cuando creas una cadena estás diciendo que sabes cómo obtener un A
(mediante el uso B
) y sabes cómo usar un A
. Ahora bien A
, y B
mejor había amigos cercanos, ya que sólo ellos acoplados entre sí.
Si acaba pedido algo a mano que una A
como cosa que podría utilizar A
y no habría cuidado de donde vino y B
podría vivir una vida feliz y libre de su obsesión por conseguir A
a partir B
.
En cuanto a x.doSomethingElse(a)
sin detalles de dónde x
vino, LoD no tiene nada que decir al respecto.
LoD puede alentar la separación del uso de la construcción . Pero señalaré que si trata religiosamente cada objeto como no amigable, se quedará atrapado escribiendo código en métodos estáticos. Puedes construir un gráfico de objetos maravillosamente complejo de esta manera, pero eventualmente tienes que llamar a un método para comenzar a funcionar. Simplemente tienes que decidir quiénes son tus amigos. No hay forma de alejarse de eso.
Entonces sí, una clase puede devolver a uno de sus miembros bajo LoD. Cuando lo haga, debe dejar en claro si ese miembro es amigable con su clase porque si no lo es, algún cliente puede intentar acoplarlo a esa clase usándolo para obtenerlo antes de usarlo. Eso es importante porque ahora lo que devuelve siempre debe ser compatible con ese uso.
Hay muchos casos en los que esto simplemente no es una preocupación. Las colecciones pueden ignorar esto simplemente porque están destinados a ser amigos de todo lo que los usa. Del mismo modo, los objetos de valor son amigables con todos. Pero si escribió una utilidad de validación de dirección que exigía a un empleado un objeto del que extrajo una dirección, en lugar de simplemente pedir la dirección, es mejor que espere que el empleado y la dirección provengan de la misma biblioteca.