Программист-прагматик. Путь от подмастерья к мастеру | страница 31



Также стоит подумать о комментариях в файлах заголовка и реализации. В дублировании комментария функции или заголовка класса в этих двух файлах нет абсолютно никакого смысла. Файлы заголовка используются для документирования аспектов интерфейса, а файлы реализации – для документирования некоторых подробностей, которых пользователи вашей программы знать не должны.

Неумышленное дублирование

Иногда дублирование происходит в результате ошибок в проекте.

Рассмотрим пример из области транспорта. Пусть аналитик установил, что, наряду с прочими атрибутами, грузовик имеет тип, номерной знак и водителя. Аналогично, маршрут доставки груза представляет собой сочетание маршрута, грузовика и водителя. Мы создаем программы для некоторых классов, основанных на этом представлении.

Но что происходит, если водитель по имени Салли заболевает и приходится менять водителя? Классы Truck и DeliveryRoute содержат описание водителя. Какой из них мы должны изменить? Ясно, что это дублирование неудачно. Нормализуйте его в соответствии с базовой бизнес-моделью – необходим грузовику водитель как часть базового набора атрибутов? А маршрут? Возможно, необходим третий объект, который связывает воедино водителя, грузовик и маршрут. Каким бы ни было окончательное решение, стоит избегать этого типа ненормализованных данных.

Есть не столь очевидный тип ненормализованных данных, который имеет место при наличии множественных взаимозависимых элементов данных. Рассмотрим класс, представляющий отрезок:

class Line {

public:

 Point start;

 Point end;

 double length:

};

На первый взгляд, этот класс может показаться разумным. Отрезок явно имеет начало и конец и всегда будет иметь длину (даже если она нулевая). Но происходит дублирование. Длина определяется начальной и конечной точками: при изменении одной из точек длина меняется. Лучше сделать длину вычисляемым полем:

class Line {

public:

 Point start;

 Point end;

 double length() {return start.distanceTo(end);}

};

Позже, в ходе разработки, вы можете нарушить принцип «Не повторяй самого себя» в силу требований к производительности. Зачастую это происходит, когда вам необходимо кэшировать данные во избежание повторения дорогостоящих операций. Эта уловка призвана ограничить воздействие. Нарушение принципа не подвержено воздействию внешнего мира: лишь методы в пределах класса должны поддерживаться в надлежащем состоянии.

class Line {

private:

 bool changed;

 double length;

 Point start;