Функции. Разбор книги "Чистый Код" Роберта Мартина #1 | Организованное программирование

Друзья, привет. Это подкаст Организованное программирование. Я уведущий Кирилл Мокевнин. И сегодня у меня нету гостей, потому что сегодняшний выпуск - это разбор. Разбор, который я очень давно хотел сделать. А сегодня мы разбираем книжку Чистый код. А прямо открываю текст, смотрим вещи, которые там писал Мартин. И я говорю своё мнение на эту тему, потому что периодически это возникает. периодически спрашивают, люди продолжают по ней учиться, продолжают следовать, пытаться следовать тому, что там есть. В принципе, я своё мнение много раз обозначал. Понятное дело, что в любом месте есть какие-то вещи, которые выглядят разумно, хорошо и всё такое, но для меня книжка Мартина воспринимается скорее всё равно как очень такая несистемная штука, потому что она просто говорит: "Вот смотрите, вот если так выглядит, то так, если так выглядит, то можно вот так сделать". А не ставя за рамками этого какие-то фундаментальные принципы или, кстати, даже местами не так их воспроизводят. Я там покажу несколько примеров, что приводит к тому, что человек как бы наполняется, ему кажется смыслами. У него много в голове возникает паттернов, подходов того, как что-то надо делать. При этом, а, из-за того, что нету, а, базы какой-то, это всё равно всё не приводит к реально хорошему коду и пониманию того, что такое хороший код и что такое нехороший код. [музыка] Опять же, речь не идёт о том, что приз, те вещи, которые она описывает, они там все плохие, далеко не так. Просто это чаще всего следствие каких-то других вещей, которые лучше один раз выучить, понять и запомнить и дальше применять везде. Плюс, конечно же, есть специфика, связанная с самим языком. А потому что Мартин, во-первых, он писал это всё давно. Когда он это писал, это очень сильно было завязано. и до сих пор завязаны на Java и Javaподобные языки. Поэтому большое количество принципов, которые здесь описаны, они, вообще-то, людям на других языках ну совсем никак не помогают. И что самое интересное, всё-таки Мартин с тех пор сам много чего попробовал и много во что окунулся. Например, с тех пор он там руби попробовал, он кложу попробовал и вообще, если почитать, посмотреть, изменил мнение на многие вещи. Начал говорить: "О, а вот это вот так, вот это вот так". Плюс, конечно же, кто следит за его блогом или за его твиттером, знает, сколько ему в панамку пихают и всякие другие ребята разборы делают своё отношение к этому. Опять же, здесь это всё очень странно, потому что он не является каким-то супер-мегапризнанным экспертом в плане техническом, потому что человек вообще на себя сам где-то там работает, какие-то штуки делает. То есть он в этом плане дальше от промышленного программирования, чем многие из нас, да, кто этим занимается. И при этом о нём чаще всего говорят больше всего. Вот он как-то такую славу заслужил, получил. И, собственно, вот мы поэтому всё это добро разбираем. То есть, грубо говоря, если бы про эту книжку не особо говорили, я бы, наверное, особо на неё внимание не обращал, но поскольку про неё говорят и постоянно ставят в пример, поговорить про это невозможно. Вот. Так что я ни в коем случае не хейтер Мартина, но а из-за того, что всё это рождает очень много заблуждений, нужно, конечно, это разбирать. Кстати, был такой бум лет пять назад, при том, что книжка намного раньше написана, был бум 5 лет назад. Э все делали такие видосы. Ну вот, э, я их немножко посмотрел на днях и вот решил тоже в этом добре поучаствовать. При этом м там очень много разбирают начальных э глав и очень мало разбирают то, что идёт в конце. Поэтому я попробую сделать по-другому. Я начну сразу с функций, а то, где уже есть какие-то интересные моменты, и постараюсь дойти там почти до конца. мы не затронем тему либо какие-то суперспецифические темы для Джавы, либо, например, многопоточность, потому что это не тема кода с точки зрения абстракции, это такая более техническая тема на тему того, как писать, не писать многопоточный код. Поэтому она не касается того, что мы обсуждаем, то, что называем чистым кодом. Ну что, поехали. Я открываю, показываю вам на экране, что происходит. Мне кажется, что как будто этот выпуск можно слушать, если у вас не получается его смотреть, его можно даже будет слушать. Но посмотрим, как получится. Будет интересно попробовать и такой тип разборов. Если, кстати, он зайдёт, я буду регулярно такие вещи делать, потому что книжек много, а есть что почитать, есть что пообсуждать. Да и не только книжки, статьи, в конце концов, тоже. Итак, вот она у меня открыто. Давайте посмотрим. Значит, мм, глава функции, пятьдесят пятая страничка. Поехали. 555. Вот функции. Опять же, я не буду читать всё подряд. буду выбирать только те вещи, которые наиболее интересны или там, где есть о чём поговорить, поспорить. То есть, если я что-то пропускаю, либо я с этим согласен, а, либо просто мне кажется это неинтересным здесь разбирать, но не факт, что я с этим согласен, поэтому никогда заранее, что называется, не узнайте. И да, ещё я, конечно, не буду разбирать прямо сами примеры кода глубоко, потому что, во-первых, тут листинги, ну, не на один экран, плюс это Java в том плане, что не все здесь Java знают. Плюс они ещё и без подсветки. И читать просто код с экрана такой себе. Поэтому эту часть я в основном пропущу. Может быть, где-то будем смотреть код. Но а если, честно говоря, вообще, если код разбирать, который он здесь пишет, вопросиков возникает много, потому что, э, вообще, когда мы говорим про чистый код, тоже надо вот про это сказать, примеры, которые любят приводить, они, конечно, довольно трышовые. То есть это редко вообще имеет отношение к какому-то реальному прикладному программированию. То есть, либо это уточки, кошечки, то, что вообще никуда и такого просто не бывает. Либо ощущение, что как будто мы пишем библиотеки. То есть примеры кода вот с прикладным кодом на фреймворках типовых. Если мы опять же говорим про веб-разработку, frontend, бэкэнд, то там нет таких вещей, почти не бывает. Там по-другому бывает. Ну, например, там сервис работы с каким-нибудь, а, эквайрингом, а что-нибудь по по платежам. Здесь же он такие показывает вещи, которые больше относятся к немножко другим системам или к тому, что обычно используется в библиотечном коде. Тут хочу сказать, что это сильно разные вещи. И глядя на одно, м не то чтобы очевидно, как писать другое. То есть люди, которые умеют писать библиотеки и разбираются в этом, это не те же самые люди, которые умеют просто пишут прикладной код. Так что иногда, даже если он какой-то логичный пример приводит или какую-то тему объясняет, думаю, сложно это довольно применить к нашему прикладному коду, если не понимать всю картину целиком. Вот именно из-за того, что это более такие специфические примеры, которые в реальной жизни а веборазработчиков, ну, вряд ли встретится, по крайней мере, в таком виде. Так, ну что, давайте, а, попробуем пойдём дальше. Здесь он рассказывает какие-то вещи, связанные там с тем, как про что-то про уровни абстракции, проименований, ещё всякие вещи. Ладно, это мы пропускаем. Давайте про компактность. Первое правило, функции должны быть компактными. Второе, функции должна быть ещё компактнее. А он говорит, что я не могу обосновать, но, в общем, я писал всякое разное. Я, в смысле, он, потому что я читаю книжку. И м рассказывает о том, что а сейчас нужно функции делать максимально короткими. А причём, кстати, он ещё такую интересную штуку рассказывает, что вот мы когда у нас было процедурное программирование, то был такой подход, когда нужно писать всё с одной точкой выхода, там что один return должен быть. Это всё, честно говоря, в современном мире не очень актуально, потому что got никто не использует. А плюс, если делать единый выход из функции, она достаточно большая, там возникает проблема такого плана, то, что, допустим, вы сделали нужное вычисление, которое, в принципе, всё уже, дальнейший код весь не имеет значения, то если вы в этот момент не выходите, вам нужно дальнейший весь код писать с учётом вот этого кейса, который в принципе уже вычислен, и значит его не нужно вычислять. А в конечном итоге подход с одним возвратом приводит к тому, что вам на протяжении всего кода функции придётся в каждом моменте думать про все кейсы, даже если эти кейсы могли быть уже завершены. И в реальности это только делает код сложнее. То есть сделать функцию проще с одним выходом, чем функцию с несколькими выходами невозможно. Просто потому что функция с несколькими выходами в более простых кейсах убирает их из вашей головы. То есть return - это не просто return функция. Это значит, что вы в дальнейшем ходе просто можете об этом не думать, иначе вам придётся об этом думать. Поэтому появляются всякие дополнительные переменные, дополнительные данные нужно хранить, дополнительные проверки делать. Короче, это всегда хуже. Поэтому, а, подход с гардами в этом смысле намного лучше. То есть, если вы вначале разбираете какие-то кейсы, которые как можно быстрее можно определить, вычислить и завершить, и делайте ретёрн. Ага. Ниже вы понимаете, что всё, минус один возможный сценарий, уже легче. и так дальше до тех пор, пока вы не останетесь в сценарии, где вот он самый сложный, самый глубокий, самый продвинутый. Это вот общий такой момент. Теперь, значит, по поводу количества строк. Четыре строчки, все дела. Значит, об это словно миллион копий. Я специально смотрел, что сейчас говорят зарубежные блогеры и всякие разные специалисты на эту тему. Даже, кстати, знаете, я даже хотел, честно говоря, разбор их разбора делать, потому что там есть ребята довольно известные, которые собрались и такие: "Ну что, давайте обсудим Мартина, что там, куда, с чем вы согласны, с чем нет". И это было буквально недавно. Я не помню его имя. Это такой известный чувак, который сейчас вот очень сильно на П как-то он. Да. Вот я знаю, что меня сразу в комментариях накинут. Я его имя просто никогда вслух не произносил, поэтому не запомнил, как он произносится. В общем, идея очень простая. Чем больше, чем меньше функций, тем больше их вы в какой-то момент с одной стороны разбивая на более мелкие функции, вообще в целом вынося какую-то логику, которая по смыслу должна быть вынесена и спрятана, чтобы об этом не думать, с одной стороны, мы улучшаем понимание, но, честно говоря, там довольно быстро наступает такой момент, когда разбиение на функции, какой бы вы читаемый не делали, какие бы классные вы аргументы не писали, приводит к тому, что вам приходится слишком много прыгать, чтобы собрать всю картинку целиком, и вам становится гораздо сложнее. Это классическая история, связанная с распределением. То есть, чем больше вы распределяете, тем больше появляется сложностей с тем, чтобы всё это синхронизировать. В данном случае в голове очень часто бывает, что гораздо проще написать одну нормальную функцию там строчек на 100, и при этом просто внутри функции у вас есть независимые блоки, которые каким-то образом работают, потому что рефакторить такой код, как правило, оказывается гораздо легче. Конечно же, тут возникает миллиард всяких условий и принципов того вообще, где мы работаем, с чем, какие языки, как мы работаем с побочным эффектом и так далее. То есть, конечно, тут можно и всё, что я сказал, опровергнуть, и привести контрпримеры и доказать, что я не прав. А, но в любом случае опыт индустриальный показывает, что функции могут быть очень большие и намного важнее даже скорее не размер их, а то, как действительно это связано с выполняемой задачей. То есть насколько это один уровень абстракции внутри. Ну, просто банально есть функции, которые делают какие-то вещи, которые, ну, вычислительно, может быть, большие, но при этом мало затрагивают внешних систем или вообще чисто внутренняя логика. И и в таком случае не так важно, на самом деле, какого она размера, потому что ни на что особо не влияет и ваш контекст не размазывается, и вы, например, не взаимодействуете ни с какими системами. А бывает такое, что функция суперкороткая, но там сразу везде участвует или там слишком много разного состояния меняет соседнего. Ну, конечно, это совершенно другая ситуация. Поэтому, наверное, хочется предостеречь от чего? Не считать догмой, а что функции должны быть суперкороткие. Так или иначе, большинство людей, которые пытались прямо строго, слепо следовать вот этому подходу, когда функция там чуть ли не пару строчек, все кейсы, которые я знаю, все знакомые, которые так делали, все люди, которые об этом писали, говорили, что, блин, в какой-то момент становится слишком сложно и у тебя просто теряется за деревьями лес и вообще непонятно, что происходит. У меня, наверное, такой вот пример в этом плане. Во фронтде классно об этом говорить. Вот казалось бы компонент, да, это функция, а в том же самом реаксе, а и он может быть, ну, допустим, там 500 строк. Плохо это или нет? Да, вообще неплохо, потому что у вас там просто, грубо говоря, дом дерева формируется кусок htмl, если вы очень упрощённо. А его вообще не надо выносить, если это всех устраивает, если этот компонент только так используется. Вот если внутри него появляются части, которые, например, мы хотим независимо как-то использовать или они там внутри ещё повторяются или в других компонентах повторяются, тогда мы их выносим. Но на уровень сложности это редко влияет. А он, кстати, тут ещё приводил пример по поводу навигации, а где-то там писал, но с навигации сейчас особых проблем нет, потому что в любом редакторе всё абсолютно классно подсвечивается, всякие идентификаторы, элспишные переходы, в общем, красота. Так что тут особых проблем нет. Короче, размер функции не принципиален. Принципиально абстракция, которую вы выделяете. И если оно внутри, ну, достаточно изолировано само по себе, в принципе, оно даже может быть внутри довольно грязно быть. Ничего страшного. Главное, что вот мы правильно выделили. Но здесь единственное, что хочется сказать ещё выделение функций. Я об этом даже в докладах рассказывал, это всё-таки в первую очередь не про повторное использование кода, а в первую очередь про смысловую абстракцию. Почему это важно и почему это не одно и то же? Потому что редактор, например, кода, он может, вообще-то, вам свиню подкладывать. Он, например, видит какой-то кусок кода, который используется повторно, и он может предложить вам сказать: "О, давайте вот выделим эту функцию, смотрите, оно так используется". Но с точки зрение смысла это не является функцией. То есть у вас, грубо говоря, получится, что в рамках одной функции соединены совершенно разные вещи, которые к ней не имеют отношения. Получается, что вы как бы функцию вроде сделали, но по факту это реально вынесен просто некий блок кода, хотя на самом деле сам по себе он не является смысловым блоком. Поэтому функция - это почти всегда про определение того, а какую проблему и задачу мы решаем. Я причём боюсь говорить слова из серии одна ответственность, потому что мне очень не нравится эта формулировка. Почему? Потому что она создаёт впечатление хорошо делай, хорошо будет и как будто мы все понимаем, о чём идёт речь. Опять же, опыт показывает, когда вы берёте разных программистов, сажаете рядом, ну, в смысле, наоборот, они другу не видят, вы даёте одну и ту же задачу и говорите: "Вот, пожалуйста, мне реализуй". А, и они такие: "Да, начитали с солида, начитали, значит, других каких-то подходов". И говорят: "Вот, мол, одна причина, там много формулировок, одна причина изменений, одна ответственность, делает одно". А потом, когда начинаешь смотреть, всегда это очень ситуативная штука, которая зависит от контекста. То есть, например, что мы считаем одной задачей? У вас класс вообще может быть целым приложением. И это во многих фреймворках так сделано. Это одна ответственность, а внутри у вас там дофига что происходит. Или, например, вот берём какой-нибудь отчёт. Вот, например, функция, которая генерит отчёт. одна ответственность. А если внутри это гигантская сложная система, когда вам надо, например, там хитрым образом генерировать, а, ячейки, там ещё что-нибудь в этом духе, форматы разные, это одна ответственность или нет? И что бы вы не говорили, как бы вы не придумывали, не казалось, что: "Ой, я тут всё понял", вот так система раскладывается, мы берём второго программиста, говорим ему ту же самую задачу, у него будет совершенно другой расклад, за исключением тех случаев, когда у них был опыт создания таких систем. Потому что, как правило, те люди, которые в какой-то теме поднатарели, у них уже начинает что-то получаться. Я про это ещё чуть позже скажу. Так, поехали дальше. Блоки отступа. Это неинтересно. А-а, правила одной операции. Да, совершенно очевидно, что функция выполняет множество операции. Даёт буферы, производит выборку данных, а, ищет у наследование страницы. Ну, это он пока показывает пример той функции, что типа она делает всё подряд. Функция должна выполнять только одну операцию. Она должна выполнять её хорошо. Ничего другого она делать не должна. Вот это для меня, оно звучит красиво, но оно ничего не означает по факту, потому что в любом случае, вот, допустим, там репорт тот же самый, я говорю, у вас всё равно будет функция, которая в конечном итоге, которая генерит отчёт. А внутри, даже если вы там всё это поразбивали на мелкие функции, будет куча совершенно разных действий. И тогда получается опять мы это можем выносить это в разные функции, а можем не выносить. С точки зрения функции, которая генерирует отчёт - это некая единая штука. А то, что там по пути ещё надо сходить в базу, сделать разных кучу вещей, ну, это вторично. Потом, конечно, может возникнуть вопрос: "О'кей, а если там за данными надо в базу ходить? Ну, давайте вынесем эту логику". Можем. Но чрезмерное увлечение изоляции побочных эффектов и абстракций тоже несёт за собой проблемы, потому что в таком случае вы получите код, в котором слишком-слишком много абстракций. То есть это вот такая типичная история в Джаве, когда вы смотрите и у вас там просто вот так вот друг в друга как матрёшка собирается перед тем, как что-то получается. То есть вместо того, чтобы выполнить простую операцию, у вас там нагромождено просто этих фабрик, абстрактных фабрик и и так далее. Причём, кстати, здесь это тоже будет как пример приводиться, и об этом мы чуть дальше поговорим. Вот поэтому, мм, вот э какой важный момент я ещё хотел сказать. Если посмотреть на реальную практику создания приложений, и причём, когда мы говорим не прикладных приложений, а вот библиотечного кода, да, можем ли мы сказать, что вот прочитав вот эту книгу, другие какие-то книги, люди, которые идут создавать свои собственные библиотеки, у них, значит, они такие: "О, теперь я делаю правильно, смотрите, я правильно по функциям разбил, я правильно всё понял". Ответ вообще так не работает. Если вы посмотрите на развитие библиотек, особенных мажорных версий, э, любых вообще в любых языках, то всё, как правило, зависит от опыта, который получили разработчики её разрабатываемой в процессе и поняли, какие ошибки они допустили и как люди это используют, и какие ограничения, сложности возникают при том интерфейсе, который они создали или тех возможностях, которые есть в этой библиотечке. И только после этого они понимают: "Ага, мы, значит, ошиблись в дизайне этой системы, этой библиотеки, давайте её менять". И выпускают, допустим, новую версию, в которой они, как правило, она обратно несовместимая, в которой они делают значительные изменения, расширения, тра-та-та-та-та, и внутри там всё переписывают. И это касается часто и самих фреймворков, это касается библиотек, ну, и в целом вот таких вот вещей. И помог ли им совет Мартина, например, что они такие: "Ну вот мы с первой версией сделали всё правильно". Да, вообще нет, потому что там перераспределение просто даже по модулям, которые там будут, оно просто другое, потому что обычно идёт переосознание полностью всего этого добра. Поэтому с одной стороны мы не можем сделать сразу хорошо в любом случае, пока у нас нет соответствующего опыта. И поэтому, кстати, более сильные те, кто делает что-то не первый раз. То есть, если я, например, специализируюсь на создание, не знаю, сироэмок или, если мы говорим про прикладной код или про библиотечки на создании, не знаю, фронтенд фреймворков, то у меня будет получаться в какой-то момент довольно неплохо, да, даже с первого раза. А если нет, то будет [ __ ] какую бы книжку я не прочитал. Есть, конечно, некоторые принципы, которые позволяют что-то сделать лучше, но по большому счёту нужно успокоиться и плыть по течению, потому что а никто ещё с первого раза даже с самым классным экспириенсом не сделал. так не работает. К счастью или к сожалению, скорее это просто помогает немножко успокоиться и просто больше рефлексировать на тему того, что о'кей, мы запустили, посмотрели, изменили, улучшили и так далее. Но не все изменения имеют смысл делать. СМ переход с питона 2 на pтоon 3. О'кей. А поехали дальше. Ну дальше, в принципе, можно это всё пропускать. Это там он растекается по идее одного уровня абстракции. И да, один уровень абстракции имеет смысл чуть-чуть подробней. Действительно, есть концепция того, что когда мы работаем, вот, например, мы функцию открываем, какой-то кусок кода, и там есть определённые строчки, да, с которыми мы работаем, то, конечно, в идеале а желательно, чтобы действительно это был один уровень абстракции. Но это не всегда очевидно, о чём вообще идёт речь, потому что, например, в одном месте мы читаем из базы, а тут работаем с файлом, а тут работаем с моделями. И вот типа, например, одновременно работа с файлом и работа с моделями моей предметной области, является это одним уровнем абстракции или нет? Кто-то скажет, что да, точно, это не один уровень абстракции там и так далее, но даже если вы спрячете это за какую-то функцию, работа с файлом там никуда не денется. И учитывая, что это всё-таки побочный эффект - это, честно говоря, такой, а, как бы иллюзия изоляции, в реальности это не совсем изоляция. Наверное, один из ярких примеров нарушения уровня абстракции, оно заключается вот в чём. А те люди, которые, а, я подозреваю, что всё-таки большинство так или иначе, кто смотрит, они с этим сталкивались. Это если мы берём классический ээкэнд, какой-нибудь фреймворк и, допустим, у вас естьмка и вы работаете с моделями, да? Вот у вас есть модельки, и вы, соответственно, мм, не знаю, там какие-то делаете выборки, ну, даже не выборки, а, скажем, выбрали модель, используя стандартные механизмы вашего фреймворка, и дальше выполняете какую-то логику с ними. И вот если на этом уровне, на котором вы это делаете, а это скорее всего, кстати, сервис, то есть такие вещи ещё в сервисе делаются. Вот если вы на этом уровне вот работали с моделями, работали, работали, а потом херакс, делаете просто сырой запрос в базу, но вот это явно не тот уровень абстракции, с которым надо работать. И это точно надо выделять. И тут вообще дело не в размере функции, не в размере кода, запроса и всего остального. Здесь просто проблема здесь вот в чём. Если вы начинаете писать такой код, то в одном месте как бы, если он появился, ну, жить с этим точно можно и как-то дальше, э, менять это тоже можно. Но он создаёт неприятную ситуацию. То есть он показывает другим разработчикам, особенно более молодым, незрелым, новеньким, что это нормально. Они смотрят на этот код, такие: "Ну так, ну так пишут". Они могут даже не отрефлексировать, что здесь вообще какое-то нарушение уровня абстракции. Они просто видят, что вот это код вот, который у нас есть. К чему это приводит? Это приводит к тому, что они потом этот код будут копировать. Они будут в других местах продолжать так делать, потому что, ну, мы же так уже делали, а никто нам не объяснял, что это оказывается разным уровне абстракции. То есть это ещё надо догадаться. Вот поэтому такие вещи лучше писать правильно сразу с первого раза и думать вообще об этом, если вы понимаете, что не вы единственный владеете этим кодом, и вы контролируете всё, что надо. Потому что если я пишу один, я могу сказать: "О'кей, я это сделал, потому что я могу сделать это быстро, а второй раз, когда мне это понадобится или я доберусь до этого куска кода, я сделаю рефакторинг". Это работает только в том случае, если вы единственный над кодом работаете. И тогда вы можете любой шаг продумывать наперёд и не бояться сделать какой-то косяк, с которым вы потом сами справитесь, потому что вы знаете, как вы будете работать. Если вы работаете в команде, это никогда не работает. Всегда работает копипаста, и только долг это отрастёт. Так, чтение кода сверху вниз правил понижения. Я читал, читал, читал и вот прямо совсем, что он хотел сказать, не до конца понял. Вот поэтому я, наверное, это пропущу. Я, честно говоря, не вижу в этом ничего. То есть понятно, что он пытается сказать, как надо подряд выстраивать функции по уровню абстракции, но, вообще говоря, у вас обычно функция разбросана сильно везде по разным местам и вообще то, с чем вы работаете. Поэтому оно не в одном месте расположено, поэтому, честно говоря, выглядит как-то немножко странно. Ну вот если речь идёт про то, что в рамках класса ты это делаешь, ну это ничто такое принципиальное. Так, дальше. Написать кома компактную команду Switch довольно сложно. же команды вмест, да, больше места. Это немножко манипуляция, потому что он сам себе придумал проблему и сам себе её на неё отвечает. То есть он такой сказал: "Функции должны быть короткими". И потом говорит: "Так, Switch не укладывается в эту концепцию". Поэтому относиться к этому надо сдоли определённой скепсиса. Вот. И когда он пишет: "К сожалению, обойтись без консвич не удаётся не всегда. Никакому сожалению. Просто если у вас есть задача свичиться, это абсолютно нормальная задача". Примерно с таким же успехом можно было говорить, что, к сожалению, обойтись без Ифа удаётся не всегда. Ну камон, это просто нормальная часть программирования, что у вас так всё это устроено. А дальше он показывает функцию, которая вообще ничего кроме свичи нет. И объясняет там какие-то всякие недостатки, типа, во-первых, она велика. Ну здравствуйте. Показали функцию, в которой только один свич. Я уже говорил, что отношение к этому всё-таки, слава богу, сейчас более-менее здравое в сообществе разработчиков о том, что не надо так упороваться по размеру функции, и это ни к чему хорошему не приводит. Вот. А при добавлении новых типов работников она будет разрастаться. Короче, а здесь он на самом деле приводит к идее того, что, ребята, у нас тут, мол, м, смотрите, стратегия, а, давайте сделаем общий интерфейс. А давайте, значит, заменим это на по сути полиморфное поведение, и тогда вот этого вообще всего не будет. Это нормальная история, и такое встречается, бывает, когда вам это нужно. Но, вообще-то, не всегда нужно стараться абсолютно всё решать полиморфном поведении. Ну, то есть когда у нас просто подменяется тип и мы не кейсами делаем, а у вас фактически логика зашита в сове, ну, в какую-то имплементацию, в какой-то, допустим, класс, если вы пишете на классовом языке, но это не обязательно, кстати, так может и без классов то же самое быть сделано. И в таком случае, да, у вас как будто свича будет, но это очень особый случай использования свича. А когда конкретно мы вызываем логику в зависимости такой ближе к типу она привязана, не всегда, но ближе к типу. У неё даже здесь в примере как раз тип. Фактически это немножко другое. Это как раз стоило, наверное, показывать пример в разделе, который называется не то, что sвиt плохой, а что конкретно диспетчеризация по типу sвиtch этого типа ручками реализуете ООП, да? Потому что ООП подразумевает использование полиморфизма. А хотя на самом деле даже те, кто пишет в Оп в таких языках, они многие понимают, что не надо в каждое место пихать полиморфизм свич, иногда хорошо и нормально. Но иначе задолбайтесь, у вас количество интерфейсов и всяких таких штук будет бесконечно много. Не всё должно быть конфигурируемо на 100% и сдаваться через м контейнер какой-нибудь. А просто потому что любое абстрагирование, любая попытка обобщить код, честно говоря, делает его сложнее. То есть сначала кажется всё классно, весело, здорово, но в какой-то момент, если у вас весь код такой, то в количестве абстракции сложности вы просто потеряетесь. Вот он тут ещё пишет. Во-вторых, она совершенно очевидно выполняет более одной операции. В-третьих, она шашает в принципе ответственности. Ой, просто функция, которая просто делает диспатч. Вот. И ничего она не нарушает. Да ладно, я не буду с ним здесь спорить. Короче, он тут и все грехи, какие только можно притянул. Ну, в основном свои, которые он определяет как-то. Вот. А, ну нет, один всё-таки скажу. В четвёртых, о, нарушает принцип открытости, закрытости, потому что код функции должен меняться при каждом добавлении новых типов. Да, это абсолютная правда, что если вы не используете полиморфное поведение, при котором вы можете где-то задать конфигурацию, у вас по всему коду будет использоваться, то действительно это так. Но он опять же исходит из того, что он он сам это описал, сам сказал, что это важно, сам сказал, что без этого жить нельзя. И типа давайте так делать, это фундаментальный принцип программирования. Нет, э принцип открытости и закрытости не фундаментальный принцип программирования. Если у вас вся программа построена так, что она меняется только за счёт конфигурации, это означает, что она у вас невероятно сложная и внутри невероятно много всякого абстрактного кода. Это надо делать только тогда, когда у вас действительно есть такая потребность. Причём, кстати, чаще всего это делается реально в инструментах, то есть в либах, в каких-то штуках, которые можно конфигурить, но но, например, не в прикладном коде. То есть фреймворк, да, он часто такой внутри, там всё можно так подменить. Там редко бывают подобные кейсы, собственно, там всё завязано на абстракции. А когда вы пишете конкретный рекламной код, ну, например, у вас есть там модель юзера, вы просто тупо инстанцируете этот модель и работаете с ней напрямую. Вы даже через контейнер не проводите. Это касается не только моделей, это может касаться и любых инфраструктурных или там дополнительных каких-то штук, которые у вас есть в коде. Вот поэтому принцип понятный, это всё чётко важно понимать. То есть здесь у меня вообще никаких вопросов нет. Классно, когда вы осознаёте свечи связь с полиморфизмом, сыфами и с подменой имплементации, с динамическим расширением поведения за счёт того, что не надо переписывать код, но при этом а без догматики, да, что вы понимаете, где вы это используете, где это не используете. А вот если вы этого не понимаете до конца, то тогда, конечно, возникает догматика. Смотрите: "А вот он это написал, наверное, так правильно". Да. Но всё в конечном итоге сводится к пониманию полиморфизма и тому, как он работает. Конкретно речь в данном случае про сабтайпинг, то есть полиморфизм подтипов. Не путать с параметрическим полиморфизмом. Ну дальше он говорит, что, мол, давайте абстрактную фабрику пилить, не надо пилить абстрактную фабрику на каждую штуку. Ну да. И он дальше немножко про полиноморфные объекты говорит и ещё что-то в этом духе. Кстати, здесь он ещё одну вещь упоминает. Я не буду на ней глубоко и широко останавливаться. Она называется он, кстати, очень часто забавно. Он не говорит какой-то понятийный аппарат, который известен людям, который описан, которые знают. Он начинает это какими-то своими словами либо немножко не то даёт. То есть когда он описывает, что в одном случае, то есть есть у вас свич или типы, в одном случае проще добавлять поведение, в другом случае проще добавлять новые типы, а вообще-то эта штука имеет название, это называется expression problem. Если вы с этим никогда не сталкивались, почитайте разок. Это очень полезно. Как раз вот в тему замены свича полиморфизмом. Там действительно есть такой прикол, что если вы распихиваете логику по типам, вам проще добавлять новый тип, динамический, всё такое, но сложнее добавлять операцию, потому что её надо добавить типа во все места, во все типы, да? То есть вам проще добавить новый тип, а новое поведение, которое свичом в одном месте формируется, вам типа проще добавить в один свич. Ну это при условии, конечно, не используется в пятидесяти разных местах. Я сейчас вот сказал, подумал, может быть, ээ, я слишком абстрактно звучу, потому что, когда я про это говорю, в моей голове выглядит всё очень логично, я прямо вижу код. Но вполне возможно, что не у всех прямо во время прослушивания возникают эти картинки. Вы, кстати, напишите про это, тоже интересно, потому что вполне возможно, когда в момент прослушивания таких видео вы скажете: "Блин, Кирилл, сорян, вообще не успеваем за тобой, потому что я тут мою посуду или что-то ещё делаю". И слишком всё это звучит непонятно, просто потому что я перед собой не вижу кода. Аэ, мне просто на будущее, чтобы я понимал, стоит ли так глубоко копать или можно как-то по-другому это подавать. Всё, поехали дальше. Используйте содержательные имена. Ну, о'кей, согласен. Аргументы функции. В идеальном случае количество аргументов функции равно нулю. Абсолютная хрень вообще не так. То, что он говорит - это вообще кошмар. Это, по сути, либо а использование глобального состояния, либо неявного состояния, что у вас всё скрыто, у вас всё, видимо, опять же из того, что он в Джаве пишет, всё в объектах, и у вас всё, значит, всё там стоит запрятан в объекте и выполняются, значит, все операции. Любой функциональщик вам скажет, что это вообще противоречит нормальному здравому смыслу, потому что, наоборот, весь стейт должен быть явный, передаваться через аргументы, через параметры функций. И речь не идёт о том, что они должны быть ужасны, их должно быть много и так далее. Речь идёт о том, что у вас должно быть явное состояние. А, конечно, баланс где-то посередине, потому что, ну, всё-таки, если мы пишем в Джаве, как не крутите, у нас есть объекты, и мы с этим как бы живём. Но при этом пытаться полностью весь стейт пихать внутрь куда-то и работать только через функции, которые вообще не принимают никаких параметров, ну, ничего хорошего из этого не получится. Вот сразу могу сказать, поэтому всегда вопрос в смыслах. Вопрос не в количестве аргументов, параметров, которые принимает функция, а вопрос в том, какую проблему вы решаете. и как это вписывается в вашу архитектуру. Кстати, я, например, не пишу мобилки, но когда я код видел Андроида и пытался что-то делать, я помню, как меня поразило, что там многие функции принимают прямо реально по 10 аргументов. Причём, когда ты их туда передаёшь, тебе сначала там навов надо 10, ну, в смысле, пять, например, там передать в каком-то порядке, чтобы дойти до тех смыслов, которые тебе нужны. Вот это выглядит перебором. И опять же, кстати, это же спроектировано людьми, которые там Android делают и так далее. То есть серьёзные ребята, которые читают серьёзные книжки, работают в серьёзной компании Google. И в этом смысле как минимум им бы помог какой-нибудь именованные аргументы, да, и хотя бы так можно было на не передавать. Но, возможно, это решает следствие, а не причину, потому что сама причина в том, что аргументов слишком много. Тут не скажу. В реально мм ходе прикладных приложений я редко видел, чтобы вот настолько сильно злоупотребляли параметрами. Вот мобилки только, наверное, я так видел, и то на уровне стандартных библиотек и фреймворков. а не прикладного кода. Верю, что кто-то где-то такое пишет, но не думаю, честно говоря, что это прямо такая самая большая проблема, потому что всё равно аргументы функции, честно говоря, это следствие того, как люди проектируют. То есть таким образом просто можно всё, что угодно придумать, ещё 500 принципа вывести, но в реальности мы говорим о том, как человек проектирует свою систему и выделяет абстракции и работает с тем, что там внутри. Вот. О'кей. Мотаем дальше. Во. Аргументы флаги уродливы. передача логического значения функции Вастина ужасная привычка не менее сложается на этого метода а бла-бла-бла-бла-бла провозглашая что функция выполняет более одной операции это не совсем так с одной стороны я как бы с ним согласен и флаги чаще всего это плохая идея но далеко не всегда это другая функция я могу простейший пример привести это допустим Markдаун то есть когда вы рендерите marрdдау у вас как правило огромное количество опций того как его рендерить отображать ссылки не отображать делать 1 2 3 4 и таких примеров можно привести ещё много. Является ли это проблемой? И, к сожалению, мы там передаём флаги и что-то делаем. Да нет, это нормальная задача, абсолютно логичная и стандартная. То есть так везде устроено. Разница просто скорее в том, что флаги передаются в таком случае не в виде просто аргументов, они передаются, как правило, специальнымгурационным объектом. Но тут, конечно, уже зависит от языка, то есть где-то в тайпскрипте или какой-нибуд динамике попроще, потому что там можно просто объект передавать. А в каком-нибудь в каком-нибудь Джаве это сильно сложнее сразу, потому что, допустим, если у вас есть набор конфигурационных параметров, которые надо передать, у вас как бы тут же сразу всплывает ещё один класс какой-нибудь configuration, что-нибудь markдаdown config, который вам надо отдельно создать, заполнить и, соответственно, передавать его дальше. Либо, да, получается, когда на всё это смотрят, думают: "Нафиг надо". И просто пихают 100 флагов туда. Ну вот, да. Так что проблема, честно говоря, чаще, мне кажется, возникает вот в подобных языках, где простейшая история с передачей параметров, конфигурационных параметров, она требует использования классов, а не просто простого литерального какого-нибудь синтаксиса объектов, как, например, это в JC Тайпскрипте работает. Кстати, поэтому, да, вербозности, конечно, гораздо больше в таких языках. Так, функцию с двумя аргументами понять сложнее, чем унарную. Ну, хрень какая-то, блин. Если у вас функция суммы считает два аргумента, тут ничего сложного нет. Это это уже притягивание за уши. Тут надо смотреть в смыслы. Ладно. Мотаем дальше. Объекты как аргументы. Если функция должна получать более трёх аргументов, весьма вероятно, что некоторые из этих аргументов стоит упаковывать в отдельном классе. Здесь вот как раз идёт вот подмена понятий. Человек, который на Джаве не писал и читает эту книжку, он может неправильно понять вообще, о чём идёт речь. Просто именно проблема в том, что в Джаве ты не можешь просто взять и передать набор параметров. Их нужно упаковывать во что-то, а упаковывать там можно только в класс. Поэтому он и говорит об этом. Но по факту, что он имеет в виду? Что их можно передать как набор опций. И в этом плане он абсолютно прав. Очень часто есть в функциях очень важные параметры, без которых никак. Это вот прямо то, что надо аргументами передавать. А есть, например, набор там какой-нибудь последний параметр, который называется options. И там уже можно какие-то разные конфигурационные штуки передать. И да, в Джаве это надо делать классом. Ну, не только в Джаве, а в Сишарпе, в котлине, я думаю, вряд ли сильно отличается. Ну, по крайней мере, на момент, когда я ра с этими языками сталкивался, там, конечно, так всё было. Мало ли что там придумали ещё дополнительно. А дальше глаголы, ключевые слова. Ну, тут понятно, что это глаголы. Ой, давайте поговорим про мм побочные эффекты. Очень важная тема, в которой Мартин немножко путает понятие. Сейчас мы поговорим, что имеется в виду. Значит, побочные эффекты суть ложь. Ваша функция обещает делать что-то одно, но делает что-то другое, скрытое от пользователя. Иногда она вносит неожиданное изменения в переменно своего класса, скажем, присваивает им значение переменных или глобальных перемен системы. В любом случае такая функция является коварной вредоносной ложью, которая часто приводит к созданию противоестественных временных привяз других зависимостей. Для примера возьмём безвредный, на первый взгляд функцию из листинга. Функция использует стандартный алгоритм для проверки пары, имя пользователя, пароль. Она возвращает true, false, там, тра-та-та. Ну и в функции имеется побочный эффект. Сможете ли вы его обнаружить? Он приводит пример функцию checkpassword, в которой внутри есть session и, ну, инициализация сессии. Почему? Я считаю, что то, что он делает, э, это вообще не очень классно. Создаёт немножко извращённое восприятие реальности. Дело в том, что побочный эффект - это важно. У него, кстати, везде тут примеры сплошных побочных эффектов. И дальше вот перед этим он там показывал функции всякие врайты и так далее. Там везде побочные эффекты. Что-то он про это ни разу не говорил, потому что он как бы говорит про побочные эффекты, но в реальности показывает другую проблему. То есть она, конечно, связана с побочными эффектами, но он неправильно определяет это как проблема побочных эффектов. То, что он здесь показывает - это очень известный, распространённый принцип, который я часто привожу в пример и говорю, что он как раз является одним из самых фундаментальных. И с ним мы сталкиваемся буквально в коде каждый день. Все, кто пишет код. Он называется Command Query Separation, то есть разделение команды запросов. Грубо говоря, у него есть другой способ описать себя. Он звучит примерно так: задавая вопрос, не изменяя ответ. То есть, если вы пишете какой-то предикат или просто извлекаете данные, то, конечно, вы ни в коем случае не должны менять состояние системы очевидным образом, да? То есть, если вы спрашиваете, админ ли пользователь, подходит ли пароль, конечно, в этот момент ничего менять нельзя. Если у вас команда, а, запиши что-то, измени, создай, естественно, там будет побочный эффект. И это абсолютно не просто нормально, это правильно и так должно быть. А поэтому, когда он пишет, что побочный эффект суть ложь, ну, честно говоря, это вообще фраза, ну, я не знаю, ну, нельзя здесь такую фразу писать. Дело не в побочных эффектах, просто в местах, где вам нужно читать, не создавайте побочных эффектов. При этом, конечно, если мы начинаем копать глубже, там всё чуть хитрее, потому что мы такие скажем: "О'кей, а как же, например, лейзи какой-нибудь, да, линевая инициализация?" А, например, вот бывают такие штуки, тоже самый ST Overflow, ну или вообще статьи, да? Вот вы статью в браузере открываете, и у вас сама статья - это чтение. По идее, везде в коде должно быть только чтение. И, кстати, поэтому даже вы такие можете подумать: "О, я буду с реплики только для чтения читать данные все, да, чтобы там эффективно распределять нагрузку в БКЕ". А потом выясняется, что у вас есть счётчик просмотров, и вы такие: "Опа, казалось бы, да, вот мы читаем, а на самом деле ещё меняем этот счётчик". А там ещё может быть условия какие-то и правила. То есть с одной стороны не всегда возможно избежать и иногда это часть бизнеса, и тогда вам никакой программированиние не поможет. Она просто против бизнеса в данном случае. Второе. Иногда это можно делать незаметно. То есть есть языки или системы, которые позволяют так сделать, потому что не везде так можно сделать, когда у вас чтение превращается в побочный эффект, связанный с ленивой загрузкой. И это тоже нормальный подход. Почему? Потому что снаружи при правильной имплементации человек никогда не узнает, что там вообще-то был побочный эффект. То есть всё будет выглядеть так, как будто его не было. Ну а если есть собственно какоя-то операция, которую надо сделать, ну это просто должно быть командой. Это не должно быть checkчек password, это должно быть set password а или ещё что-то в этом духе. Вот и всё. При этом это не означает, что с побочными эффектами не надо как-то особенно работать. Не просто надо, а очень надо. Просто их надо к другому привязывать. И обычно этот принцип называют функциональное ядро, императивная оболочка. То есть идея в чём? В том, что код, который занимается логикой, он максимально отделён от собственно побочных эффектов. При этом побочные эффекты вынесены в отдельный уровень, да? То есть мы сохраняем, читаем, что-то делаем отдельно от программы. Я вот приведу сейчас очень классный пример, который хорошо это показывает. Допустим, у нас есть просто консольная утилита, которая берёт на вход файлик, например, CVS, и из него делает отчёт в каком-то другом формате, в XML или там, а, доковском, и выдаёт. То есть вот очень простая программка. При этом внутри, ну, сколько там, ну, допустим, там 1.000 строк кода. А я периодически ставил такой эксперимент. Я спрашивал у ребят разных, говорю: "Как вы думаете, сколько кода с побочным эффектом в этой функции?" побочными эффектами, да, мы не говорим про побочные эффекты с точки зрения изменения каких-то переменных. То есть, понятно, что можно очень по-разному написать непосредственно код, но я скорее больше именно про работу там в целом с внешними системой взаимодействия. И всегда, когда люди про это говорят, они такие 50%, 7%, 10, там ещё сколько-то процентов. Я говорю: "Ну, смотрите, по большому счёту, побочных эффектов здесь не даже в процентах так мало, что их можно проще посчитать по пальцам. Их тупо два. Первое - это прочитать файлик. Второе - это записать файлик". И основная логика вашей программы в данном случае - это, собственно, формирование этого отчёта. А и получается, что фактически при правильном построении у вас получается наверху программы есть чтение исходного файла и запись его туда, а посередине функция, которая непосредственно строит этот отчёт. И, соответственно, у вас таким образом разделены ответственности. И вот при таком подходе, при таком взгляде императивное ядро, в смысле функциональное императивное ядро, вы из этого можете многомного разных выводов делать о том, как вообще надо писать код и на что обращать внимание. Внимательный слушатель и смотрятель моего подкаста скажет: "Кирилл, а ведь не совсем всё так". Потому что, если ты так напишешь программу, это, конечно, очень классно, но если у тебя там файл на пару гигабт, ты получишь очень неэффективный код. А потому что он загружает всё это в память, жрёт просто очень много всего и, соответственно, всем приносит проблемы. И для того, чтобы это было реализовано правильно, нужно делать стриминг. Правда, это всё так и есть. Нужно читать данные порционно и выплёвывать их, но при этом это не означает, что сама логика переплетена с этим стримингом. То есть это можно очень грамотно всё разносить. Хотя, конечно, сам побочный эффект э растянется, но он может быть всё равно довольно неплохо изолирован. Поехали дальше. Выходные аргументы. Аргументы своим образом интерпретируются как входные данные функции. Каждый, кто наверняка сталкивался с необходимостью дополнительной проверки аргументов, которые на самом деле оказывались выходными, а не входными. Пример appendфтер. Присоединяет ли эта функция S в качестве завершающего блока к чему-то другому или она присоединяет какой-то завершающий блок? Проблема вроде как бы есть, но проблема, честно говоря, связана с тем, что мы работаем с неявным состоянием. Кстати, ещё вот он такую вещь рассказывает, которая кардинально поменялась за последние там несколько лет, я думаю, за последние 5 лет прямо очень сильно и перестало быть проблемой. Значит, он здесь пишет про то, что надо смотреть сигнатуру. Он часто, кстати, приводит этот пример, что надо смотреть сигнатуру, надо смотреть сигнатуру. Без сигнатуры мы не поймём и всё очень плохо, если мы не видим сигнатуру. Дело в том, что во всех современных редакторах, будь тоim, будь то, будь то, показываются все типы. Их нету в коде, но они показываются в файле, да? То есть мы, например, определяем переменную через вывод типов просто там const или ещё как-то в зависимости от языка, но вообще-то там сразу показано, какого она типа. То же самое касается и лямда функции, когда вы описываете их и внутри есть какие-то данные, они вам всё посвечивают. Определений вызовов и так далее. Короче, сейчас это встроено везде. И проблема смотреть в сигнатуру, она, ну, её нет, просто мы это просто видим, а в коде по дефолту во всех современных редакторах. Это не заменяет никаких историй про то, что код должен быть понятным, но сама проблема, она как бы отсутствует. Вот. А то, что он здесь пытается описать, но это надо отдельно обсуждать уже более глубоко про проектирование, потому что он такое начинает рассказывать, приводя плохой пример. А я считаю, что он вообще сам принцип организации кода. И когда он здесь показывает, собственно, мрепорт appendфтер, я вообще не согласен с таким кодом. То есть он изначально написал код, который, в принципе, писать не надо было, и такой говорит: "О, это неправильный код". При этом показывает здесь как решение вообще какую-то другую историю. Ну, как я уже говорил, он убирает аргументы, перенося полностью в стейт внутрь. А-а означает, что так нужно писать код. Вот. Ну давайте не будем погружаться, говорю, здесь надо прямо этот репортер брать, который он придумал, и смотреть, почему он вообще его так написал, потому что я бы написал по-другому. Он здесь как бы пишет про разделение команд и запросов, которые я только что рассказывал. Но прикол в том, что он это как бы отдельно делает. То есть вот то, что он про побочные эффекты сверху засунул, он не связал с этим. И поэтому а люди, которые это читают, я уверен, даже не поймут, о чём идёт речь, потому что здесь ничего не сказано про побочные эффекты вообще. Ну, с одной стороны, он говорит, что либо возвращать информацию об этом объекте, но здесь, во-первых, привязка. Причём здесь объект? Это слишком джавовая история. Во-вторых, он опять упускает вот эту историю, связанную с побочными эффектами. То есть он так говорит, как будто здесь речь просто идёт про изменение полей объекта. Ну нет, это же не об этом а принцип. Хотя конкретный кейс, да, это ещё одна проблема в этой книжке. Он берёт какую-то штуку, которую надо как-то посерьёзнее обсудить со всех сторон, чтобы человек понял концепцию. Даёт её вот знаете, в каком стиле он даёт это? В стиле шорцев каких-то или рилсов, когда очень коротко, очень такое броское, чтобы тебе в голову что-то вошло, но на выходе ты выходишь с мусором, потому что у тебя не формируют социальной картинки. То есть это не нормальное такое последовательное описание принципа построения кода. просто такой вспышка бам тут, бам, тут, бам, тут, причём не связано. И из-за этого я не верю, что человек, проти читавший эту книгу, может выйти и, например, подробно, вот как я сейчас приме рассказывал, рассказать про разделение команды запросов, связь, значит, с побочными эффектами, эти кейсы и так далее. Надо свою книжку писать на эту тему. Хотя уверен, что где-то это я же сам это где-то тоже читал всё не раз в разных местах. Ну вот интересно, есть ли такая книжка, которая подробно вот именно так всё это описывает? Это хороший вопрос. Используйте исключение вместо возвращения кодов ошибок. Я вчера, когда готовился к записи и читал его немножко вот книжку заново, чтобы посмотреть, что он здесь пишет, вот посмеялся над этим пунктом, потому что когда он это писал на го ещё мало кто писал, да, и сейчас очень смешно то, что всё, что он здесь пишет, полностью противоречит. То есть он это показывает как абсолютное зло. Он говорит, что возвращение кодов ошибок функциями является очевидным нарушение принципа раздения комаза запросов. Хотя, вообще, честно говоря, здесь ни при чём. А он показывает код довольно типовой для Гошки и рассказывает: "Смотрите, какой кошмар". При этом он показывает слишком глубокую вложность, опять же, там, где можно было написать по-другому. Понятно, почему он это делает, понятно, почему всё это происходит. Скорее, правильно было бы написать, что, ребят, мы работаем в Джаве. Java - это язык с исключениями, у них есть определённые смыслы, и мы определённым образом должны как бы с этим работать. Это не означает, что на каждую ситуацию у нас бросает исключение, но мы работаем с исключениями. Получается, что работать с кодами ошибок - это просто писать против ветра, если мы работаем в Джаве. Но просто тупо с этой системой никто другой взаимодействовать не сможет, и она ни с кем не сможет нормально интегрироваться. Поэтому в данном случае это специфика джавовая, потому что человек, который, например, из той же Гошки или там Хаскиля того же, да, а где тоже нет исключения, по-другому это работает, а читает вот эту штуку, он как бы вообще не поймёт, а в чём смысл. То есть вроде чистый код, а какая-то такая супербольшая специфика. Поэтому, да, есть языки, в которых вот так устроено. Это абсолютно нормально. Аа, можно, конечно, покрасивше, чем в ГО это было реализовать, но в любом случае большинство людей наоборот счастливо. То есть замечаете, как бы он это рассказывает как абсолютное зло. Куча людей спрыгнула на такую систему и говорит: "Слава богу, мы больше не пишем исключения. У нас вот нет вот этого всего трэша". Так что вот так вот мир довольно быстро и сильно, как видите, меняется. Поехали дальше. Изолируйте блоки Тракеч. Блоки тракеч выглядят весьма уродливо. Любит он, конечно, закидывать так, чтобы потом все, возможно, кстати, весь успех его книг заключается в том, что он на вентилятор накидывает и делает так, что все потом срутся и постоянно его обсуждают. Так что допускаю, что это главный критерий успеха его книжек. Они запутывают структуру кода, смешивают обработкой, ошиб с нормальной обработкой, а, бла-бла-бла-бла-бла-бла-бла. А, ну что тут очень просто всё. А исключение, в идеале, всё-таки это какая-то обработка на самом верхнем уровне, а внутри кода это нормальная проверка какая-то, что можно сделать, что нельзя. Это не всегда возможно, есть всякие гоночки и так далее. А, но, мм, наверное, против чего он здесь выступает в первую очередь, это, конечно, против того, чтобы жёстко завязывать логику на это поведение, когда мы как goto по сути начинаем использовать исключение, чтобы практически в том же месте, где мы исключение бросаем, его ловить. Вот это очень такой паттерн действительно плохой. Сразу видно, что исключение в данном случае будут использоваться как логика. Но в целом, опять же, не будем на этом сильно останавливаться, потому что с исключениями это прямо отдельная история, как они работают, как с ними правильно работать. И тем более не во всех языках они есть, особенно сейчас, когда много и без него. Опять специфика Джавы. Поехали дальше. Да, мы частично затрагивали структурное программирование. Он тут начал про него говорить, наверное, зря чуть раньше про это рассказал, а, про выход из функции, но, в принципе, речь идёт именно про это, что структурное программирование подход, при котором вот мы м делаем ровно один выход. И это было связано, конечно, с большим использованием Go. Честно говоря, всё это довольно давно неактуально, поэтому можно в эту сторону особо не смотреть, потому что сейчас у нас программы прямолинейная, если, конечно, мы тракетчим там не используем для того, чтобы менять поведение. На этом первая часть закончена. Мы сегодня разобрали функции, потом я буду разбирать остальные главы до тех пор, пока мы не пройдём всю книжку до конца. Если вам понравилось это видео, поставьте лайк, а если нет, дизлайк. Обязательно напишите комментарии, если вы со мной не согласны, и прямо бомбаните по мне как следует. Если согласны, тоже что-нибудь напишите. Самое главное, мне очень важен любой ваш, э, фидбэк для того, чтобы понять, как что лучше говорить, что лучше не говорить. А может быть, я где-то ошибаюсь, может быть, вы для себя открыли что-то новенькое. И в конечном итоге мы пройдём полностью эту книжку, завершим и дальше, а, начнём уже разбирать не то, как не надо и где какие проблемы, а то, как классные, какие классные штуки существуют. Всем спасибо. Пока.

[музыка]

Функции. Разбор книги "Чистый Код" Роберта Мартина #1 | Организованное программирование
Broadcast by