(Картинка без намека, просто уж очень хотелось котика в статью добавить! Ведь это основной залог популярности в интернетах, правда? :))
У меня очень неоднозначное отношение к книгам Роберта Мартина… В них довольно много здравых и интересных мыслей, но иногда они выражаются столь категорично, что неокрепшим программерским
Вот и получается, что идеальной аудиторией для этих книг является продвинутый разработчик, окрепший достаточно, чтобы критически оценивать советы «гуру», но при этом не настолько матерый, чтобы эти советы не звучали из разряда «Спасибо, Кэп!».
Хотя, нужно признать, что если в книге «Принципы, паттерны и методики гибкой разработки» спорных советов с моей точки зрения было очень много, то в «Чистом коде» приводится значительно больше разумных и прагматичных советов.
Но поскольку паранойи в книге тоже достаточно, поэтому я хочу начать именно с неоднозначных моментов, а уже потом перейти к радостям.
Спорные и сомнительные моменты
В «Чистом коде» есть несколько откровенно сомнительных моментов. Во-первых, в ней довольно много кода, читать который на страницах книги очень сложно. В 15-й главе рассматривается улучшение парсера командной строки на 60 страницах, 40 из которых – это сплошной код на Java. Главы 16-17 написаны в том же формате, но они короче, поэтому следовать рассуждениям автора проще.
СОМНИТЕЛЬНЫЙ СОВЕТ
Первое правило: функции должны быть компактными. Второе правило: функции должны быть еще компактнее. … Из сказанного выше следует, что блоки в командах if, else, while и т.д. должны состоять из одной строки, в которой обычно содержится вызов функции. Это не только делает вмещающую функцию более компактной, но и способствует документированию кода, поскольку вызываемой в блоке функции можно присвоить удобное содержательное имя.
Некоторые главы откровенно слабые. Мне вообще не понятна цель главы 13 о параллелизме, в которой даются лишь общие сведения о проблемах многопоточности, а затем в приложении А разбираются те же самые темы, но уже более детально и с необходимыми примерами.
Но больше всего меня смущает неоднозначное отношение автора к состоянию и побочным эффектам.
Побочные эффекты суть ложь. Ваша функция обещает делать что-то одно, но делает что-то другое, скрытое от пользователя. Иногда она вносит неожиданные изменения в переменные своего класса – скажем, присваивает им значения параметров, переданных функции…
Несмотря на этот совет, автор во многих примерах использует код с побочными эффектами и отговаривает всеми силами использовать аргументы, используя вместо этого состояние объекта:
private String render(boolean isSuite) /*throws Exception*/
{
this.isSuite = isSuite;
if (isTestPage())
includeSetupAndTeardownPages();
return pageData.getHtml();
}
private void includeSetupAndTeardownPages() throws Exception {
includeSetupPages();
includePageContent();
includeTeardownPages();
updatePageContent();
}
private void includeSetupPages() /*throws Exception*/
{
if (isSuite)
includeSuiteSetupPage();
includeSetupPage();
}
СОМНИТЕЛЬНЫЙ СОВЕТ
… Аргументы создают массу проблем с точки зрения тестирования. Только представьте, как трудно составить все тестовые сценарии, проверяющие правильность работы кода со всеми комбинациями аргументов.
В чем разница с точки зрения тестирования между статическим методом с четырьмя аргументами и экземплярного метода объекта с четырьмя полями? Количество граничных условий в обоих случаях одно и тоже; просто в первом случае мы все входные данные протаскиваем явно, а во втором случае – неявно через this.
Стилю кодирования в книге уделено много внимания, при этом большинство советов вполне разумными. Но встречаются и очень неоднозначные:
СОМНИТЕЛЬНЫЙ СОВЕТ
Стандарт кодирования определяет, где объявляются переменные экземпляров; как именуются классы, методы и переменные; как располагаются фигурные скобки и т.д. Документ с явных описанием этих правил не нужен – сам код служит примером оформления.
Перевод
Перевод, мягко говоря, не порадовал. Иногда он «радовал» настолько, что приходилось лезть в оригинал, чтобы понять, о чем идет речь:
ЦИТАТА
Когда у вас появился полный набор тестов, можно заняться чисткой кода и классов.
Для этого код подвергается последовательной переработке (рефакторингу). Мы добавляем несколько строк кода, делаем паузу и анализируем новую архитектуру.
WTF! Как добавление двух строк может повлиять на архитектуру?!?! Есть два варианта: либо мы имеем дело с очень длинными строками, или же авторы здесь говорят не об архитектуре, а о чем-то ином, например, о дизайне! Вся глава 12 (из которой взята эта цитата) полностью испорчена тем, что термин “design” переведен в ней как «архитектура», что делает многие советы автора спорными.
Как обычно, переводчики не потрудились оставить оригинальные термины, так что приходилось догадываться, что же имеется ввиду под терминами «логическая привязка» или «многопоточность» (оказывается, что это high coupling и concurrency, соответственно).
Поскольку содержимое книги относительно простое, то переводчикам удалось лишь «подпортить» впечатление, но не запороть ее полностью.
Дельные советы
На самом деле, все не настолько плохо и «дядюшка» Боб сотоварищи дают много хороших советов. Вот некоторые из них:
Об именовании
Не используйте имена, передающие информацию о реализации. Имена должны отражать уровень абстракции, на котором работает класс или функция.
О понятности кода
Легко писать код, понятный для нас самих, потому что в момент его написания мы глубоко понимаем решаемую проблему. У других программистов, которые будут заниматься сопровождением этого кода, такого понимания не будет.
О длине и выразительности имен
Длина имени должна быть связана с длиной его области видимости. Переменным с крошечной областью видимости можно присваивать очень короткие имена, но у переменных с большей областью видимости имена должны быть длинными. … Таки образом, чем длиннее область видимости, тем более длинным и точным должно быть ее имя.
О содержимом функций
Все операторы в функции должны находиться на одном уровне абстракции, который должен быть на один уровень ниже операции, описываемой именем функции.
Совет кажется простым, но он очень ценен. Код должен читаться, как хорошая проза, а для этого просто необходимо, чтобы функция содержала операторы одного уровня.
Юнит-тесты в качестве инструмента изучения библиотек
Изучение чужого кода – непростая задача. Интеграция чужого кода тоже сложна. Одновременное решение обоих задач создает двойственные сложности. А что, если пойти по другому пути? Вместо того, чтобы экспериментировать и опробовать новую библиотеку в коде продукта, можно написать тесты. Проверяющие наше понимание стороннего кода. Джим Ньюкирк (JimNewkirk) называет такие тесты «учебными тестами».
Этому совету я следую давно и использую юнит-тесты для изучения новых инструментов и библиотек. Это позволяет лучше разобраться с библиотекой и легко возвращаться к примерам использования, поскольку они всегда под рукой.
Очень повеселил один совет. Давайте так: что вам говорит магическая константа 5280? Ничего? Странно, по словам автора, это одно из значений, которое можно спокойно «хардкодить»!
Некоторые числа так легко узнаются, что их не обязательно скрывать за именованными константами – при условии, что они используются в сочетании с ясным кодом. … Число 5280 – количество футов в миле – настолько хорошо известно и уникально, что читатель сразу узнает его, даже если оно будет располагаться вне какого-либо контекста.
Качество книги можно косвенно оценить по количеству интересных цитат и количеству блог-постов, появившихся в процессе чтения. И если в процессе чтения «Принципов, паттернов и методик» появились критические статьи типа «Контракты, состояние и юнит-тесты», то в результате «Чистого кода» появились «Пять принципов чистых тестов» и «Лучшая метрика для определения качества кода».
Достоинства: приличное количество приличных советов
Недостатки: часть советов весьма спорны; иногда советы непоследовательны; перевод хромает на обе ноги.
Оценка: 4-
Автор: SergeyT