Domanda

Dopo un paio di settimane di lettura su questo forum ho pensato che era giunto il momento per me di fare il mio primo post.

Al momento sto rileggendo codice completo. Penso che sia 15 anni dall'ultima volta, e trovo che non riesco ancora a scrivere codice ;-)

In ogni caso a pagina 138 nel codice completo a trovare questo esempio codifica orrore. (Ho rimosso una parte del codice)

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

 bool IsZipCodeValid( Address address);
 ...

private: 
   ...
}

Che Steve pensa che è male è che le funzioni sono vagamente correlate. O si è scrive "Non c'è alcun nesso logico tra i dipendenti e le routine che controllano Codici di avviamento postale, numeri di telefono o classificazioni di lavoro"

Ok Sono totalmente d'accordo con lui. Forse qualcosa di simile l'esempio che segue è migliore.

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

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

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

Quando si controlla se la cerniera è valida si avrebbe bisogno di fare qualcosa di simile.

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

E che non è buono per quanto riguarda la Legge di Demetra .

Quindi, se vi piace di rimuovere due dei tre punti, è necessario utilizzare la delega e un paio di funzioni wrapper come questo.

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

Ma poi di nuovo si dispone di routine che non ha alcuna connessione logica.

Personalmente ritengo che tutti e tre gli esempi in questo post sono cattivi. E 'un altro modo che non ho pensato?

È stato utile?

Soluzione

E 'pagare ora vs. pagare più tardi.

È possibile scrivere le funzioni di delega e involucro in anticipo (paga ora) e poi avere meno lavoro cambiando le interiora di employee.IsZipCodeValid () in seguito. In alternativa, è possibile tunnel attraverso di IsZipCodeValid scrivendo

employee.GetAddress().GetZipCode().IsValid();
ovunque ne avete bisogno nel codice, ma paga poi se dovessi decidere di cambiare il design di classe in un modo che rompe questo codice.

Si arriva a scegliere il vostro veleno. ;)

Altri suggerimenti

Ti manca la connessione logica:

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

Dal momento che non c'è alcuna connessione logica tra la classe Employee e convalida il CAP, si potrebbe mettere la validazione del codice postale nella classe Indirizzo a cui appartiene in modo più logico. Poi si può chiedere la classe di indirizzo per convalidare il codice di avviamento postale per voi.

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

Poi fare

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

Credo che questo sia soddisfacente sotto i vincoli di associazione logica e Legge di Demetra.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top