Code Complete 2ed, состав и делегирование

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

Я сейчас перечитываю 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;
    ...
}

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

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

И это не хорошо в отношении закона Деметры.

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

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

Но опять же у вас есть подпрограммы, которые не имеют логической связи.

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

3 ответа

Решение

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

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

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

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

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

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

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

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

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

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

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

Другие вопросы по тегам