¿Qué es un código de "envidia de características" y por qué se considera un olor a código?

53

Esta pregunta sobre SO habla de corregir lo que el OP pensó que es el código de envidia de características . Otro ejemplo en el que vi esta ingeniosa frase citada es en una respuesta dada recientemente aquí en programadores.SE. Aunque dejé un comentario a esa respuesta solicitando la información, pensé que sería de ayuda general para los programadores que siguen las preguntas y respuestas para comprender lo que significa el término envidia de características . Siéntase libre de editar etiquetas adicionales si lo considera apropiado.

Friki
fuente

Respuestas:

88

La envidia de características es un término utilizado para describir una situación en la que un objeto llega a los campos de otro objeto para realizar algún tipo de cálculo o tomar una decisión, en lugar de pedirle al objeto que haga el cálculo en sí.

Como ejemplo trivial, considere una clase que representa un rectángulo. El usuario del rectángulo puede necesitar saber su área. El programador podría exponer widthy heightcampos y luego hacer el cálculo fuera de la Rectangleclase. Alternativamente, Rectanglepodría mantener el widthy heightcampos privados y proporcionar un getAreamétodo. Este es posiblemente un mejor enfoque.

El problema con la primera situación, y la razón por la que se considera un olor a código, es porque rompe la encapsulación.

Como regla general, cada vez que se encuentre haciendo un uso extensivo de campos de otra clase para realizar cualquier tipo de lógica o cálculo, considere mover esa lógica a un método en la clase misma.

jhewlett
fuente
77
+1, aunque su ejemplo no es realista, ya que una clase Rectángulo útil normalmente expondría los campos de ancho y alto.
Doc Brown
2
Y aunque la ruptura de la encapsulación puede ocurrir junto con el "entorno ambiental", en la mayoría de los ejemplos del mundo real que he visto hasta ahora, probablemente no fue el caso. Ocurre más en situaciones "hey, necesito calcular algunas cosas solo en el código usando ese objeto, y no estoy seguro de si puedo tocar la implementación de ese objeto / si deberíamos darle la responsabilidad al objeto de ese cálculo". Y luego uno implementa el cálculo usando campos que ya están expuestos (aunque probablemente sería posible una implementación mucho más limpia dentro del objeto).
Doc Brown
2
@DocBrown Imagine un rectángulo dibujado en la superficie de un toro, cono o esfera. Si mi biblioteca de dibujo de formas produce objetos que son capaces de producir los resultados correctos en tales contextos, sería una tontería no dejarlos para calcular sus propias áreas, en cualquier contexto.
itsbruce
1
@OskarN .: Por definición, estamos hablando de funciones que son necesarias. Obviamente, son necesarios si otras clases los vuelven a implementar una y otra vez.
Aaronaught
1
@ OskarN .: depende; a veces la decisión es clara, a veces es una cuestión de gustos, y la mayoría de las veces es una cuestión de experiencia. En su artículo, hay buenas razones por las que Scott Meyers escribe "a veces menos es más", y que le llevó años comprender cuándo no aplicar su "algoritmo para decidir cuándo hacer que un miembro funcione".
Doc Brown
1

Existe una posible situación en la que está bien usar ampliamente otros métodos de clase / estructura, cuando su clase / estructura es un contenedor de datos. Por lo general, hay algo que puede hacer con estos datos sin contexto externo.

Dichas clases aún pueden contener algo de lógica interna, pero con mayor frecuencia se usan como contenedores:

class YourUid {
 public:
  YourUid(int id_in_workplace_, int id_in_living_place_, DB* FBI_database, int id_in_FBI_database);
  bool IsInvalidWorker() const { return id_in_workplace == consts::invalid_id_in_workplace; }
  bool CanMessWith() const { return !FBI_database_.is_cool(id_in_FBI_database_); }
  int id_in_workplace;
  int id_in_living_place;
 private:
  int id_in_FBI_database_;
  const DB* FBI_database_;
};

@jhewlett en su respuesta se refiere a este artículo para demostrar que no debe usar ampliamente a otros miembros de la clase, pero hay otra situación de olores de código descrita allí con defensores de mi ejemplo:

Lista larga de parámetros. Limite el número de parámetros que necesita en un método determinado, o use un objeto para combinar los parámetros.

Riga
fuente
1
¿Cómo responde esto a la pregunta que se hace?
mosquito
@gnat La Q trata de por qué se considera "código de olor". jhewlett da una A con algunas suposiciones demasiado generales cuestionadas en los comentarios. Mi respuesta es 2 centavos para distinguir el "código de olor" de la práctica normal.
Riga