Pergunta

Depois de um par de semanas de leitura neste fórum eu pensei que era hora de eu fazer o meu primeiro post.

Atualmente estou relendo completa Código. Eu acho que é 15 anos desde a última vez, e eu acho que eu ainda não pode escrever código ;-)

De qualquer forma, na página 138 no código completo que você encontrar este exemplo horror codificação. (Eu removi parte do código)

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

 bool IsZipCodeValid( Address address);
 ...

private: 
   ...
}

O que Steve acha que é ruim é que as funções são vagamente relacionados. Ou ele escreve: "Não há nenhuma conexão lógica entre funcionários e rotinas que verificam ZIP códigos, números de telefone ou classificações de trabalho"

Ok eu concordo totalmente com ele. Talvez algo como o exemplo abaixo é melhor.

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

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

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

Ao verificar se o zip é válido você precisa fazer algo como isto.

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

E isso não é bom em relação ao Lei de Demeter .

Então, se você gostaria de remover dois dos três pontos, você precisa usar a delegação e um par de funções de mensagens publicitárias como esta.

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();

Mas, novamente você tem rotinas que não tem nenhuma ligação lógica.

Pessoalmente, penso que todos os três exemplos neste post são ruins. É alguma outra forma que eu não tenha pensado?

Foi útil?

Solução

É de pay agora vs. pagar mais tarde.

Você pode escrever a delegação e funções de mensagens publicitárias na frente (pay agora) e, em seguida, ter menos trabalho mudando as entranhas de employee.IsZipCodeValid () mais tarde. Ou, você pode túnel através de IsZipCodeValid por escrito

employee.GetAddress().GetZipCode().IsValid();
em todos os lugares que você precisa-lo no código, mas pagar mais tarde se você decidir mudar o seu design de classe de uma maneira que rompe esse código.

Você começa a escolher o seu veneno. ;)

Outras dicas

Está faltando a conexão 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();

Uma vez que não há nenhuma conexão lógica entre a classe Employee e do código postal de validação, você pode colocar a validação CEP para a classe Endereço onde mais logicamente pertence. Então você pode pedir a classe Endereço para validar o código postal para você.

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

Então você faz

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

Eu acho que isto é satisfatório sob os constrangimentos da associação lógica e da Lei de Demeter.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top