2010-05-25 9 views
5

que tienen un código que se parece a:¿Cómo corrijo la envidia de la característica en este caso?

class Parent { 
private Intermediate intermediateContainer; 
public Intermediate getIntermediate(); 
} 

class Intermediate { 
private Child child; 
public Child getChild() {...} 
public void intermediateOp(); 
} 

class Child { 
public void something(); 
public void somethingElse(); 
} 

class Client { 
private Parent parent; 

public void something() { 
    parent.getIntermediate().getChild().something(); 
} 

public void somethingElse() { 
    parent.getIntermediate().getChild().somethingElse(); 
} 

public void intermediate() { 
    parent.getIntermediate().intermediateOp(); 
} 
} 

entiendo que es un ejemplo de la "función de la envidia" olor código. La pregunta es, ¿cuál es la mejor manera de solucionarlo? Mi primer instinto es poner los tres métodos en los padres:

parent.something(); 
parent.somethingElse(); 
parent.intermediateOp(); 

... pero siento que esto duplica código y desordena la API de la clase padre (que ya es bastante ocupado).

¿Quiero guardar el resultado de getIntermediate(), y/o getChild(), y mantener mis propias referencias a estos objetos?

+0

¡Gracias! Todas estas respuestas fueron útiles, así que las subí – RMorrisey

Respuesta

5

En mi experiencia, haciendo lo que sugiere (todos los métodos solo llaman "el siguiente nivel") ayudará a iluminar los cambios en su API que debe hacer. Así que sí, realice esos cambios a pesar de que está saturando su API y puede descubrir la forma adecuada de lidiar con los problemas.

El "hecho" es que algo tiene un cliente cuando debería tener (o quiere tener) algo más. Esto implica que o bien la funcionalidad de esa otra cosa está en el lugar equivocado o la cosa que solicita que la funcionalidad esté en el lugar equivocado. Desafortunadamente, es difícil dar ejemplos concretos sin un código mucho más completo.

Cuando finalmente se da cuenta de cuáles son los "problemas", las soluciones pueden no ser tan fáciles de implementar. Eso es un fastidio, ¡pero sigan con la buena batalla y refaccionen hacia esa solución de todos modos!

+1

Me di cuenta de que, en mi caso, Child (un origen de datos para mi componente UI) no tenía que ser propiedad ni administrado por su componente principal, y dejó de pertenecer únicamente a Parent cuando Empecé a usarlo en Client (otro componente de UI que funciona en paralelo). Llevé la construcción de Child a una clase superior que posee padres y clientes, y la pasé a ambos. – RMorrisey

10

Esto no es exactamente Feature Envy, sino más bien un problema de acoplamiento entre estas clases y una violación definitiva de la Ley de Demeter http://www.ccs.neu.edu/research/demeter/demeter-method/LawOfDemeter/general-formulation.html. Sin embargo, su primer pensamiento de tener los métodos directamente en el padre es bueno. Los clientes no deberían necesitar llamar a la pila de esa manera.

Si le preocupa que el padre esté demasiado ocupado, tal vez tenga demasiada funcionalidad y se divida en algunas clases más pequeñas. Las clases deben ser de un solo propósito.

3

¿Quién está accediendo al Client? ¿Necesita mantener su parent en privado, o debería exponerlo para que el código de llamada pueda navegar hasta donde están las características necesarias?

Si le preocupa exponer parent por completo, otra opción es extraer una interfaz de Parent y exponerla de Client.

Cuestiones relacionadas