После нескольких недель, читая на этом форуме я думал, что пришло время для меня сделать мое первое сообщение.
Я в настоящее время перечитываю Завершенный Код. Я думаю, что это - 15 лет с прошлого раза, и я нахожу, что все еще не могу написать код ;-)
Так или иначе на странице 138 в Коде, Завершенном, Вы находите этот пример ужаса кодирования. (Я удалил часть кода),
class Emplyee {
public:
FullName GetName() const;
Address GetAddress() const;
PhoneNumber GetWorkPhone() const;
...
bool IsZipCodeValid( Address address);
...
private:
...
}
То, что думает Steve, плохо, то, что функции свободно связаны. Или он имеет, пишет, что "нет никакого логического соединения между сотрудниками и стандартными программами, которые проверяют почтовые индексы, номера телефона или классификации заданий"
Хорошо я полностью соглашаюсь с ним. Возможно, что-то как ниже примера лучше.
class ZipCode
{
public:
bool IsValid() const;
...
}
class Address {
public:
ZipCode GetZipCode() const;
...
}
class Employee {
public:
Address GetAddress() const;
...
}
При проверке, допустима ли zip, необходимо было бы сделать что-то вроде этого.
employee.GetAddress().GetZipCode().IsValid();
И это не хорошо относительно к Закону Demeter.
Таким образом, если Вам нравится удалять две из трех точек, необходимо использовать делегацию и несколько функций обертки как это.
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();
Но с другой стороны у Вас есть стандартные программы, который не имеет никакого логического соединения.
Я лично думаю, что все три примера в этом сообщении плохи. Это - некоторый другой способ, о котором я не думал?
Это платите сейчас, а платите позже.
Вы можете написать функции делегирования и оболочки заранее (заплатите сейчас), а потом у вас будет меньше работы, изменяя внутренности 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());
Я думаю, что это удовлетворительно в соответствии с вашими ограничениями логической ассоциации и закона Деметры.