Code Complete 2ed, состав и делегирование - PullRequest
5 голосов
/ 11 марта 2010

После нескольких недель чтения на этом форуме я подумал, что пришло время написать мой первый пост.

Я сейчас перечитываю Code Complete.Я думаю, что прошло 15 лет с прошлого раза, и я обнаружил, что до сих пор не могу написать код ;-)

В любом случае, на странице 138 в Code Complete вы найдете этот пример ужаса кодирования.(Я удалил часть кода)

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

 bool IsZipCodeValid( Address address);
 ...

private: 
   ...
}

Что Стив считает плохим, так это то, что функции слабо связаны.Или он пишет: «Нет никакой логической связи между сотрудниками и процедурами, которые проверяют почтовые индексы, номера телефонов или классификации должностей»

Хорошо, я полностью согласен с ним.Может быть, что-то вроде приведенного ниже примера лучше.

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

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

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

При проверке действительности почтового индекса вам нужно будет сделать что-то вроде этого. Закон Деметры .

Поэтому, если вы хотите удалить две из трех точек, вам нужно использовать делегирование и несколько функций-оболочек, подобных этой.1022 * Но опять же у вас есть подпрограммы, которые не имеют логической связи.

Лично я считаю, что все три примера в этом посте плохие.Это какой-то другой способ, о котором я не думал?

Ответы [ 3 ]

7 голосов
/ 11 марта 2010

Вам не хватает логического соединения:

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();
1 голос
/ 11 марта 2010

Сейчас платят сейчас, а платят позже.

Вы можете написать функции делегирования и обертки заранее (заплатите сейчас), а затем у вас будет меньше работы по изменению внутренних значений employee.IsZipCodeValid () позже. Или вы можете туннелировать до IsZipCodeValid, написав

employee.GetAddress().GetZipCode().IsValid();
везде, где это необходимо, в коде, но заплатите позже, если вы решите изменить дизайн своего класса таким образом, который нарушает этот код.

Вы можете выбрать свой яд. ;)

0 голосов
/ 11 марта 2010

Поскольку между классом Employee и проверкой почтового индекса нет логической связи, вы можете поместить проверку почтового индекса в класс Address, где он более логически принадлежит. Затем вы можете попросить класс Address подтвердить для вас почтовый индекс.

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

Тогда вы делаете

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

Я думаю, что это удовлетворительно при ваших ограничениях логической ассоциации и Закона Деметры.

...