Comments 125
Согласен насчёт совершенного кода. Я сперва прочитал её и на многое открылись глаза
Потом мельком видел чистый код, и не понял, почему люди фанатеют от весьма спорных утверждений в этой книге.
именно потому, что спорные?
как можно "фанатеть" от утверждения, что "2+2=4" или "2+2<>4" ? Проверил, принял к сведению. Фанатеть же - с любым знаком - как раз можно только от "истина где-то рядом"
Есть еще "Рецепты чистого кода" Максимилиано Контьери (O'Reilly) - относительно недавно вышедшая книга.
Если здесь есть кто-то уже прочитавший её, дайте, пожалуйста, отзыв. Интересно сравнить её и тот же "Совершенный код".
А то у меня все руки не доберутся, а хочется сразу прочитать что-то самое правильное и полезное.
Есть одна интересная книга, называется A philosophy of software design, автор John Ousterhout, и она рассказывает о когнитивной сложности в разработке ПО и методах ее упрощения. И некоторые ее положения весьма далеки от догм энтерпрайзного классоклепания, от чего у кучи народа подгорает и бомбит. Как же так - не клепать классы на каждый чих, или писать комменты на высокоуровневую структуру и неявные связи компонент - ведь мой код написан по солид, а значит непогрешим! Бабах. Но если книженцию почитать и вдуматься, то это тот подход к разработке ПО, который мы потеряли где-то во времена становления "агильности".
заголовок кликбейтный, правильный заголовок звучит так "В 2024 году я наконец-то добрался до книги, купленной мною в 2016, прочитав я осознал что она идет в разрез с моим видением мира, и поскольку выплеснуть свое несогласие и негатив больше было некуда, решил тут"
Учусь маркетингу у лучших представителей айти!
Звучит как название какого-то аниме :Д
...какого-то недавнего аниме.
Если взять аниме, которым 10-20-30 лет, то там вроде такой фигни не было.
Скорее это звучит, как заголовок главы из развлекательных романов 19-го века.
Глава 123-я
...в которой Робинзон узнаёт...
...и дальше полстраницы мелким текстом :-)
Вы упускаете из виду контекст. Лично я никогда не писал на Java и примеры кода в его книжках меня тоже не восхищают. Но я вполне допускаю, что конкретно для Java того времени - этот код может быть заметно лучше среднего. То же касается и SOLID - будучи в целом здравым подходом оно не везде и не всегда полезно на практике (напр. в не ООП языках и "не совсем ООП" языках вроде Go где нет наследования от LSP пользы нет, равно как в небольших компаниях/проектах где один источник требований нет пользы от SRP, DIP стала настолько штатным и привычным механизмом что сегодня нет смысла её как-то особенно выделять, подход к интерфейсам в том же Go делает бессмысленным явное соблюдение ISP - оно само собой соблюдается, …). Но это не отменяет полезности всех частей SOLID в те времена и для тех языков и проектов, на которых SOLID был сформулирован. И тем более не отменяет полезности и адекватности идей, которые продвигает дядя Боб - просто надо понимать суть этих идей и уметь адаптировать их для своего текущего проекта, а не тупо заучивать формальные определения каждой буквы из SOLID и столь же тупо требовать использования их всех в любых проектах.
Конда-то давно я был джуном и пытался вкатится в мир энтерпрайз разработки на джаве.
Что я могу сказать - люди сами превратили принципы в универсальные, религиозные догмы, а теперь сами с ними борятся.
Надо понимать, что те чуваки как бы не пытались дать универсальный ответ на все вопросы разработки, особенно будущей.
Они делились своим опытом. Тот же Мартин прямо говорил, что нпльзя сразу создать идеальную архитектуру, а значит вы будете разрабатывать через тестирование. Но вы не можете постоянно всё ломать и переделывать. Значит вам нужно проводить свою эволюцию гибко, так как у вас большая система и маленький кусочек может положить всё.
Именно из этого растут ноги принципов и рекомендаций. Чем проще механизмы, тем сложнее их сломать.
Это же касалось неймингов - Мартин предлагал именовать классы намерениями, а не действиями. Т.е чего я ожидаю от исполнения класса.
Более того, сам Мартин писал, что чистый код это не о правилах, а о дисциплине и он создаётся в процессе практик, а не с первого раза.
А если добить, то сам же дядя Боб говорил, что книга его, это не уникальные идеи, а компиляция. Там есть ссылка на того же Тима Оттингера.
В итоге люди, прочитавшие книгу, решили, что это не попытка научить думать и предложить хорошие практики, а библия, заповеди и догмы. И теперь сами недовольны
Сам Мартин в первой главе на страница 35 пишет вот так:
Мы излагаем свои мнения в виде беспрекословных истин и не извиняемся за свою категоричность. Для нас, на данном моменте наших карьер, они являются беспрекословными истинами. Они составляют нашу школу мысли в области чистого кода.
[...]
Мы утверждаем, что если вы последуете нашему учению, то это принесёт вам такую же пользу, как и нам, и вы научитесь писать чистый и профессиональный код.
Довольно близко к библии, заповедям и догмам.
Спасибо. Вы показали явный пример того, о чём я говорил. Вы сами привели текст и буквально тут же, не отходя от кассы, придали ему нужный вам смысл.
Давайте начнём с простого и примитивного - дядя Боб на Русском не пишет и вряд-ли его знает. Вы согласны с этим?
Впрочем, это мелка придирка.
Куда большая придирка - вырывать фразы из контекста. А теперь давайте откроем эту книжку в оригинале, ту самую 1 главу. ней есть часть о том, что ряд изестных разрабтчиков делятся мыслями о том, что такое чистый код. И вот приведённая вами цитата (которая находится на 43 листе оригинала) выглядит вот так. Буквально копи-паст
Schools of Thought
What about me (Uncle Bob)? What do I think clean code is? This book will tell you, in hideous detail, what I and my compatriots think about clean code. We will tell you what we think makes a clean variable name, a clean function, a clean class, etc. We will present these opinions as absolutes, and we will not apologize for our stridence. To us, at this point in our careers, they are absolutes. They are our school of thought about clean code.
В целом видно, что пишет дядя Боб и даже пишет что-то похожее. И внезапно, смысл немного другой. Прямым текстом написано, что книга это просто мысли.
Внезапно, но формулировки использованы другие. Не "беспрекословные истины", а абсолют. да и "резкость" превращается в stridence. Нет, конечно, можно перевести это слово так, но что оно означает вообще? Ну, вообще таким словом, обычно, обозначают звучание чьего-то голоса. Ну, например такой голос у Мардж Симпсон в мультсиреале. Иногда его используют вокалисты метал групп. По нашему этот голос назвали бы "прокуренным", наверное. По смыслу это "громкий, скрипучий и не очень приятный, мелодичный тон".
Немного отличается от вашей трактовки, не находите? Уже звучит не как догма, а больше похоже на... инженера. Т.е. человек сразу говорит о том, что хочет донести мысль в том виде, в котором она имеется. И да, не смотря на то, что у неё есть несовершенства, они не хотят заострять на них внимание в текущий момент. Вот именно потому тут хорошо перекликается absolute и strident. По нашему это было бы "пою, как умею петь сейчас".
А знаете, что идёт буквально в следующих предложениях, после этого куска (вы их, наверное, случайно, забыли вставить. Ну, не знаметили, а не потому, что они не попадают в вашу мысль, так ведь? Ведь так?)
Martial artists do not all agree about the best martial art, or the best technique within a martial art. Often master martial artists will form their own schools of thought and gather students to learn from them. So we see Gracie Jiu Jistu, founded and taught by the Gracie family in Brazil. We see Hakkoryu Jiu Jistu, founded and taught by Okuyama Ryuho in Tokyo. We see Jeet Kune Do, founded and taught by Bruce Lee in the United States. We Are Authors 13 Students of these approaches immerse themselves in the teachings of the founder. They dedicate themselves to learn what that particular master teaches, often to the exclusion of any other master’s teaching. Later, as the students grow in their art, they may become the student of a different master so they can broaden their knowledge and practice. Some eventually go on to refine their skills, discovering new techniques and founding their own schools. None of these different schools is absolutely right
Знаете, что там написано? Что есть разные школы боевых искусств, где преподают так, как видит мастер и что ученики этих мастеров могут открыть школы, со своими взглядами и тоже преподавать. И ни одна из различных школ не является самой правильной.
Блин, как-то не стыкуется с догмами, не правда ли? Опять говорят о какой-то своей школе мысли, не претендуя на то, что есть только она и что она даст ответы на все вопросы. Прямо признают, что в другом месте могут учить иначе, а их собственные ученики могут с ними быть несогласны. Ну, т.е. ровно то, о чём сказал я и то, что вы, по какой-то причине, не вставили.
Ну и так как текста и так много, давайте уж последний кусочек, который вы привели?
Consider this book a description of the Object Mentor School of Clean Code. The techniques and teachings within are the way that we practice our art. We are willing to claim that if you follow these teachings, you will enjoy the benefits that we have enjoyed, and you will learn to write code that is clean and professional.
Мне всё ещё надо переводить и трактовать или вы уже сами поняли, что не правы и прежде, чем что-то утверждать, стоит всё же немного изучить предмет дискуссии?
Иначе вы играете в какой-то сломаный телефон. Ну или вспомнить старую шутку о том, что Паваротти не очень, а знаю я это потому, что мой сосед был в Италии, послушал оперу, а вернувшись домой напел мне.
Или вот знаете, Селин Дион, когда её попросили исполнить песню My heart will go on хотела отказаться. Потому, что песня ей не понравилась и даже вызвала отвращение. Как это возможно? Да собственно композитор, который писал музыку, решил презентовать песню. Пригласил Селин и её мужа к себе в номер, начал играть музыку на фортепиано, а потом ещё решил спеть. Песня абсолютно не понравилась певице, но вот муж сказал, что типа давайте мы там через месяц на студии звукозаписи что-нибудь накидаем.
Через месяц Дион, которой песня всё ещё не нравилась, где-то там в перерыве между основной работой (записью альбома), решила накидать демку. Ну, так, между делом, без особой подготовки и работы над вокалом.
ТАк вот, если вы слышали эту песню в фильме, то знайте - вы слышали ту самую демку песни, которая не нравилась певице и которая была записана между делом.
Знаете, к чему я это расписал? А к тому, что первое впечатление может быть обманчиво и что некоторые вещи могут давать потрясающие результаты, даже если они не идеальны. Просто потому, что сама идея правильная и была применена в нужное время, в нужном месте, правильными исполнителями.
Это не моя трактовка, это трактовка российского издания 2016 года выпуска. Вырван ли это текст из контекста? Да! Поэтому в цитате стоит многоточие в квадратных скобках и написана страница, где текст можно почитать целиком.
Дал ли я свою трактовку прочитанному? Да! Всё люди пропускают потребляемую информацию через собственный фильтр. Но если посмотреть на то, насколько сильно российское айти-сообщество тащиться от этой книги, такую трактовку дал не только я.
LSP из SOLID это просто медийный шум.
По сути, он не имеет отношения к трудам той самой Барбары, где она лишь приводила похожую цитату из более ранней работы своего коллеги.
По существу, когда появились нормальные работы по теории типов, и люди разрбрались с вариантностью, его уже нельзя воспринимать всерьёз.
В оригинале, Барбара и ко размышляли над поведением программы в рантайме и в итоге зашли со своим тезисом в тупик на уровне логики (что, в принципе, нормально для науки). Т.е., если замена одного компонента другим не меняет поведения программы, то зачем вообще это делать? Ведь обычно цель у разработчиков как раз обратная - мы заменяем один компонент на другой, для того что-то изменить в поведении программы.
В следующей части своей работы они попытались добавить в тезис уточнений, более точно очертив рамки неизменности. Но это не дало им особых преимуществ, лишь усложнив само правило. Как я понял, дальше эту тему решили не развивать.
Через несколько лет Дядя Боб вспомнил эту историю, которую когда-то услышал на совместной конференции, и решил использовать в качестве названия для только что придуманного им принципа, применительно к ООП. Позже Барбара говорила, что хоть LSP и не является тем, что она изначально имела ввиду, но благодарна Дяде за то, что тот увековечил её имя.
Книги неплохие. Они заставляют подумать. Проблема не в книгах, а в фанатиках, которые бездумно воспринимают информацию и не проверяя верят ей.
По ощущениям мне кажется (ссылок на пабмед не будет), что книги Мартина сформировали наибольшее количество фанатиков. Они написаны в таком безапелляционном стиле и на словах пропагандируют за всё хорошее и против всего плохого. На мой вкус, виноваты не только фанатики.
Хотя, возможно, это я просто так рационализирую то, что когда-то сам был фанатиком...
мне кажется читать книги нужно не в поисках истины а в поисках себя.
я когда начинал, читал книги, и много не понимал, потом перечитывал, сверялся и понимал, а потом перечитывал, и был не согласен.
Поясню. есть строительство домов. например малоэтажное. выбор для тех стека, огромен. И все будет работать. а есть пятиэтажки. пятиэтажки строят другие люди, у них другие требования. другие расчеты. тот кто строит пятиэтажку, построит легко двухэтажный дом. тот кто строит двухэтажные дома, не построит пятиэтажку. далее. 16 этажки. там начинаются такие требования, что пятиэтажники не сталкиваются. подъем воды. пожарная безопасность. кондиционирование и всякое такое. 16 этажники, построят 5 этажку, пятиэтажники, не построят 16 этажку. А те кто строят аля бурдж халиф, у них вообще такие патерны, что кажутся оверинженерингом. и 16 этажники не построят такое. т.е. все правы, но есть ньюанс. каждую задачу нужно решать на своем уровне. для кого то патерны это мелочь, для кого то - основа. Вспоминается история, когда мне один хорший программист, задвигал что мультивертуальные методы в языке, это важно, потому что решать задачу, перкидывания одной шмотки на другую в инвентарях, только так и решить. но оказывается, в некоторых играх, перекидывание шмоток, это настолько высокоуровнеевый код, что само понятие языка программирования, там не имеет значение. и это далеко также как, например, обновление хп персонажа проперти в коде. и как биндинг поля в модели из распределенной базы данных.
хорошо, есть частица - точка, есть грани куба - а виртуально или куб или сфера, она летит как-то, как-то мы узнали о каком-то методе и вот мы уже начинаем читать тонну книг по этой тематике, как тут найти себя, если вопрос интересный стоит надо чтоб симуляция не лагала или была приемлемой на единицу времени, а отсюда связь со структурами, если дом это стек - то документации на стек не достаточно, наверняка есть какието книги или наблюдения/хитрости/тонкости
Посмотрел оригинал и все не так страшно как может показаться после прочтения данной статьи.
Можно немножко навалить контекста. Изначально это был длиннющий код Кнута, который автор и решил "оптимизировать". Причем идея была не менять алгоритм оригинала.
Данный пример я бы не сказал, что корректно перенесен на ts. Сам я Джаву не знаю, но уже беглого знакомства с исходниками и последующих комментариев Мартина понятно для чего использовался класс. На ts что бы получить все теже самые ништяки и даже выглядейть будет почти как на джаве достаточно использовать замыкания и получится что-то типа:
```
function primeGenerator(n: number) {
const primes = Array<number>(n)
const multiplesOfPrimeFactors: number[] = []
set2AsFirstPrime();
checkOddNumbersForSubsequentPrimes();
return primes;
function set2AsFirstPrime() {
primes[0] = 2;
multiplesOfPrimeFactors.push(2);
}
function checkOddNumbersForSubsequentPrimes() {
let primeIndex = 1;
for (let candidate = 3; primeIndex < this.primes.length; candidate += 2) {
if (this.isPrime(candidate))
this.primes[primeIndex++] = candidate;
}
}
...
}
```
А вот оригинал
```
public class PrimeGenerator {
private static int[] primes;
private static ArrayList<Integer> multiplesOfPrimeFactors;
protected static int[] generate(int n) {
primes = new int[n];
multiplesOfPrimeFactors = new ArrayList<Integer>();
set2AsFirstPrime();
checkOddNumbersForSubsequentPrimes();
return primes;
}
private static void set2AsFirstPrime() {
primes[0] = 2;
multiplesOfPrimeFactors.add(2);
}
...
}
```
Ну, т.е. статичный класс и методы делают все то, что на js доступно из коробки с помощью замыканий. А так как сама задача это переписывание алгоритма сверху вниз все функции легко выстраиваются в порядке необходиом для их вызова.
По поводу длиннющих названий. Мне такое читать было дискомфортно. Я английский читаю именно выражениями и когда нет пробелов к которым я привык, мне стало неудобно. Но я вполне допускаю, что носитель языка легко справится с такими именами.
А лаконичные имена в коде написанном русскоговорящим разрабом являются действительно более подходящими для чистого кода.
А вот пристрастие пилить на функции в том смысле в котором это сделано сдесь - это дискуссионный вопрос. Даже в данном примере, на мой взгляд, достаточно пробелов до и после кода внутри set2AsFirstPrime вместо вынесения этого в отдельную функцию, комментариев не нужно. Да и в целом заменить `// you comment` на `youComment()` довольно сомнительное решение. Если убрать часть таких одноразовых функций и предварить код комментарием будет, как минимум, не хуже. А просто потому, что одну простыню заменяем на другую. Но одна читается за проход сверху вниз, а другая заставляет скакать глазами в произвольном порядке.
Если я верно помню, важным посылом было стараться писать код так, что бы его можно было "читать, как книгу". Отсюда и такие длинные названия. Думаю, носителю языка действительно может и не будет дискомфортно читать это.
статичный класс и методы делают все то, что на js доступно из коробки с помощью замыканий
Нет, статичный класс делает кое-что ещё. Он ломает работу в многопоточном окружении.
Можно провести эксперимент и написать эти длинные названия по-русски
private static isPrime(candidate: number): boolean {
if (this.являетсяНаименееРелевантнымКратнымСледующегоБольшегоПростогоМножителя?(candidate)) {
this.кратныеПростымМножителям.push(candidate);
return false;
}
return this.неКратенНиОдномуИзПредыдущихПростыхМножителей?(candidate);
}
у вас случайно в роду нет 1С-ников?
А можно не извращаться, а всего лишь использовать змеиный регистр, и читать без малейших затруднений, is_least_relevant_multiple_of_next_larger_prime_factor
Но увы, поезд уже ушёл, и верблюжий стал незыблемым стандартом. При том что длинные строки объективно читать легче в змеином.
Можно немножко навалить контекста. Изначально это был длиннющий код Кнута, который автор и решил "оптимизировать".
Длиннющий код — это не совсем то, что написал Кнут. Такой код получается, если конвертировать Кнутовский WEB в обычный код. Улучшать его — это что-то вроде рефакторинга JS файлов, скомпилированных из тайпскриптовых сорсов. Можно, но зачем?
Сам код написан в концепции Literate Programming и разбит на аккуратные составные части. Кнут тоже отделяет генерирование простых чисел от записи этих чисел в файл, и не сваливает весь код в одну кучу.
То есть, Мартин действительно рефакторит портянку. Но он сам получил эту портянку довольно странным образом и на нескольких страницах героически сражается с ней.
Что же вы критикуете (не)дядюшку Боба по его книге 2008 года? Не логичнее ли сегодня рассматривать его книгу 2024 года Functional Design: Principles, Patterns, and Practices, в которой он преподносит свои принципы SOLID уже в иной форме, чем раньше. (Да, теперь он топит за функциональщину!) Хотя он сам признаётся, что его новая книга по сути представляет из себя вольное переизложение старой доброй SICP.
Потому что книгу 2008 до сих пор рекомендуют к прочтению, спрашивают про чистый код на собесах и срутся по поводу чистоты на код-реаью. Когда новая книга завирусится так же сильно, можно будет и её прочитать и покритиковать.
Вы путаете причины со следствиями. Причина происходящего в неумении проводить собесы и делать ревью, а не в дяде Бобе. Если запретить на собесах и ревью упоминать SOLID и чистый код - их место просто займёт какой-то другой карго-культ.
Прочитал - спрашивают про чистый код на небесах
Не логичнее ли сегодня рассматривать его книгу 2024 года Functional Design: Principles, Patterns, and Practices, в которой он преподносит свои принципы SOLID уже в иной форме, чем раньше.
Так она ещё хуже, потому что:
Обсуждаемая книга 2008-го года о продакшен-коде написана человеком, который не писал продакшен-код 18 лет, а книга 2024-го года о продакшен-коде написана человеком, который не писал продакшен-код 34 года, и это видно.
Пик слайтли релейтед Недядя Боб не понимает функциональщину ещё больше, чем он не понимает ООП.
Если цель — найти причины не любить Боба, то это отличная книга. Если цель — научиться разрабатывать ПО в функциональной парадигме, то это отвратительная книга, и книги domain modeling made functional или algebra-driven design лучше в <целочисленное переполнение> число раз.
Посмотрел что за книга Algebra Driven Design, автор знакомый...
Ба, да это же Sandy Maguire! Я читал его книгу Thinking with Types. Прикольный чувак - он в книге про себя сам написал, что уволился с солидной рабыты в серьёзном оффисе, чтобы вести полубродяжническую жизнь в трейлере, много играть на гитаре, ваять игру мечты и писать концептуальные книги по программированию. Уже за одно только это респект ему и уважуха!
При проверке на простоту достаточно проверить не делимость только на простые числа.
Учитывая, что список простых чисел у вас уже есть, причём в отсортированном виде - можно и нужно идти по нему.
Хорошо, что сперва почитал комменты, прежде чем писать самому.
Кстати, как раз хороший пример задачки для собеса именно на понимание
А еще нужно брать простые числа, которые меньше квадратного корня тестируемого числа
Это уже учтено в решении автора.
Это уже в предлагаемом решении, о чём я прямо написал вот тут:
> Учитывая, что список простых чисел у вас уже есть, причём в отсортированном виде (*).
Так что я не очень понимаю, что вы хотели сказать?
*) исходя из этого вся разница сведётся к диффу:
< for divisor in range( 2, check_upper_bound + 1):
---
> for divisor in primes:
> if divisor > check_upper_bound:
> break
Ну ещё можно вместо деления (относительно тяжёлой операции) проводить проверку на делимость нескольких первых простых чисел.
Мы заведомо проверяем только делимость на заведомо простые, причём меньшеие, чем sqrt(candidate))
Какую ещё оптимизацию вы предлагаете?
Ну например не брать в выборку чётные числа. А так же числа оканчивающиеся на 5. Насчёт остальных проверок хз, что быстрее будет. Поделить на 3 или проверить признак делимости?
А - проверять остатки от деления на произведения первых n простых множителей.
Но кроме х2 - она ведёт к неприятной иррегулярности, которая выливается во вложенный цикл и усложнение кода.
К тому же эти остатки надо ещё сформировать. Либо руками (и тогда считать их не ошибаясь) либо автоматически (и тогда это фактически удваивает размер кода)
2k => 2k +1
6k => 6k + {1, 5}
30k => 30k + {1, 7, 11, 13, 17, 19, 23, 29}
Типичный Эскобар. Выберешь алгоритмический примитивный пример и попытаешься показать принцип формирования и сегрегации функционала, критик скажет - зачем всё это, если кода будет больше.
Если возьмешь пример с бизнес кодом, то пока объяснишь доменную область, напишешь текста больше чем во всей книге. И обвинят в генерации воды.
Что же делать несчастному старику, который пытался донести идеи, а породил два лагеря религиозных фанатиков?
Тоже хотел это написать. В книге нужен какой-то простой пример, чтобы научить людей писать сложные бизнес-задачи в красивом виде. Но если вписать на каждый пример по бизнес-задаче, то никто не захочет в них вдумываться, а книга вырастет в несколько раз.
Поэтому и берётся простая математическая задача, которая известна всем со школы и 99% программистов её уже решали, когда учились программировать на своём первом языке.
В книге есть примеры и реального кода. В другой ветке его прокомментировал: https://habr.com/ru/articles/875426/comments/#comment_27818290
Я читал эту книгу, но не читал код из неё (точнее читал, очень поверхностно, хотя в книге и утверждается, что уж она то меня научит программировать и сделает лучше). Я нахожу ценными идеи и бесполезным демонстрацию этих идей кусками кода.
Одна из причин плохих примеров кода в любых книгах, это их устаревания из-за появления новых идей. Вы верно пишете про Side Effect в комментарии, но если вы возьмете ДРУГИЕ очень хорошие и полезные книги с примерами кода на Java, то обнаружите ту же самую проблему (чтобы не быть голословным: Сэджвик, Уэйн "Аглоритмы на Java" (тот же 2016 год, что и ваше издание) (одна из лучших книг про алгоритмы для начинающих, в принципе). Второй пример: Копец, "Классические задачи Computer Science, на языке Java" (2022).
Это весьма грязный код и не промышленный, но позволяющий относительно упростить изложение.
Пример с передачей isSuite внутрь промышленного класса конечно дурацкий, но он требует отдельного размышления и погружения в контекст конкретно той главы (а повторюсь, этот код я просто прочитал по диагонали, т.к. он устарел и нелеп). Даже в рамках концепций этой книги, он загрязняет код, если уж так Мартину хотелось, он должен был снабдить класс стартегией (feature toggles в данном случае), а не признаком "а это тест".
Беда в том, что если не следвоать ни одному совету из этой книги, то получается успешный проект, который поглащён энтропией и требует в 10 раз больше усилий, чем требуется на него.
Особенно это хорошо можно наблюдать не в используемой Мартином Java (там всё в порядке - там Spring формализовавший идеи этой книги в граните, решил все проблемы), а в довольно симптоматичном go. Где люди на серьезных щщах идут "своим путём", настолько своим, что даже набор металинтеров пройти ни один промышленный проект в нашей стране не способен.
Что же делать несчастному старику, который пытался донести идеи […]
Простой рецепт для желающего доносить идеи, а не продавать свои безумные иллюзии:
Напиши много кода, в который любопытный читатель сможет заглянуть, чтобы увидеть жизненный пример (а пытливый читатель — туда заглянет, чтобы удостовериться, что книжка написана практикующим разработчиком выше среднего уровня, а не инфоцыганом с претензиями).
Выкристаллизуй идеи из написанного (и выкаченного в продакшн) кода из п.1 (а не из болтовни в переписке с такими же скучающими бездельниками).
Сформулируй эти идеи, подкрепив их примерами кода попроще, и дав ссылку на полновесные решения из п.1. Сформулируй идеи, болван, а не подгоняй их под придуманный не тобой среднего качества метаакроним.
Как видим, Мартин не справился ни с одним из этих простых пунктов. А его уровень как разработчика — легко увидеть по последним коммитам в его репозиторий на гитхабе (AoC 2024 на Clojure — ссылки не даю, потому что это сродни детской порнографии, но найти несложно).
Мой практический опыт, показывает, что среднестатистический критик чего угодно, профессионально практикующий, не способен самостоятельно без фреймворка написать ничего поддерживаемого, работающего и тестируемого. Даже после 10 лет работы в бигтехе.
Вообще книжка для джуниор разработчиков и если бы её осилили текущие сеньоры, я бы уже лет 10 был без работы.
Если я смог правильно перевести на русский этот пассаж, и если «критик» — это про меня, то у меня есть открытый гитхаб, который можно легко найти по моим текстикам — там более двадцати примеров поддерживаемого, работающего и тестируемого, причем это библиотеки общего назначения, некоторые из которых — фреймворки.
Эта книжка — для дегенератов, о себе не заботящихся, и если бы ее причитали (и следовали принципам) все вокруг, мне бы сейчас платили миллиард в час..
Какой-то нелепый квест. Найти в каких то текстиках, когда ссылку можно было прислать просто в комментарий. Ведь код всегда говорит за себя сам, для него не нужны какие-то дополнительные слова.
ссылку можно было прислать просто в комментарий
Если бы я видел хоть какой-то в том смысл — я бы так и сделал.
код всегда говорит за себя сам
Это бесспорно. И у меня его в открытом доступе полно́. Если вам не интересно — это нормально (у вас же уже есть целый практический опыт), но тут открытые комментарии, а не приватная переписка в локальном чатике, попадаются люди, которым интересно.
P. S. текстики — это то, что хабрахомяки высокопарно и безосновательно величают «статьями».
Вы от чего-то усердно продолжаете мне хамить, вместо того, чтобы оставить ссылку на профиль в гитхабе с своим самым любимым вкладом в опенсорс.
P.S. Если не видите смысла, то можете просто и не отвечать же.
Меня всегда забавляет¹, как люди по сути требуют от других продемонстрировать их регалии перед тем, как хотя бы даже попытаться воспринять их слова по существу, хотя сами не делают ничего: не демонстрируют собственных достижений (что необходимо в их логике), да и даже не говорят ничего по существу, вместо этого размахивая вокруг вялым адхомом.
¹ вру, раньше расстраивало, а забавляет только последние пару лет
Тоже хотелось взглянуть на исходный код, но не нашел ссылку на github.
а я открыл формулы и гдето итерации с 10 по коду я остановился но тут - решение в целом не правильное ) не хватает точности какогото фактора )

решение в целом же неверное (ну вы же даблы не всерьёз используете, да?).
primes_count(x) = log(x) - это формула примерная и на неё полагаться нельзя.
Правильным будет то, что ниже.
*) Ну и примитивное "решето Эратосфена" же всё равно быстрее, если можете позволить себе память.
def calc_primes( primes_cnt):
primes = []
candidate = 2
while ( len( primes) < primes_cnt):
candidate_is_prime = True
sqrt_check = (int)(candidate ** (1/2))
for i in primes:
# +1 - на всякий случай не доверяем округлению флотов
if i > sqrt_check + 1:
break
if candidate % i == 0:
candidate_is_prime = False
break
if candidate_is_prime:
primes.append( candidate)
candidate += 1
return primes
Нормальный человек решит эту задачу внутри одной функции на 19 строчек кода. Тут не нужны кучи вспомогательных методов с нечитаемыми названиями и скрытыми мутациями. Всего одна функция или статический метод.
Ну это ж пример, демонстрирующий саму идею. Допустим в конкретном алгоритме такое деление избыточно, и действительно следует реализовать его одной функцией. Но автор книги предполагает, что у читателя есть абстрактное мышление, и читатель способен понимать ИДЕЮ.
Что если речь о бизнес-логике, а не об одном алгоритме? Отличие бизнеса от ваших зазубренных алгосов в том, что бизнес-правила имеют свойство меняться со временем. Могут добавляться новые правила, старые удаляться. И так далее. И все это на ходу и с бешеной скоростью.
Так вот, когда у тебя код состоит не из одной портянки, а из набора явно выраженных и обозначенных самостоятельных бизнес-правил, выделенных в отдельные элементы, вносить изменения в него получится проще и безопаснее.
Ну и конечно, о здравом смысле не забываем, до крайностей доводить любые идеи тоже плохая идея)
В данном случае идея была взять портянку Кнута и сделать ее самодокументируемой. Т.е. вместо блоков комментариев, которые для этого и предназначены стали использоваться одноразовые функции. Причем даже для двух строк кода. То о чем вы говорите, никакого отношения к этому не имеет. Портянка Кнута действительно не очень короткая, но это не означает, что любой блок нужно оборачивать в функцию. А именно о такой идее тут идет речь.
> Т.е. вместо блоков комментариев, которые для этого и предназначены
В то же время хороший код - это такой, который не требует комментирования :) Где истина? А истина где-то рядом))
Часто ли вы по своей воле любите писать комментарии в коде? Не док-блоки у заголовка функции, а именно комменты в самом мясе портянки кода? Комментарии - это для исключительных случаев, когда ну прям совсем не понятно без них. Я чаще всего комментами крою только какие-нибудь дикие куски легаси-кода, которые прямо сейчас рефакторить нет времени, но хочется поделиться с будущими читателями результатами своего исследования того, что делает этот код.
Короче, я сторонник самодокументированного кода. Но не в простых функциях поиска каких-то там чисел, т.е. я против доведения правил до абсурда
Мартин именно захотел написать такие комментарии. Но не захотел это делать с помощью блоков комментариев. Вот в этом суть. Поэтому зачем нужны эти размышления, если тут прямо стояла цель комментировать портянку Кнута.
А вот то, о чем вы пишете как раз и послужило поводом, потому что куча комментариев в коде - это дурной тон, а вот если вместо них функции, то типа норм. Имя функции должно быть понятным? Да. Но это все таки должна быть функция, т.е. либо многократно используемый код, либо вынесенный в отдельное место весомый участок кода. Выносить же пару строк - это зачем? Даже 3-4 строки тоже вызовут такие же вопросы.
Поэтому когда начинаешь думать какие задачи были поставлены и как они решены как раз и получается непонимание подобного решения.
дабл
А в чём здесь идея? В длинных нечитаемых названиях методов, скрытых сайд-эффектах и неявном дата-флоу? Код для бизнеса от такого лучше не станет.
Если что, в книге есть не только такой алгоритмический пример. Всю третью главу Мартин ссылается на листинг 3.7. Это реальный код из библиотеки для тестирования Fitnesse. В нём чуть больше ста строк кода, поэтому уберу под спойлер, но его обязательно стоит почитать.
Пример реального чистого кода
package fitnesse.html;
import fitnesse.responders.run.SuiteResponder;
import fitnesse.wiki.*;
public class SetupTeardownIncluder {
private PageData pageData;
private boolean isSuite;
private WikiPage testPage;
private StringBuffer newPageContent;
private PageCrawler pageCrawler;
public static String render(PageData pageData) throws Exception {
return render(pageData, false);
}
public static String render(PageData pageData, boolean isSuite)
throws Exception {
return new SetupTeardownIncluder(pageData).render(isSuite);
}
private SetupTeardownIncluder(PageData pageData) {
this.pageData = pageData;
testPage = pageData.getWikiPage();
pageCrawler = testPage.getPageCrawler();
newPageContent = new StringBuffer();
}
private String render(boolean isSuite) throws Exception {
this.isSuite = isSuite;
if (isTestPage())
includeSetupAndTeardownPages();
return pageData.getHtml();
}
private boolean isTestPage() throws Exception {
return pageData.hasAttribute("Test");
}
private void includeSetupAndTeardownPages() throws Exception {
includeSetupPages();
includePageContent();
includeTeardownPages();
updatePageContent();
}
private void includeSetupPages() throws Exception {
if (isSuite)
includeSuiteSetupPage();
includeSetupPage();
}
private void includeSuiteSetupPage() throws Exception {
include(SuiteResponder.SUITE_SETUP_NAME, "-setup");
}
private void includeSetupPage() throws Exception {
include("SetUp", "-setup");
}
private void includePageContent() throws Exception {
newPageContent.append(pageData.getContent());
}
private void includeTeardownPages() throws Exception {
includeTeardownPage();
if (isSuite)
includeSuiteTeardownPage();
}
private void includeTeardownPage() throws Exception {
include("TearDown", "-teardown");
}
private void includeSuiteTeardownPage() throws Exception {
include(SuiteResponder.SUITE_TEARDOWN_NAME, "-teardown");
}
private void updatePageContent() throws Exception {
pageData.setContent(newPageContent.toString());
}
private void include(String pageName, String arg) throws Exception {
WikiPage inheritedPage = findInheritedPage(pageName);
if (inheritedPage != null) {
String pagePathName = getPathNameForPage(inheritedPage);
buildIncludeDirective(pagePathName, arg);
}
}
private WikiPage findInheritedPage(String pageName) throws Exception {
return PageCrawlerImpl.getInheritedPage(pageName, testPage);
}
private String getPathNameForPage(WikiPage page) throws Exception {
WikiPagePath pagePath = pageCrawler.getFullPath(page);
return PathParser.render(pagePath);
}
private void buildIncludeDirective(String pagePathName, String arg) {
newPageContent
.append("\n!include ")
.append(arg)
.append(" .")
.append(pagePathName)
.append("\n");
}
}
Тут ровно такой же паттерн, как и в алгоритмическом примере: неявный дата-флоу и скрытые мутации. Есть только один плюс -- тут не такие длинные названия методов.
По поводу скрытых мутаций. Можно подумать, что Мартин не рассматривает изменение переменных своего класса как мутацию. Но вот цитата прямо из этой же третьей главы (страница 69).
Побочные эффекты суть ложь. Ваша функция обещает делать что-то одно, но делает что-то другое, скрытое от пользователя. Иногда она вносит неожиданные изменения в переменные своего класса -- скажем, присваивает им значения параметров, переданных функции, или глобальных переменных системы. В любом случае такая функция является коварной и вредоносной ложью, которая часто приводит к созданию противоестественных временных привязок и других зависимостей.
Я согласен с цитатой на все сто процентов. Но что мы видим в коде, который Мартин считает чистым, правильным и достойным находиться в его книге? Метод render
принимает объект pageData
и делает скрытую мутацию этого объекта в методе updatePageContent
. Я бы никогда в жизни не ожидал, что передав pageData
в статический метода SetupTeardownIncluder.render
я получу мутацию. Почему рендер вносит какие-то изменения в контент страницы? Где здесь пресловутый принцип единственной ответственности?
У меня очень много вопросов к этому реальному коду! Зачем он сохраняет переменную isSuite
на уровне инстанса класса? Если явно прокинуть её в методы, то код получится более... явный и простой в чтении. Почему он не использует собственный принцип "Один уровень абстракции на функцию" из этой же главы (страница 61), а вместо этого в метод render
пихает сборную солянку: установку значения для переменной, два вызова приватных методов, возврат результата выполнения pageData.getHtml()
? Я не джавист, но решил немного отрефакторить этот код. После рефакторинга сразу видно, что класс просто утилитарный, которому не нужно никакое внутреннее состояние, а мутация пусть и осталась (её здесь никак не убрать), но зато находится на самом видном месте. При желании весь этот код можно просто поместить внутрь класса PageData
.
public class SetupTeardownIncluder {
public static String render(PageData pageData) throws Exception {
return render(pageData, false);
}
public static String render(PageData pageData, boolean isSuite) throws Exception {
if (!pageData.hasAttribute("Test")) return pageData.getHtml();
StringBuffer newPageContent = new StringBuffer();
newPageContent
.append(getContent(pageData, "SetUp", "-setup"));
.append(pageData.getContent());
.append(getContent(pageData, "TearDown", "-teardown"));
if (isSuite) {
newPageContent
.insert(0, getContent(pageData, SuiteResponder.SUITE_SETUP_NAME, "-setup"));
.append(getContent(pageData, SuiteResponder.SUITE_TEARDOWN_NAME, "-teardown"));
}
pageData.setContent(newPageContent.toString());
return pageData.getHtml();
}
private static String getContent(PageData pageData, String pageName, String arg) {
String pagePathName = getPagePathName(pageData, pageName);
if (!pagePathName) return "";
StringBuffer content = new StringBuffer();
return content
.append("\n!include ")
.append(arg)
.append(" .")
.append(pagePathName)
.append("\n")
.toString();
}
private static String getPagePathName(PageData pageData, String pageName) {
WikiPage testPage = pageData.getWikiPage();
WikiPage inheritedPage = PageCrawlerImpl.getInheritedPage(pageName, testPage);
if (inheritedPage == null) return null;
PageCrawler pageCrawler = testPage.getPageCrawler();
WikiPagePath pagePath = pageCrawler.getFullPath(inheritedPage);
return PathParser.render(pagePath);
}
}
Воспользуюсь фишечкой Роберта Мартина и изложу своё мнение о своём же рефакторинге в виде беспрекословных истин и не буду извиняться за свою категоричность. Код получился гораздо более явный и простой для понимания. В этот код легче и быстрее внести изменения, если этого потребует бизнес. Каждая функция внутри класса имеет явный инпут и аутпут и понятный дата-флоу, поэтому об этих функциях проще размышлять и их легко тестировать. Такой код достоин называться профессиональным.
Сам "дядюшка" писал, что его советы не "истины" в абсолютном смысле.
Пруф

Ни одна из этих разных школ не обладает абсолютной истиной. Тем не менее в рамках конкретной школы мы действуем так, будто её учение и арсенал приёмов верны.
[...]
Считайте, что эта книга является описанием Школы учителей Чистого кода. [...] Мы утверждаем, что если вы последуете нашему учению, то это принесет вам такую же пользу, как и нам, и вы научитесь писать чистый и профессиональный код. Но не стоит думать, что наше учение "истинно" в каком-то абсолютном смысле. Существуют другие школы и мастера [...].
Так он тут пишет, что никто не обладает абсолютной истиной. Но следование "Школе учителей Чистого кода" обязательно принесёт пользу и научит писать профессиональный код. Лично я читал эту книгу, чтобы сделать свой код "профессиональным", поэтому эти два абзаца забайтили меня не на поиск "других школ", а на следование учению "Школы учителей Чистого кода".
Если бы у книги цель была не в погружении в своё "учение", то альтернативные "школы" хотя бы были приведены списком. Я нашёл этот отрывок (Глава 1, страница 35). Ни до, ни после нет никаких примеров других "школ". Но зато есть несколько восхитительных цитат в начале страницы:
Мы излагаем свои мнения в виде беспрекословных истин и не извиняемся за свою категоричность. Для нас, на данном моменте наших карьер, они являются беспрекословными истинами. Они составляют нашу школу мысли в области чистого кода.
[...]
Они [ученики школы] посвящают себя изучению того, чему учит конкретный мастер, часто отказываясь от учений других мастеров.
Короче, для меня вся эта страница -- очень мощная агитка, которая призывает следовать "учению" Роберта во имя написания профессионального кода. Смотря на то, как глубоко эта книга сидит в головах многих программистов, агитка сработала на "отлично".
Насколько я знаю, Мартину не нравится прозвище "дядюшка Боб". Это прозвище он получил от читателей, когда был редактором журнала C++ Report.
Так что зря вы пишите, что он "втирается в доверие".
Впрочем, я согласен, что ваша версия кода генерации простых чисел проще и понятнее, чем у Мартина.
Ну так если не сделать себе соломенное чудище - можно же и не победить в споре)
Всегда воспринимал речи Uncle Bob как некую сказку, жвачку для ума, не более. У каждого есть какое-то своё понимание хорошей архитектуры, и представление Боба -- не истина в последней инстанции. Ради интереса попросил Claude AI накидать архитектурные принципы, которыми я руководствуюсь в своём коде, на основе краткой беседы с ним:
Вот так получилось
## 1. Фундаментальные принципы
### 1.1. Принцип Управляемой Сложности
- Система должна быть достаточно простой для понимания отдельным разработчиком
- Сложность должна соответствовать решаемой задаче, любое усложнение системы должно иметь явное обоснование
- При выборе между двумя эффективными решениями предпочтение отдается более простому
### 1.2. Принцип Модульности
- Система разделяется на четко определенные, слабо связанные модули
- Каждый модуль имеет единую ответственность
- Взаимодействие между модулями происходит через четко определенные интерфейсы
- Внутренняя реализация модуля может меняться без влияния на другие части системы
### 1.3. Принцип Предсказуемости
- Поведение системы должно быть понятным и предсказуемым
- Похожие задачи должны решаться похожим образом
- Система должна следовать принципу наименьшего удивления: изменения в одной части системы не должны вызывать неожиданных эффектов в других частях, сообщения об ошибках должны явно давать представление об их местонахождении и причинах
## 2. Практические принципы реализации
### 2.1. Организация кода
- Структура проекта должна отражать предметную область, связанные компоненты располагаются рядом
- Код организуется вокруг бизнес-концепций, а не технических деталей реализации
- Используется последовательная система именования
### 2.2. Управление зависимостями
- Зависимости должны быть явными и минимальными. Циклические зависимости не поощряются
- Модули верхнего уровня не должны зависеть от деталей реализации
- Внешние зависимости изолируются через адаптеры, либо их использование минимизируется
### 2.3. Работа с данными
- Структуры данных должны быть простыми и понятными
- Сложные структуры данных вводятся только при явной необходимости
- Потоки данных в системе должны быть прозрачными и отслеживаемыми
- Доменные объекты, обогащенные бизнес-логикой структуры данных, специфичные для конкретного домена, хранятся вместе с бизнес-логикой
## 3. Принципы эволюции системы
### 3.1. Управление изменениями
- Система должна быть готова к изменениям требований
- Изменения локализуются в минимальном количестве модулей
- Новая функциональность добавляется через расширение, а не модификацию
### 3.2. Технологический стек
- Используются проверенные и широко распространенные технологии
- Новые технологии вводятся постепенно и обоснованно, поддерживается баланс между инновациями и стабильностью
- Технологический стек должен соответствовать команде и задачам
### 3.3. Документация и обмен знаниями
- Неочевидные архитектурные решения всегда документируются вместе с обоснованием их полезности
- Поддерживается актуальная документация по API и интеграциям
- Знания о системе распределяются между членами команды
## 4. Принципы качества
### 4.1. Тестируемость
- Архитектура должна упрощать написание тестов
- Модули проектируются с учетом возможности их изолированного тестирования
- Критические пути в системе имеют максимальное покрытие тестами
### 4.2. Самотестирование кода
- Ключевые инварианты системы проверяются через assertions
- Проверки инвариантов включают:
- Входные параметры функций и методов
- Выходные значения критически важных операций
- Состояние объектов после важных изменений
- Корректность форматов данных
- Assertions используются для раннего обнаружения проблем:
- Нарушений бизнес-правил
- Некорректных состояний системы
- Нарушений контрактов между компонентами
- Самотестирование не заменяет модульные тесты, а дополняет их
- В production-окружении assertions могут быть отключены для оптимизации производительности
### 4.3. Производительность
- Производительность учитывается на этапе проектирования
- Оптимизации вводятся на основе измерений, а не предположений
- Система масштабируется в критических направлениях
- Производительность не должна ухудшать читаемость кода без веской причины
### 4.4. Безопасность
- Безопасность встраивается в архитектуру изначально
- Все внешние входы в систему проходят валидацию
- Чувствительные данные изолируются и защищаются
- Система устойчива к типовым атакам и уязвимостям
Особенно мне нравятся принципы управляемой сложности, предсказуемости и наименьшего удивления: это ровно то, чего я всегда пытаюсь добиться в своём коде. Но это не значит, что теперь я мессия, и буду нести своё сакральное знание в массы.
А что такое - Каждый модуль имеет единую ответственность
в твоём понимании? Ведь каждый модуль часть чего-то большего, что включает ответственность всех его модулей.
Я для себя сформулировал так: ответственность можно кратно и понятно описать. Т.е. множество функций должны как-то обобщаться во что-то одно.
Это просто переложение https://en.wikipedia.org/wiki/Unix_philosophy#Do_One_Thing_and_Do_It_Well . Необязательно каждый модуль является частью чего-то большего: в горизонтальных структурах, вроде микросервисов, у нас большинство сервисов имеет равный ранг, ни один не входит в другой, и, тем не менее, каждый имеет ограниченную зону ответственности, которую должен обслуживать хорошо. Естественно, зона ответственности описывается на естественном языке в терминах целевой области знания, формально определять её было бы странно.
Условно, даже в монолитной архитектуре модуль работы с БД не должен хорошо уметь форматировать дату или записывать логи, для этого есть другие модули, которые он может использовать через ограниченный интерфейс.
Я понимаю, что любое взаимодействие между модулями можно притянуть к размыванию ответственности, но с таким подходом вообще невозможно построить никакого разграничения, так что на практике это выглядит как комментарий в шапке модуля "Этот модуль занимается тем-то и тем-то. Тем-то и тем-то не занимается." и, по возможности, явной проработкой случаев, когда модуль со своими задачами не справляется: выбросом ошибок ли, флагом "микросервис недоступен" ли, или как-то ещё.
Так в этом и прикол. Модуль - очень размытое понятие. Модулем даже отдельный класс могли называть. Тем более что SOLID и S для классов мы считаем чем-то хорошим.
И как не круги, одни модули входят в другие. Ваши равные микросервисы - всего-лишь сервис в рамках более крупной структуры, типа архитектуры предприятия.
Поэтому для себя принцип единственности ответственности понимаю примерно так: можно эту самую ответственность как-то нормально/кратно сформулировать.
Исходя из этого определения - у монолита тоже одна ответственность: обслуживать бизнес.
Мне кажется, что в такого рода статьях, в начале нужно указывать сколько у вас самих реального опыта в годах. Что бы люди понимали с каких позиций вы выходите +/-. Просто как совет.
Прошу прощения, но кажется, что в случае с книгой “Чистый код“ большой опыт не нужен, чтобы понять, что с функцией с названиемset2AsFirstPrime
что-то не так.
К счастью, автор статьи написал свою версию кода, поэтому мы можем игнорировать личностные характеристики и оценивать непосредственно две реализации одной и той же задачи.
Спасибо за статью!
Сталкивался на работе с фанатиками, приходилось спорить со ссылками на авторитеты (книга Чистый код, цитаты Боба Мартина).
Находил тогда статью “Вероятно, хватит рекомендовать «Чистый код»“ , и рад, что новые статьи пишутся, потому что люди до сих пор думают, что книга 2008 все еще является образцом чистого кода.
Цель чистого когда - чтобы программы было легко понимать и менять. Человеческое восприятие работает "от общего к частному" и, внезапно, дядюшка Боб в своей книге и пытается дать рецепты как структурировать программу чтобы было "от общего к частному".
В процессе чтения, поразительно, что некоторые примеры я просто пропустил (вероятно, не слишком внимательно читал листинги на Java). С примерами согласен, но не всё в его книге ерунда, тут, как уже высказались ранее, необходимо постоянно думать, оценивать предлагаемые советы и решения, а не мельком пробежаться по книге. Разве плохо давать содержательные имена, или декомпозировать гигантскую функцию, избегать супер-классов :-)
Проблема в том, что некоторые его утверждения воспринимаются как догма, ну и масла в огонь подливают такие его "качественные" листинги на Java :)
Самое ценное в книгах дядюшки Боба – это ход его мыслей. Да, безусловно, неокрепший разум сразу пытается следовать его идеям точь в точь. Но это не проблема книги или автора.
Лично начал знакомиться с его книгами на третьем году коммерческого опыта разработки. И для меня стало открытием то, как автор рассуждает о каждой строке кода.
Если до этого я писал код, чтобы он работал (ну и выглядел симпатично), то после я начал прорабатывать множество вариантов реализации в попытках достичь определённых свойств написанного кода.
И вот, спустя 6 лет я могу детально объяснить почему конкретную строку или выражение написал именно так. Да, я не следую его рекомендациям. Я даже смутно помню их. Но способ мыслить оказался бесценен.
P. S. То же самое с паттернами проектирования. Знакомство с ними объяснило саму суть ООП и для чего все это нужно. Я вряд ли смогу по памяти повторить один в один какой-либо паттерн, кроме простейших. Но я понимаю идеи, которые за ними стоят. И реализую решения, которые нужны для конкретной ситуации со всеми её нюансами.
Я вряд ли смогу по памяти повторить один в один какой-либо паттерн, кроме простейших.
Сам Мартин Фаулер в своей книге по паттернам писал, что знать наизусть паттерны не нужно, нужно просто использовать его книжку как справочник, в который периодически заглядывать, когда возникает задача решить какую-то проблему.
Но наши IT-фанатики этого не поняли, и теперь все же как ни крути, но паттерны наизусть помнить нужно, чтобы проходить собеседования :)
Сам Мартин Фаулер в своей книге по паттернам писал, что знать наизусть паттерны не нужно, нужно просто использовать его книжку как справочник […]
Завидую людям с таким непрошибаемым воздействием эффекта Даннинга-Крюгера. Странно, что он не написал ещё сводную книжку математических аксиом, штук на триста, в которую надо заглядывать в любой непонятной ситуации: от сложного рефакторинга до поноса.
Я не встречал, чтобы на собеседовании просили повторить реализацию паттерна. Но перечислить их и описать, какой для чего нужен, мне кажется, вполне нормально. Дело в том, что чтобы распознать ситуацию, когда можно применить какой-то паттерн, их в любом случае нужно помнить, хотя бы условно.
Я немного о другом. Довольно часто требуется создать механизм, задачи которого выходят за рамки классических паттернов. Иногда можно собрать его из 4+ паттернов, но результат получается сложным и запутанным. Вот как раз в таких ситуациях эффективнее спроектировать уникальный механизм под конкретную задачу. И сами идеи, которые стоят за паттернами, помогли мне создавать такие механизмы, которые обладают нужными свойствами.
Программист, которому в эту лапшу придётся вносить изменения, охренеет в голове выстраивать дата-флоу, сделает git blame, распечатает листинг на ватмане, вычислит автора по айпи и засунет этот листинг автору в анальное отверстие. Мне сложно представить другое развитие событий.

Рядовой программист завернул Роберта Мартина в листинг его дата-флоу и спрашивает, достаточно ли тот чист для операции кодирования.
Позиция ТС мне сразу напомнила откровения тех интересных личностей, которые пытаются с двух ног вкатиться в асу тп со словами: "да нафига тут эти ваши промышленные плк за многоденяк, щас всë за шапку сухарей на голом esp32 замастырю.".
Оффтопик
Вы не заметили, что URL строка в Яндексе иногда сходит с ума ?
Давно уже понял - надо держаться подальше от фанатиков, причем не важно на какой почве у них произошел сдвиг по фазе, на почве чистого кода или микросервисов/монолитов или еще бог знает чего. Как правило такие фанаты выдают настолько жуткий код, что работать с ним становится практически физически больно, при этом он может на все 100% соответствовать всем Канонам Веры.
А у меня противоположный опыт.
Люди которые знакомы с Чистой архитектурой и Чистым кодом, понимают SOLID, KISS, DRY. Знают базовые паттерны проектирования - выдают кратно более поддерживаемый код, который еще и unit тестами легко покрывается без лишних зависимостей.
Люди же фанатично отторгающие труды Роберта выдают сильно связанный код. Тесты бизнес логики, в которой моки пишутся на уровне http транспортов, так как иначе не получится (DIP нарушен). Короче много приколов. Интерфейсы на десяток не связанных методов (SRP, IPS) - легко.
Жуть в общем.
Думаю причина в микросервисах. В небольших кодовых базах легко отходить от принципов.
чистую архитектуру точно стоит прочитать
точно не стоит делать ее единственной книгой о качестве кода, которую ты читал
На роль единственной (если уж совсем влом читать больше одной книжки) отлично подходит упомянутый в коментах «совершенный код». А чистая архитектура отлично его дополняет. И после «совершенного кода» очень бросается в глаза неумение Мартина давать имена переменным и методам :)
Джавист не может быть крутым программистом по определению. Статья в точку, и убожество ОПП и джавы демонстрирует отлично.
А кто может? ДжаваСкриптист?)
Говнокод в статье на java, а на TS (~JS) как раз таки как правильно. И это особенность языка и ООП.
В JS тоже есть классы, но есть и возможность их вовсе не использовать, что многое и делают. В убогой жаве такой возможности нет.
В убогой жаве такой возможности нет.
вообще-то, есть
https://openjdk.org/jeps/445 но с недавних пор :)
Хаскелист, конечно.
Вообще, js очень мультипарадигменный. Можно перепробовать кучу подходов, не меняя языка.
убожество ОПП и джавы демонстрирует отлично.
Опять бла бла бла, уже несколько месяцев жду вашу обещанную статью про то, почему классы это плохо, но всё нет и нет её. Когда уже?
А меня смущает сравнение императивного и декларативного подхода.
a = b +1
это разве не декларативно?
А если учесть асинхронность скрывающуюся где-то там глубже?
И декларативность вроде как улучшает читаемость, но развращает магией.
Вообще статья хороший пример того что восприятие кода, как и в целом восприятие текста, субъективно. Кому-то нравится Толстой, а кому-то Достоевский. Хороший код - тот с которым тебе удобно работать, и это тоже субъективно. Меня скорее отпугивают те программисты, которые это не осознают, и начинают возводить вкусовщину в абсолют, не важно Мартин это или кто то другой.
Если бы я попросил кандидата решить подобную задачу и в ответ получил бы такие шестьдесят строк, то кандидат не прошёл бы собеседование.
Если бы Вы проходили у меня собеседование, то Ваш код на 16 строчек, был бы завернут на первой же строке. const primes: number[] = [];
Сравните эту же строку с кодом Мартина. И попробуйте пояснить почему Вас бы сразу завернули.
Потому, что он говорит о Вашем не знании того как работает JS изнутри.
В то же время код Мартина, заставил бы меня задать несколько уточняющих вопросов и продолжить собеседование.
Мне кажется, что Вы не поняли главное о чем писал дядя Боб. Он не давал Вам рецептов. Он прививал культуру мышления. Ваш код в 16 строчек - выполняет свою задачу. Он прекрасно может быть использован для решения на коленке. Но он безобразен. Безобразен хотя бы потому, что не оставляет никаких шансов современным оптимизаторам что-то с этим кодом сделать.
В тоже время код от Мартина такие возможности дает. И если инструмент способен делать подобные оптимизации - он с кодом Мартина может сделать много чего полезного и интересного. А с кодом в 16 строк - почти ничего.
Даже если и так, в чем я лично сомневаюсь. То может потому что этому коду и не нужны оптимизации компилятора?
Представьте на секунду, что Agent исполняющий JS код, автоматически научился распределять нагрузку на все доступные потоки.
Код Мартина будет оптимизирован автоматически. Менять ничего не нужно будет. Вычисление простого числа воспользуется всеми доступными ресурсами многопроцессорной архитектуры.
Код на 16 строк, все так же будет работать в одном потоке. И оптимизировать его сможет только человек.
Это Вам как самый показательный пример.
Немного не понял, т.е. вы нашли во всей книжки 2, возможно не совершенных примера кода, вырвали их из контекста, в результате чего стало не понятно, что эти примеры демонстрировали и на этом написали "разгромную" статью?
Вся книга на таких примерах строится. Ещё один пример, который "ближе к жизни и не алгоритмический" в комменте разобрал: https://habr.com/ru/articles/875426/comments/#comment_27818290
Важно понимать, что это один из первых примеров. Т.е. тот, что должен продавать всю книгу. Я в своё время был немного в афиге от него.
После прочтения статьи у меня только один вопрос. Кто такой программист-анальник?
В последнее время на хабре вываливается много статей c критикой SOLID и Чистого года. Мне не кажется это совпадением...
Компактность тестов зависит от решаемой задачи.
Когда у вас множество тестов, то важно понимать, что вы не упустили какой-то случай. Для этого нужны максимально компактные тесты. Когда каждый тест состоит буквально из пары строк. Тогда можно поставить две строки с assert рядом, и сразу будет видна разница между кейсами. С длинными многострочными тестами вы поседеете, пока будет проверять все assertTrue/assertFalse.
Однако, подход c компактными тестами имеет недостаток - в них надо сперва разобраться. Что довольно-таки бесит залётного разработчика, который привык к традиционным юнит-тестам: где предусловие? где действие? где проверки? Что за хрень тут этих двух строчках творится?!
Совершенный код, Стив Макконнелл:
"На самом деле для решения некоторых задач лучше использовать один крупный метод".
Эта цитата прекрасно описывает данную ситуацию.
Роберт, ты мне не дядюшка