Как правило, основной причиной перехода на низкий уровень абстракции называют эффективность. Однако это следует делать только в случае реальной необходимости (раздел 25.2.2). Использование низкоуровневых (более примитивных) языковых свойств не всегда повышает производительность программы. Иногда оно исключает возможности оптимизации. Например, используя класс Phonebook
string[max]
и Value_type[max]
или в виде класса map
. Для одних приложений более эффективным оказывается первый вариант, а для других — второй. Естественно, производительность не является основным фактором, если вы пишете программу для хранения записей из своей телефонной книжки. Но оно становится существенным, если необходимо хранить и обрабатывать миллионы записей. Что еще важнее, использование низкоуровневых средств сопряжено с затратами рабочего времени, которого программисту не хватит на усовершенствование (повышение производительности или чего-то другого).22.1.2.5. Модульность
Здесь оба пользователя используют модуль С. Пока вы не заглянете внутрь модуля С, вы можете подумать, что оба пользователя получают преимущества благодаря тому, что совместно используют общедоступный компонент. Выгоды от совместного использования (повторного) могут (в данном случае этого не происходит) включать в себя более легкое тестирование, меньший объем кода, расширения пользовательской базы и т.д. К сожалению, за исключением случая излишнего упрощения, это не редкая ситуация.
Чем можно помочь? Может быть, следует создать общий интерфейс классов А и В?
Эти диаграммы подсказывают, что следует использовать наследование и параметризацию соответственно. В обоих случаях, для того чтобы работа имела смысл, интерфейс должен быть меньше, чем простое объединение интерфейсов классов А и В. Иначе говоря, для того чтобы пользователь получил выгоду от принятого решения, классы А и В должны иметь фундаментальную общность. Обратите внимание на то, что мы снова вернулись к интерфейсам (см. разделы 9.7 и 25.4.2) и, как следствие, к инвариантам (см. раздел 9.4.3).
22.1.2.6. Логичность и минимализм
• Не добавляйте свойство, если сомневаетесь в его необходимости.
• Похожие свойства должны иметь похожие интерфейсы (и имена), но только если их сходство носит фундаментальный характер.
• Непохожие свойства должны иметь непохожие имена (и по возможности разные интерфейсы), но только если их различие носит фундаментальный характер
Логичное именование, стиль интерфейса и стиль реализации облегчают эксплуатацию программы. Если код логичен, то программист не будет вынужден изучать новый набор соглашений, касающихся каждой части крупной системы. Примером является библиотека STL (см. главы 20-21, раздел Б.4–6). Если обеспечить логичность не удается (например, из-за наличия старого кода или кода, написанного на другом языке), то целесообразно создать интерфейс, который обеспечит согласование стиля с остальной частью программы. В противном случае этот чужеродный (“странный”, “плохой”) код “заразит” каждую часть программы, вынужденную к нему обращаться.