Pull to refresh

Comments 97

А вот шизокод часто остается безнаказанным, птм что его сложнее выявить и понять объем вреда от него.

Я бы заметил, что шизокод поощряется. Слишком часто логика работы программы теряется за необозримой иерархией классов и функций, которые были объявлены и написаны только потому, что "не более трех (пяти) строк на функцию" и "не более трех (пяти) методов на класс", а не исходя из назначения класса или функции.
Все-таки частенько многостраничная простыня одной функции понятнее мешанины кода, разбитого на функции только из соображений формальных количественных метрик.

Вроде бы мы в одном русле мыслим. Речь именно про проблему множественной иерархии классов.
Там где можно обойтись 1 классом Синглтоном — видишь вдруг наследования классов бесмысленных и беспощадных которые делаются 1 раз в рамках конкретной иерархии без переиспользования. И все их можно было бы без вреда соединить в 1 классе который решает свою задачу.
Там где можно обойтись 1-2 наследованиями — видишь 3-4 наследования из множества микроклассов.
Где то встречал фразу «не удачные абстракции». Но все ли одинаково поймут это )
> Я бы заметил, что шизокод поощряется
Вот тут не понял. Хочется узнать личную оценку. Поощерение шизокода это хорошо или плохо?

Поощрение шизокода — это плохо.
Все-таки бездумное строгое следование формальным метрикам до добра не доводит, особенно если граница допустимого очень занижена (три строки на функцию, как рекомендуют (а порой и требуют) некоторые — как-то маловато будет).

UFO just landed and posted this here

Простыня всегда читается плохо. Но она всегда читается лучше бездумно разорванного на фрагменты кода. Это как большая книга одним свитком и она же, порванная случайно на одинаковые кусочки.
Все-таки разбиение кода на модули и функции должно обуславливаться исключительно логикой алгоритма, а не формальными требованиями. И если имеется логичный связный блок в десять строк, то не стоит его разрывать в угоду правила, требующего не более трех строк.

Логичный связанный блок на десять строк — да. А связанный блок на 300 строк — это кошмар. Если между первыми и последними строками есть связь — то пользоваться им невозможно. Поддерживать и дорабатывать крайне тяжело.

Зато в случае реверса одна функция на 300 строк — подарок, 100 функция по 5 строк (в сумме уже не 300, и это без учёта заголовка) — наказание.

Какого реверса? Вы имеете ввиду Git reverse commit? Какая разница гиту? Да и сам юзкейс непонятен. Что это за коммит, который затронет 100 функций? Как часто вы это делаете? Зачем?

Я имею в виду что зачастую нужен реверс-инжиниринг. Это в теории или на сайтиках проще выкинуть, а иногда нужно разобраться как оно работает, имея крайне ограниченный набор (типа исходников после обфускации). Да, это не часто, но бывает. Не всем интересны задачи «наляпать во фреймворке формочек», это выглядит как точить одни и те же гайки на конвейере.

Моя текущая работа наполовину состоит из такого реверс-инжиниринга. Я бы предпочел 10 последовательных условно-чистых функций с читабельными именами. Но нет, 300 строк "подарка", с такими неадекватными ифами, что я, при необходимости небольшой доработки, через раз выкидываю и пишу заново.


Не потому, что понять нельзя — понять можно, "подарок" же. А потому что дерево выполнения огромно, нереально внести исправления так, что бы не было хитрых неучтенных побочных явлений. Ладно хоть код достаточно старый (часть его — десятилетней давности). Искренне надеюсь, что больше так никто не пишет.

Учитывая "типа исходников после обфускации" про "функций с читабельными именами" можно не мечтать.

Интерфйсы и экспортируемые функции рулят — там имена хоть вменяемые и служат отправными точками. В остальном «спасибо, что не машинный код».
Сложно представить неделимый монолит на 300 строк. Такое иногда случается, но всегда можно что-то вынести за скобки, даже если за этим не стоит никакой логики. Например, редко редактируемый фрагмент какой-то просто убрать в другой метод чтобы не мешался и не заставлял скроллить. Самым большим препятствием этому может служить использование большого количества общих переменных этой простыни и придется их большим списком в этот метод передавать и списком же возвращать.

А эти постулаты типа «метод должен быть не больше 20 строк» могут быть только пожеланиями, но никак не причиной реструктуризации кода на ровном месте. Разбиение программы на классы и методы в первую очередь должно быть подчинено логике самой программы, а не каким-то пожеланиям стилистическим.
Готов согласиться. Проблема только в том что есть логика программы и здравый смысл?

Матеры разработчики это осознают благодаря эмпирическим знаниям.

Задача — найти некое описание, которое будет формализовано и понятно джунам/мидлам. Джуны как правило вообще не одупляют что почем. А мидлы часто буквально воспринимают рекомендации и начинают пилить 100500 функций на 3-4 строки и 55 классов с 1-2 методами — птм что так написано в библии Чистого кода.

Причем в РФ из за дефицита разработчиков часто мидлов и ставят сеньорами или тим лидами (из принципа — а лучше пока никого не нашли). Так и образуется рассадник шизокода, который спускается сверху теми кто до старшинства еще умом не дорос.
Тут такое. Если отпимально иметь один класс на 10 методов по 30 строк, то обычно гораздо лучше иметь 10 классов по 10 методов по 4 строки каждый, чем один класс с одним методом на 300 строк.
использование большого количества общих переменных

Именно так. 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 чем хардкод с нуля

на мой взгляд — надо применять паттерн Best of breed.
для сайта я возьму WordPress. для магазина WooCommerce.
если мне надо написать какое то хитрое веб приложение — Laravel.
для API предпочту NodeJS или Go.
если что то системное то мб Python/Go.

тут мб куча факторов:
— мода на тот или иной фреймворк/язык
— компетенции команды
— адекватность инструмента задаче

Всегда приходится делать выбор исходя из множества факторов. Идеальных инструментов под все задачи пока не придумали.
Может и не происходить, это может быть задел на будущее. Точнее, если произошёл, то убиравший просто ошибочно принял нужный код за лишний.

С существующими решениями двойная ситуация: бизнесу может очень дорого обойтись изучение cсуществующих решений, особенно если в итоге будет принято решение писать-таки интернет магазин на чистом ларавеле. Ну или будет выбрана магента, разработчик потратит какое-то время на минимальное изучение, что-то сделает особо не вникая, в итоге будет криво, небезопасно и т. п., хотя на ларавеле было бы нормально, потому что разработчик его уже хорошо знает.
Но бывает что причина только одна… разработчику хочется уталить свою жажду красоты >и показать что он знает что такое наследование… и вот мы получаем кучу бесполезных >классов, наследований и лишних слоев абстракции…

Вот чего-чего, сколько разных архитектурных косяков и глупых решений я ни делала, но никогда не было мыслей воспользоваться наследованием (или каким-то паттерном) только для того чтобы показать какую-то красоту и то, что умею наследование (или какой-то паттерн). Мне кажется такое впечатление создается от того, что не возможно узнать в действительности почему и зачем так делалось… какие-то другие планы или изначальные требования, или недостаточное понимание требований разработчиком… Или просто ваше непонимание причин их использования.

Везунчик. Я тоже до последнего времени страдал только от Говнокода и Хардкода. Но оно было не так затратно. А вот Шизокод долго не мог осознать. Ну а его проявление в куче классов пока что встретил лишь 1 раз. Но подумалось что причина та же самая… отсутствие желания у разработчика следовать стандартам и лучшим практикам, использованию существующих методов и функций, а вместо этого написать 10 своих классов и потом раскидать их по всей системе через 3-4 наследования в каждом. Насчитал более 300 строк кода и более 10 классов, которые можно было уместить в 3-4 строки кода и уже существующие методы внутри платформы. Решил что природа этого заболевания та же самая что и желание разработчиков писать свои CMS/фреймворки )
Но это не точно )
Где-то и функция-портянка на 300 строк норм,

В случае php она никогда не норм. Всегда можно выделить какой-то независимый кусок с читаемым именем.

Можно ещё выделить разновидность шизокодинга — криптокодинг.
Некоторые языки позволяют сооружать совершенно страшные конструкции, в которых даже автор спустя время не сразу разберётся. Хотя при большом желании в любом языке можно накриптокодить.
Шизокодинг
Мыслетопливо

Похоже, принцип бритвы Оккама нарушен уже в самой статье, хотя и упоминается в ней)

1) видимо имелось процедурное программирование, а не функциональное. Слово function PHP оно про процедурное прежде всего.
2) и ПП, и ФП, и ООП позволяют создавать, или даже созданы для создания абстракций. Было бы желание, ООП тут не виноватое.
3) ООП было создано для уменьшения потребления «мыслетоплива» в процессе работы над конкретной задачей за счёт инкапсуляции. Грубо говоря, если в знакомом приложении для решения задачи нужно разбираться больше чем в трёх слоях наследования или композиции, значит или задача недостаточно декомпощирована, или инкапсуляции по сути нет.
4) но часто мне хватает Синглтонов, статических методов и stateless

Не очень понятно, что тут значит stateless, но синглтоны и статические методы обычно сильно усложняют понимание, тестирование и отладку. Основное разумное применение статических методов в PHP или реализация порождающих паттернов, или обход отсутствия автозагрузки функций. Всё остальное, обычно, обходится путями более пригодными для дальнейшей поддержки.
> Не очень понятно, что тут значит stateless
Это значит что класс не хранит состояние (переменные, константы и т д) и применяется только для инкапсуляции методов. Такой стиль часто встречается в WordPress (например некоторые классы в WooCommerce). Обе платформы №1 в своих сегментах. Ну и в некоторых закрытых Enterprise проектах такое встречал.

Сам часто пишу именно в этом стиле. Птм что он с одной стороны дает возможность быстро писать код на старте не думая о будущем, а с другой стороны потом быстро переходить в любой из стилей по необходимости: Синглтон, классы с наследование, ФП и т. д.

Это из моего опыта: Enterprise, eCommerce, веб-приложения… на разных платформах: flat php, Laravel/Symfony, WP/WooCommerce…

Идеальный мир условно достижим на MVC фреймворках типа Laravel/Symfony. Но это в теории. На практике серьезных проектов на их базе не встречал. Только API и простые микросервисы/веб приложения.

кгм… брать WordPress за образец...


Идеальный мир условно достижим на MVC фреймворках типа Laravel/Symfony. Но это в теории. На практике серьезных проектов на их базе не встречал

<_sarcasm>Действительно, какие могут быть серьёзные проекты на Laravel и Symfony… весь мир ведь вертится вокруг вордпресс… </_sarcasm>

После этих строчек стало всё понятно :-) Вам предстоит еще долгий путь

> После этих строчек стало всё понятно :-) Вам предстоит еще долгий путь

дай то бог )

надеюсь что вы уже не в конце своего пути )
Symfony не MVC-фреймворк, если что :)
Глобальное потепление — это плохо.

Мой манифест простой:
  • давайте меньше глобальное потепление


Не совсем понятно, о чем статья. На выбранный стиль изложения можно было бы закрыть глаза, но я не увидел основного — предложенного решения названной проблемы. По сути проблема названа абстрактная, а в ней — возможные причины, с которыми и можно было бы согласиться, но не в предлагаемой формулировке. Например, точно НЕ в такой:
В функциональном стиле проще наговнокодить, но шизокодить там сложно.

На мой взгляд, все описанные в статье проблемы с кодом так или иначе можно объяснить одним — допущением их существования разработчиком, который этот код писал. Решаться, следовательно, они должны через создание препятствий, которые будут «мешать» разработчику идти на подобные допущения. Опускаю случаи, когда наличие упомянутых проблем может быть в определенной степени оправдано:
— недостатком квалификации, обусловленный отсутствием опыта, а не слабоумием
— недостатком ресурсов (время/деньги), потому что чистый код — это хорошо, но порой решение нужно уже вчера

В остальных же случаях:
— проблема «хардкода» и нарушений стиля решается через применение практики code review с соответствующими требованиями к тем, кто их проводит
— «тем больше точек отказа, тем больше ошибок» — через применение практики непрерывной интеграции; при этом важно не просто наличие тестов как таковых, а наиболее полное покрытие кода, которое позволило бы выявлять неочевидные ошибки
— переизбыток/недостаток абстракций, проблемы с архитектурой — зависят от опыта конкретного разработчика на конкретной должности; решения для общего случая, на мой взгляд, нет

Во всех случаях в целом, особенно в последнем, проблемы нередко могут совершаться из-за наличия уже существующих, появившихся из-за неверно принятых решений в прошлом. В итоге их количество растет подобно снежному кому, потому что сделать «не идеально» получается правильнее (в контексте ограниченных ресурсов), чем менять архитектуру и переписывать все с нуля.

Суть манифеста, думаю, я понял, просто вместо простого перечисления проблем хотелось бы слышать:
— с предложением решений называемой проблемы
— без лексики, пригодной для «курилки»
— с логическими рассуждениями, когда в конкретном стиле чаще встречаются ошибки по конкретным причинам, а не «просто потому что»
> без лексики, пригодной для «курилки»
можно пример лексики которая не пригода и пригодна?
пишут собственные CMS/фреймворки

то есть любая новая cms или фреймворк — зло?
это смотря с какой стороны посмотреть :)
думаю ничто не зло в абсолютном выражении. везде есть частичка добра )
но я встречался с проектами на своих CMS/фреймворках, где 80% времени приходилось тратить на угадывание логики ее авторов. а это не просто и очень дорого )
потому для себя решил что лучше буду работать с каким то платформами из топ-3, а лучше топ-1 )
странное мнение.
это смотря с какой стороны посмотреть :)


и

Решил что природа этого заболевания та же самая что и желание разработчиков писать свои CMS/фреймворки )


нужно как то определится, либо частичка добра, либо заболевание…
нужно как то определится, либо частичка добра, либо заболевание

Про CMS не скажу, но фреймворки обычно пишутся, для того что бы кто то другой мог переиспользовать какую то часть кода под себя. По факту, если вы не будете заниматься продвижением своего фреймворка, о нем никто не узнает и никто кроме вас его использовать не будет. Смысл тратить время?
Фреймворки обычно пишутся для того, чтобы создавать новые приложения без написания одного и того же кода. И обычно не для абстрактного «кого-то», а для себя. Потом может быть принято решение опубликовать фреймворк для общего использования, но это не обязательно.
Угу, но подразумевается, что мы один раз напишем и будем использовать еще раз. В реальности получается что в 90+% случаев никто не использует это вторично, каждый новый проект вы говорите себе, нет, этот фреймворк не очень вышел и он устарел, вот сейчас у нас есть шанс написать все с нуля и на этот раз правильно, красиво и по феншую. Так же подразумевается, что на написание фреймворка мы не тратим дополнительного времени и получаем его бесплатно, но так ли это на самом деле? Вместо того что бы решать конкретную задачу, мы пытаемся ее решить не самым простым способом, а самым гибким, так что бы код потом можно было переиспользовать и это берет дополнительное время, иногда во много раз больше, чем требовалось на простое решение задачи, но мы говорим ладно, сегодня построим велосипед, зато завтра быстро поедем.
У вас другой опыт написания фреймворков?
Такого не встречал, чтобы писали новый фреймворк с каждым новым проектом. Обновление, развитие фреймворка- да.

Нет, не подразумевается. Подразумевается, что сейчас мы вложимся в создание/развитие фреймворка, зато следующие проекты будем делать быстрее. Инвестиции типа.
Новые проекты не каждый день же появляются. Через год, два фреймворк обрастает такой бородой… Как это бывает, в начале была задача 1, под нее сделали архитектуру и все хорошо спланировали, потом задача немного поменялась, градусов на 178. Код написан, архитектуру уже так просто не исправишь, в бой идут костыли и пластырь, переписывать некогда, дедлайн то никуда не делся. Сентиментов к фреймворку уже никто не испытывает.

Подразумевается, что сейчас мы вложимся в создание/развитие фреймворка, зато следующие проекты будем делать быстрее. Инвестиции типа.

Какой процент инвестиций по факту отбили?

зато следующие проекты будем делать быстрее

Откуда вы знаете, какие задачи вам нужно будет решать завтра? Вы же не делаете одно и тоже. Может задачи завтрашнего дня, лучше решать завтра? Хотя бы будет известно, что нужно сделать, плюс завтра у вас будет больше опыта и вы сможете подобрать лучшее решение, чем сегодня?
Фреймворки обычно делают не на первом, и даже не на втором проекте. Когда замечаешь, что из проекта в проект пишешь один и тот же по сути инфраструктурный код, то и наступает время задуматься о фреймворке. Сторонний или свой в целом детали.

По хорошему свой фреймворк не должен решать задачи завтрашнего дня. Он должен аккумулировать удачные решения задач вчерашних, и иногда внедрять сегодняшних.
Инфраструктура, общие библиотеки это еще не фреймворк. Фреймворк это то, что обязывает вас писать код каким то конкретным способом и больше никак. Например соблюдать naming convention, чтобы «магия» фреймворка сработала или имплементировать какой то интерфейс, что бы ваш код можно было «воткнуть» в фреймворк. И общие библиотеки и фреймворки для повторного использования какого то кода, но разница между ними, что с общими библиотеками вы пишете свободный код, который делает вызовы из общих библиотек. Фреймворки же ограничивают свободу действий. Несмотря на то что можно сказать что фреймворки стандартизируют, но не все задачи можно привести к одному стандарту и получается что иногда вы будете вынуждены писать костыли, что бы остаться в рамках фреймворка.
При этом я не утверждаю, что фреймворки это зло, никогда так не делайте. Я говорю делайте это только когда это что то дает.
Я знаю чем отличается фреймворк от библиотеки. Но не всегда фреймворки ограничивают свободу действий, бывает, что ты просто волен выбирать использовать что-то из фреймворка, или делать свою реализацию. Грубо, отнаследовался от класса фреймворка и не надо больше ни о чём думать, магия, но если поведение фреймворка не устраивает, то просто не наследуешься, а пишешь всё сам, пока не придёт понимание, что эту логику пора во фреймворк перенести.
Каждый волен по своему определять, но фреймворк это прежде всего каркас, нет каркаса, нет ограничений, нет фреймворка.
Библиотека для логирования, это всего лишь библиотека, она ничего не ограничивает и не имеет каркаса, но например реализация патерна dependency injection, это фреймворк, потому появляются ограничения на формат кода.
Каркас необязательно должен быть ограничивающими рамками, он может быть несущими конструкциями, на которые по желанию навешиваются более-менее стандартные элементы, но такой каркас не запрещает в нестандартных случаев создавать самонесущие элементы или воздвинуть рядом новый каркас.
VolCh опередил с ответом. я думаю, что далеко не все разработчики пишут фреймворки, чтобы о них потом узнали. ну точно не ради этого.
Около лет 10 назад в интернетах прогремела статья, не смог найти оригинал, пишу по памяти, «10 признаков настоящего программиста» и один из пунктов был, «вы написали минимум один фреймворк», любой кто читал эту статью воспринимал этот пункт как «вызов принят». Начался какой то ад, люди перестали решать задачу и начали думать а как же мне тут запилить фреймворк, получалось плохо, 3 строчки кода превращались в 300, потому что 3 строчки это не фреймворк, это курам на смех, но если их обернуть несколько раз слоями абстракций будет самое то.
так же см ответ
PSR для того и сделали, чтобы код был понятным, хоть ты из Канады, Индии, Китая, странно когда команда приняла другой стандарт, это как бы вызов сообществу, фигню вы придумали и нам это не удобно.
С другой стороны плохо простой код разбивать на 5 классов в каждом из которых 3-4 метода по 3-4 строки, со множеством бесполезных наследований, когда можно обойтись одним или двумя с минимальным наследованием или даже без наследования если его можно избежать.
А что в этом плохого, если класс и методы выполняют ровно то что и должны?
Можно разбить класс на 10 методов, главное интерфейсы не перегружать, а если методы непонятно названы, и тебе нужно переходить в метод чтобы понять что он делает, тогда вопрос к автору кода, а это уже другая история.
Понятный и поддерживаемый код это когда в команде разрабоки 80% его понимают, всегда найдутся те кому чужой код говно.
Если родительский класс переиспользуется — ничего плохого.
Ключевое слово — излишество. Когда можно обойтись без наследования — надо обойтись без него. Птм что лишний слой абстракции — это нарушение бритвы Оккама. И там много негативных последствий.
Речь не о том что наследование это абсолютное зло и плохо. А о ситуации когда оно делается без причины. Если не встречались с таким — бамбалейо. Поздравлямба и все такое. Все впереди )
в статье ориентир на какой-то идеальный мир, где лишь код и ничего более…

вернемся чуть дальше — а там стоит менеджмент, и очень часто в развивающейся компании нужно срочно вносить некоторые изменения, одни критичны для стабильной работы, другие — не очень, но задевают несколько мест программы\логики\етс., в таких условиях нужно чтобы работало, тупо чтобы работало, и побыстрей, никому из выше стоящих не интересна чистота кода, я уже не говорю про стартапы, где лепится черт и что, куча логик, по многу раз переделывается, лишь таск «рефакторинг» где-то в будущем даст время привести все в порядок.

Просто уже пора слезть с PHP и начать использовать нормальные языки и фреймворки в точности для того, для чего они были созданы :)
Чем же вам PHP не угодил? Он ведь создан для Web разработки.
И список нормальных языков для Web.
PHP был создан как язык шаблонов, а не как язык разработки. SSI имел ограниченную функциональность, а в Perl, на котором тогда делался веб-бэкэнд, нормального языка шаблонов не было. Как замена print из кода в Perl он был хорош, чтобы по-быстрому лепить странички. Но потом из него зачем-то стали делать полноценный язык. При том фундаменте, который был заложен в PHP вплоть до версии 3.x, на нём слишком просто писать плохо, что и происходит до сих пор.

Сейчас, к счастью, ситуация с языками для веб гораздо лучше. Есть отличные языки шаблонов (и, главное, быстрые парсеры), например, шаблоны в Django (и его расширение Jinja2, для которого есть поддержка не только в Python). Для легких случаев есть Mustache.
Насчет замены PHP как языка для веб-бэкэнда: Python (Django, aiohttp), JavaScript (он ужасен, но nodejs сделал из него хороший инструмент для «херак-херак и в продакшен»), Java (главное, не тащить J2EE-стэк — сейчас есть хорошие легковесные фреймворки), функциональные языки (много разных вариантов на выбор).
Из нормальных языков вы еще C# не указали.
По поводу PHP. Это инструмент который позволяет относительно быстро (быстрее чем Perl) обучиться и начать писать работающий код. Качество кода напрямую зависит от самого программиста и культуры разработки в коллективе где он работает. Можно и на строго типизированном языке говнокод написать.
Вообще же выбор языка как инструмента очень важен.
«был создан», «стали делать». Что сейчас не устраивает? Ну и на PHP реализованы свои языки шаблонов типа Smarty или Twig. Заменить PHP на бэкенде можно чаще всего, но зачем?
PHP меня ничем не устраивает. Не нужно его заменять, лучше сразу обойтись без него. Зачем себя мучить, если есть нормальные языки? Мой комментарий был об этом.
Чем PHP ненормален тогда? Есть нюансы, но они есть у всех языков. Нет чего-то что есть в некоторых других, но есть и то, чего нет в некоторых других. Есть плюсы и минусы и для бизнеса, и для разработчиков. Но так же и со всеми языками.
Чтобы лучше объяснить, позвольте узнать, какие языки вы используете и как долго?
Какая разница, что человек использовал? От этого зависит «ненормальность» PHP?

Объясните его минусы по сравнению с другими распространенными языками для wеb программирования. И сразу можно указывать минусы тех языков, по сравнению с PHP.
Проще всего объяснить на сравнении. Но чтобы сравнение имело смысл, оно должно быть с языком, с которым человек знаком. Абстрактные «в этом языке лучше это, а в том то» не работают, пока не начнешь на нём писать. Для меня PHP был адом (до него мой бэкграунд был на C/C++, Perl и Java — для веб разработки). Но потом ко мне попал проект на Python/Django, и я офигел от того, насколько удобным и продуманным может быть язык и фреймворк, и больше на PHP не писал.
Это ваше личное субъективное предпочтение, и вы так и не обозначили ни одного объективного критерия, по которому PHP был бы «ненормальным»
Разумеется, это моё субъективное мнение. На объективность не претендую. Чуть ниже в комменте подробно изложил своей мнение.
Сейчас основные PHP и TypeScript. А так много было, от ассемблера и Форта через C* и Java до Ruby и Python. Но вот как-то последние лет 20 PHP основной, может пару лет на нём не писал, но возвращался.
Чтобы ответить на ваш вопрос, сравню ключевые (для меня) аспекты PHP с Java и Python (для веб я их использовал больше всего). Остановлюсь на двух: простоте входа в разработку и базовых принципах языка. Есть и другие, но эти, пожалуй, сильней всего влияют на моё субъективное восприятие языков.
  1. Простота входа в язык и разработку. Чем проще, тем хуже, т.к. простой вход позволяет начать кодить, не особо разбираясь в разработке вообще. Как результат, большое количество чужого ужасного кода, с которым приходится работать. Это про разработку больших систем. С точки зрения быстрой разработки странички, которую никто никогда не будет поддерживать и повторно использовать, быстрый вход как раз плюс, но это не моя ниша.
    PHP в этом плане слишком простой, что привело к появлению огромного количества недо-библиотек и недо-фреймворков, использование которых заставляет страдать. То же самое можно сказать о легаси-коде, которого в больших системах много.
    На Java гораздо сложнее начать писать, и код на Java гораздо лучше (в среднем), чем код на PHP — я говорю про чужой код, который приходится поддерживать в больших системах. Свой код никто не мешает писать хорошо на любом языке.
    Python тоже довольно прост, но, в отличие от PHP, его синтаксис изначально хорошо продуман и элегантен. Это приводит к тому, что на Python можно научиться писать быстро сразу хорошо. Да, разумеется, плохой код на Python тоже имеется (в больших системах), но его на порядки меньше. Т.е. вот если на PHP хороший код встречается как исключение, то на Python скорее наоборот — иногда встречается говнокод среди вполне годного кода. (Субъективно, без количественных метрик.)
  2. Базовые принципы языка. Язык создается на основе каких-то принципов, также язык создается человеком (группой людей), у которго есть определенные ценности и характер, что влияет на результат. 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 стало гораздо приятней писать.
А причем тут фреймворки, если разговор о языке? Фреймворк это модель, которую пишут какие-то программеры в силу своего развития и желания привязать других к своему продукту. Фреймворк не язык. На Python наверняка тоже написано много корявых фреймворков. Если Oracle или Google захотят написать CMS на PHP, они сделают это как надо.

Сравнивать PHP и Java это как сравнивать разговорный язык, и язык делегатов какого-нибудь математического симпозиума.
Вы сможете переписать простой «Hello world» блог на Wordpress на Java? Не на JSP, потому что это не Java, а на сервлетах. Просто представьте, как вы это делаете, и в добрый путь.
Потому что это всегда разговор не только о языке, а об окружении, которое приходит (навязывается) с языком, а также о сообществе, которое языком пользуется и на этот язык влияет.

Язык определяет, какой код и как он будет написан. Также он косвенно определяет, кто будет на нём писать. Условно сравнивая с человеческими языками, можно говорить на языке из трёх матерных слов и вполне выражать всё, что нужно в повседневной жизни, но если посмотреть, какое окружение будет вокруг этого языка и кто будет на нём говорить, я бы в таком окружении жить не захотел.

Про ваш вопрос о простом блоге на Java: если говорить просто о блоге — да, это простая задача, не вижу ничего сложного (без JSP и даже сервлетов, хоть они и часть стандартного Java EE, просто есть лучшие варианты как для ядра, так и для frontend — можно даже вообще без серверных шаблонов обойтись). Если же говорить о переписывании Wordpress как о платформе, да, это задача сложная, но дело не в Java или PHP, а в сложности сделать архитектуру платформы хорошей (скопировать архитектуру Wordpress на любом языке — дурная идея).
Если я правильно понял, то основной минус PHP для вас, это не сами особенности языка как такового, а большое количество плохо пахнущего кода, с которым вам приходилось работать? Пускай особенности языка написание такого кода провоцирует, но выбор остаётся за разработчиком, не так ли?

Кстати, в мире PHP код и архитектура Wordpress, наверное самого успешного продукта на PHP, считается каноническим образцом как не надо писать серьёзные продукты :)

Может глянете несколько минут на, например, github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpKernel/HttpKernel.php?
Да, именно так, хотя и в самом языке есть неудобные (для меня) вещи, например, исторический $ в названии переменных, Java-подобные описания классов (питоновские классы очень радуют в этом плане, несмотря на нестрогость с точки зрения ООП), {} скобки (питон избаловал отсутствием синтаксического мусора).

Выбор не всегда остается за разработчиком. Бывают большие проекты с дурно пахнущим кодом, с которым приходится взаимодействовать.

HttpKernel.php посмотрел.
Но вот вы как-то Java выделяли как образец нормального языка, а в PHP среди трёх недостатков называете два «из» Java. Так Java нормальный язык или нет? Ну не в долларе же дело?

Выбор всегда остаётся за разработчиком. Большие проекты с дурно пахнущим кодом бывают, да, но вот работать с ними или нет — выбор разработчика.

Похоже это на тот PHP-код от которого вас воротит?
Как язык Java излишне многословен по сравнению с Python, но у него чертовски хороший JIT. Python пока не догоняет по скорости. Также проекты на Java стоят дороже, так что игра стоит свеч :).

Выбор, согласен, в конце-концов остается за разработчиком — если что-то не устраивает, всегда можно сменить проект, компанию, клиентов и т.п. Рынок пока еще позволяет.

Код 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 хорошим фреймворком, удачно балансирующим на грани академической правильности и практического удобства использования.


Спасибо за уделенное время.

Неявное изменение состояний объектов — один из источников ошибок (на Python, кстати, на эти грабли еще проще наступить, т.к. все поля класса открыты), которого лучше всё же избегать, по-моему мнению. По крайней мере важно разделять неизменные объекты и изменяемые. Когда делается гибкая архитектура с «мягкими» правилами (которые нужно соблюдать по факту использования, но не по факту определения), обязательно найдется код, который сделает это недостаточно корректно.
Не хочу критиковать архитектуру Symphony, т.к. толком с ней не знаком, но когда используется общий принцип/вызов передачи сообщений для совершенно различных операций над объектами (как, например, прокинуть какие-то параметры через универсальный изменяемый объект-событие), затрудняется еще и поиск кода, который такие изменения делает (т.к. все участники делают однотипные вызовы с примерно похожими параметрами). И одно дело, если это что-то вроде протокола шины обмена сообщениями (который сверху обернут в более высокоуровневый протокол с методами/функциями, названия которых говорят о совершаемом действии), и другое, если это основной способ общения между объектами в архитектуре приложения. Я сейчас такую проблему вижу в Django Channels — фреймворке-надстройке над Django, который добавляет в него асинхронности (слишком просто всё делать через channel.send(message), к счастью, содержимое message никто не меняет).

В общем, всё сложно, и особенно сложно сделать всё хорошо :)

Спасибо за разговор.
Забыл ответить на вопрос.
Похоже это на тот PHP-код от которого вас воротит?

Да, это он.

Не хочу сказать ничего плохого про автора коммита, о котором я написал выше. Возможно, его код не так уж плох. Возможно, дело в архитектуре Symphony.
  • Блог на Symfony. При том что весь мир для этого использует WordPress.
  • Интернет-магазины на Laravel, при том что есть WooCommerce (№1 в мире), Magento (тоже хорошо), 1С-Битрикс (на худой конец, лучше чем Laravel)

Полный бред, выглядит как реклама WordPress.
1)Не очень согласен с разделением кода на категории.
Стиль написания какой бы он ни был в моем понятии не делает код Говнокодом.
А вот излившее усложнение кода очень даже.
Но кроме усложнения могут быть наверное еще признаки говнокода (тут надо подумать).
2) Есть такой принцип Кiss.(делай это как можно проще). В википедии при описании его приведены цитаты нескольких известных людей и они тоже подходят как илюстрация к теме данной статьи. При этом идея несколько шире чем принцип Оккамы( Не плоди лишних сущностей).
В статье очень не хватает примеров плохого кода.
Например, прослойка между сторонним фраймворком и проектом, состоящую из пустых классов, это плохо или нет? Дополнительная обстракция, но может сэкономить кучу нервов при срочном апдейте.
Код превращается в шизокод тогда, когда исполнитель начинает пользоваться паттернами КОП — Костыльно-Ориентированного Программирования.
С его костылированием, инкостыляцией, поликостылизьмом.
Можно продолжить: есть хардостатьи, говностатьи и шизостатьи
UFO just landed and posted this here
часто мне хватает Синглтоночасто мне хватает Синглтонов, статических методов и statelessв, статических методов и stateless


Синглтон — антипаттерн, статические методы — то ещё зло, и использовать их стоит разве что для альтернативных конструкторов. В авторе заметен большой поклонник Wordpress (который в плане кода является идеальным примером того, как не надо делать).
UFO just landed and posted this here
Грех №0 — хайпокод. Это когда начитываешься кучи статей с «манифестами», и руководствуешься ими, а не здравым смыслом.

На самом деле очень хорошая статья, и действительно отражающая реалии из жизни команды программистов. Грехи эти имеют место быть, особенно у начинающих программистов.

Не понимаю за что ее заминусовали, отличная статья, часто кидаю ссылку на нее.

Sign up to leave a comment.

Articles