Эти диаграммы подсказывают, что следует использовать наследование и параметризацию соответственно. В обоих случаях, для того чтобы работа имела смысл, интерфейс должен быть меньше, чем простое объединение интерфейсов классов А и В. Иначе говоря, для того чтобы пользователь получил выгоду от принятого решения, классы А и В должны иметь фундаментальную общность. Обратите внимание на то, что мы снова вернулись к интерфейсам (см. разделы 9.7 и 25.4.2) и, как следствие, к инвариантам (см. раздел 9.4.3).
22.1.2.6. Логичность и минимализм
• Не добавляйте свойство, если сомневаетесь в его необходимости.
• Похожие свойства должны иметь похожие интерфейсы (и имена), но только если их сходство носит фундаментальный характер.
• Непохожие свойства должны иметь непохожие имена (и по возможности разные интерфейсы), но только если их различие носит фундаментальный характер
Логичное именование, стиль интерфейса и стиль реализации облегчают эксплуатацию программы. Если код логичен, то программист не будет вынужден изучать новый набор соглашений, касающихся каждой части крупной системы. Примером является библиотека STL (см. главы 20-21, раздел Б.4–6). Если обеспечить логичность не удается (например, из-за наличия старого кода или кода, написанного на другом языке), то целесообразно создать интерфейс, который обеспечит согласование стиля с остальной частью программы. В противном случае этот чужеродный (“странный”, “плохой”) код “заразит” каждую часть программы, вынужденную к нему обращаться.
Для того чтобы обеспечить минимализм и логичность, следует тщательно (и последовательно) документировать каждый интерфейс. В этом случае легче будет заметить несогласованность и дублирование кода. Документирование предусловий, постусловий и инвариантов может оказаться особенно полезным, поскольку оно привлекает внимание к управлению ресурсами и сообщениям об ошибках. Логичная обработка ошибок и согласованная стратегия управления ресурсами играют важную роль для обеспечения простоты программы (см. раздел 19.5).
22.1.3. Стили и парадигмы
• Процедурное программирование.
• Абстракция данных.
• Объектно-ориентированное программирование.
• Обобщенное программирование.
Иногда их называют (несколько помпезно) парадигмами программирования. Существует еще несколько парадигм, например: функциональное программирование (functional programming), логическое программирование (logic programming), продукционное программирование (rule-based programming), программирование в ограничениях (constraints-based programming) и аспектно-ориентированное программирование (aspect-oriented programming). Однако язык С++ не поддерживает эти парадигмы непосредственно, и мы не можем охватить их в одной книге, поэтому откладываем эти вопросы на будущее.
• sqrt()
и cos()
. В языке С++ этот стиль программирования основан на использовании функций (см. главу 8). Вероятно, самой ценной является возможность выбирать механизм передачи аргументов по значению, по ссылке и по константной ссылке. Часто данные организовываются в структуры с помощью конструкций struct
. Явные механизмы абстракции (например, закрытые данные-члены и функции-члены класса не используются). Отметим, что этот стиль программирования — и функции — является интегральной частью любого другого стиля.