Comments 97
А вот шизокод часто остается безнаказанным, птм что его сложнее выявить и понять объем вреда от него.
Я бы заметил, что шизокод поощряется. Слишком часто логика работы программы теряется за необозримой иерархией классов и функций, которые были объявлены и написаны только потому, что "не более трех (пяти) строк на функцию" и "не более трех (пяти) методов на класс", а не исходя из назначения класса или функции.
Все-таки частенько многостраничная простыня одной функции понятнее мешанины кода, разбитого на функции только из соображений формальных количественных метрик.
Там где можно обойтись 1 классом Синглтоном — видишь вдруг наследования классов бесмысленных и беспощадных которые делаются 1 раз в рамках конкретной иерархии без переиспользования. И все их можно было бы без вреда соединить в 1 классе который решает свою задачу.
Там где можно обойтись 1-2 наследованиями — видишь 3-4 наследования из множества микроклассов.
Где то встречал фразу «не удачные абстракции». Но все ли одинаково поймут это )
Вот тут не понял. Хочется узнать личную оценку. Поощерение шизокода это хорошо или плохо?
Простыня всегда читается плохо. Но она всегда читается лучше бездумно разорванного на фрагменты кода. Это как большая книга одним свитком и она же, порванная случайно на одинаковые кусочки.
Все-таки разбиение кода на модули и функции должно обуславливаться исключительно логикой алгоритма, а не формальными требованиями. И если имеется логичный связный блок в десять строк, то не стоит его разрывать в угоду правила, требующего не более трех строк.
Логичный связанный блок на десять строк — да. А связанный блок на 300 строк — это кошмар. Если между первыми и последними строками есть связь — то пользоваться им невозможно. Поддерживать и дорабатывать крайне тяжело.
Какого реверса? Вы имеете ввиду Git reverse commit? Какая разница гиту? Да и сам юзкейс непонятен. Что это за коммит, который затронет 100 функций? Как часто вы это делаете? Зачем?
Моя текущая работа наполовину состоит из такого реверс-инжиниринга. Я бы предпочел 10 последовательных условно-чистых функций с читабельными именами. Но нет, 300 строк "подарка", с такими неадекватными ифами, что я, при необходимости небольшой доработки, через раз выкидываю и пишу заново.
Не потому, что понять нельзя — понять можно, "подарок" же. А потому что дерево выполнения огромно, нереально внести исправления так, что бы не было хитрых неучтенных побочных явлений. Ладно хоть код достаточно старый (часть его — десятилетней давности). Искренне надеюсь, что больше так никто не пишет.
А эти постулаты типа «метод должен быть не больше 20 строк» могут быть только пожеланиями, но никак не причиной реструктуризации кода на ровном месте. Разбиение программы на классы и методы в первую очередь должно быть подчинено логике самой программы, а не каким-то пожеланиям стилистическим.
Матеры разработчики это осознают благодаря эмпирическим знаниям.
Задача — найти некое описание, которое будет формализовано и понятно джунам/мидлам. Джуны как правило вообще не одупляют что почем. А мидлы часто буквально воспринимают рекомендации и начинают пилить 100500 функций на 3-4 строки и 55 классов с 1-2 методами — птм что так написано в библии Чистого кода.
Причем в РФ из за дефицита разработчиков часто мидлов и ставят сеньорами или тим лидами (из принципа — а лучше пока никого не нашли). Так и образуется рассадник шизокода, который спускается сверху теми кто до старшинства еще умом не дорос.
использование большого количества общих переменных
Именно так. 50 массивов — по одному на каждую колонку таблицы (зачем — уже не у кого спросить). Делать метод, куда передавать 10-20 массивов из этого набора — это закапывать себя ещё глубже. Часть мест поддерживаю, часть выкидываю, пишу заново.
Проекция «на себя» не работает — я пишу, мне всё понятно.
Проекция «на коллег» не работает — коллеги тоже могут оказаться теми еще извращенцами.
Проекция «на всех» не работает по очевидным причинам.
Писать «как принято» — опять же, не панацея. Потому что «как принято» может быть объективно плохо, и тогда с этим надо в меру возможностей бороться, а не вливаться.
Скажем если я в проекте на Symfony то буду писать с PSR, CamelCase & MVC (Model View Controller).
А если в проекте с WordPress, то буду писать в их стандарте с snake_case & EDA (Event Driven Architecture).
Те кто привык к MVC с трудом понимают EDA и наоборот. Хотя вроде бы язык один — php.
У каждой платформы свой стиль и своя архитектура, которую нужно понимать и придерживаться. Тогда внутри команды будет больше взаимопонимания.
Так, чтобы через год не плеваться от своего говнокода :-)) И если плеваться тянет — это хорошо!
Пункт 3 действительно, очень специфичный. И на первый взгляд вроде кажется правильным и логичным, но… для абстрактного кода в ваккууме. На самом деле нельзя классы/методы рассматривать вне контекста и задачи. Где-то и функция-портянка на 300 строк норм, а где-то классы на 2- 3 метода дадут гораздо больше профита.
Есть очень большая разница, когда ты просто решаешь конкретно поставленную задачу, с целью чтобы работало, и когда пишешь приложение/библиотеку которая должна поддерживать расширяемость и иметь определенную гибкость. Когда работаешь один, и когда работаешь в команде.
Переабстракция — это плохо. Особенно в языках не поддерживающих перегрузку. Но когда класс смешивает в себя кучу разной логики из разных кейсов и слоёв — это тоже не есть гуд. Лучше 10 небольших классов отвечающих за свои юз-кейсы и сферы взаимодействия, чем один супер-класс на все и вся… и, конечно же, обязательно синглтон.
Это понимание прийдёт с опытом и временем. SOLID, паттерны, чистый код — придуманы и написаны давным-давно. Но даже на 100 раз прочитав про них, на практике до них еще нужно дойти. (и да… это не панацея, иногда их можно и даже нужно нарушать :-) )
Думаю тут важный момент — бритва Оккама. Речь именно про нее :)
Это лучший из известных мне способов объяснить абстрактно про излишнюю абстрактность :) Но боюсь он не идеален и не всем понятен с наскоку.
Если взять бритву то далее есть две ситуации:
— пишем все в 1 классе до тех пор пока нет веских причин разбивать его на подклассы
— появилась веская причина? разбиваем класс на разные классы
Какие могут быть причины? Их много:
— основной класс стал слишком большим и не понятным
— нужно разбить код на шаблоны и логику
— нужно часть функционала переиспользовать в других классах
и т д
Но бывает что причина только одна… разработчику хочется уталить свою жажду красоты и показать что он знает что такое наследование… и вот мы получаем кучу бесполезных классов, наследований и лишних слоев абстракции…
Тема весьма спорная и в отрыве от конкретной ситуации сложна для обсуждения.
Конечно говнокодинг и хардкодинг встречаются чаще. Их и лечить проще.
Однако шизокодинг существенно дороже. Мы тут зацепились за идею с излишним наследованием. Что действительно редкое проявление шизокодинга. Но все же бывает.
Гораздо чаще встречается ситуация когда разработчики начинают свои костыли пилить (при условии наличия существующих методов), фреймворки, CMS или делать Интернет магазин/Блог на чистом Laravel. На мой взгляд причина одна и таже — разработчик не удосужился изучить существующие решения. И начал пилить велосипед. И это дорого. Очень дорого обходится бизнесу.
CMS или делать Интернет магазин/Блог на чистом Laravel
то есть по-вашему уже нет смысла разрабатывать блоги, cms и магазины, потому что всё уже давно придумано и написано?
Иногда действительно встречаются, мягко говоря, неудачные поделия… но в конце-концов, лучше уж на Laravel чем хардкод с нуля
для сайта я возьму WordPress. для магазина WooCommerce.
если мне надо написать какое то хитрое веб приложение — Laravel.
для API предпочту NodeJS или Go.
если что то системное то мб Python/Go.
тут мб куча факторов:
— мода на тот или иной фреймворк/язык
— компетенции команды
— адекватность инструмента задаче
Всегда приходится делать выбор исходя из множества факторов. Идеальных инструментов под все задачи пока не придумали.
С существующими решениями двойная ситуация: бизнесу может очень дорого обойтись изучение cсуществующих решений, особенно если в итоге будет принято решение писать-таки интернет магазин на чистом ларавеле. Ну или будет выбрана магента, разработчик потратит какое-то время на минимальное изучение, что-то сделает особо не вникая, в итоге будет криво, небезопасно и т. п., хотя на ларавеле было бы нормально, потому что разработчик его уже хорошо знает.
Но бывает что причина только одна… разработчику хочется уталить свою жажду красоты >и показать что он знает что такое наследование… и вот мы получаем кучу бесполезных >классов, наследований и лишних слоев абстракции…
Вот чего-чего, сколько разных архитектурных косяков и глупых решений я ни делала, но никогда не было мыслей воспользоваться наследованием (или каким-то паттерном) только для того чтобы показать какую-то красоту и то, что умею наследование (или какой-то паттерн). Мне кажется такое впечатление создается от того, что не возможно узнать в действительности почему и зачем так делалось… какие-то другие планы или изначальные требования, или недостаточное понимание требований разработчиком… Или просто ваше непонимание причин их использования.
Но это не точно )
Где-то и функция-портянка на 300 строк норм,
В случае php она никогда не норм. Всегда можно выделить какой-то независимый кусок с читаемым именем.
Некоторые языки позволяют сооружать совершенно страшные конструкции, в которых даже автор спустя время не сразу разберётся. Хотя при большом желании в любом языке можно накриптокодить.
Шизокодинг
Мыслетопливо
Похоже, принцип бритвы Оккама нарушен уже в самой статье, хотя и упоминается в ней)
2) и ПП, и ФП, и ООП позволяют создавать, или даже созданы для создания абстракций. Было бы желание, ООП тут не виноватое.
3) ООП было создано для уменьшения потребления «мыслетоплива» в процессе работы над конкретной задачей за счёт инкапсуляции. Грубо говоря, если в знакомом приложении для решения задачи нужно разбираться больше чем в трёх слоях наследования или композиции, значит или задача недостаточно декомпощирована, или инкапсуляции по сути нет.
Не очень понятно, что тут значит stateless, но синглтоны и статические методы обычно сильно усложняют понимание, тестирование и отладку. Основное разумное применение статических методов в PHP или реализация порождающих паттернов, или обход отсутствия автозагрузки функций. Всё остальное, обычно, обходится путями более пригодными для дальнейшей поддержки.
Это значит что класс не хранит состояние (переменные, константы и т д) и применяется только для инкапсуляции методов. Такой стиль часто встречается в WordPress (например некоторые классы в WooCommerce). Обе платформы №1 в своих сегментах. Ну и в некоторых закрытых Enterprise проектах такое встречал.
Сам часто пишу именно в этом стиле. Птм что он с одной стороны дает возможность быстро писать код на старте не думая о будущем, а с другой стороны потом быстро переходить в любой из стилей по необходимости: Синглтон, классы с наследование, ФП и т. д.
Это из моего опыта: Enterprise, eCommerce, веб-приложения… на разных платформах: flat php, Laravel/Symfony, WP/WooCommerce…
Идеальный мир условно достижим на MVC фреймворках типа Laravel/Symfony. Но это в теории. На практике серьезных проектов на их базе не встречал. Только API и простые микросервисы/веб приложения.
кгм… брать WordPress за образец...
Идеальный мир условно достижим на MVC фреймворках типа Laravel/Symfony. Но это в теории. На практике серьезных проектов на их базе не встречал
<_sarcasm>Действительно, какие могут быть серьёзные проекты на Laravel и Symfony… весь мир ведь вертится вокруг вордпресс… </_sarcasm>
После этих строчек стало всё понятно :-) Вам предстоит еще долгий путь
Глобальное потепление — это плохо.
Мой манифест простой:
- давайте меньше глобальное потепление
Не совсем понятно, о чем статья. На выбранный стиль изложения можно было бы закрыть глаза, но я не увидел основного — предложенного решения названной проблемы. По сути проблема названа абстрактная, а в ней — возможные причины, с которыми и можно было бы согласиться, но не в предлагаемой формулировке. Например, точно НЕ в такой:
В функциональном стиле проще наговнокодить, но шизокодить там сложно.
На мой взгляд, все описанные в статье проблемы с кодом так или иначе можно объяснить одним — допущением их существования разработчиком, который этот код писал. Решаться, следовательно, они должны через создание препятствий, которые будут «мешать» разработчику идти на подобные допущения. Опускаю случаи, когда наличие упомянутых проблем может быть в определенной степени оправдано:
— недостатком квалификации, обусловленный отсутствием опыта, а не слабоумием
— недостатком ресурсов (время/деньги), потому что чистый код — это хорошо, но порой решение нужно уже вчера
В остальных же случаях:
— проблема «хардкода» и нарушений стиля решается через применение практики code review с соответствующими требованиями к тем, кто их проводит
— «тем больше точек отказа, тем больше ошибок» — через применение практики непрерывной интеграции; при этом важно не просто наличие тестов как таковых, а наиболее полное покрытие кода, которое позволило бы выявлять неочевидные ошибки
— переизбыток/недостаток абстракций, проблемы с архитектурой — зависят от опыта конкретного разработчика на конкретной должности; решения для общего случая, на мой взгляд, нет
Во всех случаях в целом, особенно в последнем, проблемы нередко могут совершаться из-за наличия уже существующих, появившихся из-за неверно принятых решений в прошлом. В итоге их количество растет подобно снежному кому, потому что сделать «не идеально» получается правильнее (в контексте ограниченных ресурсов), чем менять архитектуру и переписывать все с нуля.
Суть манифеста, думаю, я понял, просто вместо простого перечисления проблем хотелось бы слышать:
— с предложением решений называемой проблемы
— без лексики, пригодной для «курилки»
— с логическими рассуждениями, когда в конкретном стиле чаще встречаются ошибки по конкретным причинам, а не «просто потому что»
пишут собственные CMS/фреймворки
то есть любая новая cms или фреймворк — зло?
думаю ничто не зло в абсолютном выражении. везде есть частичка добра )
но я встречался с проектами на своих CMS/фреймворках, где 80% времени приходилось тратить на угадывание логики ее авторов. а это не просто и очень дорого )
потому для себя решил что лучше буду работать с каким то платформами из топ-3, а лучше топ-1 )
это смотря с какой стороны посмотреть :)
и
Решил что природа этого заболевания та же самая что и желание разработчиков писать свои CMS/фреймворки )
нужно как то определится, либо частичка добра, либо заболевание…
нужно как то определится, либо частичка добра, либо заболевание
Про CMS не скажу, но фреймворки обычно пишутся, для того что бы кто то другой мог переиспользовать какую то часть кода под себя. По факту, если вы не будете заниматься продвижением своего фреймворка, о нем никто не узнает и никто кроме вас его использовать не будет. Смысл тратить время?
У вас другой опыт написания фреймворков?
Нет, не подразумевается. Подразумевается, что сейчас мы вложимся в создание/развитие фреймворка, зато следующие проекты будем делать быстрее. Инвестиции типа.
Подразумевается, что сейчас мы вложимся в создание/развитие фреймворка, зато следующие проекты будем делать быстрее. Инвестиции типа.
Какой процент инвестиций по факту отбили?
зато следующие проекты будем делать быстрее
Откуда вы знаете, какие задачи вам нужно будет решать завтра? Вы же не делаете одно и тоже. Может задачи завтрашнего дня, лучше решать завтра? Хотя бы будет известно, что нужно сделать, плюс завтра у вас будет больше опыта и вы сможете подобрать лучшее решение, чем сегодня?
По хорошему свой фреймворк не должен решать задачи завтрашнего дня. Он должен аккумулировать удачные решения задач вчерашних, и иногда внедрять сегодняшних.
При этом я не утверждаю, что фреймворки это зло, никогда так не делайте. Я говорю делайте это только когда это что то дает.
Библиотека для логирования, это всего лишь библиотека, она ничего не ограничивает и не имеет каркаса, но например реализация патерна dependency injection, это фреймворк, потому появляются ограничения на формат кода.
так же см ответ
С другой стороны плохо простой код разбивать на 5 классов в каждом из которых 3-4 метода по 3-4 строки, со множеством бесполезных наследований, когда можно обойтись одним или двумя с минимальным наследованием или даже без наследования если его можно избежать.А что в этом плохого, если класс и методы выполняют ровно то что и должны?
Можно разбить класс на 10 методов, главное интерфейсы не перегружать, а если методы непонятно названы, и тебе нужно переходить в метод чтобы понять что он делает, тогда вопрос к автору кода, а это уже другая история.
Понятный и поддерживаемый код это когда в команде разрабоки 80% его понимают, всегда найдутся те кому чужой код говно.
Ключевое слово — излишество. Когда можно обойтись без наследования — надо обойтись без него. Птм что лишний слой абстракции — это нарушение бритвы Оккама. И там много негативных последствий.
Речь не о том что наследование это абсолютное зло и плохо. А о ситуации когда оно делается без причины. Если не встречались с таким — бамбалейо. Поздравлямба и все такое. Все впереди )
вернемся чуть дальше — а там стоит менеджмент, и очень часто в развивающейся компании нужно срочно вносить некоторые изменения, одни критичны для стабильной работы, другие — не очень, но задевают несколько мест программы\логики\етс., в таких условиях нужно чтобы работало, тупо чтобы работало, и побыстрей, никому из выше стоящих не интересна чистота кода, я уже не говорю про стартапы, где лепится черт и что, куча логик, по многу раз переделывается, лишь таск «рефакторинг» где-то в будущем даст время привести все в порядок.
И список нормальных языков для Web.
Сейчас, к счастью, ситуация с языками для веб гораздо лучше. Есть отличные языки шаблонов (и, главное, быстрые парсеры), например, шаблоны в Django (и его расширение Jinja2, для которого есть поддержка не только в Python). Для легких случаев есть Mustache.
Насчет замены PHP как языка для веб-бэкэнда: Python (Django, aiohttp), JavaScript (он ужасен, но nodejs сделал из него хороший инструмент для «херак-херак и в продакшен»), Java (главное, не тащить J2EE-стэк — сейчас есть хорошие легковесные фреймворки), функциональные языки (много разных вариантов на выбор).
По поводу PHP. Это инструмент который позволяет относительно быстро (быстрее чем Perl) обучиться и начать писать работающий код. Качество кода напрямую зависит от самого программиста и культуры разработки в коллективе где он работает. Можно и на строго типизированном языке говнокод написать.
Вообще же выбор языка как инструмента очень важен.
Объясните его минусы по сравнению с другими распространенными языками для wеb программирования. И сразу можно указывать минусы тех языков, по сравнению с PHP.
- Простота входа в язык и разработку. Чем проще, тем хуже, т.к. простой вход позволяет начать кодить, не особо разбираясь в разработке вообще. Как результат, большое количество чужого ужасного кода, с которым приходится работать. Это про разработку больших систем. С точки зрения быстрой разработки странички, которую никто никогда не будет поддерживать и повторно использовать, быстрый вход как раз плюс, но это не моя ниша.
PHP в этом плане слишком простой, что привело к появлению огромного количества недо-библиотек и недо-фреймворков, использование которых заставляет страдать. То же самое можно сказать о легаси-коде, которого в больших системах много.
На Java гораздо сложнее начать писать, и код на Java гораздо лучше (в среднем), чем код на PHP — я говорю про чужой код, который приходится поддерживать в больших системах. Свой код никто не мешает писать хорошо на любом языке.
Python тоже довольно прост, но, в отличие от PHP, его синтаксис изначально хорошо продуман и элегантен. Это приводит к тому, что на Python можно научиться писать быстро сразу хорошо. Да, разумеется, плохой код на Python тоже имеется (в больших системах), но его на порядки меньше. Т.е. вот если на PHP хороший код встречается как исключение, то на Python скорее наоборот — иногда встречается говнокод среди вполне годного кода. (Субъективно, без количественных метрик.)
- Базовые принципы языка. Язык создается на основе каких-то принципов, также язык создается человеком (группой людей), у которго есть определенные ценности и характер, что влияет на результат. PHP был создан, как я уже писал, как удобная замена Perl и SSI. С этой ролью он отлично справлялся (после того, как я первый раз увидел PHP, я больше ни разу не писал веб на Perl и SSI, это был настоящий прорыв). Стандартную библиотеку PHP наполняли стихийно — понадобилась функция, добавили. Там было (и есть?) много близких функций с разной нотацией. Потом стали добавлять объекты и классы, потом переделали, потом… (потом я ушел на Python, так что 6-ую версию уже не застал). В итоге (с учётом п.1) на PHP каждый писал и пишет, кто во что горазд. Язык не настаивает на том, какой должен быть код, как должны быть структурированы модули (и нужны ли они вообще) и т.п. Позже эти принципы были добавлены, но они не жесткие, поэтому для простоты и быстроты от них отказываются. Дополнительные проблемы создает динамическая типизация, которая в PHP рождает много проблем на этапе отладки. Результат: много плохого кода.
Java в этом плане дает гораздо меньше свободы. Плюс статическая типизация обнаруживает много тупых ошибок на этапе компиляции, а не в продакшене. Плюс принципы ООП, которые можно нарушить, но это настолько не удобно, что для этого нужна некоторая квалификация, что снижает вероятность ошибок (см. п. 1). Java не делали, чтобы можно было быстро лабать странички, её создавали для упрощения ООП-разработки (по-сравнению с C++, у которого достаточно высокий порог входа) и дальнейшего развертывания кода.
Python был создан, чтобы програмировать снова было в кайф. Базовые принципы языка Python таковы, чтобы на нем было удобно программировать. На нём просто писать хорошо. В Python так же хорошо реализованые такие аспекты языка, как динамическая типизация (она немного строже, чем в PHP, и ошибок, с ней связанных, меньше), встроенные типы (нет с ними путаницы), функциональные возможности. Это привлекает в Python-сообщество квалифицированных программистов, которые пишут хороший код.
Использование грамотно спроектированных и разработанных фреймворков во многом спасает ситуацию. В PHP они, вероятно, тоже есть. (Автор статьи положительно пишет о Wordpress, но говорить так, можно лишь сравненивая с другими PHP-фреймворками, продуктами и библиотеками. Остальные хуже, но Wordpress — это тоже адово адище, если сравнивать с действительно нормальными, например, Django. Я соглашусь, что не вполне корректно сравнивать пакетный продукт и фреймворк для разработки. В данном случае я говорю о Wordpress как о стартовом пакете для дальнейшей разработки продукта.)
Мой собственный опыт таков, что стоило мне уйти с PHP на Python, как количество головной боли в моей жизни, рожденной чужим кодом, с которым я должен дружить, стало исчезающе малым. Прямо волшебство.
Ну а на Java, после того, как туда добавили дженерики и функциональщину, асинхронность и пр., после того как программисты наелись корявым EE и паттернами разработки, а также посмотрели, как может быть коротко, просто и ясно на других языках, на Java стало гораздо приятней писать.
Сравнивать PHP и Java это как сравнивать разговорный язык, и язык делегатов какого-нибудь математического симпозиума.
Вы сможете переписать простой «Hello world» блог на Wordpress на Java? Не на JSP, потому что это не Java, а на сервлетах. Просто представьте, как вы это делаете, и в добрый путь.
Язык определяет, какой код и как он будет написан. Также он косвенно определяет, кто будет на нём писать. Условно сравнивая с человеческими языками, можно говорить на языке из трёх матерных слов и вполне выражать всё, что нужно в повседневной жизни, но если посмотреть, какое окружение будет вокруг этого языка и кто будет на нём говорить, я бы в таком окружении жить не захотел.
Про ваш вопрос о простом блоге на Java: если говорить просто о блоге — да, это простая задача, не вижу ничего сложного (без JSP и даже сервлетов, хоть они и часть стандартного Java EE, просто есть лучшие варианты как для ядра, так и для frontend — можно даже вообще без серверных шаблонов обойтись). Если же говорить о переписывании Wordpress как о платформе, да, это задача сложная, но дело не в Java или PHP, а в сложности сделать архитектуру платформы хорошей (скопировать архитектуру Wordpress на любом языке — дурная идея).
Кстати, в мире PHP код и архитектура Wordpress, наверное самого успешного продукта на PHP, считается каноническим образцом как не надо писать серьёзные продукты :)
Может глянете несколько минут на, например, github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpKernel/HttpKernel.php?
Выбор не всегда остается за разработчиком. Бывают большие проекты с дурно пахнущим кодом, с которым приходится взаимодействовать.
HttpKernel.php посмотрел.
Выбор всегда остаётся за разработчиком. Большие проекты с дурно пахнущим кодом бывают, да, но вот работать с ними или нет — выбор разработчика.
Похоже это на тот PHP-код от которого вас воротит?
Выбор, согласен, в конце-концов остается за разработчиком — если что-то не устраивает, всегда можно сменить проект, компанию, клиентов и т.п. Рынок пока еще позволяет.
Код HttpKernel аккуратный и на первый взгляд неплох. Но потом в конце класса мы видим
private function varToString($var): string
{
if (\is_object($var)) {
return sprintf('an object of type %s', \get_class($var));
}
...
}
Стоп, что это делает в коде Http ядра и используется один единственный раз для вывода сообщения об ошибке?
Функцию явно добавили «по-быстрому» (к хорошей архитектуре она отношения не имеет), поэтому смотрим туда, где её вызывают:
$event = new GetResponseForControllerResultEvent($this, $request, $type, $response);
$this->dispatcher->dispatch(KernelEvents::VIEW, $event);
if ($event->hasResponse()) {
$response = $event->getResponse();
} else {
$msg = sprintf('The controller must return a "Symfony\Component\HttpFoundation\Response" object but it returned %s.', $this->varToString($response));
// the user may have forgotten to return something
if (null === $response) {
$msg .= ' Did you forget to add a return statement somewhere in your controller?';
}
throw new ControllerDoesNotReturnResponseException($msg, $controller, __FILE__, __LINE__ - 17);
}
И видим неявное изменение переменной $event, внутри dispatch(). Окружение мало говорит о том, что там в $event могли поменять (мы видим только то, что проверяется дальше). Более того, сам факт того, что объект «событие» подлежит изменению, также говорит о проблеме в архитектуре. Тут внутрь события засунут еще и response.
Но вижу в коде и хорошее — если response не установлен, фреймворк напомнит разработчику о том, что он нужен. Фреймворк знает, что он достаточно сложен и не очень хорошо спроектирован, чтобы у разработчика была возможность не сделать обязательное действие, но старается это исправить (ок, хотя бы так).
Но что это? Посмотрите на параметры ControllerDoesNotReturnResponseException():
__LINE__ - 17
Почему именно 17? Смотрим коммит "[HttpKernel] Better exception page when the controller returns nothing", в котором это было добавлено. Есть даже тест, хорошо.
// `file` index the array starting at 0, and __FILE__ starts at 1
$line = file($first['file'])[$first['line'] - 1];
$this->assertContains('call_user_func_array', $line);
Ага, автор кода брал определенную (эмпирически определенную) строчку из стэктрейса, но даже коммента не оставил, почему именно -17.
Последнее на что смотрим: коммиты автора кода "-17". 21 его коммит из 34-х (что я вижу на первой странице) привели к падению тестов в среде continuous integration проекта (уже не полезу смотреть детали).
А как по-вашему, хороший фреймфорк Symphony?
Неявное изменение event в Symfony — скорее не проблема, а особенность архитектуры. Эти события не предназначены для бизнес-логики, а на них построена собственно архитектура фреймворка, в частности любой обработчик события может добавить к нему что-то или прекратить дальнейшую обработку остальными обработчиками. Можно сказать, что это альтернатива мидлварному подходу, в чём-то более удобная, в чём-то менее.
И да, я считаю Symfony хорошим фреймворком, удачно балансирующим на грани академической правильности и практического удобства использования.
Спасибо за уделенное время.
Не хочу критиковать архитектуру Symphony, т.к. толком с ней не знаком, но когда используется общий принцип/вызов передачи сообщений для совершенно различных операций над объектами (как, например, прокинуть какие-то параметры через универсальный изменяемый объект-событие), затрудняется еще и поиск кода, который такие изменения делает (т.к. все участники делают однотипные вызовы с примерно похожими параметрами). И одно дело, если это что-то вроде протокола шины обмена сообщениями (который сверху обернут в более высокоуровневый протокол с методами/функциями, названия которых говорят о совершаемом действии), и другое, если это основной способ общения между объектами в архитектуре приложения. Я сейчас такую проблему вижу в Django Channels — фреймворке-надстройке над Django, который добавляет в него асинхронности (слишком просто всё делать через channel.send(message), к счастью, содержимое message никто не меняет).
В общем, всё сложно, и особенно сложно сделать всё хорошо :)
Спасибо за разговор.
Похоже это на тот PHP-код от которого вас воротит?
Да, это он.
Не хочу сказать ничего плохого про автора коммита, о котором я написал выше. Возможно, его код не так уж плох. Возможно, дело в архитектуре Symphony.
- Блог на Symfony. При том что весь мир для этого использует WordPress.
- Интернет-магазины на Laravel, при том что есть WooCommerce (№1 в мире), Magento (тоже хорошо), 1С-Битрикс (на худой конец, лучше чем Laravel)
Полный бред, выглядит как реклама WordPress.
Стиль написания какой бы он ни был в моем понятии не делает код Говнокодом.
А вот излившее усложнение кода очень даже.
Но кроме усложнения могут быть наверное еще признаки говнокода (тут надо подумать).
2) Есть такой принцип Кiss.(делай это как можно проще). В википедии при описании его приведены цитаты нескольких известных людей и они тоже подходят как илюстрация к теме данной статьи. При этом идея несколько шире чем принцип Оккамы( Не плоди лишних сущностей).
Например, прослойка между сторонним фраймворком и проектом, состоящую из пустых классов, это плохо или нет? Дополнительная обстракция, но может сэкономить кучу нервов при срочном апдейте.
С его костылированием, инкостыляцией, поликостылизьмом.
часто мне хватает Синглтоночасто мне хватает Синглтонов, статических методов и statelessв, статических методов и stateless
Синглтон — антипаттерн, статические методы — то ещё зло, и использовать их стоит разве что для альтернативных конструкторов. В авторе заметен большой поклонник Wordpress (который в плане кода является идеальным примером того, как не надо делать).
На самом деле очень хорошая статья, и действительно отражающая реалии из жизни команды программистов. Грехи эти имеют место быть, особенно у начинающих программистов.
Не понимаю за что ее заминусовали, отличная статья, часто кидаю ссылку на нее.
3 греха программиста: Хардкодинг, Говнокодинг и Шизокодинг