Стандарты программирования на С++. 101 правило и рекомендация
Шрифт:
Во многих фирмах еще не столь популярны, как хотелось бы, вознаграждения за качество кода, а также какие-либо вложения времени или средств в его повышение. Надежд на кардинальное изменение ситуации мало, но все же изменения в этой области, пусть медленно, но происходят; в частности, это связано с вопросами надежности и безопасности программного обеспечения. Коллективное рецензирование кода помогает в решении этих вопросов, в дополнение к тому, что это отличный и к тому же бесплатный метод обучения сотрудников.
Даже если ваш работодатель не намерен заботиться о рецензировании кода, постарайтесь донести мысль о его необходимости до менеджеров (маленькая
Лучшие результаты дает оперативное рецензирование кода, разрабатываемого в настоящий момент. Для этого не требуется никакого формализма — достаточно простой электронной почты. При такой организации работы легче отслеживать ваши собственные действия и избегать дублирования.
Когда вы работаете с чужим кодом, зачастую удобно иметь под рукой список того, на что именно следует обращать внимание. Мы скромно предлагаем в качестве варианта такого списка оглавление данной книги.
Мы знаем, что читаем проповедь, но мы должны были сказать это вслух. Да, ваше эго может ненавидеть показывать свои исходные тексты для всеобщей критики, но поверьте, маленькому гениальному программисту внутри вас по душе рецензирование его кода, потому что в результате он сможет писать еще более талантливые программы.
[Constantine95] §10, §22, §33 • [McConnell93] §24 • [MozillaCRFAQ]
Стиль проектирования
Дураки игнорируют сложности. Прагматики терпят их. Некоторые ухитряются их избегать. И только гении устраняют их.
Я также знал, но забыл афоризм Хоара о том, что преждевременная оптимизация — корень всех зол в программировании.
Очень сложно отделить стиль проектирования от стиля кодирования. Мы попытались поместить в очередном разделе те вопросы, которые обычно проявляются, когда вы начинаете писать реальный код.
В этом разделе внимание уделяется принципам и практическим вопросам, область применения которых больше, чем просто отдельный класс или функция. Классические примеры — баланс между простотой и ясностью (рекомендация 6), избежание преждевременной оптимизации (рекомендация 8) и пессимизации (рекомендация 9). Эти рекомендации применимы не только на уровне кодирования отдельной функции, но и к большим областям — проектированию классов и модулей или к решениям с далеко идущими последствиями по поводу архитектуры приложений. (Они применимы также для всех программистов. Если вы считаете иначе — еще раз прочтите приведенную выше цитату Кнута и даже заучите ее на память.)
Многие из прочих рекомендаций этого и следующего разделов имеют дело с управлением зависимостями — краеугольным камнем проектирования программного обеспечения и часто повторяющейся в данной книге темой. Остановитесь и задумайтесь над произвольной методикой проектирования программного обеспечения — любой хорошей методикой. Какую бы методику вы ни выбрали, так или иначе вы столкнетесь с ослаблением зависимостей. Наследование? Разрабатываемый код должен делать производный класс как можно менее зависимым от базового класса. Минимизация использования глобальных переменных? Снижает дальнодействующие зависимости, осуществляемые посредством широко видимых разным частям программы данных. Абстракция? Устраняет зависимости между кодом, который управляет концепциями, и кодом, который их реализует. Сокрытие информации? Делает код клиента менее зависимым от деталей реализации. Забота об управлении зависимостями отражается в устранении совместного использования состояния (рекомендация 10), применении сокрытия информации (рекомендация 11) и прочем.
В этом разделе самой важной нам кажется рекомендация 6: "Главное — корректность, простота и ясность".
5. Один объект — одна задача
Концентрируйтесь одновременно только на одной проблеме. Каждый объект (переменная, класс, функция, пространство имен, модуль, библиотека) должны решать одну точно поставленную задачу. С ростом объектов, естественно, увеличивается область их ответственности, но они не должны отклоняться от своего предназначения.
Хорошая идея, будучи высказанной вслух, должна быть пояснена одним предложением. Аналогично, каждая сущность в программе должна иметь одно ясное предназначение.
Объект с разнородными предназначениями обычно несоразмерно трудно использовать, поскольку он представляет собой нечто большее, чем просто сумму решений, сложностей и ошибок составляющих его частей. Такой объект больше по размеру (зачастую без особых на то причин) и сложнее в применении и повторном использовании. Зачастую такие объекты имеют весьма убогий интерфейс для каждого из своих отдельных предназначений, поскольку частичное перекрытие разных областей функциональности приводит к невозможности четкой реализации в каждой из них.
Объекты с разнородными функциями обычно трудны для проектирования и реализации. "Множественная ответственность" зачастую приводит к тому, что количество возможных вариантов поведения и состояния объектов разрастается в соответствии с законами комбинаторики. Предпочтительнее использовать короткие функции с четко указанным единственным предназначением (см. также рекомендацию 39), маленькие классы, предназначенные для решения одной конкретной задачи, и компактные модули с четко очерченными границами.
Абстракции высокого уровня предпочтительно строить из меньших низкоуровневых абстракций. Избегайте объединения нескольких низкоуровневых абстракций в большой низкоуровневый конгломерат. Реализация сложного поведения из набора простых существенно легче решения обратной задачи.
Пример 1.