Многие технические книги начинаются с ужасно скучного и муторного введения. Исключений немного, и книга «Идеальный код», о которой я рассказал в прошлом посте — одна из тех, введение которой стоит прочесть.
Математические книги нужно читать имея под рукой ручку и бумагу, все остальные — имея под рукой гугл. Последний раз когда я читал введение в «Идеальный код», у меня не было под рукой гугла. Думаю, тогда я упустил из виду нечто важное.
Вот первые два абзаца:
Я начал работать программистом летом 1982 года. Через пару недель после этого один из системных администраторов дал мне почитать книги «The Elements of Programming Style», Brian W. Kernighan, P. J. Plauger, и «Algorithms + Data Structures = Programs», Niklaus Wirth.
Это стало для меня открытием. Я впервые узнал, что программы — это нечто большее, чем простые инструкции для компьютера. Они могут быть элегантными, как ближайшее окружение президента, изящными, как подвесной мост, и красноречивыми, как эссе Джорджа Оруэлла.
Наверняка про книгу Вирта слышали многие. А вот про старую книгу Кернигана — наврядли. В сети на этот счет глухо — есть электронная версия перевода времен СССР, но она лежит на буржуйском ресурсе с повременным доступом, поэтому скопировать её за вменяемое время не представляется возможным.
«Элементы стиля программирования» это небольшой ~150-страничный
сборник примеров кода с пояснениями, почему приведенный код —
говно. Книга действительно древняя, все примеры написаны на Фортране и
PL/1 с обилием прелестей а'ля 20 goto 10
, но внимания заслуживают
несколько десятков «правил», разбросанных по всей книге. Определенно,
эти правила важны как история становления философии UNIX. Очень
похожие правила можно найти в книге Рэймонда «Искусство
программирования для UNIX».
Ниже вы увидите большую часть этих правил и немного моих комментариев.
Перефразируя высказывание из «Элементов стиля» («Elements of Style» by Strunk & White), правила стиля программирования, как и стиля английского языка, иногда нарушают даже лучшие писатели. Впрочем, когда правило нарушается, обычно в программе находится некое компенсирующее качество, которое достигается за счет нарушения. Если вы не уверены в улучшении, вероятно, лучше всего будет следовать правилам.
-
Говорите то, что вы имеете в виду, просто и прямо.
Сама суть философии UNIX: «Будь проще, тупица».
-
Пишите программы просто — не делайте их слишком
хитроумными.
Аналогично Правилу ясности: Ясность лучше заумности.
Чаще всего этим грешат хаскеллисты и большие любители паттернов проектирования.
- Пользуйтесь библиотечными функциями.
- Избегайте промежуточных переменных.
- Пишите понятно — не жертвуйте ясностью ради «эффективности».
-
Пусть машина делает грязную работу.
Аналогично Правилу экономии: Время программиста дорого; сократите его, используя машинное время.
-
Заменяйте повторяющиеся выражения вызовами функций.
Лисперы добавят: заменяйте повторяющиеся управляющие конструкции макросами.
-
Скобки исключают двусмысленность.
Обилие скобочек в правильных местах избавит от двусмысленности, повысит читаемость и увеличит расширяемость — лисперы знают о чем я (loop & iterate).
- Выбирайте имена переменных так, чтобы они не приводили к путанице.
-
Не используйте goto, если хотите сохранить программу читаемой.
Мантра «структурного программирования».
- Избегайте ненужных ветвлений.
-
Используйте хорошие средства языка и не используйте плохие.
Над этим правилом уже 20 лет ломают голову программисты на С++.
-
Используйте «телефонный тест» для проверки читабельной программы.
Как в анекдоте: если Рабинович сможет правильно «напеть» вашу программу — она прошла тест.
-
Используйте сдвиг строк (идентацию) для разделения блоков кода.
Если пишите на питоне — можете проигнорировать это правило.
- Делайте программы читаемыми сверху вниз.
- Используйте if и else чтобы подчеркнуть необходимость выполнения только одного из двух действий.
- Используйте if … else if … else для ветвлений по нескольким направлениям.
- Пользуйтесь основными конструкциями потока управления.
- Если логическое выражение трудно понять — попробуйте его преобразовать.
-
Пусть данные определяют структуру программы.
Аналогично Правилу представления Реймонда: Храните знания в данных так, чтобы логика программы была тупой и надёжной.
-
Сперва напишите на псевдокоде, потом переведите на машинный язык.
Литературное программирование пошло дальше в этом подходе — сперва напишите на псевдокоде, а потом допишите машинным языком.
- Каждый модуль должен выполнять одну функцию, но хорошо.
- Не исправляйте плохую программу — перепишите её.
- Пишите и тестируйте программу небольшими частями.
-
Используйте рекурсивные процедуры для рекурсивных структур данных.
Рекурсия не должна быть затычкой в каждой бочке (как в языке Scheme), с ней нужно быть очень осторожным — по убийственной силе она близка старому доброму goto (если считаете иначе — попробуйте разобраться в системе из хотя бы трех взаиморекурсивных функций). В большинстве случаев лучше предпочесть итеративные конструкции рекурсивным.
- Проверяйте вводимые данные на обоснованность и правдоподобие.
- Убедитесь, что входные данные не приведут к вылету программы.
- Определяйте плохие входные данные; восстанавливайтесь, если это возможно.
- Делайте входные данные легкими для подготовки, а выходные — понятным.
- Используйте единый формат ввода.
- Делайте входные данные легко корректируемыми.
- Делайте входные данные понятными и используйте значения по-умолчанию.
- Инициализируйте переменные перед использованием.
- Тестируйте программы на граничных условиях.
- Убедитесь, что особые случаи действительно особые.
- Проверте некоторые результаты вручную.
- Будте осторожными в вычислениях с плавающими точками и дробями.
- Сделайте программу правильной перед тем как сделать её быстрой.
- Сделайте программу отказоустойчивой перед тем как сделать её быстрой.
- Сделайте программу ясной перед тем как сделать её быстрой.
- Оставте простые оптимизации компилятору.
- Не напрягайтесь с повторным использованием кода; вместо этого — реорганизуйте его.
- Держите программу простой чтобы сделать её быстрой.
- Не раздувайте код чтобы сделать его быстрым — найдите лучший алгоритм.
- Используйте профайлер. Измеряйте скорость перед тем как делать программу «эффективнее».
- Убедитесь, что комментарии и код совпадают.
- Не повторяйте код в комментариях — сделайте каждый комментарий значимым.
- Не комментируйте плохой код — перепишите его.
- Используйте значащие имена переменных и имена меток goto.
- Форматируйте программу так, чтобы помочь читателю понять её.
- Документируйте структуры данных.
- Не комментируйте сверх меры.