Книга "Программист-прагматик"

Эндрю Хант, Дэвид Томас "Программист-прагматик", Питер, 2007

Книга местами уже устарела, но в целом выглядит как неплохой сборник многократно пересекающихся кулинарных рецептов для холостяков. Многие сюжеты освещены в том же ключе, что и в моей "Дефрагментации мозга", тоже начавшей устаревать. Поскольку я не знал о существовании книги коллег, приятно, что параллельно мы пришли к похожим выводам по многим вопросам.

Несколько заметок по ходу чтения.

В главах 19-20 "Обработка текста" и "Генераторы текстов программ" авторы подступаются к теме разработки по моделям. Чтобы не пугать заумными терминами программистов "от сохи", выбраны предельно простые случаи. Например, по каким-то описаниям схемы базы данных скрипт на Перле (или другом языке сценариев) генерирует много полезного кода от SQL до Web-страничек и описания в XML (!). На самом деле, текст уже представляет собой описание модели на некотором языке (который проще создать на базе XML), поэтому для продвижения по этой дорожке все же придется углубляться в подход.

В главе 21 "Проектирование по контракту" поется осанна методу, продвигаемому Бертраном Мейером с 1980-х годов. Хороший довесок к статической типизации. В языке Ява контракты могут быть описаны в комментариях и обработаны препроцессором.

/**
* @pre f != null
* @post getFont() == f
 */

Следует помнить однако, что код проверки контракта, если не принимать дополнительных мер, исполняется и при отладке, и в эксплуатации, что не всегда приемлемо с точки зрения производительности. Альтернативой могут служить тесты, код проверок исполняется только при испытаниях.

В примере контракта с инвариантом цикла условие инварианта дублирует сам цикл, таким образом контракт может легко нарушать правило неповторяемости исходников, которое авторы справедливо пропагандируют на протяжении книги, окрестив DRY (don't repeat yourself).

Глава 24 "Случаи, в которых используются исключения" содержит "много букв". Я предпочитаю использовать собственное простое правило:

  • если подпрограмма знает, как обработать ошибку, то делаем это внутри
  • если не знает - надо сообщить вызывающей подпрограмме: исключение, ошибка времени выполнения или некоторый протокол возврата статуса (например, код ошибки)

Глава 26 "Несвязанность". "Скромные" программы - философия UNIX, это уже стало модой, включая нынешний хайп микросервисов, который, надеюсь, мы благополучно переживем. И снова авторы скатываются в апологетику крайностей: либо автономные программки либо сплошной монолит, третьего не дано. К слову, подход "автономные команды" (читай, ячейки подпольщиков) vs базар "все знают всех" применим и к организации процесса. Нет ничего безумнее горизонтальной команды, превышающей десяток человек.

Аналогично упомянутому в "Дефрагментации" признаку "система начала жить своей жизнью", авторы определяют хрупкий дизайн как "разработчики, которые боятся изменить программу, поскольку они не уверены, как и на чем скажется это изменение".

Как следствие, мне кажется очевидным, что любой человек разумный должен мочь самостоятельно догадаться, например, откуда растут ноги у антипаттерна "волшебный класс". Дело в том, что внутри класса связность сильная => классы с широким набором функций хрупкие.

Хорошие формулировки авторов:

  • "...логическое и физическое проектирование должно осуществляться в тандеме"
  • "...устранение повреждений в большом фрагменте программы, нанесенных ему циклическими зависимостями, представляется чрезвычайно трудным делом"

Совет почитать книгу "Large-Scale С++ Software Design" тоже очень к месту.

Глава 27 "Метапрограммирование" отчасти дублирует упомянутые выше подходы генерации программ по моделям. Однако он статичен, в то время как система класса ERP требует динамики. Рад, что авторы не преминули вспомнить подход "ядро + метаданные", использованный практически во всех моих проектах.

Глава 33 "Реорганизация" была написана по всей видимости до введения в обиход более расплывчатого термина "рефакторинг". Действительно, "реорганизация" грубо намекает на ошибки эффективных менеджерков, а "реструктуризация" и "факторизация" слишком академичны для массового пользователя.

Содержание главы предваряет попытки популяризацию рефакторинга. Необходимость тестов еще не постулируется, но недвусмысленно упоминается. А следующая глава -- целиком о тестах.

Что имеем сегодня?

Популяризация рефакторинга и тотальных тестов провалилась. Несмотря на ключевую важность этих элементов для аджайлов, они игнорируются. Аджайлы превращаются в обычную восходящую разработку (снизу-вверх), известную всеми своими проблемами еще с 1950-х годов.

Глава 35 "Злые волшебники". Снова возвращаясь к теме генерации кода, авторы делают совершенно верный вывод: код неуправляем, если программист не понимает сути сгенерированного текста. Еще одна причина высокого порога входа в model-driven разработку.

Подсказка 53: Абстракции живут дольше, чем подробности. Удачная формулировка принципа, подтверждающего необходимость проектирования.

Подсказка 57: Некоторые вещи лучше сделать, чем описывать. Обоснование для создания прототипов, но не бесконечного цикла итераций в аджайлах.

В целом книгу лучше прочитать, чем пропустить.