Пожалуй, в главной мере успех рецензирования определяется тем, будет ли оно интересно людям. Рецензирование ориентировано на участвующих в нем людей. Если собрание по рецензированию проходит в неприятной или скучной атмосфере, трудно будет кого-либо мотивировать. Проводите рецензирование кода в неформальной обстановке, и пусть главной задачей мероприятия станет распространение знаний среди членов команды. Оставьте в стороне сарказм, а вместо него принесите тортик или бутерброды.
Пиши код с умом
Йехиль Кимхи
Попытки доказать корректность программного обеспечения вручную приводят к формальному доказательству, которое длиннее самого кода и содержит ошибки с большей вероятностью, чем сам код. Желательно применять автоматизированные средства, но это не всегда возможно. Ниже описывается срединный путь: полуформальное доказательство корректности.
Метод основан на разделении исследуемого кода на короткие фрагменты размером от одной строки, которая может содержать вызов функции, до блоков длиной не более 10 строк и обсуждении их корректности. Доказательство должно оказаться достаточно убедительным для вашего коллеги, играющего роль «адвоката дьявола».
Фрагменты следует выбирать таким образом, чтобы в конечной точке блока состояние программы (а именно счетчик адреса команд и значения всех «живых» объектов) удовлетворяло простому в описании свойству, а функциональность этого фрагмента (преобразование состояния) легко описывалась в виде одной независимой задачи. Соблюдение предложенных правил упрощает ведение доказательства. Такие свойства конечной точки фрагмента обобщают понятия пред-условий и пост-условий для функций, а также инвариантов для циклов и классов (в отношении экземпляров классов). Необходимо стремиться, чтобы фрагменты как можно меньше зависели друг от друга, что облегчает доказательство и очень пригодится, если предполагается изменять эти фрагменты.
Многие хорошо известные (хотя и, видимо, реже применяемые) и имеющие статус «качественных» практики написания кода также облегчают проведение доказательств. Таким образом, одно лишь намерение провести в будущем доказательство корректности своего кода способствует улучшению его стиля и структуры. Не стоит удивляться, что большинство подобных практик проверяется статическими анализаторами кода:
• Избегайте операторов goto, потому что они создают сильную зависимость между фрагментами, разнесенными в коде.
• Избегайте изменяемых глобальных переменных, потому что они делают зависимыми между собой все фрагменты, в которых используются.
• Область видимости каждой переменной должна быть наименьшей из возможных. Например, локальный объект можно объявить непосредственно перед первым использованием.
• Делайте объекты неизменяемыми (immutable), где это возможно.
• Улучшайте читаемость кода посредством пробелов — как горизонтальных, так и вертикальных. Например, выравнивайте отступы для родственных структур и разделяйте фрагменты кода пустыми строками.
• Пишите самодокументируемый код, выбирая содержательные (но достаточно короткие) имена для объектов, функций, типов и т. д.
• Если фрагмент оказывается вложенным, превратите его в функцию.
• Каждая функция должна решать единственную задачу и быть короткой. Ограничение длины функции 24 строками, введенное много лет назад, по-прежнему действует. Размер и разрешение экрана по сравнению с 60-ми годами прошлого века увеличились, но человеческие возможности восприятия остались прежними.
• У функции не должно быть много аргументов (хорошая практика — не более четырех). Это не ограничивает объем передаваемых функции данных: объединение родственных аргументов в одном объекте локализует инварианты объекта, что упрощает доказательство в плане проверки согласованности и состояний объектов.