2008-10-02 20 views
60

El Law of Demeter indica que solo debe hablar con los objetos que conoce directamente. Es decir, no realice el método de encadenamiento para hablar con otros objetos. Cuando lo hace, está estableciendo vínculos inadecuados con los objetos intermedios, de manera inapropiada coupling su código a otro código.Acoplamiento, Cohesión y la Ley de Demeter

Eso es malo.

La solución sería que la clase que conoces exponga esencialmente envoltorios simples que delegan la responsabilidad al objeto con el que tiene relación.

Eso está bien.

Pero, eso parece dar como resultado que la clase tenga bajo cohesion. Ya no es simplemente responsable de lo que hace exactamente, sino que también tiene delegados que, en cierto sentido, hacen que el código sea menos cohesivo al duplicar partes de la interfaz de su objeto relacionado.

Eso es malo.

¿De verdad resulta en la reducción de la cohesión? ¿Es el menor de dos males?

¿Es esta una de esas áreas grises de desarrollo, donde puede debatir dónde está la línea, o hay formas fuertes y de principios de tomar una decisión de dónde trazar la línea y qué criterios puede usar para tomar esa decisión? ?

+0

Aunque un poco fuera de tema recomiendo encarecidamente Ted Faisons "Programación basada en eventos: llevando los eventos al límite" [enlace] (http://books.google.co.uk/books?id=9CL446IzhuAC&pg=PA38&lpg= PA38 y dq = eventos + capítulo + uno + acoplamiento y fuente = BL & ots = qmJTOuCz90 y sig = EZKvZBjF8QmGohatC97HsmAqG0c & hl = es & ei = wj6tTqe5LcTX8gON_YyiCw & SA = X & oi = book_result y ct = resultar y resnum = 6 y ved = 0CEMQ6AEwBQ # v = OnePage y q = eventos% 20chapter% 20one% 20coupling & f = false). Proporciona un gran desglose de los problemas comunes de acoplamiento y proporciona un buen sistema para medir el grado de acoplamiento en un sistema dado –

+0

Al violar el LoD, el hecho de que los enlaces adicionales sean ** "incorrectos" depende de la naturaleza del acoplamiento. clases enlazadas **: si estas son muy prominentes (piense en Fila, Columna, Celda en la implementación de Excel), el acoplamiento a ellas no es problemático y el LoD es demasiado restrictivo. Del mismo modo, si las clases en cuestión son deliberadamente meras clases de datos sin ningún comportamiento. –

Respuesta

43

Grady Booch en "Análisis Orientado a Objetos y Diseño":

"La idea de cohesión también viene de diseño estructurado En pocas palabras, la cohesión mide el grado de conectividad entre los elementos de un solo módulo (y . para el diseño orientado a objetos, una única clase u objeto). La forma menos deseable de cohesión es la cohesión fortuita, en la que las abstracciones totalmente no relacionadas son lanzadas en la misma clase o módulo. Por ejemplo, considere una clase que comprende las abstracciones de perros y naves espaciales, cuyos comportamientos no guardan relación. La forma más deseable de cohesión es es la cohesión funcional, en la que los elementos de una clase o módulo trabajan juntos para proporcionar un comportamiento bien delimitado. Por lo tanto, la clase Perro es funcionalmente coherente si su semántica abrazan el comportamiento de un perro, el perro entero, y nada más que el perro."

perro Subsitute con el Cliente en lo anterior y podría ser un poco más claro. El objetivo es, en realidad, apuntar a la cohesión funcional y alejarse de la cohesión casual tanto como sea posible. Dependiendo de sus abstracciones, esto puede ser simple o podría requerir alguna refactorización.

Nota: la cohesión se aplica tanto a un "módulo" que a una sola clase, es decir, un grupo de clases trabajando juntas. Entonces, en este caso, las clases Cliente y Orden todavía tienen una cohesión decente porque tienen esta relación fuerte, los clientes crean pedidos, los pedidos pertenecen a clientes.

Martin Fowler dice que le sea más cómodo llamándolo el "Consejo de Demeter" (véase el artículo Mocks aren't stubs):

"probadores con imitaciones qué hablar más acerca de cómo evitar 'descarrilamientos' - cadenas de método de estilo de getThis(). getThat(). getTheOther(). Evitar cadenas de métodos también se conoce como seguir la Ley de Demeter. Mientras que las cadenas de métodos son un olor, el problema opuesto de los objetos de los hombres medios hinchados con los métodos de reenvío también es un olor. Siempre sentí que estaría más cómodo con la Ley de Demeter si se llamara Sugerencia de Demeter.) "

Esa suma Siento muy bien de dónde vengo: es perfectamente aceptable y, a menudo, necesario tener un nivel de cohesión más bajo del que podría exigir el estricto cumplimiento de la "ley". Evite la cohesión casual y apunte a la cohesión funcional, pero no se obsesione con los ajustes donde sea necesario para encajar de forma más natural con su abstracción de diseño.

+1

Me gusta esta respuesta, parece implicar que es algo gris. Entonces, si puedo parafrasear, ¿argumentarías que mientras mantengas una alta cohesión en los objetos involucrados, es aceptable violar la Ley de Demeter? –

+0

Absolutamente, esa es una buena manera de expresarlo. BTW, ¿ha visto JQuery, el encadenamiento de llamadas a métodos 3+ niveles es común. Aunque podría estar en un contexto diferente (más procedimental), alguien que viene de JQuery para decir que Java/C#/C++ va a tener todo tipo de malos hábitos para "desaprender". – Ash

+1

Si puedo sugerir que agregue este punto a su publicación (sobre que está bien violar la Ley de Demeter) ... en este momento es la mejor respuesta que he visto. –

0

En las situaciones en las que parece haber una compensación entre el acoplamiento y la cohesión, probablemente me preguntaría "si alguien más ya hubiera escrito esta lógica, y estuviese buscando un error en ella, ¿dónde miraría primero? ? ", y escriba el código de esa manera.

20

Si usted está violando la Ley de Demeter por tener

int price = customer.getOrder().getPrice(); 

la solución no es crear un getOrderPrice() y transformar el código en

int price = customer.getOrderPrice(); 

sino que tener en cuenta que esto es a code smell y realice los cambios pertinentes que, ojalá, aumenten la cohesión y reduzcan el acoplamiento. Desafortunadamente no hay una refactorización simple aquí que siempre se aplique, pero probablemente debería aplicar tell don't ask

+4

El enlace para "decir, no preguntar" bien vale la pena leerlo. ¡Gracias! –

+0

"Decir, no preguntar" también lo acerca a las abstracciones en el dominio del problema (requisitos del usuario) en comparación con los detalles de implementación (diseño o requisitos derivados). – Fuhrmanator

1

No sé si esto realmente reduce la cohesión.

La agregación/composición se trata de una clase que utiliza otras clases para cumplir el contrato que expone a través de sus métodos públicos. La clase no necesita duplicar la interfaz de sus objetos relacionados. De hecho, está ocultando cualquier conocimiento sobre estas clases agregadas del llamador del método.

Para obedecer la ley de Demeter en el caso de niveles múltiples de dependencia de clase, solo necesita aplicar agregación/composición y buena encapsulación en cada nivel.

En otras palabras, cada clase tiene una o más dependencias en otras clases, sin embargo, estas solo son dependencias de la clase a la que se hace referencia y no de ningún objeto devuelto por los derechos/métodos.

+0

Para utilizar otro ejemplo de carteles, si un objeto del cliente ahora necesita saber no solo sobre el pedido del cliente, sino el precio del pedido del cliente, entonces eso está arruinando la interfaz del cliente de una manera que parecería reducir la cohesión . –

+0

También se trata del nivel/tipo de abstracción que se utiliza. Un Cliente, por definición, debe tener alguna asociación cercana con una/s Orden/s. Por lo tanto, el customer.getOrderPrice() no reduce la cohesión de un Cliente; refactorización Ejemplo: el cliente puede usar un decimal simple como orderPrice. – Ash

+0

¿Cómo eso no reduce la cohesión? No está relacionado con el Cliente, está relacionado con el Pedido. Simplemente lo está exponiendo al nivel del Cliente. ¿Cuándo comienza a reducir la cohesión? ¿Customer.getOrderAddressStreet() causa una reducción en la cohesión? Tal vez es todo gris .... –

6

Creo que es posible que haya entendido mal lo que significa cohesión.Una clase que se implementa en términos de varias otras clases no necesariamente tiene baja cohesión, siempre que represente un concepto claro y tenga un propósito claro. Por ejemplo, puede tener un class Person, implementado en términos de las clases Date (para la fecha de nacimiento), Address y Education (una lista de las escuelas a las que acudió la persona). Puede proporcionar envoltorios en Person para obtener el año de nacimiento, la última escuela a la que asistió o el estado donde vive, para evitar exponer el hecho de que Person se implementa en términos de esas otras clases. Esto reduciría el acoplamiento, pero haría Person no menos cohesivo.

3

Es un área gris. Estos principios están destinados a ayudarlo en su trabajo, si se da cuenta de que está trabajando para ellos (es decir, se interponen en su camino y/o le resulta más complicado su código) entonces se está conformando demasiado duro y necesito retroceder

Haga que funcione para usted, no trabaje para ello.

+0

esta es una buena descripción para Law of Demeter "Haz que funcione para ti, no trabajes para ello". – erhun

Cuestiones relacionadas