На сколько я помню, когда я подавал статью "SOLID в Go и щепотка паттернов" на конкурс - это точно была не категория фронтенд :/ Может ошибка случилась тут при составлении списка шортлиста?
В армии я не только служил, но и прошёл путь от рядового срочной службы до офицера. Но в контексте данной статьи это было бы, в целом, абсолютно не обязательно. Сам принцип, его понимание и его применение к разработке вообще не имеют к этому никакого отношения. Поэтому попытка в «не служил — не мужик» не прошла, извините. Служил и много.
Где вы увидели, что что-то перекладывается на кого-то? Я тоже не понимаю.
Простите, но у меня складывается впечатление, что вы сами создаёте тезисы и сами их опровергаете.
Да и в целом получается какая-то абсолютная нестыковка. Если разработчик обязан следовать стандартам, которые устанавливает техлид, который, по вашим рассуждениям, должен делать то, что в статье, то как он будет соблюдать эти требования и стандарты, установленные ему, не понимая того, о чём эта статья? Он будет городить новые реализации в каждом пулреквесте, делать всё по-своему, и каждый раз техлид должен это вычитывать снова и снова, указывая лично, как нужно? А разработчик не будет учиться следовать этим стандартам и продолжит писать, как ему хочется, уже на следующей таске? Очень странная картина получается.
Да и вообще, если писать код — это творчество, только если «дикое поле и ворочу, что хочу» — само по себе странно. Тогда все эти линтеры, кодстайлы, сотни книг о том, как стоит писать код — все убивают творчество, получается? Творчество и отсутствие рамок и ориентиров вообще не связаны между собой. Творчество — это процесс создания чего-то нового само по себе. Вы созидаете, творите, сооздаете что-то новое и можете увидеть результат своего труда. Это и есть творчество, от слова творить. В живописи, в архитектуре, да, в любой творческой профессии есть свои правила, гайдлайны и ограничения. Инженер-конструктор, который разрабатывает новую модель самолета - творец не меньше разработчика ПО. Но у него есть жесткие регламенты и рамки, как ему все делать, документировать и проектировать. За границы стандартов можно выходить, раздвигать их, но когда это делают хорошие творцы и полностью осознанно, понимая, для чего и почему они отказываются соблюдать их в интересах своего нового творения. А выход за любые границы на постоянной основе — просто потому, что я вот такая снежинка, и если мне хоть чуть-чуть укажут, что есть какие-то стандарты, я расстроюсь и перестану чувствовать творчество — немного абсурдно.
А по поводу того, что высокое качество кодовой базы не нужно разработчикам — опять противоречие. Низкое качество кодовой базы ведёт к росту трудозатрат, как вы сами пишете. То есть, чтобы сделать то, что можно было бы сделать просто и быстро, вам приходится делать это сложно, дорого и больно. И с каждым годом такого подхода становится всё больше и больше. Да, вам за это платят, но какой интерес в том, чтобы внедрять фичи всё сложнее и сложнее, какой интерес в том, чтобы усложнять себе самому работу? Нет, может, кому-то нравится, что спустя пять лет такого развития проекта внедрение банальной фичи занимает не пару дней, а пару недель, с постоянным головняком и кучей лишней ментальной работы над кодом, который начинает рассыпаться от каждого чиха, и приходится всё это латать, держать в голове кучу ненужного контекста и так далее. Качественная кодовая база нужна разработчикам, чтобы их работа была спокойной, интересной и приятной. Бизнесу качество кодовой базы становится интересно только тогда, когда всё начинает сыпаться от багов, и фичи внедряются месяцами.
Я не знаю, почему вы так зацепились за фразу «у каждого проекта должен быть тот, кто заботится о нём душой». Можем перефразировать её как «хорошо, когда у проекта есть тот, кто заботится о нём душой». Теперь без этого слова «должен», но суть не меняется. Просто хорошо и приятно работать в проектах, где разработчики пишут их с душой, заботятся о качестве кодовой базы.
Качество кодовой базы — это то, что в первую очередь нужно самим разработчикам. Бизнесу и работодателю это просто не понять: они не профильные спецы в этом деле. И вы это делаете — работаете над качеством именно в рабочее время. Общаетесь с вашим работодателем, бизнес-заказчиком, и объясняете, что нужно провести такие технические работы, устранить такой-то техдолг, провести рефакторинг. Если работодатель категорически против и вообще не даёт на это времени, так как пилим бизнес-фичи и только бизнес-фичи, то вы уже пишете, как есть возможность. Но это уже повод задуматься: как долго вы хотите работать там, где техдолгом вообще не занимаются?
Просто поймите: из ваших сообщений складывается впечатление, что ваше предложение — просто писать по факту, чтобы бизнес-фича была готова, а техдолг и рефакторинг — для обманутых кровавым энтерпрайзом прослойки разработчиков, которых душу заставили продать вместе с кодом. А единственная цель и удовлетворение — срубить побольше бабла как можно раньше и уйти в закат, чтобы этот код больше не попадался вам на глаза. Тем, кто любит писать код — и не просто код, а хороший, качественный и поддерживаемый код, менеджеры и работодатели просто вдолбили это в мозги своими манипуляциями и внушением.
- Вам это, на самом деле, не нравится, как и мне, и не может нравиться! Просто я понял, как устроен этот мир, а вы ещё нет. Если по книге Лукьяненко, то если вы получаете удовольствие от работы по написанию кода, вы почти что ущербный.
Последнее предложение, грубо, конечно, но по вашему тексту получается фактически так.
Принцип «безобразно, но единообразно» как раз полностью согласуется с инженерной красотой. Если вы не можете по каким-то причинам добиться в коде единого, хорошего и лучшего подхода, то пусть он будет таким, каким он может быть в данный момент, но везде единообразным. И это вполне себе инженерная красота — единообразно написанный проект, который потом намного проще улучшить централизованным рефакторингом.
В общем, намечается бесконечный спор. В конечном итоге каждый выбирает, как ему работать. Но очень и очень не хотелось бы прийти на проект, который писали по принципу «фича сделана и славно, техдогом и рефакторингом мы тут не занимаемся, а уж о качестве кодовой базы тем более думать не собираемся». Вы или получаете удовольствие от процесса, или не получаете. А от этого дальше уже идёт расхождение взглядов на вопрос.
Тут уже пошла какая‑то философия о том, как мы подходим к тому, что делаем, и что значит для человека быть профессионалом своего дела. Кто‑то делает любое дело на совесть, как раз "вкладывая в него душу", так как хочет быть профессионалом и гордится тем, что создаёт. И даже если это просто красивое инженерное решение где‑то в глубине бэкенда, о котором ни кто, кроме него не узнает, такой специалист всё равно получит внутреннее удовлетворение от того, что смог создать что‑то настолько элегантное и нетривиальное, что ему самому будет просто хорошо – как раз на самой этой душе.
Исповедовать подход «задачу сделал и плевать, как сделал, для бизнеса всё‑равно - не проверят, а я, может, через полгода ещё раз работу сменю» для кого‑то может быть и путь, но вряд ли это то, что можно современным языком назвать «путь джедая». Почему сразу о сменить работу через пол года речь? Просто потому, что если разработчик планирует работать на проекте долго, 5-10 лет или даже больше, то в первую очередь делать все качественно и вкладывать душу в его же интересах. Ему этот код и дорабатывать и поддерживать спустя годы. Да и как расти над собой, в том числе как инженер или разработчик, если конечная цель только одна – «плевать, как сделал, задачу формально закрыл и забыл».
Наверное, тут фундаментальная разница ещё в том, как человек относится к своей работе как таковой. Если разработчик работает от звонка до звонка и в гробу видел вообще всё это, поскорее бы рабочий день подошёл к концу, то, наверное, это даже как‑то грустно. Не испытывать вообще никакого огонька, никакого желания сделать классно, красиво и по‑инженерному правильно, при этом не для кого‑то, а в первую очередь для себя – это или терминальная стадия выгорания, или, может, изначально не та выбранная стезя в жизни.
На появившийся постскриптум могу только дать комментарий: вся статья как раз о том, почему этот принцип можно применять и каким образом. Соответственно, даже и добавить нечего.
На самом деле, я не вижу тут противоречий. В первую очередь правильным является единство подходов в проекте, чему и посвящена статья. В ней прямо говорится о том, что нужно внедрять правильные подходы, но делать это следует продуманно.
К сожалению, у разработчиков слишком часто совершенно разное мнение о том, что является правильным, а что — нет. На эту тему я привожу в пример лекцию Мартина Фаулера "Software Design in the 21st Century". В ней он довольно красочно описывает, как дядя Боб, будучи рецензентом, высказывал ему: «Так писать код нельзя!»
О чем это говорит? Сегодня вы — техлид, которому передали этот проект. Вам кажется, что что-то сделано неправильно, и вы пишет новые фичи на свой лад. Завтра вы уволились, или проект передали другой команде, где новый техлид считает ваши решения неудачными и снова пишет новые фичи по своему. В итоге каждый учит и развивает свою команду, не выходя за рамки собственных представлений о правильности, а проект тем временем обрастает тремя разными подходами, между которыми команде приходится метаться туда-сюда.
Чтобы этого не происходило, и написана статья. Лучшее — враг хорошего. Иногда важно думать о гармоничном развитии проекта и его консистентности в более широком смысле. Уча сходу свою команду «правильному» подходу в таком проекте без обязательного рефакторинга старого кода на этот подход, вы фактически закладываете мысль, что параллельное сосуществование разных реализаций одних и тех же вещей в коде — это норма.
В общем, мне кажется, что суть статьи никоим образом не отрицает необходимость обучения команды хорошим практикам.
Есть ощущение, что периоды идиократии уже случались в прошлом. Это происходило даже в обществах, где люди умели считать в уме, знали стихи и обладали одним из самых передовых образований в мире. Тем не менее, половина страны заряжала банки с водой перед телевизором, а другая половина несли деньги в финансовые пирамиды вроде МММ. Казалось бы, качественное и фундаментальное образование должно было защитить общество от подобного мракобесия. Но реальность оказалась сложнее.
Подход к образованию действительно нуждается в переосмыслении. Большинство людей до сих пор учатся по шаблонам, разработанным веками назад. То, что происходит сейчас, — это не хорошо и не плохо, это просто перемены, требующие новых подходов. Главное в образовании — развивать у человека достаточное количество нейронных связей и стимулировать активную работу мозга, чтобы к зрелому возрасту он обладал развитым мышлением и был готов к интеграции в профессиональную среду.
Кстати, ещё Сократ говорил: «Нынешняя молодежь привыкла к роскоши, она отличается дурными манерами, презирает авторитеты, не уважает старших, дети спорят со взрослыми, жадно глотают пищу, изводят учителей».
Этот цикл изменений — часть естественного развития общества.
Го не принуждает, к сожалению. Обработку ошибок можно просто скипать. Вот в языках, где есть монады типа Result, тебе уже точно придется распаковать ее и проверить, что внутри — ошибка или результат. И придется обработать все.
Эх, предложили бы сразу монады Result и Maybe. И еще pattern matching с ними сразу бы завезли для их обработки красиво. А там и до Railway oriented programming рукой подать =)
Фактически, все, что десятилетиями изучается широкими массами в программировании, так или иначе создано опытными людьми, как компиляция их пройденного пути с набитыми шишками на поприще программирования.
И не важно, начнете ли вы читать «Совершенный код» Макконелла, «Рефакторинг» Фаулера, «Чистую архитектуру» дяди Боба или «Паттерны» от Банды четырех — все это передача ими эмпирического опыта в предметной области. Это не доказанные истины, не математически стройные и выверенные подходы. По большей части это укладывается в формулу: "я писал много-много лет, даже десятилетий, и кое-что понял, а то, что понял, хочу передать вам".
SOLID, YAGNI, DRY, KISS, DDD, TDD и так далее и тому подобное — все это инструменты, получившие широкую известность в профессии. Инструменты, которые стоит изучить, переняв опыт тех, кто это все собрал вместе и записал в красивые и запоминающиеся аббревиатуры.
А вот применять эти инструменты уже все учатся сами, и разумный баланс в своей работе, в своем проекте всех этих принципов, паттернов и подходов каждый находит исключительно сам.
Собственно, об этом сказано в заключительном слове в статье. Сектантство всегда плохо, догматизм того хуже. Ведь "только ситхи все возводят в абсолют". 😉
Не только в Python, но и в Clojure, которые теперь активно продвигает дядя Боб. Тот же Javascript. Все это уже используется активно в энтерпрайз разработке. Ну и если человек видит, что что-то имеет явное указание по соглашению, что это нельзя трогать (то же нижнее подчеркивание в начале название), но берет и игнорирует это, то вероятно такой разработчик в любом случае набедокурит в другом месте, если не в этом. Обратится к чему-то приватному, что обозначено, как приватное, можно только осознано. Если ты хотя бы базово знаком с конвенцией языка, на котором пишешь.
К тому же есть другие способы сокрытия. Через замыкания внутри тех же функций.
Тут хотелось бы спросить, а какие именно ограничения Java помогают совершать принципиально меньше ошибок? В случае с Haskell я бы мог понять такое утверждение, ведь не зря говорят "if a Haskell program compiles, it probably works". Его компилятор и система типов действительно делают нечто особенное по сравнению с большинством языков. Но Java?
Миллениалы изобрели процедурное программирование со всеми его недостатками.
Если в программе есть и процедурный и другие подходы - оно от этого так сильно хуже? Мы уже видели в виде классической Java через что приходится проходить и какие финты придумывать, чтобы существовать исключительно в чистом ОО мире. Когда нужно сделать какую-то не сложную вещь. К примеру, Go достаточно процедурный язык, что не делает его менее популярным в наше время. И его же за чем-то создали сейчас именно таким? При чем не глупые люди, которые явно знакомы со всеми парадигмами и подходами. Или набирающий популярность Rust, который тоже не является классическим ООП языком. Такие языки, как Питон - мультипарадигменные. Почему нужно боятся где-то написать процедурный код? Или ФП код? Кажется, что причин для этого нет, кроме предубеждений.
Поэтому разработчикам и остаётся писать конструкции c протоколами.
И в этом нет ничего плохого. Протоколы по сути те же интерфейсы. Прекрасно можно ими пользоваться в Питоне. А разговор начат с классов как раз по тому, что именно они в купе с наследованием и есть то самое классическое ООП, о котором идет речь. Есть ООП языки без классов и это не делает их менее ООП. Эталонного ООП просто не существует в настоящий момент. О чем речь тоже идет в статье. Есть разные вариации реализации этой идеи, но подходы могут серьезно отличаться.
И не надо пытаться сделать вид, что такая реализация ООП — это какое-то достоинство Питона.
Вроде ни кто и не пытался, не знаю, где это подается в таком виде. Такой мысли в статье не было.
Чем это будет удобнее? Объяснения нет.
Удобство заключается в том, что отсутствует сама проблема заранее точно определять кому и какое поведение принадлежит и с каким объектом оно должно ходить пришитым. А это частно далеко не самый тривиальный вопрос проектирования. В случае, когда это функция, которая работает с каким-то типом объекта согласно своей сигнатуре, рефакторинг, изменение и ее перемещение становится гораздо проще. Что и было показано в примере в статье. И в целом проще становится конструирование тех самых конвейеров из всех этих функций.
Любой, кто поработал хотя бы немного с ООП в JS, знает, что лучше бы там были обычное ООП и наследование.
Это просто холиварная тема. Как бы нет, не лучше:) И я оставил ссылку на статью, где даже есть подробно описанное мнение почему это так. И привел в пример React, где уже несколько лет никаких классов, наследования и все отлично. React в отличной форме. Можно даже сказать, что в лучшей из тех, что был.
Все аргументы сводятся к «оказывается, код можно как-то написать и без классов» и вырванным из контекста цитатам из авторитетов (причём, если тот же авторитет пишет что-то с чем вы не согласны, нужно обязательно добавить «ну это же было давно и неправда»).
Потому, как речь в целом изначально речь и идет о книгах и подходах, которые эти сами авторитеты и писали. И эти цитаты призваны показать, как менялось с годами их же мнение. Как они не боялись сказать, что в чем-то заблуждались и были где-то не правы. Или что-то переосмыслили. Если вы увидели где-то фразу, которую вырвали из контекста, то можете на нее указать. Когда я подбирал цитаты, то как минимум оставил ссылки на все оригиналы. Где можно прочитать указанные цитаты и мнения с полным контекстом, откуда они были взяты в статью.
Желательно, стараться операции I/O двигать к границам и группировать все в отдельные транзакционные функции. Там уже в ней происходит все необходимое.
Если мы говорим про последовательность шагов в рамках транзакции, то тут встает вопрос, а чего в ней больше - бизнес логики или инфраструктуры? По идее последовательность шагов в транзакции соответствует бизнес процессу. Что за чем сохраняем и как откатываем. Но в то же время мы используем низкоуровневую инфраструктуру для проведения транзакции. Тот же курсор. Так, что вероятнее лучше держать такие вещи на слое persistance, не перетягивая их в слой сервисов. Все-таки, хоть там и есть минимальная логика, но она только про работу с источниками и механизмами их отката. То есть по большей части связана с хранением данных, чем этот слой и занимается. Имя в таком случае лучше подбирать более сфокусировано на общем процессе :) update_post_and_add_comment_and_update_user_and_notify вполне может быть просто названа той причиной, почему эти действия объедены в одну транзакцию. К примеру handle_post_activity или process_post_interaction. Это так, навскидку. Для этого нужно в проекте выработать свою удобную всем конвенцию наименования. Собственно, я не называю этот слой именно репозиторием по двум причинам: во-первых, само определение, как должен быть реализован настоящий репозиторий часто вызывает некоторые холиварные споры, а во-вторых как раз по тому, что там может быть такая транзакционная работа.
В рамках работы нескольких последовательных операций с sql источником на самом деле все не так сложно. Несколько последовательных вызовов к базе группируются и работают с одним и тем же курсором в одной транзакции, если нужно обеспечить механизм rollback. Принимают его в качестве опционального параметра.
Ну, а для работы с другими источниками или серией вызовов для работы с разными источниками тут как и без репозитория приходится прописывать логику rollback уже как-то самому в зависимости от того, как можно откатить действие.
Есть варианты, к примеру, если мы работаем с серией вызовов к источнику sql и нужно сделать какой-то запрос по HTTP и в случае не успеха откатить все. Тогда все операции как раз можно обернуть в контекстный менеджер работы с базой и если HTTP часть завершится с ошибкой, то можно просто исключением прервать транзакцию и выйти из контекста инициировав в ней rollback. Соотвественно, если перед этим была какая-то логика отката по HTTP, то сначала выполняем ее.
Для разных источников sql можно сделать вложенные контекстные менеджеры. В общем большая часть проблем идентична проблемам работы с разнородными источниками и при других подходах.
Опять же, если стараться выдавливать операции I/O к границам, то для бизнес логики это все может оставаться так же абстрагированно.
Как я понял суть этой ветки разговора речь о том, когда пользователю кода не дают делать не хорошие вещи с объектами. И о ситуации, пользователи начинают обращаться к низкоуровневым полям, к которым они не должны обращаться. В общем случае с Питоном это просто решается добавлением нижних подчеркиваний в названия тех вещей, которые трогать не нужно. И это или соблюдается или нет. Добавили ли вы поведение в класс и сделали его методом. Или передали в функцию экземпляр класса, которая должна с ним работать. То, что трогать не желательно по задумке определения этой доменной сущности будет и в том и в том случае обозначатся одинаково в самом названии атрибутов. Соблюдать или игнорировать эту конвенцию можно при любом подходе.
Да, но это больше конвенция, чем реальная преграда. Для класса MyClass атрибут __myattr будет напрямую доступен просто через _MyClass__myattr. Это не говоря о всех тех непотребствах, которые можно натворить прямо в рантайме с помощью того же манки патчинга :)
На самом деле эта картинка намеренно такая "косожопая" вставлена, ведь она в тексте рядом с FizzBuzzEnterpriseEdition. Что как бы намекает, что такой подход порождает что-то подобное на этой картинке :)
На сколько я помню, когда я подавал статью "SOLID в Go и щепотка паттернов" на конкурс - это точно была не категория фронтенд :/ Может ошибка случилась тут при составлении списка шортлиста?
В армии я не только служил, но и прошёл путь от рядового срочной службы до офицера. Но в контексте данной статьи это было бы, в целом, абсолютно не обязательно. Сам принцип, его понимание и его применение к разработке вообще не имеют к этому никакого отношения. Поэтому попытка в «не служил — не мужик» не прошла, извините. Служил и много.
Где вы увидели, что что-то перекладывается на кого-то? Я тоже не понимаю.
Простите, но у меня складывается впечатление, что вы сами создаёте тезисы и сами их опровергаете.
Да и в целом получается какая-то абсолютная нестыковка. Если разработчик обязан следовать стандартам, которые устанавливает техлид, который, по вашим рассуждениям, должен делать то, что в статье, то как он будет соблюдать эти требования и стандарты, установленные ему, не понимая того, о чём эта статья? Он будет городить новые реализации в каждом пулреквесте, делать всё по-своему, и каждый раз техлид должен это вычитывать снова и снова, указывая лично, как нужно? А разработчик не будет учиться следовать этим стандартам и продолжит писать, как ему хочется, уже на следующей таске? Очень странная картина получается.
Да и вообще, если писать код — это творчество, только если «дикое поле и ворочу, что хочу» — само по себе странно. Тогда все эти линтеры, кодстайлы, сотни книг о том, как стоит писать код — все убивают творчество, получается? Творчество и отсутствие рамок и ориентиров вообще не связаны между собой. Творчество — это процесс создания чего-то нового само по себе. Вы созидаете, творите, сооздаете что-то новое и можете увидеть результат своего труда. Это и есть творчество, от слова творить. В живописи, в архитектуре, да, в любой творческой профессии есть свои правила, гайдлайны и ограничения. Инженер-конструктор, который разрабатывает новую модель самолета - творец не меньше разработчика ПО. Но у него есть жесткие регламенты и рамки, как ему все делать, документировать и проектировать. За границы стандартов можно выходить, раздвигать их, но когда это делают хорошие творцы и полностью осознанно, понимая, для чего и почему они отказываются соблюдать их в интересах своего нового творения. А выход за любые границы на постоянной основе — просто потому, что я вот такая снежинка, и если мне хоть чуть-чуть укажут, что есть какие-то стандарты, я расстроюсь и перестану чувствовать творчество — немного абсурдно.
А по поводу того, что высокое качество кодовой базы не нужно разработчикам — опять противоречие. Низкое качество кодовой базы ведёт к росту трудозатрат, как вы сами пишете. То есть, чтобы сделать то, что можно было бы сделать просто и быстро, вам приходится делать это сложно, дорого и больно. И с каждым годом такого подхода становится всё больше и больше. Да, вам за это платят, но какой интерес в том, чтобы внедрять фичи всё сложнее и сложнее, какой интерес в том, чтобы усложнять себе самому работу? Нет, может, кому-то нравится, что спустя пять лет такого развития проекта внедрение банальной фичи занимает не пару дней, а пару недель, с постоянным головняком и кучей лишней ментальной работы над кодом, который начинает рассыпаться от каждого чиха, и приходится всё это латать, держать в голове кучу ненужного контекста и так далее. Качественная кодовая база нужна разработчикам, чтобы их работа была спокойной, интересной и приятной. Бизнесу качество кодовой базы становится интересно только тогда, когда всё начинает сыпаться от багов, и фичи внедряются месяцами.
Я не знаю, почему вы так зацепились за фразу «у каждого проекта должен быть тот, кто заботится о нём душой». Можем перефразировать её как «хорошо, когда у проекта есть тот, кто заботится о нём душой». Теперь без этого слова «должен», но суть не меняется. Просто хорошо и приятно работать в проектах, где разработчики пишут их с душой, заботятся о качестве кодовой базы.
Качество кодовой базы — это то, что в первую очередь нужно самим разработчикам. Бизнесу и работодателю это просто не понять: они не профильные спецы в этом деле. И вы это делаете — работаете над качеством именно в рабочее время. Общаетесь с вашим работодателем, бизнес-заказчиком, и объясняете, что нужно провести такие технические работы, устранить такой-то техдолг, провести рефакторинг. Если работодатель категорически против и вообще не даёт на это времени, так как пилим бизнес-фичи и только бизнес-фичи, то вы уже пишете, как есть возможность. Но это уже повод задуматься: как долго вы хотите работать там, где техдолгом вообще не занимаются?
Просто поймите: из ваших сообщений складывается впечатление, что ваше предложение — просто писать по факту, чтобы бизнес-фича была готова, а техдолг и рефакторинг — для обманутых кровавым энтерпрайзом прослойки разработчиков, которых душу заставили продать вместе с кодом. А единственная цель и удовлетворение — срубить побольше бабла как можно раньше и уйти в закат, чтобы этот код больше не попадался вам на глаза. Тем, кто любит писать код — и не просто код, а хороший, качественный и поддерживаемый код, менеджеры и работодатели просто вдолбили это в мозги своими манипуляциями и внушением.
- Вам это, на самом деле, не нравится, как и мне, и не может нравиться! Просто я понял, как устроен этот мир, а вы ещё нет. Если по книге Лукьяненко, то если вы получаете удовольствие от работы по написанию кода, вы почти что ущербный.
Последнее предложение, грубо, конечно, но по вашему тексту получается фактически так.
Принцип «безобразно, но единообразно» как раз полностью согласуется с инженерной красотой. Если вы не можете по каким-то причинам добиться в коде единого, хорошего и лучшего подхода, то пусть он будет таким, каким он может быть в данный момент, но везде единообразным. И это вполне себе инженерная красота — единообразно написанный проект, который потом намного проще улучшить централизованным рефакторингом.
В общем, намечается бесконечный спор. В конечном итоге каждый выбирает, как ему работать. Но очень и очень не хотелось бы прийти на проект, который писали по принципу «фича сделана и славно, техдогом и рефакторингом мы тут не занимаемся, а уж о качестве кодовой базы тем более думать не собираемся». Вы или получаете удовольствие от процесса, или не получаете. А от этого дальше уже идёт расхождение взглядов на вопрос.
Тут уже пошла какая‑то философия о том, как мы подходим к тому, что делаем, и что значит для человека быть профессионалом своего дела. Кто‑то делает любое дело на совесть, как раз "вкладывая в него душу", так как хочет быть профессионалом и гордится тем, что создаёт. И даже если это просто красивое инженерное решение где‑то в глубине бэкенда, о котором ни кто, кроме него не узнает, такой специалист всё равно получит внутреннее удовлетворение от того, что смог создать что‑то настолько элегантное и нетривиальное, что ему самому будет просто хорошо – как раз на самой этой душе.
Исповедовать подход «задачу сделал и плевать, как сделал, для бизнеса всё‑равно - не проверят, а я, может, через полгода ещё раз работу сменю» для кого‑то может быть и путь, но вряд ли это то, что можно современным языком назвать «путь джедая». Почему сразу о сменить работу через пол года речь? Просто потому, что если разработчик планирует работать на проекте долго, 5-10 лет или даже больше, то в первую очередь делать все качественно и вкладывать душу в его же интересах. Ему этот код и дорабатывать и поддерживать спустя годы. Да и как расти над собой, в том числе как инженер или разработчик, если конечная цель только одна – «плевать, как сделал, задачу формально закрыл и забыл».
Наверное, тут фундаментальная разница ещё в том, как человек относится к своей работе как таковой. Если разработчик работает от звонка до звонка и в гробу видел вообще всё это, поскорее бы рабочий день подошёл к концу, то, наверное, это даже как‑то грустно. Не испытывать вообще никакого огонька, никакого желания сделать классно, красиво и по‑инженерному правильно, при этом не для кого‑то, а в первую очередь для себя – это или терминальная стадия выгорания, или, может, изначально не та выбранная стезя в жизни.
На появившийся постскриптум могу только дать комментарий: вся статья как раз о том, почему этот принцип можно применять и каким образом. Соответственно, даже и добавить нечего.
На самом деле, я не вижу тут противоречий. В первую очередь правильным является единство подходов в проекте, чему и посвящена статья. В ней прямо говорится о том, что нужно внедрять правильные подходы, но делать это следует продуманно.
К сожалению, у разработчиков слишком часто совершенно разное мнение о том, что является правильным, а что — нет. На эту тему я привожу в пример лекцию Мартина Фаулера "Software Design in the 21st Century". В ней он довольно красочно описывает, как дядя Боб, будучи рецензентом, высказывал ему: «Так писать код нельзя!»
О чем это говорит? Сегодня вы — техлид, которому передали этот проект. Вам кажется, что что-то сделано неправильно, и вы пишет новые фичи на свой лад. Завтра вы уволились, или проект передали другой команде, где новый техлид считает ваши решения неудачными и снова пишет новые фичи по своему. В итоге каждый учит и развивает свою команду, не выходя за рамки собственных представлений о правильности, а проект тем временем обрастает тремя разными подходами, между которыми команде приходится метаться туда-сюда.
Чтобы этого не происходило, и написана статья. Лучшее — враг хорошего. Иногда важно думать о гармоничном развитии проекта и его консистентности в более широком смысле. Уча сходу свою команду «правильному» подходу в таком проекте без обязательного рефакторинга старого кода на этот подход, вы фактически закладываете мысль, что параллельное сосуществование разных реализаций одних и тех же вещей в коде — это норма.
В общем, мне кажется, что суть статьи никоим образом не отрицает необходимость обучения команды хорошим практикам.
Есть ощущение, что периоды идиократии уже случались в прошлом. Это происходило даже в обществах, где люди умели считать в уме, знали стихи и обладали одним из самых передовых образований в мире. Тем не менее, половина страны заряжала банки с водой перед телевизором, а другая половина несли деньги в финансовые пирамиды вроде МММ. Казалось бы, качественное и фундаментальное образование должно было защитить общество от подобного мракобесия. Но реальность оказалась сложнее.
Подход к образованию действительно нуждается в переосмыслении. Большинство людей до сих пор учатся по шаблонам, разработанным веками назад. То, что происходит сейчас, — это не хорошо и не плохо, это просто перемены, требующие новых подходов. Главное в образовании — развивать у человека достаточное количество нейронных связей и стимулировать активную работу мозга, чтобы к зрелому возрасту он обладал развитым мышлением и был готов к интеграции в профессиональную среду.
Кстати, ещё Сократ говорил:
«Нынешняя молодежь привыкла к роскоши, она отличается дурными манерами, презирает авторитеты, не уважает старших, дети спорят со взрослыми, жадно глотают пищу, изводят учителей».
Этот цикл изменений — часть естественного развития общества.
Го не принуждает, к сожалению. Обработку ошибок можно просто скипать. Вот в языках, где есть монады типа Result, тебе уже точно придется распаковать ее и проверить, что внутри — ошибка или результат. И придется обработать все.
Эх, предложили бы сразу монады Result и Maybe. И еще pattern matching с ними сразу бы завезли для их обработки красиво. А там и до Railway oriented programming рукой подать =)
Да, именно так, спасибо. Поправил в тексте.
Да, именно так. В статье это как раз в таком виде и отражено - Принцип инверсии зависимостей (Dependency Inversion Principle). О чём именно речь?
Фактически, все, что десятилетиями изучается широкими массами в программировании, так или иначе создано опытными людьми, как компиляция их пройденного пути с набитыми шишками на поприще программирования.
И не важно, начнете ли вы читать «Совершенный код» Макконелла, «Рефакторинг» Фаулера, «Чистую архитектуру» дяди Боба или «Паттерны» от Банды четырех — все это передача ими эмпирического опыта в предметной области. Это не доказанные истины, не математически стройные и выверенные подходы. По большей части это укладывается в формулу: "я писал много-много лет, даже десятилетий, и кое-что понял, а то, что понял, хочу передать вам".
SOLID, YAGNI, DRY, KISS, DDD, TDD и так далее и тому подобное — все это инструменты, получившие широкую известность в профессии. Инструменты, которые стоит изучить, переняв опыт тех, кто это все собрал вместе и записал в красивые и запоминающиеся аббревиатуры.
А вот применять эти инструменты уже все учатся сами, и разумный баланс в своей работе, в своем проекте всех этих принципов, паттернов и подходов каждый находит исключительно сам.
Собственно, об этом сказано в заключительном слове в статье. Сектантство всегда плохо, догматизм того хуже. Ведь "только ситхи все возводят в абсолют". 😉
Прочитал и сразу вспомнил вот этот отрывок
https://youtube.com/shorts/p5hdkk8LycQ?si=X3fFlKi-DeLsZGsU
Не только в Python, но и в Clojure, которые теперь активно продвигает дядя Боб. Тот же Javascript. Все это уже используется активно в энтерпрайз разработке. Ну и если человек видит, что что-то имеет явное указание по соглашению, что это нельзя трогать (то же нижнее подчеркивание в начале название), но берет и игнорирует это, то вероятно такой разработчик в любом случае набедокурит в другом месте, если не в этом. Обратится к чему-то приватному, что обозначено, как приватное, можно только осознано. Если ты хотя бы базово знаком с конвенцией языка, на котором пишешь.
К тому же есть другие способы сокрытия. Через замыкания внутри тех же функций.
Тут хотелось бы спросить, а какие именно ограничения Java помогают совершать принципиально меньше ошибок? В случае с Haskell я бы мог понять такое утверждение, ведь не зря говорят "if a Haskell program compiles, it probably works". Его компилятор и система типов действительно делают нечто особенное по сравнению с большинством языков. Но Java?
Если в программе есть и процедурный и другие подходы - оно от этого так сильно хуже? Мы уже видели в виде классической Java через что приходится проходить и какие финты придумывать, чтобы существовать исключительно в чистом ОО мире. Когда нужно сделать какую-то не сложную вещь. К примеру, Go достаточно процедурный язык, что не делает его менее популярным в наше время. И его же за чем-то создали сейчас именно таким? При чем не глупые люди, которые явно знакомы со всеми парадигмами и подходами. Или набирающий популярность Rust, который тоже не является классическим ООП языком. Такие языки, как Питон - мультипарадигменные. Почему нужно боятся где-то написать процедурный код? Или ФП код? Кажется, что причин для этого нет, кроме предубеждений.
И в этом нет ничего плохого. Протоколы по сути те же интерфейсы. Прекрасно можно ими пользоваться в Питоне. А разговор начат с классов как раз по тому, что именно они в купе с наследованием и есть то самое классическое ООП, о котором идет речь. Есть ООП языки без классов и это не делает их менее ООП. Эталонного ООП просто не существует в настоящий момент. О чем речь тоже идет в статье. Есть разные вариации реализации этой идеи, но подходы могут серьезно отличаться.
Вроде ни кто и не пытался, не знаю, где это подается в таком виде. Такой мысли в статье не было.
Удобство заключается в том, что отсутствует сама проблема заранее точно определять кому и какое поведение принадлежит и с каким объектом оно должно ходить пришитым. А это частно далеко не самый тривиальный вопрос проектирования. В случае, когда это функция, которая работает с каким-то типом объекта согласно своей сигнатуре, рефакторинг, изменение и ее перемещение становится гораздо проще. Что и было показано в примере в статье. И в целом проще становится конструирование тех самых конвейеров из всех этих функций.
Это просто холиварная тема. Как бы нет, не лучше:) И я оставил ссылку на статью, где даже есть подробно описанное мнение почему это так. И привел в пример React, где уже несколько лет никаких классов, наследования и все отлично. React в отличной форме. Можно даже сказать, что в лучшей из тех, что был.
Потому, как речь в целом изначально речь и идет о книгах и подходах, которые эти сами авторитеты и писали. И эти цитаты призваны показать, как менялось с годами их же мнение. Как они не боялись сказать, что в чем-то заблуждались и были где-то не правы. Или что-то переосмыслили. Если вы увидели где-то фразу, которую вырвали из контекста, то можете на нее указать. Когда я подбирал цитаты, то как минимум оставил ссылки на все оригиналы. Где можно прочитать указанные цитаты и мнения с полным контекстом, откуда они были взяты в статью.
Желательно, стараться операции I/O двигать к границам и группировать все в отдельные транзакционные функции. Там уже в ней происходит все необходимое.
Если мы говорим про последовательность шагов в рамках транзакции, то тут встает вопрос, а чего в ней больше - бизнес логики или инфраструктуры? По идее последовательность шагов в транзакции соответствует бизнес процессу. Что за чем сохраняем и как откатываем. Но в то же время мы используем низкоуровневую инфраструктуру для проведения транзакции. Тот же курсор. Так, что вероятнее лучше держать такие вещи на слое persistance, не перетягивая их в слой сервисов. Все-таки, хоть там и есть минимальная логика, но она только про работу с источниками и механизмами их отката. То есть по большей части связана с хранением данных, чем этот слой и занимается. Имя в таком случае лучше подбирать более сфокусировано на общем процессе :) update_post_and_add_comment_and_update_user_and_notify вполне может быть просто названа той причиной, почему эти действия объедены в одну транзакцию. К примеру handle_post_activity или process_post_interaction. Это так, навскидку. Для этого нужно в проекте выработать свою удобную всем конвенцию наименования. Собственно, я не называю этот слой именно репозиторием по двум причинам: во-первых, само определение, как должен быть реализован настоящий репозиторий часто вызывает некоторые холиварные споры, а во-вторых как раз по тому, что там может быть такая транзакционная работа.
В рамках работы нескольких последовательных операций с sql источником на самом деле все не так сложно. Несколько последовательных вызовов к базе группируются и работают с одним и тем же курсором в одной транзакции, если нужно обеспечить механизм rollback. Принимают его в качестве опционального параметра.
Ну, а для работы с другими источниками или серией вызовов для работы с разными источниками тут как и без репозитория приходится прописывать логику rollback уже как-то самому в зависимости от того, как можно откатить действие.
Есть варианты, к примеру, если мы работаем с серией вызовов к источнику sql и нужно сделать какой-то запрос по HTTP и в случае не успеха откатить все. Тогда все операции как раз можно обернуть в контекстный менеджер работы с базой и если HTTP часть завершится с ошибкой, то можно просто исключением прервать транзакцию и выйти из контекста инициировав в ней rollback. Соотвественно, если перед этим была какая-то логика отката по HTTP, то сначала выполняем ее.
Для разных источников sql можно сделать вложенные контекстные менеджеры. В общем большая часть проблем идентична проблемам работы с разнородными источниками и при других подходах.
Опять же, если стараться выдавливать операции I/O к границам, то для бизнес логики это все может оставаться так же абстрагированно.
Как я понял суть этой ветки разговора речь о том, когда пользователю кода не дают делать не хорошие вещи с объектами. И о ситуации, пользователи начинают обращаться к низкоуровневым полям, к которым они не должны обращаться. В общем случае с Питоном это просто решается добавлением нижних подчеркиваний в названия тех вещей, которые трогать не нужно. И это или соблюдается или нет. Добавили ли вы поведение в класс и сделали его методом. Или передали в функцию экземпляр класса, которая должна с ним работать. То, что трогать не желательно по задумке определения этой доменной сущности будет и в том и в том случае обозначатся одинаково в самом названии атрибутов. Соблюдать или игнорировать эту конвенцию можно при любом подходе.
Да, но это больше конвенция, чем реальная преграда. Для класса MyClass атрибут __myattr будет напрямую доступен просто через _MyClass__myattr. Это не говоря о всех тех непотребствах, которые можно натворить прямо в рантайме с помощью того же манки патчинга :)
На самом деле эта картинка намеренно такая "косожопая" вставлена, ведь она в тексте рядом с FizzBuzzEnterpriseEdition. Что как бы намекает, что такой подход порождает что-то подобное на этой картинке :)