Pregunta

Después de un par de semanas de lectura en este foro pensé que era el momento para mí para hacer mi primer post.

Actualmente estoy releyendo código completo. Creo que es de 15 años desde la última vez, y me parece que todavía no puedo escribir código ;-)

De todos modos, en la página 138 en el código completo que encuentre este ejemplo de terror de codificación. (He quitado una parte del código)

class Emplyee {
public: 
 FullName GetName() const;
 Address GetAddress() const;
 PhoneNumber GetWorkPhone() const;
 ...

 bool IsZipCodeValid( Address address);
 ...

private: 
   ...
}

Lo que Steve piensa que es malo es que las funciones son vagamente relacionados. O que ha escribe "No hay conexión lógica entre los empleados y rutinas que comprueban los códigos postales, números de teléfono o clasificaciones de trabajo"

Ok estoy totalmente de acuerdo con él. Tal vez algo como el ejemplo a continuación es mejor.

class ZipCode
{
public:
 bool IsValid() const;
    ...
}

class Address {
public:
   ZipCode GetZipCode() const;
   ...
}

class Employee {
public: 
 Address GetAddress() const;
    ...
}

Al comprobar si la cremallera es válido lo que tendría que hacer algo como esto.

employee.GetAddress().GetZipCode().IsValid();

Y eso no es bueno con respecto a la Ley de Demeter .

Así que si quieres eliminar dos de los tres puntos, es necesario utilizar la delegación y un par de funciones de contenedor como este.

class ZipCode
{
public:
 bool IsValid();
}

class Address {
public:
   ZipCode GetZipCode() const;
   bool IsZipCodeValid() {return GetZipCode()->IsValid());
}

class Employee {
public: 
 FullName GetName() const;
 Address GetAddress() const;
 bool IsZipCodeValid() {return GetAddress()->IsZipCodeValid());
 PhoneNumber GetWorkPhone() const;
}

employee.IsZipCodeValid();

Pero, de nuevo tiene rutinas que no tiene ninguna conexión lógica.

Yo personalmente creo que los tres ejemplos en este post son malos. ¿Es de alguna otra manera que no he pensado?

¿Fue útil?

Solución

Es pagar ahora frente a pagar más tarde.

Puede escribir las funciones de delegación y la envoltura en la delantera (pagar ahora) y luego tener menos trabajo cambiando las entrañas de employee.IsZipCodeValid () más tarde. O bien, pueden crear un túnel a través de IsZipCodeValid escribiendo

employee.GetAddress().GetZipCode().IsValid();
donde quiera que lo necesite en el código, pero paga más adelante si usted decide cambiar el diseño de la clase de una manera que se rompe este código.

Se pueden escoger su veneno. ;)

Otros consejos

se echa en falta la conexión lógica:

class ZipCode
{
public:
 bool IsValid();
}

class Address {
public:
   ZipCode GetZipCode() const;
   bool IsAddressValid();
   bool IsValid() {return GetZipCode()->IsValid() && IsAddressValid());
}

class Employee {
public: 
 FullName GetName() const;
 Address GetAddress() const;
 bool IsEmployeeValid();
 bool IsValid() {return GetAddress()->IseValid() && IsEmployeeValid());
 PhoneNumber GetWorkPhone() const;
}

employee.IsValid();

Dado que no hay conexión lógica entre las clases de empleados y validación de código postal, se puede poner la validación del código postal en la clase de dirección que le corresponde de manera más lógica. A continuación, puede pedir a la clase de direcciones para validar el código postal para usted.

class Address
{
    public:
        static IsZipValid(ZipCode zip) { return zip.isValid(); }
};

A continuación, hacer

Address::IsZipValid(employee.GetAddress().GetZipCode());

Creo que esto es satisfactorio en sus limitaciones de asociación lógica y la Ley de Demeter.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top