Стандарты программирования на С++. 101 правило и рекомендация
Шрифт:
Функциональные объекты должны быть адаптируемы. Стандартные связыватели и адаптеры полагаются на наличие определенных инструкций
Постарайтесь избежать наличия нескольких операторов
Не все функциональные объекты являются предикатами — предикаты представляют собой подмножество функциональных объектов (см. рекомендацию 87).
[Allison98] §15, §C • [Austern99] §4, §8, §15 • [Gamma95] Bridge • [Josuttis99] §8.2.4 • [Koenig97] §21, §29 • [Meyers97] §34 • [Meyers01] §38, §40, §46 • [Musser01] §2.4, §8, §23 • [Sutter00] §26-30 • [Vandevoorde03] §22
Безопасность типов
Если вы лжете компилятору, он будет мстить.
Всегда будут вещи, которые мы будем хотеть сказать в наших программах и которые трудно сформулировать на любом языке программирования.
Последней (не по важности) темой книги является корректность типов — очень важное свойство программ, которое вы должны изо всех сил стараться поддерживать. Теоретически корректная с точки зрения типов функция не может обратиться к нетипизированной памяти или вернуть неверные значения. На практике, если ваш код поддерживает корректность типов, он тем самым избегает большого количества неприятных ошибок, от непереносимости программ до порчи содержимого памяти и неопределенного поведения программ.
Основная идея поддержки корректности типов — всегда считывать информацию в том формате, в котором она была записана. Иногда С++ позволяет легко нарушить это правило; приведенные в этом разделе рекомендации помогут вам избежать подобных ошибок.
В этом разделе мы считаем наиболее значимой рекомендацию 91 — "Работайте с типами, а не с представлениями". Система типов — ваш друг и верный союзник. Воспользуйтесь ее помощью и попытайтесь не злоупотреблять ее доверием.
90. Избегайте явного выбора типов — используйте полиморфизм
Избегайте явного выбора типа объекта для настройки поведения. Используйте шаблоны и виртуальные функции для того, чтобы поведение объекта определялось его типом, а не вызывающим кодом.
Настройка поведения в зависимости от типа объекта с использованием инструкции выбора
В идеале добавление новых возможностей в программу должно осуществляться добавлением нового кода, а не изменением старого (см. рекомендацию 37). В реальной жизни это не всегда так — зачастую в дополнение к написанию нового кода мы вынуждены вносить изменения в уже имеющийся код. Такие изменения, однако, крайне нежелательны и должны быть минимизированы по двум причинам. Во-первых, изменения могут нарушить имеющуюся функциональность. Во-вторых, они препятствуют масштабируемости при росте системы и добавлении новых возможностей, поскольку количество "узлов поддержки", к которым надо возвращаться и вносить изменения, все время возрастает. Это наблюдение приводит к принципу Открытости-Закрытости, который гласит: любая сущность (например, класс или модуль) должна быть открыта для расширений, но закрыта для изменений (см. [Martin96c] и [Meyer00]).
Каким же образом мы можем написать код, который будет легко расширяем без внесения изменений? Используйте полиморфизм для написания кода в терминах абстракций (см. также рекомендацию 36), после чего при необходимости добавления функциональности это можно будет сделать путем разработки и добавления различных реализаций упомянутых абстракций. Шаблоны и виртуальные функции образуют барьер для зависимостей между кодом, использующим абстракции, и кодом, их реализующим (см. рекомендацию 64).
Конечно, управление зависимостями обусловлено выбором верных абстракций. Если абстракции несовершенны, добавление новой функциональности потребует изменений интерфейса (а не просто добавления новых реализаций интерфейса), которые обычно влекут за собой значительные изменения существующего кода. Но абстракции потому и называются "абстракциями", что предполагается их большая стабильность по сравнению с "деталями", т.е. возможными реализациями абстракций.
Совсем иначе обстоит дело с предельно детализированным кодом, который использует мало абстракций или вовсе обходится без них, работая исключительно с конкретными типами и их отдельными операциями. Добавление новой функциональности в такой код — сущее мучение.
Пример. Рисование фигур. Классический пример — рисование различных объектов. Типичный подход в стиле С использует выбор типа. Для этого определяется член-перечисление