Как стать автором
Обновить

Комментарии 634

Бедная похапешечка, сколько раз её убивали.

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

Если язык "взлетел", оброс большим количеством проектов, в том числе коммерческих, умирать он будет долго, медленно. Даже если мы представим, что вдруг внезапно всем очевидно, что (неважно, но для примера, допустим) Golang 100% лучше, чем PHP, все равно, PHP может умирать еще десятилетия!

Если в бизнесе уже есть приложение на умирающем языке, никто в здравом уме не будет его переписывать просто потому, что язык уже не моден. Работает - и хорошо! Соответственно, есть спрос на программистов, работающих на этом языке (кто-то же должен обслуживать и развивать это ПО). Более того, этот похапешный отдел скорее всего и новые проекты будет на похапе делать (потому что мозгу так проще, иметь в голове одну модель языка, а не переключаться). Можно даже в каком-то смысле воспринимать ЯП как вирус - если контора заболела каким-то "плохим" языком программирования в детстве - есть риск, что она будет так болеть вечно. И еще может быть в ходе агонии породит новые проекты на этом "условно умирающем" языке, в том числе и более-менее успешные.

Помните, такой язык как Perl? Если про PHP можно спорить про его умирание, то Perl, наверное, более мертв (чем PHP)? Однако, до сих пор SpamAssassin на множестве почтовых серверов в мире - на перле. И инсталляшки дебиана его, вроде используют. И чтобы с ними как-то что-то делать - востребованы программисты на Perl. Инерция.

Perl с сетью хорошо работает. хBSD во многом жива по тем же причинам.

буквально вчера на одном сайте видел в адресной строке что-то типа /cgi-bin/stat.pl?ses=111&uu=222&pp=333

Так что даже web приложения на perl где-то ещё работают

Вовсе не факт. Иногда старые URL-ки просто сохраняют для совместимости (чтобы работали старые ссылки), а на деле под капотом может быть PHP или Python + Django или что угодно ещё, ведь маршрутизацию URL можно как угодно настроить.

Мы с друзьями делали URL-ки, заканчивающиеся на *.jsp, и ещё в заголовках отдавали «X-Powered-By: Apache Tomcat» вообще чисто забавы ради, т.к это был бэкенд.

О да, я хулиганства ради на Node.js делал урлы, заканчивающиеся на .php.

Факт - uu pp и ses это штаны от моего проекта, которому 15 лет минимум (лом смотреть сколько) - и им пользуются провайдеры

Да, и половина экономики США держится на COBOL.

Заставляет переосмыслить, что же опаснее - современные вирусы и атаки, от которых нет обновлений для старых систем, или сами эти обновления.

Да тут скорее анекдот про неуловимого Джо больше подходит... У них всё было хорошо, потому что они пропустили время перехода на актуальный софт. Поэтому все, кто искал уязвимости их и не находили: они ж искали в новом софте, не ожидая, что там что-то древнее. Ну, теперь после новостей, все, кто хотел, уже знают какие уязвимости надо проверять для win3.1 и win95 - всё давно описано и легко гуглится. Так что я не удивлюсь следующей очевидной новости про эту компанию)

А вторая на excel

Моя любимая БД =)

Буквально вчера понадобилось обрезать PDF от пустых полей по краям. Подходящий инструмент оказался уже на компьютере: pdfcrop из поставки LaTeX, тоже написан на Perl.

Люблю php. Начинал с него. Он ни беден, ни велИк, он - самодостаточен, красив и мудр. И его не победить,...наверно :).

Про PHP я могу сказать только одно... но пятью разными способами

Это про Perl, там способов будет 10, 5 из которых вообще даже автор не прочитает через месяц

Но ведь PHP создан, чтобы умирать. А среди меня PHP давно заменён на Rust. Всё, что я когда-то скриптовал на PHP, теперь делаю на Расте.

Пошел тем же путем. Искренне убежден, что Rust один из лучших языков для бекенда. Но первый опыт бекенда лучше получить на ООП языке. И PHP прекрасно для этого подходит.

Rust один из лучших языков для бекенда

Серьезно?) Один из лучших языков для того чтобы шиппить в прод в 20 раз медленнее чем на любом другом япе

При наличии опыта разработка на Расте не медленнее, чем на других языках. Я тоже заблуждался как вы когда-то.

А что там не так с шиппингом? С помощью sccache полная сборка среднего проекта будет длиться минут 5-7 на ci.

Абстракции там хорошие, тулзы удобные, поддержка со стороны ide хорошая. Библиотеки вполне себе есть в наличии.

Защита от дурака сильная. Какие вообще могут быть сложности в типовом проекте? Не типовой же в принципе нельзя быстро шиппить, да и не получится при всем желании.

Больно может стать если вот вдруг задача на сложные графы с циклами, но это не типовая задача.

Что угодно, лишь бы не осваивать дотнет, ага.

То чувство, когда с .NET переходишь на Go

А чем продиктовано такое решение?

Причины лежат скорее в области ощущений, чем логики

  1. win 10 для меня последняя версия винды, которую я ставил себе на домашний комп. Был и есть ноут с линуксом, но через 3-5 лет и домашний десктоп перекочует на линукс. Просто потому что win 11 не нравится, а у 10ки поддержка рано или поздно будет становиться плачевной. Да и в целом дистанцируюсь от мелкомягких. А .NET и линукс не до конца дружат - gui уже сколько лет не могут завести например.

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

На самом деле легаси в go больше чем должно было бы быть. Скажем, api модуля os было стянуто с Питона, где оно на тот момент уже было странным.

Что то не похоже что вы всерьез были на дотнете, раз с такими аргументами переходите на Go.

Про кроссплатформенность это несерьезно начиная с появления .Net Core.
Для UI есть Avalonia которая хороша чуть более чем полностью, это если про десктопы говорить. Про веб я вообще молчу, упомяну только что есть офигенный Blazor.
Cовершенно непонятно, чем шарпы неэффективны в "сетевых" приложениях, может речь идет о физических уровнях OSI? Ну и про легаси это веселый пассаж.

Интересно с каких пор Avalonia стала частью языка или хотя бы стандартной библиотеки. Или для вас библиотеки и языки вещи тождественные?

чем шарпы неэффективны в "сетевых" приложениях,

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

результат работы компиляции в виде одного простого бинарника без всякой лабуды

Дотнет умеет в собираться в натив и бандлиться в один файл.

Уметь и делать из коробки - разные вещи

Почитать две статьи и выставить нужные флаги при сборке - великий труд, действительно)

Собирать в один файл умеет штатная сборочная система, входящая в состав .NEt SDK. Если это вас не устраивает - то что вообще в вашем понимании является "коробкой"?

Golang или Rust для бека? (Хочется уже куда то двигаться, а выбрать не получается 😅)

Раст, конечно. Поначалу будет трудно, но потом очень легко.

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

Rust. Очень хорошо спроектированный язык (в отличие от мистера "дженерики не нужны" 😀). Очень хорошая интеграция с VSCode, очень хороший тулинг из коробки. Для бэка есть фреймворки (axum, actix), а есть и более простые либы. Есть и ОРМ (diesel), есть query-builder (sqlx).

Я сам фронт, но недавно начал пилить свои проекты, там в основном бэк. Можно почитать https://llogiq.github.io/2024/03/28/easy.html , чтобы меньше было затыков в начале, ну и Copilot или аналогичный чатбот сильно упрощает процесс починки ошибок и написания кода.

Из минусов - порой очень сложные для понимания ошибки (на первые разы), иногда сложности с тяп-ляп и в прод (а иногда оно надо), долгая компиляция, непонятки с borrow checker'ом. Но со временем, когда подучишь язык, всё становится намного проще.

Golang скомпилированный под локальную машину выполнял команду - 452.430ms
PHP в docker-образе выполнял команду - 390.859ms

один вызов я так понимаю? то есть заодно померяли инициализацию виртуальной машины тоже?

> Так же провел замеры при работе http сервера и PHP показал себя с хорошей стороны, в docker-образе, с подключением к базе данных, вставкой строки в базу и последующим селектом данных и базы и передачей json ответа http сервер на php выдержал 10.000 rps, со средним временем ответа 40мс, максимальным 500мс и минимальным 200 микросекунд, но об этом более детально напишу в следующих статьях.

Так а что тут мерялось? Подключение к БД и вставку строки?

Это просто пример, в котором PHP обогнал golang. В реальной жизни совершенно другие задачи. Замеры были только выполнения кода по десериализации json, не более того.

На счет http-сервера - это спойлер к будущей статье, в которой уже более детально об этом расскажу

10000 rps 40мс со вставкой в бд и чтением на коленке? А чем нагружали?

Что-то тут нечисто. 10т реквестов на одной машине уже нетривиально сгенерить. Хочется посмотреть как это делалось.

k6 использовал для нагрузки

база postgresql, для подключения использовал пул соединений

На одной и той же машине?

да, все в docker

И операционной системе хватило сокетов?

да, за счет того, что ответы были быстрые и не было лага по ответу, за пределы соединений на одной машине не уходило, поэтому сокетов хватило.

Если вопрос к http2, что количество сокетов было снижено, то - нет, запросы были http первой версии

Ну измерения так всеравно не делают, надо делать показательную выборку и смотреть перцентили, модальность, ошибку, доверительный интервал, коэфф экцесса и т.д., а не только среднее и мин/макс.

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

Так у го нет виртуальной машины

помню и node.js тоже был с такими же амбициями, так что и go переживет )

Последние несколько лет на рынке, по моему сугубо личному мнению, golang вытесняет PHP с рынка, а многие компании считают, что проекты, которые сейчас написаны и работают на PHP должны быть переписаны на golang, чтобы было хорошо.

ничего глупее не встречал, те из одного болота нырнуть, в другой, вопрос, а зачем?

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

Последние несколько лет на рынке, по моему сугубо личному мнению, golang вытесняет PHP

Здесь не согласен, просто, подавшись хайпу, народ то на node.js, то на go, то на битрикс делает, потом волна спадает, приходится искать специалистов для поддержки проекта, а мигрировать на новый стек, это очень дорого. Поэтому компании едят кактус и плачу, но продолжают есть.

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

Другими словами, дело в людях, а не технологиях. Если в компанию придёт команда со знанием стека руби, и при этом заимеет внутри-политически сильные позиции, значит в компании будет основным ЯП Руби, и совершенно плевать, насколько он подходит и выгоден ли для решаемых задач. Главное, что команда его знает, и не знает ничего другого. Значит будет Руби, а не Go или PHP. Даже если придётся городить костыли.

Смена технологий меняется с переосмыслением технологий у людей.

у людей переосмысление тоже не особо происходит, смена технологий происходит скорее со сменой людей

Мы примерно об одном говорим, но, но есть нюансы. Компания это не всегда технически подкованные люди, им все равно на чем написано, чистый там или грязный код, им нужен продукт, причем вчера И тут попадается некий разработчик, более голосистый, более убедительный, кстати про это были статьи на хабре. Он убеждает, что надо сделать, условно на чем-то, что по его словам эта технология, за которым будущее и все крупные вендоры перешил на него. Проект запущен, разработчик уходит и тут возникает вопрос, а как его поддерживать и развивать? Наступает момент истины, надо кого-то искать, hh начинает пестрить вакансиями, а переехать куда-то это очень накладно и болезненно для компании.

ничего глупее не встречал, те из одного болота нырнуть, в другой, вопрос, а зачем?

давайте тогда на шапры переведем, это будет более грамотная миграция

Я правильно понимаю, что в вашей картине мира, миграция на C# - это единственное решение всех проблем и аргументации мы, конечно, же, не услышим, вы просто так чувствуете?

  1. Есть иммутабельные типы. Да и вообще с типами в C# заметно лучше. И проблем с null/undefined заметно меньше в сравнении с js/ts/php.

  2. Интерфейсы есть с незапамятных времен, в пых только недавно завезли трейты, в чистом JS их вообще нет. Барбару Лисков без них ублажать заметно сложнее и багованнее.

  3. Потенциал к появлению SIMD инструкций в коде и как результат больший перформанс по сравнению с двумя остальными.

  4. Время компиляции TS vs C# сдаётся мне будет на стороне C#.

в пых только недавно завезли трейты

Ничего, что трейты появились в PHP 5.4 аж 12 лет назад?

Это не те трейты. Хотя я тоже не понимаю причём тут трейты...

Это не те трейты

Вмысле НЕ ТЕ?

В смысле в PHP трейтами зовутся миксины

Нет. У трейтов в PHP состояния как у миксинов в руби нет.

Не эксперт в PHP. Видел какой-то недавний релиз (~год назад), который делал некоторый пример с трейтами и видимо я их таки спутал с интерфейсами. Тем не менее и интерфейсы и трейты помогают с композицией. Но, учитывая что типизацию допиливают по сей день и интеграция с фреймворками вроде не самая глубокая - С# в этом смысле побеждает.

Не знаю, но на JS/TS достаточно комфортно писать backend. Основная проблема в том, что экосистема еще недостаточно развита. Из перечисленных вами критична только проблема с SIMD инструкциями, но такому языку это не особо и нужно. С# тоже как язык очень хорош, но если нужна производительность, то тогда уже сразу можно использовать Rust. С# выглядит как полумера.

Это не полумера, так как сложность написания кода на языке с GC и без очень сильно различается

Языки с GC все же не так кардинально отличаются друг от друга. Если использовать кластеризацию и современный фрейморк в Node.js, то он может работать не в разы медленнее Golang. Аналогичное хочет показать и автор статьи, как мне кажется. Как правило, путылочным горлышком оказываются компоненты вроде БД, которые и так написаны на C/C++. В таком случае использовать ещё один язык с GC не особо эффективно

Погодите, но вся эта "кластеризация" не в вакууме же крутится? Есть конкретные железяки, на которых это все запускается, и эти железяки стоят вполне реальных денег. И вот в производительности на рубль стоимости железяки нода сливает, простите за откровенность, едва ли не любому конкуренту.

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

К тому же железо далеко не единственный фактор. Например, программист может стоить дороже и послать его потом делать интерфейс или администрировать сервисы будет сложнее, бутылочным горлышком в итоге окажется БД или какая-нибудь Kafka, из-за чего даже переход на язык вроде Rust ничего не кардинально не поменяет, если только не переписать Kafka на Rust.

Об этих вещах я и говорю, подразумевая "полумеру".

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

Вот тут, к сожалению, проще завалить ресурсами, чем пытаться производительную апишку на C++ написать. Изкоробочная многопоточность сроляет гораздо больше, а с памятью пооптимизировать и в GC-языках можно.

 Если заменить один язык с GC на другой, то даже не факт, что код в итоге будет работать быстрее

Время исполнения одного запроса, скорее всего, критически различаться не будет, если уметь правильно готовить. А вот по поводу RPS вы ой как не правы.

Весь движ с производительностью веб-апишек же строится не вокруг оптимизации атомарного запроса (по факту, пользователю насрать, 30 милисекунд исполнялся его запрос, или 32), а вокруг возможности выполнять тысячи запросов параллельно за адекватное время. И вот тут один GC-язык от другого может отличаться настолько разительно, что вы офигеете. Прям в разы, если не на порядки.

не факт, что будет экономия, особенно если железо мощное по современным меркам.

Как раз факт экономии и будет. "Мощное по современным меркам железо" стоит достаточно ощутимых денег (особенно, если вы арендуете мощности). В момент, когда деньги на ресурсы начинают считать, вдруг начинает ролять тот факт, что Go на железке, на которой Node вообще не запускается, умудряется вывозить больше RPS, чем нода в лучшие свои годы.

программист может стоить дороже и послать его потом делать интерфейс или администрировать сервисы будет сложнее

А вы, простите, по какую сторону баррикад?) Нормального бекенд-программиста хрен вы заставите делать интерфейс или работать сисадмином.

 бутылочным горлышком в итоге окажется БД

Да, скорее всего, она. Хороший бекендер, к слову, в большинстве случаев знает, что с этим делать.

или какая-нибудь Kafka

А вот это, как раз, вряд ли)

даже переход на язык вроде Rust ничего не кардинально не поменяет

На Rust - абсолютно точно не поменяет. Rust вообще про другое.

SIMD инструкциями в C# можно пользоваться уже довольно давно. Мне странно, что вы говорите о Rust, но Rust - со всеми своими проблемами совершенно точно не лучше классики C/C++.

Rust ещё можно выучить как второй язык, C++ - нет. Я в основном JS/TS разработчик и для меня это ключевой момент

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

Минус в том, что шарписты обходятся дороже компании. Плюсы экосистема MS ориентирована на бизнес, с хорошей поддержкой.

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

Засчитывается, вопросов нет)
В целом, это согласуется с другим тезисом, который привели в комментариях:

всё зависит от того, адепты какой платформы сидят у руля

В этот раз вы были не у руля.

подавшись хайпу, народ то на node.js, то на go, то на битрикс делает

Извините, а когда Битрикс не на пыхе стал работать? Я что-то пропустил?

Для сравнения Golang и PHP вы взяли дополнительное расширение для PHP - Swoole.

Подскажите, это расширение 100% совместимо с популярными PHP фреймворками, на которых пишут современные веб приложения - Symfony (особенно интересно, т.к. люблю этот фреймворк), Laravel, Yii. Имеется ввиду, что приходится расширять код фреймворков, где расширение кода не предусмотрено, или перегружать функции из стандартной библиотеки PHP, т.е. "черные" хаки.

Спасибо.

Да, для ускорения использовался Swoole, он работает на основе event-loop (очень похоже на nodeJS), за счет этого получилось быстро выполнить программу.

Полная документация по swoole есть на их официальном сайте https://wiki.swoole.com, также есть большое количество composer-пакетов, которые позволяют подключить этот модуль к проекту.

Важный момент, простое подключение swoole в рабочий проект будет равносильно использованию php-fpm или apache или другим web-серверам.

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

Это еще та китайская суходр..ка. Был проект, наелся, была версия, где даже xdebug нельзя было прикртить. Изначально пых был сделан для другого, нужна асинхронщина, почему не использовать другие технологии, заточенные под это?

Потому что дешевле и проще держать один стек

Рекомендую посмотреть в сторону hyperf. После Laravel вполне себе привычно. 3 года - полет отличный.

Помню как здесь, лет 10 назад был хайп вокруг Ruby, который вот-вот убъёт php. Как дела?

Нашел свою нишу и вполне себе живет до сих пор - на нем написаны GitHub, GitLab, Shopify, Stripe.

Один Redmine чего стоит.

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

А в случае перечисленных выше проектов, я не вижу, чем они особенны, почему там уместнее руби, чем тот же пайтон? Это не ниша, а исторические причины - первый программист в компании на момент создания проекта предпочел Ruby. Выбор во многом эстетический и субъективный.

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

А дальше, если проект дорастает до каких-то нагрузок, начинаются вопросы производительности и переписывания монолита.

на Python проще, легче, быстрее и дешевле сделать почти все

Очень спорно. Давно когда-то на нём писал достаточно долго, потом лет на 5-6 забросил. Захотел на днях скрипт сделать, но как-то знатно офигел, насколько же там всё неудобно и непривычно. Долго ковырялся, забил на питон. При этом, на расте, который я изучал меньше года, всё вышло куда проще и быстрее.

 Соответственно, любой новый проект лучше делать на

том, что хорошо знаешь (если команда - где больше экспертизы) и где получше экосистема.

Соответственно, любой новый проект лучше делать на

том, что хорошо знаешь (если команда - где больше экспертизы) и где получше экосистема.

Вот тут на 100% согласен - свой первый web-проект писал вообще на компилируемом Quick Basic (да-да, IIS, обвязки stdin/stdout для CGI, вот эти все архаики), потом переписал на asp, а потом лет на 10+ вообще отошёл от бэка, а когда в конце нулевых понадобилось набросать служебный отчётик по трафику, понял, что ни qb, ни asp на FreeBSD поднять в разумные сроки не выйдет, пришлось срочно осваивать PHP, и очень даже "зашло", правда, в процедурной, а не объектной нотации (уточню - я не разработчик ПО - все мои поделки - сугубо вспомогательные, и программирование я изучал с 1991 по 1994 годы, так что "музыканта" прошу не ругать). Но то, что доводится сейчас встречать в продакшене, порой вызывает оторопь - операция, занимающая порядка 3 секунд может выполняться часами, обычно из-за неоптимальных алгоритмов - чаще всего гоняют по медленным маршрутам (soap/wsdl, ole и прочие коннекторы с дорогой инициализацией) сотни мелких запросов. Но опять же, это моё видение со стороны эксплуатанта - возможно, чего-то не знаю.

на Python проще, легче, быстрее и дешевле сделать почти все

переписываем узкие места на golang

Нужны либо питонисты со знанием Go, либо отдельныая команда. Это уже не просто и не дешево.

Для всех тех, кто пришел сюда прочитав заголовок, но не читая статью. Пых давно убит морально. Статьи про fractal of bad design и картинки с молотком из двух гвоздодёров сделали своё дело. Он не существует в информационном поле. А точнее существует в виде "какой-то старпёрский язык для говнокода". На Stack Overflow даже индусы сейчас не задают вопросов по пхп, передав эту пальму синьор-девелоперам из Центрально-Африканской республики. Да, сейчас он не имеет ничего общего с тем языком, про который писались ругательные статьи. Да, он все так же является основным языком бэкенд разработки веб-приложений. Но информационную войну он проиграл давно и прочно, и это со временем скажется и на его использовании.

Да, он все так же является основным языком бэкенд разработки веб-приложений.

Сомнительное утверждение. В бэке, в плане старта каких-то новых проектов, его уже давно подвинула компания состоящая из nodejs, .net, java, python. Разумеется я сейчас говорю про глобальный рынок и про какие-то custom решения, а не поднятие интернет магазина методом накидывания плагинов на wordpress.

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

Адепты Laravel с вами не согласятся

Но да, публичности бы им явно побольше

Речь, разумеется, не про адептов, а про остальной мир. В /r/php регулярно, раз в месяц, появляются посты "ой, я весь колледж слышал со всех сторон, что пхп - это параша, а сейчас пишу и нормальный язык". Есть в мире такая штука, как клише. Например, что Раша - это медведи и балалайки. И ты хоть усрись доказывая, что в Канаде медведей на бэкъярдах на порядки больше, но уже сложившуюся картинку не перешибёшь.

А балалайки у медведей в Канаде есть?
Вот то-то и оно.

Плюс всякие новые предложения (CodeRun от Яндекса, Giga IDE от Сбера и т.д.) уже не добавляют PHP в список поддерживаемых языков. Что тоже формирует определённую картину мира разработки.

Учитывая, что GigaIDE это Intelij IDEA CE, к которой поддержка PHP (в виде php storm или php plugin) является коммерческим продуктом, то неудивительно, что их там нет.

Golang скомпилированный под локальную машину

Операционка то какая? Тестируйте в одинаковом окружении.

Вроде же PHP всегда славился низким порогом входа, а тут в примере создаётся асинхронный event loop, который вот совсем не простой для понимания.

То есть, мы фактически из php сделали go. Ну, наверное, это хорошо. Но вот это усложняет понимание и увеличивает шансы выстрела в ногу.

Go то хотя и простой язык, но ошибаться на нём тоже довольно просто.

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

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

С другой стороны, golang - строгая статическая типизация с компиляцией. Просто так написать фигню и запустить едва ли получится.

В какой-то момент в пыху завезли статическую типизацию, но пользуются ей далеко не всегда и не охотно, люди не привыкли) Но зато язык все ещё для вкатунов, и те самые пол интернета, ранящиеся на нем, чем гордится все сообщество вкатунов php, использует lamp с хостингом.

P.s.: разумеется, что язык - лишь инструмент. И если знать, что ты делаешь - то все ништяк с любым. На том же PHP нормальные люди с IQ не как у картошки используют Лару, симфони, yii2 или ещё что-то, адекватно проектируя систему и код-стайл. Но то, что некоторые технологии позволяют все подряд и плодят убогое ПО уже 30 лет подряд - это проблема!

Но ведь Swoole написан на Go... А если я PHP скомпилирую под .NET (PeachPie), сравнение будет валидным?

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

Статья про то, что - все проблемы PHP можно победить - имея хороший инструмент (стек) и код. Но например у меня опыта в стеке, который победит все проблемы PHP - нету.

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

Да, согласен надо искать инструменты, которые дают серьезные преимущества, т.е. прорывные инструменты, а не побеждать проблемы.

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

Swoole не написан на go, возможно вы сравниваете с roadrunner

https://github.com/swoole/swoole-src - ссылка на модуль

Да-да, перепутал с RR. Но тут C++, тоже по сути ни разу не PHP.

Получается, что код на Go полностью самодостаточен, он компилится и работает, ничего не требует для своей работы (кроме непосредственно ОС). А тут надо ещё прикорячить Swoole/RR/php-fpm+Nginx, которые писаны совершенно на других ЯП. И зачем такие сложности? Тут собственно и ответ, почему Go.

А по тестам. Давайте подадим нагрузку 1000 запросов в одно время на PHP и Go с обращениями в БД, посмотрим что получится? Какой будет профиль утилизации, сколько запросов вообще не отработает или отвалится?

а еще у go есть https://github.com/valyala/fasthttp


Я понимаю, докеры и все такое. Но бинарник на go это и вебсервер сразу.

код на Go полностью самодостаточен

Какое практическое преимущество это дает на бэкенде, обмазанном контейнерами?

которые писаны совершенно на других ЯП

При прочих равных, какая разница, на каких языках написаны вспомогательные инструменты?

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

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

производительность, так как любой лишний маршаллинг это затраты

Единый язык не гарантирует отсутствие маршаллинга, тот же PHP может быть на каком-нибудь трансляторе. Тут, наверное, подразумевался единый процесс. Go же по дефолту использует libc?

разработчики могут в равной степени участвовать в развитии всей платформы

Больше похоже на маркетинг, если честно) Порог вхождения в такие проекты достаточно высок, чтобы отсеять начинающих.

выходить за эти рамки тяжело, а без доп. инструментов попросту невозможно

Появилась необходимость - появились и инструменты. Размер комьюнити играет важную роль.

Какое практическое преимущество это дает на бэкенде, обмазанном контейнерами?

Имхо, как минимум, в процессе разработки, у меня не уходит полгода на то, чтобы собрать окружение для проекта. Да и билд/деплой быстрее, и контейнеры поменьше (мы же сервера таки платим, да?). Ну и вдогонку: сторонние зависимости за собой тянут и определенные риски.

С тем же php, допустим, если мы в кубере живем... В контейнере с приложением будет сам пых + вебсервер (вероятнее всего nginx+phpfpm?). При этом перед этим всем будет еще балансировщик куберный и ingress (зачастую тот же nginx). Вуаля, у нас 2(два) nginx'а до сервиса на ровном месте, удачной отладки!

у меня не уходит полгода на то, чтобы собрать окружение для проекта

Тут один раз делается шаблон, который потом копипастится для каждого нового сервиса. Да и всякие БД, кафки и прочие инфраструктурные вещи в любом случае придется разворачивать, +1 инструмент погоды не сделает.

билд/деплой быстрее

Самый быстрый билд - его отсутствие =3 Один файл скопируется быстрее, чем тысяча, но это крохи, которые игру не перевернут.

При этом перед этим всем будет еще балансировщик куберный и ingress

Разве для Go-приложения это не потребуется?

у нас 2(два) nginx'а до сервиса на ровном месте

Go сам себе веб-сервер, тоже второй в этой цепочке, тогда какая принципиальная разница?

Тут один раз делается шаблон, который потом копипастится для каждого нового сервиса.

А потом этот шаблон правится под требования каждого последующего.

А потом в очередной раз вы начинаете билдить новый проект, и вдруг `FROM nginx-phpfpm:5.13.67` перестает работать, потому что версию депрекейтнули и выкинули. Вы берете посвежее, а там код поломался... Как минимум, этих болячек в го нет.

Самый быстрый билд - его отсутствие =3 Один файл скопируется быстрее, чем тысяча, но это крохи, которые игру не перевернут.

Инфра под билд, очевидно, уже не роляет?

Go сам себе веб-сервер, тоже второй в этой цепочке, тогда какая принципиальная разница?

Разница в том, что гошный вебсервер - часть приложения, которую вы полностью контролируете. Вы можете быть уверены, что GET-запрос не закешируется по дороге, например. NGINX вполне может посчитать законным вернуть ответ из своего кеша, посчитав его идемпотентным. Т.е. между куберным ингрессом и приложением мы воткнули еще один ингресс - это точно хорошая идея?

шаблон правится под требования каждого последующего

Методом выкидывания ненужного или заполнения плейсхолдеров. В то время, как на Go писалась бы базовая машинерия с сервером.

NGINX вполне может посчитать законным вернуть ответ из своего кеша

Сконфигурируете так, чтобы не мог.

между куберным ингрессом и приложением мы воткнули еще один ингресс - это точно хорошая идея?

А зачем еще один ингресс? Веб-сервер - это часть PHP-приложения.

В то время, как на Go писалась бы базовая машинерия с сервером.

if err := http.ListenAndServe(":8080", router) {
  log.Fatal(err)
}

Вы про это?

Сконфигурируете так, чтобы не мог.

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

А зачем еще один ингресс?

Ingress-контроллер - это штука, которая маршрутизирует трафик снаружи внутрь. Просто термин для обозначения реверс-прокси.

Собственно, один у вас на входе в кластер, а еще один - ваш nginx внутри контроллера. Причем на входе в кластер, с вероятностью процентов 80 - тоже nginx.

Вы точно уверены, что 2 реверс-прокси в цепочке обработки вызова - это очень хорошо?

Веб-сервер - это часть PHP-приложения.

Часть приложения - это то, что есть в его кодовой базе. NGINX'а там нет.

В чем проблема? Ну, например, был у вас образ на базе какого-нибудь nginx-phpfpm:7.10, вы переползли на awesome.new.containers.com/nginx-phpfpm:7.10 - просто другой билд того же инструмента. Вы даже не задумывались, что там nginx с другими правилами внутри может быть, а грабля в лоб уже ударила.

В Go такое исключено. И это - хорошо!

Вы про это?

Суть такая, да. Для реального приложения кода будет больше.

его сконфигурирую сначала в кубере, а потом еще в контейнере, второй раз. Это прям хорошо?

А в чем может быть проблема? Про копипасту конфигурации - ранее уже говорили.

Часть приложения - это то, что есть в его кодовой базе. NGINX'а там нет.

Веб-приложение без веб-сервера не работает, очевидно. У PHP туда еще рантайм входит.

Вы точно уверены, что 2 реверс-прокси в цепочке обработки вызова - это очень хорошо?

Я не особо шарю в нюансах подключения PHP к веб-серверу, но по идее именно проксировать HTTP (второй раз) не нужно, модуль расширения должен вызывать интерпретатор напрямую. Т.е. это не реверс-прокси, а аппликейшн сервер.

был у вас образ на базе какого-нибудь nginx-phpfpm:7.10, вы переползли на awesome.new.containers.com/nginx-phpfpm:7.10 - просто другой билд того же инструмента.

Какая-то надуманная проблема. Почему меняя образы вы не задумываетесь о том, что они могут быть разными? Это ведь не повышение минорной версии, а совершенно другой образ.

В Go такое исключено

Точно так же версия Go может бать пропатченной с потерей обратной совместимости. Кто же запретит?

Для реального приложения кода будет больше.

Да не намного. Вся разница: я копипащу нужные куски кода, вы - удаляете ненужные (попутно хороня где-то в недрах приложения неиспользуемый код)

Я не особо шарю в нюансах подключения PHP к веб-серверу, но по идее именно проксировать HTTP (второй раз) не нужно, модуль расширения должен вызывать интерпретатор напрямую. Т.е. это не реверс-прокси, а аппликейшн сервер.

nginx - это реверс-прокси. И он там есть. Да, в PHP он используется как application server, но это не отменяет того факта, что он - реверс-прокси, со всеми вытекающими а ля политики кеширования и т.д. и т.п.

Вы же не будете на полном серьезе утверждать, что "не иметь лишней избыточной штуки в проекте" не является преимуществом над "иметь лишнюю избыточную штуку в проекте"?

Точно так же версия Go может бать пропатченной с потерей обратной совместимости. Кто же запретит?

А какое отношение версия Go имеет к продовому контейнеру? В нем НЕТ никакого Go, в нем бинарь лежит. С "потерей обратной совместимости" у меня бинарь тупо не соберется.

в PHP он используется как application server, но это не отменяет того факта, что он - реверс-прокси

HTTP не проксируется, а передается сразу в приложение. Это другая функция относительно того реверс-прокси, что стоит снаружи.

Вы же не будете на полном серьезе утверждать, что "не иметь лишней избыточной штуки в проекте" не является преимуществом над "иметь лишнюю избыточную штуку в проекте"?

У Go эта "избыточная штука" компилируется прям в бинарник. Разница с хостящемся приложении будет лишь в том, что она здесь снаружи.

Если вся эта проблема лежит исключительно в философской плоскости, то это не стоит внимания.

А какое отношение версия Go имеет к продовому контейнеру?
В нем НЕТ никакого Go, в нем бинарь лежит

Бинарь не из воздуха берется. Такие вопросы странно читать. Слышали что-нибудь про multi-strage builds?

С "потерей обратной совместимости" у меня бинарь тупо не соберется.

У Go же такой мощный компилятор, что ловит все виды ошибок, ага)

У Go эта "избыточная штука" компилируется прям в бинарник.

В Go это не избыточная штука, гошный сервер сииильно меньше. Он умеет те самые, в лучшем случае, 10% от того, что умеет NGINX, которые нужны приложению.

Разница с хостящемся приложении будет лишь в том, что она здесь снаружи.

Так я же именно про то и говорю, что она снаружи! В этом и проблема!

Кеширование, маршрутизация - это часть логики веб-приложения. Та самая часть, которая у вас находится снаружи, а у гоферов - прямо в коде. Проблема с запросом - я смотрю в лог приложения, php-кодеры - в лог приложения и в лог контейнера. Проблема наша, надо чинить? Я чиню в коде приложения, вы - в коде приложения, в релиз-ноутсах базового образа, в конфигах nginx'а, в рантайм-зависимостях, лежащих в контейнере и б-г еще знает, где еще.

Если вся эта проблема лежит исключительно в философской плоскости

Проблема "сложнее дебажить" - это проблема, лежащая в сугубо утилитарно-практической плоскости.

Бинарь не из воздуха берется. Такие вопросы странно читать. Слышали что-нибудь про multi-strage builds?

И в чем, простите, проблема с multi-stage билдами? Не, с PHP понимаю - в релизном контейнере может оказаться не та версия PHP, например, или еще что-то из обвеса, называемого "рантайм".

В Go из рантайм-зависимостей - только glibc. Там буквально голый linux-контейнер с одним бинарем внутри.

У Go же такой мощный компилятор, что ловит все виды ошибок, ага)

Ошибки совместимости, внезапно, ловит. Вот прям буквально не соберется.

гошный сервер сииильно меньше. Он умеет те самые, в лучшем случае, 10% от того, что умеет NGINX, которые нужны приложению.

Если это важно для конкретного случая, то можно поискать сервер меньшего размера.

Кеширование, маршрутизация - это часть логики веб-приложения. Та самая часть, которая у вас находится снаружи, а у гоферов - прямо в коде.

Можно сделать и внутри PHP-приложения, аналогично Go.

Проблема с запросом - я смотрю в лог приложения, php-кодеры - в лог приложения и в лог контейнера.

Все логи будут в логах контейнера, иначе сделать - нужно еще постараться.

В Go из рантайм-зависимостей - только glibc.

Ну вот будет у вас патченная glibc. Если вы решили побалоываться альтернативными образами для PHP, почему бы и здесь не упороться?)

Ошибки совместимости, внезапно, ловит. Вот прям буквально не соберется.

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

Если это важно для конкретного случая, то можно поискать сервер меньшего размера.

Apache, NGINX, Roadrunner - поиск окончен.

Можно сделать и внутри PHP-приложения, аналогично Go.

От того, что вы сделали роутинг и кеширование (а кеширование, кстати, как? Пример кода inmemory-кеша в php-приложении покажете?) внутри php-приложения, аналогичные механизмы снаружи не пропадут.

Все логи будут в логах контейнера, иначе сделать - нужно еще постараться.

А! Понял! Логов контейнера хватит всем! А мы зачем-то с какими-то метриками возимся, с трассировками, кастомными логгерами. Логи централизованно собираем, графаны всякие поднимаем. А надо просто в логи контейнера взглянуть, и все будет понятно!

Спасибо, мил человек, просветили!

Ну вот будет у вас патченная glibc. Если вы решили побалоываться альтернативными образами для PHP, почему бы и здесь не упороться?)

Окститесь, мил человек. Glibс - это API ядра Linux. Не, не исключено, конечно, что ядро "поломатое", но тогда, извините, неработоспособное приложение - наименьшая из ваших проблем.

В PHP же ровно та же glibc в зависимостях. С "пропатченной glibc" у вас и php не заведется. Разница в том, что у вас поверх glibc еще собственно php "нужной системы" иметь нужно, фреймворк, вспомогательные библиотеки, веб-сервер и тонну всяких очень нужных вещей. Меньше зависимостей = меньше головной боли. Мне казалось, это очевидно.

Выяснять то, что вы подразумеваете под ошибками совместимости мне лениво) 

Ну ладно, прямо тут вам напишу, чтобы вы на гугл времени не тратили.

Смотрите, есть совместимость уровня API и совместимость уровня ABI. В первом случае Go не скомпилирует код, во втором - требуется только совместимость с glibc (и компилятор на пару с Торвальдсом дают определенные гарантии). Ну, в смысле, с неподходящей версией ядра гошный сервис, вероятнее всего, просто не стартует. Падать во время работы на проде - моветон.

Пример кода inmemory-кеша в php-приложении покажете?

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

Логов контейнера хватит всем! А мы зачем-то с какими-то метриками возимся, с трассировками, кастомными логгерами.

Логи в контейнере как-то запрещают подключать метрики?

Glibс - это API ядра Linux.

Это должно помешать ее пропатчить? Или компилятор Go.

Меньше зависимостей = меньше головной боли

Да, но это не повод выдавать некоторые риски за нестерпимую боль.

компилятор на пару с Торвальдсом дают определенные гарантии

Опенсорс вам никаких гарантий не дает. Если вы берете левый билд, то на выходе можете получить что его автору угодно.

Асинхронщину же на PHP делают, предполагаю, что должны быть средства и стейт иметь.

PHP "создан, чтобы умирать". Т.е. буквально на каждый запрос создается новый процесс операционной системы, который умирает сразу по завершению запроса. Бонусы - насрать на память, даже сборщика мусора нет, потому что все подчистит ОС. Минусы - нет средств иметь стейт приложения.

Логи в контейнере как-то запрещают подключать метрики?

Логи в контейнере и логи приложения - это разные сущности.

Это должно помешать ее пропатчить? Или компилятор Go.

Если вы берете левый билд, то на выходе можете получить что его автору угодно.

При чем тут левый билд-то? При чем тут специально сломанные компиляторы/ядра? Официальный билд ломает совместимость. PHP 7.4 рантайм не гарантирует работоспособность кода под версию 7.3. Да хрен бы с ним, 7.3.1 вполне может не заработать на 7.3.2-рантайме. На официальных билдах.

Да, но это не повод выдавать некоторые риски за нестерпимую боль.

Я не выдаю за нестерпимую боль наличие дополнительных рисков. Я утверждаю, что отсутствие дополнительных рисков - абсолютно точно преимущество.

Да-да, перепутал с RR. Но тут C++, тоже по сути ни разу не PHP.

Вы так говорите, как будто PHP должен быть написан на PHP. А на самом деле ядро и модули для него пишутся на C, C++, наверное ещё немного на чем-то. Собственно, как и Go, вот сюрприз.

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

на с++

Если вопрос нужны ли такие статьи, то ответ «да» возможен при одном условии. Надо разобраться и рассказать почему такие «неожиданные» результаты.

Можно конечно просто вкинуть как есть, но если в комменты придет профи, то будет неприятно)

это неадекватный тест и сравнение совершенно разных ситуаций с т.з. процессора, отсюда и слоновый проигрыш go. Напишите асинхронно с пулом и go сделает php на пару порядков.

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

я когда щас смотрю на php код - диву даюсь от сложности ... классы, наследование, абстрактные клаcсы, трейты, статические методы, статические поля, магические методы, магические поля, анонимные классы, методы классов под флагом final, магия вокруг клонирования объекта, ... все это безусловно продиктовано потребностями реального мира. Но в довесок приходят фреймворки без которых никуда в мире php...и они приносят еще несколько слоев сложности...как на уровне архитектуры так и на уровне оберток к стандартным функциям php...

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

ушел из php уже лет как 10...даже не представляю какой кошмар сейчас представляет из себя собеседования на вакансию php-разработчика..

Таки паттерны проектирования это благо, бери любой проект на spring, angular, symfony, nestjs, и уже сразу примерно знаешь, где что лежит. А вот разобраться в рандомном проекте без фреймворка, легко можно убить неделю другую просто распутывая чью-то лапшу

А вот разобраться в рандомном проекте без фреймворка, легко можно убить неделю другую просто распутывая чью-то лапшу

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

Изумительный самопис это большая редкость, не все могут в архитектуру. Ну и паттерны не зря так называются, нет никакого смысла каждый раз по разному писать решение одной и той же задачи, это скорее минус. Даже если вы один на проекте, для внесения правок каждый раз нужно вспоминать, что именно там за велосипед. Коллега тем более спасибо не скажет. По поводу сложности, паттерны это "сложность" только в первый раз. Ну и фреймворк это конечно не гарантия отсутствия говнокода, но отсутствие фреймворка это значит 100% велосипед, легаси в плохом смысле.

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

ушел из php уже лет как 10...даже не представляю какой кошмар сейчас представляет из себя собеседования на вакансию php-разработчика..

Я не ушёл из php 10 лет назад и да - Вы правы, там кошмар:

  • В требованиях (99% встречающихся вакансий) могут присутствовать как минимум 3 ведущих фреймворка. И если ты не изучал их все (в свободное время), на тебя смотрят как на какого-то неправильного php-программиста.

  • Если ты работал с Laravel, но не работал с Symfony- тебя не возьмут на работу.

  • Если ты работал с Larvael 7, но не работал с Laravel 9 - тебя не возьмут на работу.

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

Но в довесок приходят фреймворки без которых никуда в мире php...и они приносят еще несколько слоев сложности...

Совершенно верно.

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

графоманы-фрейморкоклепатели очень, очень сильно усложнили жизнь программистам

Очень, очень неортодоксальная точка зрения.

Когда-то мне тоже казалось, что php-фрейворки не нужны. Ну в принципе они не особо нужны для мелких проектов с одним разработчиком и его велосипедами.

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

Молодой программист: Убежден, что фреймворки существуют по технической причине: чтобы иногда можно было не писать код, а использовать его из библиотеки/фреймворка, где за тебя его уже сделали. Иногда 90% кода проекта - это фреймворк, а программисты написали только 10%.

Старый программист: Убежден, что фреймворки нужны по бизнес-причине, чтобы ты нанял нового программиста, и он в первый же день уже знает 90% кода твоего проекта, потому что это код фреймворка.

Но с нуля всегда проще, чем копаться в легаси коде. Переписывать с нуля без ларавеля тоже было бы проще.

Это, скорее, проблемы собеседований. Меня однажды на собеседовании про джаву спросили вопрос о том, как себя ведет такой-то код на экзотичной легаси-архитектуре (какой-то HP пятнадцатилетней давности).

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

И есть еще какая-то идея у общественности, что если ты не используешь фреймворк в своем проекте - то ты какой-то ущербный.

Это нормально сейчас. У нас, в JS/TS мире 4-5 актуальных orm и, на мой взгляд, 3 актуальных веб-фрейморвка. В каждой вакансии обязательны знания одной из комбинаций. Иногда нужен fullstack-разработчик, тогда в комбинацию добавляются браузерные фреймворк.

В мире JS/TS из фреймворков в понимании PHP/Java всего два - NestJS и Adonis, остальные - это скорее просто удобный роутинг + middlewares

Посмотрите в сторону JS - там фреймворков x10 от пхп-шных

7 лет опыта на PHP, этим летом уволился, искал работу. 30+ собеседований, всего 2 оффера. Еще штук 20 компаний отказали сразу, без собесов. 3 года назад, когда у меня было намного меньше опыта, взяли на второй день после активации резюме на Хабр.Карьере и hh.ru.

Это просто рынок труда в целом сдох, а не сам язык.

Искали на php также?

выскажу непопулярное мнение, но го победил простотой

Это не просто популярное мнение, а философия, заложенная в сам язык)

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

ногострелов там слишком дофига для простого языка

Да, тут можно подискутировать по поводу определения простоты. Лично я больше склоняюсь к утверждению, что Go намеренно простой в плане синтаксиса: есть ограниченное число конструкций, которые надо изучить, чтобы понимать любой код.

В плане синтаксиса - пожалуй, соглашусь, сам всё-таки обжигался только на семантике.

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

Не то чтобы сильно не согласен, но хочется примеров, что вы имеете в виду.

Лично я считаю Go одним из самых "немагических" языков, но возможно я какие-то вещи уже считаю нормой.

Да начиная от того, как работают каналы(что будет если прочитать/записать в закрытый канал, а если в nil) и заканчивая особенностями ΙΟ операций в горутинах, мультиплексером, парковой треда на сисколах и т.д. Да даже на уровне читабельности кода, есть вещи, про которые если не знаешь, то не догадаешься. Ну пример:

Что будет выведно на экран?

func main() {

  var i int = 1

  defer fmt.Println("result =>",func() int { return i * 2 }())

  i++ 

}

А тут?

func main() {
  var data *byte
  var in interface{}  
 
  fmt.Println(in, in == nil)
  
  in = data

  fmt.Println(data, data == nil)
  fmt.Println(in, in == nil)
  fmt.Println("eq", data == in)
}

что будет если прочитать/записать в закрытый канал, а если в nil

Это просто надо знать)

Дело в том, что это слишком специфичные вещи, чтобы в массовом сознании для них сформировался какой-то там "интуитивный подход". Вы же наверняка мне хотите сказать, что вот в языке N это происходит по-другому, и эта реализация вам кажется более интуитивной, верно? Только, скорее всего, когда вы знакомились с языком N, вы не задумывались о том, что интуитивно, а что нет, вы просто учили как это работает.

Пример 1: вы отложили Println, который инициализировался в моменте. Это ожидаемое поведение, ИМХО.

Пример 2: да, больно. Но вы изначально допустили магию в виде interface{}. В языке со строгой типизацией интуитивно понятно, что пустой интерфейс будет вести себя непредсказуемо. Какая практическая задача может стоять за таким кодом? Надеюсь, не парсинг JSON же?

1) Так в первом примере что выведет, 2 или 4? И почему это ожидаемо?

2) Дело не в том пустой интерфейс или нет, а в том, что у него появляется значение, даже если туда присвоить пустой указатель. И это абсолютно неочевидно, очередной пункт, что надо просто "знать". И кейс с выстрелом себе в ногу может быть тривиальным и бытовым:

func do(in MyInterface) {
	fmt.Println(in == nil)
	if in != nil {
		in.Do()
	}
}

type MyInterface interface {
	Do()
}

type MyData struct {
	name string
}

func (c *MyData) Do() {
	fmt.Println("Do from MyData", c.name)
}

func main() {

	do(nil) // true
	var data *MyData = nil
	do(data) // false and panic
}

В любом языке есть вещи, которые нужно просто знать. Потому что на определённом уровне погружения в язык заканчивается "common sense" и начинается фантазия разработчиков. И вероятность того, что это фантазия будет совпадать с вашей, стремится к нулю. Субъективное удобство пользования языком зависит от того, насколько глубоко эти вещи совпадают. Так работает наше мышление, отдельные языки тут не причём.

Вы же, надеюсь, не хотите своими примерами убедить меня в том, что C# вам кажется интуитивнее, потому что его вы выучили первым?

Смотрите, мы же начали с того, что "Go простой язык" и вы сами попросили примеры того, где все совсем не так просто. Речь тут не про то, что условный C# понятнее или нет, а про то, что широко рекламируемая "простота" Go обманчива и там тоже есть свои подводные камни, как и в других языках.

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

Естественно. Ваше мышление не может на 100% совпадать с мышлением Роба Пайка. Однако так ли велико количество и "глубина" этих подводных камней в сравнении с другими языками?

BTW, я выше уже отвечал собеседнику, что под простотой Go чаще рекламируют простоту синтаксиса. Притом чаще простоту чтения, а не написания: все эти бесконечные if err != nil нужны для очевидности, не для удобства. То, что язык всё равно требует изучения, чтобы на нём грамотно писать - мысль само собой разумеющаяся.

Однако так ли велико количество и "глубина" этих подводных камней в сравнении с другими языками?

Не знаю, а как вы считать предлагаете? На мой взгляд это сложный вопрос, который будет упираться в субъективное воспритие, по-этому я редуцирую тут до бинарной логики - если есть хоть один "подводный камень", значит никакой простоты уже нет.

если есть хоть один "подводный камень", значит никакой простоты уже нет

Ахаха. Ну тогда ни один язык не может называться простым, очевидно. Разве что ассемблер, но как-то реализовывать на нём бизнес-логику не тянет.

На мой взгляд это сложный вопрос, который будет упираться в субъективное воспритие

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

Ну тогда ни один язык не может называться простым

Паскаль простой язык. Но да, вряд ли вы захотите на нем писать сложный энтерпрайз код.

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

Большое это сколько? Опять же, у меня есть знакомые, которые наоборот перешли с го на .net с аргументацией что на C# писать проще(за счет библиотек, синтакс сахара, linq и т.д.). А есть те, кто с го перешел на kotlin, тоже имея свои резонные причины. Мы так просто упремся в anecdotal evidence. На мой взгляд го это хороший инструмент для определенных задач и он точно внес свой вклад в развитие разработки как таковой, занял свою нишу, но его маркетинг склонен несколько преувеличивать его достоинства, вроде простоты разработки и универсальности.

перешли с го на .net с аргументацией что на C# писать проще(за счет библиотек, синтакс сахара, linq и т.д.)

Заметьте, это буквально подтверждает то, что я написал выше: Go проще читать, не писать на нём.

Но я соглашусь, что если Go рекламируют как "простой во всём язык" - это неверно.

Go проще читать, не писать на нём.

Да вот что-то как-то нет. Я когда-то давно писал на C, потом на плюсах, потом на питоне, потом на js. Код на го не могу читать. Надо прям учить синтаксис, он как сны в 40, вроде всё знакомое, но какой-то бред происходит. При этом, новый для меня C# и rust читаются очень просто. Даже F# с хаскелем читаются проще го.

Код на го не могу читать.

Ну, это наброс. Даже прокомментировать толком нечего. Не любите Go - так и скажите.

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

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

Вот хелловорлды очень простые и понятные, тут не поспоришь.

Дело не в том пустой интерфейс или нет, а в том, что у него появляется значение, даже если туда присвоить пустой указатель. И это абсолютно неочевидно, очередной пункт, что надо просто "знать".

Вся беда в экстраполяции. Мы берем свои знания об интерфейсах в Java, C#, TS и б-г знает откуда еще и пытаемся экстраполировать на гошную реализацию. И тут, внезапно, оказывается, что у языка есть специфика, и совы не то, чем кажутся.

Только есть один нюанс. Специфика - она во всех языках есть. В JS можно приводить значение к булеву ( if (value) вернет false для null и undefined, в остальных случаях true), и это тоже надо знать. И сравниваем мы с nil, а не с null, как у соседей. Разработчики языка специально ввели nil, чтобы явно обозначить, что это не совсем то же самое (или совсем не то же самое), что null.

Ожидание от слайса поведения вектора - тоже частая беда. Он не вектор, был бы вектор, вектором бы и назывался.

Каналы ругать? Ну это совсем зря! С ними-то откуда непонимание, если у соседей их просто нет? Откуда экстраполяция ложных предположения возникает? И поведение каналов - строго логично. Паника на запись в закрытый канал - ну, вы ровно перед ней закрыли канал (т.е. буквально пообещали больше в него не писать). Чтение zero-values из закрытого канала - гениальное решение! Читателей может быть больше 1, а каналы часто используются для оповещения соседних горутин о завершении работы. Если надо оповестить 10 горутин о завершении - положить в канал 10 сообщений? А если 100? А если мы не знаем, сколько у нас подписчиков?

В языке 21 ключевое слово, и да, под буквально каждым из них "закопана какая-то грабля" с точки зрения экстраполяции опыта из других языков. Вопрос в том, что слов всего 21, поэтому мы четко знаем, что есть 21 механизм и ровно 21 грабля, которые надо знать. Это и называется "простота" с точки зрения Го. Сколько грабель закопано в C#, Java, C++, PHP и т.д. - науке пока не известно.

Мы берем свои знания об интерфейсах в Java, C#, TS и б-г знает откуда еще и пытаемся экстраполировать на гошную реализацию.

Спасибо. Это буквально мысль, которую я хотел донести.

  1. "Го - простой язык"

  2. Четыре абзаца текста про специфику, которую "надо знать, а не экстраполировать свой предыдущий опыт

Выглядит убедительно, да. Ну тогда и С++ простой язык, просто у него есть своя специфика, которую надо знать.

языке 21 ключевое слово

В брейнфаке 7 ключевых слов(символов). "Простота" программ на нем удивительна. Но вообще да, придумать собственное определение простоты и потом с ним заявлять что ты всех "победил" - отличный маркетинговый прием.

ровно 21 грабля

Если у вас на каждое ключевое слово в языке заложено по проблеме это не звучит как что-то хорошее. Ну и про "ровно" - особенности preemptive и cooperative шедулинга они к каком ключевому слову относятся? А network poller starvation на большом числе сокетов это какое слово?

С ними-то откуда непонимание, если у соседей их просто нет

Каналы есть в джаве, дотнете, расте, С++ и множестве других языков потом что это просто подход к асинхрому взаимодействию, он может быть реализован на любом языке. У кого и чего нет?

Сколько грабель закопано в C#, Java, C++, PHP и т.д. - науке пока не известно.

Эти языки никто и не называет "удивительно простыми".

Эко вас порвало, когда вам по существу ответили, а не нейтрально, как я)

Вам чем-то лично гошники насолили? Может, кто жену увёл или работу?

Мне лично "гошники насолили" тем, что мой нынешний коммерческий проект на Go, и даже несмотря на его (проекта) сравнительную простоту, например, ситуаций типа "да, компилятор это проверять не умеет, просто будь внимателен" там намного больше, чем я привык по своим персональным проектам.

Ой, как нехорошо.
Я бы, конечно, поинтересовался на чём вы пишете свои проекты, но кажется, что корень проблемы в противопоставлении "коммерческий проект" и "персональные проекты". В своём проекте для вас в любом случае всё будет понятно и очевидно - мне даже неловко это проговаривать, если честно. Все взрослые люди, а у вас получается какие-то детские обиды: "меня заставляют писать на Go, поэтому Go - плохой".
Давайте не будем так.

В своём проекте мне "будет понятно и очевидно" не потому что он мой, а потому что в нём я могу выбрать язык, компилятор которого меня подстрахует в существенно большем количестве случаев, чем это можно позволить себе в коммерческом. И да, Go для меня "плохой" не потому что "заставляют", а потому что я вижу разницу между "поменял поле, пробежался по ошибкам компилятора, собралось - работает" и "поменял поле, полчаса бегаю по подсказкам от IDE, но, пока не пройду через QA - всё равно не уверен, что поправил всё, что требовалось".

Go для меня "плохой" не потому что "заставляют", а потому что я вижу разницу между "поменял поле, пробежался по ошибкам компилятора, собралось - работает" и "поменял поле, полчаса бегаю по подсказкам от IDE, но, пока не пройду через QA - всё равно не уверен, что поправил всё, что требовалось".

Погодите, а что не так в го с изменением поля? Мне казалось "поменял поле, пробежался по ошибкам компилятора, собралось - работает" - это строго поведение Go, он же явно-строго-статически типизированный язык!

Поспешил, виноват - не "поменял поле", конечно же, а "добавил поле".

А в каком языке добавленное поле поломает компиляцию? Мы опять про Rust?)

Ну ладно, подключите линтер - отлично справляется с вашей задачей. Матерится исправно ровно на вашу ситуацию.

...в любом, в котором есть нормальное создание объекта литералом? Да хоть в том же TypeScript, как минимум (хотя, да, личные проекты у меня в основном на Rust, но он в этом плане заведомо не уникален). А линтер здесь-то поможет, а в куче других мест наругается впустую, потому как оставлять поля структур незаполненными - это, насколько я вижу по действиям коллег, вполне себе идиоматичный Go.

export class SomeClass {
    public someField: string;
    public someAnotherField: number;
    public newField?: string; // это новое поле
}

const instance: SomeClass = {someField: 'text', someAnotherField: 0};

"Ну, Андрий, помогли тебе твои ляхи?" )

Да, система типов в TS, C# со товарищи гораздо более развесистая, и даже, возможно, некоторые плюшки оттуда (постепенно и микроскопическими дозами, чтобы ничего не сломать) будут появляться в Go. Сам по себе он не то чтобы концептуально-великий язык. Он утилитарный, с ровно одной фичей, сделанной действительно хорошо: M:N асинхронность. Остальные части языка в лучшем случае неплохи (а некоторые и откровенно ниоч).

Конкретно эта беда реально закрывается линтером, если в логике вашего приложения это действительно беда (чаще не закрывается). И фишка TS, которой в этом кейсе не хватает Go - это не "нормальное создание объекта литералом", а type-safety.

В Го приняли подход с zero-values, в массе языков посвежее или одного с ним возраста - стали копать в сторону опциональных значений. По сути, гошный тип можно привести к тому же поведению, что и TS, но с линтером и приседаниями.

Вопрос в том, что вы получаете от языка. От TS - развесистую (но сиииильно не идеальную) систему типов (которая накручена поверх JS, и потому вполне неиллюзорно имеет дыры. Хотите то же самое, но без дыр - вам в C#). От Go - RPS.

Если заради RPS вы готовы написать валидацию и покрыть мутные места тестами, написать ручками конструкторы и вообще поприседать - вам в Go. Если вы пишете сложную бизнес-систему с иерархией бизнесовых сущностей, сложной доменной логикой, кучей взаимосвязанных циферок и прочими прелестями денежных транзакций - ну, вам на Go делать особо нечего, для вас есть C# и Java (не TypeScript, он не для вас)

public record SomeClass(
  string SomeField, 
  int SomeAnotherField,
  string? NewField = null
);


SomeClass instance = new("text", 0);
// или, если надо явно указать типы
SomeClass instance = new(SomeField: "text", SomeAnotherField: 0);
// или
var instance = new SomeClass("text", 0);
// смотря что имеет большее значение семантически

public newField?: string; // это новое поле

Это новое поле, явно помеченное как опциональное. Убираем опциональность, смотрим на сообщения об ошибках, правим, если надо - возвращаем опциональность обратно.

система типов в TS, C# со товарищи гораздо более развесистая

А тут не про "развесистость" системы типов вопрос. Тут вопрос про строгость проверок. Собственно type-safety, да.

Если заради RPS вы готовы написать валидацию и покрыть мутные места тестами, написать ручками конструкторы и вообще поприседать - вам в Go.

Ну вот так и живём, да. Что не отменяет того факта, что в других языках это "покрыть мутные места тестами и вообще поприседать" было бы нужно в заметно меньшей степени. Объективно это просто один из многих trade-off-ов, конечно.

А тут не про "развесистость" системы типов вопрос. Тут вопрос про строгость проверок. Собственно type-safety, да.

Собственно null-safety - это как раз про развесистую систему типов. И вот тут Go не особо хорош. Там, где она реально аффектит - Go малоприменим. Где болячки закрываются линтером - хватает Go.

в других языках это "покрыть мутные места тестами и вообще поприседать" было бы нужно в заметно меньшей степени

Совершенно верно. Просто в кейсах "просирания максимального количества RPSов в единицу времени" придется приседать уже в других языках. Так и живем, trade-off)

Просто изначально был разговор про PHP. Там мы и с RPS-ами поприседаем, и с этим кейсом. И все это от души, и безрезультатно.

Во-первых я бы не сказал что спорные заявления типа "в других языка нет каналов" это ответ по существу.

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

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

Ну тогда и С++ простой язык, просто у него есть своя специфика, которую надо знать.

Это уже не располагает к серьёзной дискуссии. Тон-то вы сохранили, а вот качество аргументов у вас куда-то делось.

Если честно уже после этого "аргумента" надо было прекращать с вами пустословить:

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

Сами для себя изобрели систему ценностей и всех по ней классифицировали. Ну поздравляю, а нас это как должно волновать?

вот он, уровень аргументации GO разработчиков

А это вообще что? Классификация разработчиков по языкам программирования? Элитаризм так и прёт и скрывать не получается?

В брейнфаке 7 ключевых слов(символов). "Простота" программ на нем удивительна

Но я ведь ровно о том и говорю: язык - простой, писать на нем программы - сложно. Сложнее, чем на PHP, например.

Если у вас на каждое ключевое слово в языке заложено по проблеме это не звучит как что-то хорошее

Вы упустили кусок "с точки зрения экстраполяции опыта из других языков". Если первая реализация интерфейсов, которую вы видите в своей жизни - гошная, то для вас может показаться странной реализация в той же Java...

Сравнение интерфейса с nil ругаете? Оно ведет себя не так, как сравнение с null? Присмотритесь внимательно, разработчики языка специально "соломку подстелили", nil в язык вместо null ввели. И даже статью написали, что одно от другого отличается. Не помогло(

Слайс не вектор? Ну, он и называется не "вектором". Ошибка не исключение? Дык, и называется не исключением. map называется map? Дык, оно и ведет себя ровно так, как у соседей! Оно даже ссылочное!

особенности preemptive и cooperative шедулинга они к каком ключевому слову относятся

А они, вообще-то, не к языку относятся. Они в разделе "детали реализации, ограничения платформы".

Эти языки никто и не называет "удивительно простыми".

Дык, у них и спецификация не на 20 страниц?

Го - простой язык. Самый простой, пожалуй, из существующих энтерпрайзных языков.

Он не в понимании простой, он по своей организации простой, компактный и достаточно непротиворечивый. Чтобы на Го писать грамотный идиоматичный код, достаточно пройти Go Tour, внимательно прочитать (и понять, что там написано) Effective Go и... и все.

Для того, чтобы написать хорошее приложение, этого, конечно, недостаточно. А чтобы идиоматичный код - вполне. В Java вы типы коллекций перебирать дольше будете, например.

 язык - простой, писать на нем программы - сложно

 Го - простой язык. Самый простой, пожалуй, из существующих энтерпрайзных языков.

Он не в понимании простой, он по своей организации простой

С этим я вполне могу согласиться. Я думаю мы даже в каком-то смысле говорим обо одном и том же, просто изначально вкладывая в понятие "простота" несколько разные смыслы.

func main() {

  var i int = 1

  defer fmt.Println("result =>",func() int { return i * 2 }())

  i++ 

}

Здесь 2


А если сделать так:

	defer func() {
		fmt.Println("result =>", func() int { return i * 2 }())
	}()

то 4.

func main() {
  var data *byte
  var in interface{}  
 
  fmt.Println(in, in == nil)
  
  in = data

  fmt.Println(data, data == nil)
  fmt.Println(in, in == nil)
  fmt.Println("eq", data == in)
}

nil true

nil true

nil false

eq true

Я принят?)

хочется примеров

Так ещё в 2016 году примеров накидали:

https://habr.com/ru/companies/vk/articles/314804/

С тех пор кол-во WAT в Go только увеличилось. То, что он простой - это не более, чем популярное заблуждение, навязанное агрессивным маркетингом Google.

Go "простой" только в понимании организации самого языка, его компактности, размера языкового багажа. Он даже не простой, а лаконичный. Примерно как язык папуасов Новой Гвинеи очень прост в сравнении с русским языком.

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

Добро пожаловать в Typescript ))

Я разрабатываю в том числе и на Го. То что нету фреймворков иногда мешает - приходится всю эту логику реализовывать самому от сервиса к сервису.

Мне показалось не очень удобным реализовывать бизнес логику - например, надо обработать сразу несколько сущностей из бд , приходится постоянно вставлять проверки на if err != nil. Мне кажется языку не хватает исключений.

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

Думаю что каждый пишет как может сервисы на Го, так как единых гайдов по организации пакетов, файлов нету.

ниразу мне за 7 лет в го не помешало то что нет фреймворков. единственное чего не хватает go - enum...все.

Думаю что каждый пишет как может сервисы на Го, так как единых гайдов {...} нету.

Есть самопровозглашённый гайд от Uber и во многих компаниях он, в принципе, считается стандартом.

То что нету фреймворков иногда мешает - приходится всю эту логику реализовывать самому от сервиса к сервису

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

надо обработать сразу несколько сущностей из бд , приходится постоянно вставлять проверки на if err != nil. Мне кажется языку не хватает исключений

Не совсем понятно, как связаны сущности из БД и проверки на err != nil. А насчет исключений - ну, подвижки в сторону групповой обработки ошибок есть, но достаточно вялые, потому что не очевидно, зачем это надо. Просто в го концепция: обработай ошибку на месте. Право на жизнь имеет, т.к. исключения тоже сильно не идеальны.

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

Боб Мартин бы с вами не согласился. Возможно даже наругал бы... Откройте для себя композицию!

У фреймворков же есть оборотная сторона: они большие, монструозные и, в 90% случаев, излишние.

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

Т.е. их надо знать, надо уметь применять, надо изучать. На выходе мы получаем специалиста в определенном фреймворке.

И чем это плохо? Эти знания лишними не будут.

Боб Мартин бы с вами не согласился. Возможно даже наругал бы... Откройте для себя композицию!

Так он и не абсолютный авторитет какой-нибудь (да и вроде он не прям категорично против наследований). А композиция - это не полная замена наследованию.

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

Однако это не отменяет вопроса о том, каким местом связан роутер и драйвер БД. Почему они часть одного фреймворка, и чем это лучше, чем роутер отдельной библиотекой + обвязка над БД - отдельной.

Заметьте, ни слова о велосипедах. Все библиотечное.

И чем это плохо? Эти знания лишними не будут.

Абстракции, принятые во фреймворке, зачастую - велосипеды. Что в этом хорошего?

Однако это не отменяет вопроса о том, каким местом связан роутер и драйвер БД. Почему они часть одного фреймворка, и чем это лучше, чем роутер отдельной библиотекой + обвязка над БД - отдельной.

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

Заметьте, ни слова о велосипедах. Все библиотечное.

Так библиотеки обычно от разных авторов (разного качества и разной степени совместимости между собой), велосипедом будет объединение этих библиотек. Сколько ни смотрел Go-шных проектов - у каждого своя уникальная архитектура, в которой не так просто быстро разобраться.

Абстракции, принятые во фреймворке, зачастую - велосипеды. Что в этом хорошего?

Но хорошо продуманные, спроектированные и обкатанные. Знание их даёт полезный опыт. Некоторые решения можно потом применять и вне фреймворков.

там все компоненты хорошо интегрированы

Роутер хорошо интегрирован с драйвером БД? А зачем (и как)? А это точно хорошо, например, что для переползания на другую БД может понадобиться переписывать маршрутизацию? Может, ну его нафиг, такую интеграцию?

Но есть же фреймворки и без всего набора (только с роутером, например).

Смотрите, фреймворк - это шаблон, штука, внутри которой вы пишете приложения. Он диктует вам, как приложение организовывать. И есть библиотека - это штука, функционал которой вы используете внутри приложения.

Если роутер (хорошо если пара процентов от суммарного размера приложения) является фреймворком (т.е. определяет то, как вам писать приложение) - может, ну его нафиг такой роутер.

А вот библиотечный роутер - это круто! Ничего против не имею, и их в Go имеется, в ассортименте, большинство хорошие.

Так библиотеки обычно от разных авторов (разного качества и разной степени совместимости между собой)

Ну какой совместимости мы хотим от роутера/контроллера и, допустим, ORM'а, драйвера БД или, например, брокера сообщений? Да они знать друг про друга ничего не должны!

велосипедом будет объединение этих библиотек

Все верно, объединение этих библиотек в одну большую сущность - велосипед, который принято называть "фреймворк".

Сколько ни смотрел Go-шных проектов - у каждого своя уникальная архитектура, в которой не так просто быстро разобраться.

Да так же все, как у людей. Роутер -> слой контроллеров (их принято называть http.Handler) -> бизнесовый сервис. Внутри сервиса - ну тут да, демократия, доходящая до анархии.

С другой стороны, видел я фреймворки, в которые автор затащил событийную модель, и попытки реализовать транзакционный CRUD поверх. Вот честно, там такое получается, го-анархистам и не снилось!

Но хорошо продуманные, спроектированные и обкатанные.

Насчет хорошо продуманных и спроектированных - да вот по-разному бывает. Иногда автор решит, например, что в контроллере заголовки запроса не нужны, или urlPath не отдаст - гений, блин.

Пожалуй, самая хорошо продуманная и спроектированная штука, которую я видел - это http.HandlerFunc в Go. Просто один контракт func(w http.ResponseWirter, r *http.Request) , делающий, де-факто, не нужными веб-фреймворки на Go.

Знание их даёт полезный опыт. Некоторые решения можно потом применять и вне фреймворков.

Вот тут, скорее, соглашусь. На них стоит посмотреть, попробовать, понять, почему они нафиг не нужны и начинать применять 3-слойную архитектуру вне фреймворков. Так в Go и делают.

Роутер хорошо интегрирован с драйвером БД?

Что значит интегрирован с драйвером? Я ничего подобного не писал же.

Если роутер (хорошо если пара процентов от суммарного размера приложения) является фреймворком (т.е. определяет то, как вам писать приложение) - может, ну его нафиг такой роутер.

А вот библиотечный роутер - это круто!

Фреймворк не обязательно должен диктовать всю структуру приложения. Такие мелкие фреймворки называются фреймворками лишь номинально. Они в принципе не могут описывать всю архитектуру.

Ну какой совместимости мы хотим от роутера/контроллера и, допустим, ORM'а, драйвера БД или, например, брокера сообщений? Да они знать друг про друга ничего не должны!

Так вы расширьте список библиотек, и узнаете. Посмотрите популярные full-stack фреймворки.

Что значит интегрирован с драйвером? Я ничего подобного не писал же.

Ну вот, вы же писали?

в большинстве типовых веб-приложениях они понадобятся, и там все компоненты хорошо интегрированы.

Окей, открываем доку Laravel: Роутинг, Цикл жизни запроса, Базы Данных, Eloquent ORM

Идем в Symphony: роутинг, бла-бла-бла, Базы Данных, Doctrine ORM

Доку Django смотреть будем? Какие там еще веб-фремворки в моде?

Каким образом и, самое главное, зачем все это интегрировано?

Фреймворк не обязательно должен диктовать всю структуру приложения.

https://ru.wikipedia.org/wiki/%D0%A4%D1%80%D0%B5%D0%B9%D0%BC%D0%B2%D0%BE%D1%80%D0%BA

Фреймворк потому и фреймворк (дословно "каркас"), что он диктует архитектуру. Если вы взяли что-то, и в рамках взятого решения пишете код - это фрейворк. Если вы взяли что-то и заюзали как придумали внутри своего кода - это библиотека.

Так вы расширьте список библиотек, и узнаете

Что я узнаю? Что http-роутер не должен иметь в зависимостях ORM? Я и так это знаю.

Посмотрите популярные full-stack фреймворки.

А можно я этого делать не буду? Ну пожаааалуйста!

Я вам говорю, что даже в пределах бекенда "тесная интеграция роутера и ORM" - зло, а вы мне предлагаете всю цепочку от фронта до таблички в Postgres'е одним бандлом узреть... Что я вам плохого-то сделал?

В Symfony компоненты изолированны друг от друга. Вы можете вообще не загружать пакет с ORM или использовать любую другую реализацию.

В документации, естественно, описаны все доступные компоненты.

И архитектуру никто не диктует, вы можете спокойно подключать нужные компоненты из vendor, только те, которые ваше приложение использует. Тот же Zend Framework (мир его праху) в моей практике тоже так использовался: отдельные компоненты подключены (валидаторы, query builder), а всякие роутеры-контроллеры - свои.

В Symfony компоненты изолированны друг от друга. Вы можете вообще не загружать пакет с ORM или использовать любую другую реализацию.

Дык, верю. И именно по этой причине искренне недоумеваю:

  1. Если они изолированы, никак друг от друга не зависят, могут быть использованы по отдельности и не накладывают ограничений на архитектуру проекта, то фреймворк, получается - просто набор рандомных библиотек? А зачем их в кучу сложили? ZverCD же какой-то получается.

  2. Если во фреймворке есть какое-то удобное решение (пусть будет самописный ORM), почему он не поставляется отдельной библиотекой? А он точно за собой половину фреймворка в зависимости не притащит? Допустим, я использую Symphony, но ORM мне Laravel'овский нравится. Что делать? Оба фреймворка в проект тащить?

Тот же Zend Framework (мир его праху) в моей практике тоже так использовался: отдельные компоненты подключены (валидаторы, query builder), а всякие роутеры-контроллеры - свои.

Ну и зачем? Почему не взять нужный валидатор, нужный query-builder, роутер и контроллер по вкусу? Все равно же, получается, делаете то же самое, что гоферы (пользуете те части фреймворка, которые нужны), только не в виде библиотек, а в виде "подключаемых отдельно частей фреймворка". В чем смысл-то?

Как из "там [речь о фреймоврке] все компоненты хорошо интегрированы" получилось "Роутер хорошо интегрирован с драйвером БД"?

Что-то мало компонентов вы перечислили. Этого на полноценное приложение не хватит. А как страницы рендерить? А статику (js/css) как собирать? Где аутентификация/авторизация? А там и отправка писем понадобится. Работа с фоновыми задачами почти наверняка пригодится. Плюс там уже продуманы базовые средства безопасности от всяких xss, csrf, sql injection и т.д.; работа с куками, сессиями, http заголовками. И конечно же, средства тестирования.

Как из "там [речь о фреймоврке] все компоненты хорошо интегрированы" получилось "Роутер хорошо интегрирован с драйвером БД"?

Дык, элементарно-логически получается. Если все компоненты хорошо интегрированы, значит смотрим в список компонентов. А там роутер есть и драйвер БД есть. И они, очевидно, должны быть интегрированы, потому что попадают под определение все.

А как страницы рендерить?

Любым из доступных способов: стандартным шаблонизатором, библиотечным, самописным, ручками собирать построчно - тысячи вариантов. Но, что важно, совершенно точно независимо от роутинга с одной стороны и работы с БД - с другой.

А статику (js/css) как собирать?

Хм, очевидно, вообще не средствами Go-шного бекенда. PHP для этой задачи тоже, впрочем, такой себе инструмент. JS хорошо бандлится, говорят, фронтовым тулингом. CSS - что-то мне шепчет про SCSS, SAAS, LESS. В любом случае кухня, к бекенду отношения не имеющая. Ответственность бекенда со стороны статики заканчивается на этапе "отдать статический файл".

Где аутентификация/авторизация?

В мидлваринах и библиотеках аутентификации/авторизации?

А там и отправка писем понадобится. 

Все верно. Когда понадобится, напишем import "some/lib/for/sending/email".

Думаю, у вас не сильно короче получится.

Работа с фоновыми задачами почти наверняка пригодится.

Вы на полном серьезе гоферу про фоновые задачи рассказываете?)

Плюс там уже продуманы базовые средства безопасности от всяких xss, csrf, sql injection и т.д.

Базовые средства безопасности - это иллюзия безопасности.

Мидлвари есть, CORS мы умеем. Побарывать SQL-injection в 2024 - уже даже не смешно. Из коробки не работает.

работа с куками, сессиями, http заголовками

Вы реально считаете, что Go не умеет работать с куками, сессиями и http-header'ами?) А вне фреймворка как-то с куками, сессиями и хедерами точно никак не поработаешь?

И конечно же, средства тестирования.

А с ними-то в Go что не так? Из коробки же!

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

Снова у вас какие-то непонятные выводы. Я ничего не писал про то, что go чего-то не умеет. Не сомневаюсь, что там есть куча разных библиотек на все случаи жизни. Я пишу о том, что входит в стандартный набор фреймворков, а то вы до пары библиотек всё сводите. Это просто готовый стандартный набор всех этих библиотек, мидлварей и тулингов, которым можно сразу быстро и легко пользоваться.

JS хорошо бандлится, говорят, фронтовым тулингом.

Не хочется ради пары скриптиков тащить этот нодовый тулинг.

Вы на полном серьезе гоферу про фоновые задачи рассказываете?)

Имел в виду отложенные, не параллельные (если вы об этом подумали).

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

https://ru.wikipedia.org/wiki/%D0%98%D0%BD%D1%82%D0%B5%D0%B3%D1%80%D0%B0%D1%86%D0%B8%D1%8F

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

Я пишу о том, что входит в стандартный набор фреймворков, а то вы до пары библиотек всё сводите.

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

Откуда ноги растут - понятно. Нестабильный рантайм языка порождает сложность сборки этих самых библиотек в одну кучу. "Интеграция" состоит в том, что кто-то заботливо сложил все в кучку, собрал нужные версии нужных кусков кода, которые способны запуститься на одной версии рантайма.

Болячка, стоит признать, постепенно отходит в прошлое (все же язык постабильней стал, хотя до сих пор вижу в резюме кандидатов строчки о достижениях на прошлых местах работы типа "переписал проект с php7.3 на php7.4"). Но привычка, мол, это типа круто и у подхода есть какие-то достоинства будет отмирать еще долго. Дольше PHP.

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

Стандартный - это когда в стандартной библиотеке языка. А тут - в каждом фреймворке свой набор велосипедов.

Не хочется ради пары скриптиков тащить этот нодовый тулинг.

Ну, положите эту пару скриптиков в одну папочку и одним статическим хендлером отдавайте наружу. PHP/Go тут вообще каким боком? Они ж бандлером JS работать все равно не умеют.

Имел в виду отложенные, не параллельные (если вы об этом подумали).

А вот это:

а) просто еще одна php-специфичная проблема, которую приходится решать сторонними средствами по типу cron'а (потому что процесс короткоживущий)

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

Ну тоже мне, счастье великое нашли.

А давайте подождём. Есть куча языков, которые "побеждали простотой". И Java, и Python, и даже C#. А проходит лет 20 -- и уже можно смотреть, с какой скоростью разбухает официальная документация. Это какая-то прямо неизбежная эволюция: начинаем с "более лучшего Бейсика", а дальше начинается: как жить без лямбд, как жить без дженериков, как жить (подставьте своё). Ну и на выходе получаем ровно то же, а то и хуже, типа C++, который на этапе "C с классами" был достаточно тонкой надстройкой над C, а теперь вот оно как вышло.

Почти все серверы поддерживают php из коробки/ по умолчанию, хостинг для php гораздо дешевле любых других языков, достаточно проработанные системы разработки, сделать магазин проще чем на wordpress не встречал, множество готовый материалов. И есть много - много действительно готовых пакетов, тем, шаблонов и прочего и это бесплатно или почти бесплатно и попробуйте сделать магазин на golang хотя бы за 10 раз больше времени, чем на php.

А скорости работы разных языков - ну редко когда нужно миллион раз в цикле чего-то разобрать. Так что на счёт скорости в реальных проектах - вроде бы golang быстрее, а может и нет, поскольку считается не только время, но и процессорные ресурсы, память, дисковое пространство и другое.

И вроде бы php вовсе не сдаёт позиции уже много лет подрят и даже неплохо развивается и даже может излишне усложняется без внятных объяснений зачем так делают.

Ну так это сравнение тёплого с мягким.

Но по существу ваших тезисов:

Go везде будет работать. Хостинг для Go это вообще любая кофеварка. Да его на будильнике можно запустить. Ему не нужно ничего. Никаких nginx, php-fpm и прочего. Только голая ОС.

Скорость работы языков сравнивать вообще моветон. Надо сравнивать производительность в конкретных типах задач. Производительность это сколько полезной работы может выполнить приложение в единицу времени. Обычно, это количество запросов с какой-никакой полезной нагрузкой (чаще всего бизнесу нужны походы в БД, в другие службы, ну или чтение/запись с диска на крайний). И сколько ресурсов ему для этого потребуется.

Вот в примере автора, никакая полезная нагрузка не приложена. Некая строка c JSON десериализуется в некий объект,.. чтобы что с ним сделать? А ничего. Оптимизатор может вообще эту инструкцию выкинуть, или использовать кеш. Сравнивать надо уметь, а неумеючи можно натянуть сову на глобус, что собственно автор и делает в статье. А ещё и без ссылок на код, из разряда "верьте мне".

PHP свои позиции сдаёт, но это процесс не быстрый, учитывая колоссальное количество бекграунда, написанных решений, поддерживаемых проектов и огромной армии разработчиков. Да, это правда, поднять средней руки интернет-магазинчик на небольшую аудиторию, выгоднее сделать на PHP, при чём даже без особых знаний этого языка, или с минимальными познаниями.

Но напрашивается вопрос. Если пыха такая непобедимая и непотопляемая, зачем и откуда развиваются другие ЯП семимильными шагами и активно внедряются в процесс разработки ПО? Ведь от добра добра не ищут. Не задумывались об этом? Я не к тому, что пыха всё, а к тому, что надо трезво смотреть на вещи не с позиции "здесь и сейчас", а ретроспективно и перспективно.

Хостинг для Go это вообще любая кофеварка. Да его на будильнике можно запустить. Ему не нужно ничего. Никаких nginx, php-fpm и прочего. Только голая ОС.

Только виртуалка с голой ОС стоит дороже шаред-хостинга с nginx (на примере хетцнера более чем в 2 раза).

Ну и в каком-нить ISPmanager/Vesta тебе сразу и вордпресс, и почтовик, и днс, и летсенкрипт и все в 2 клика мышью.

Ну вы ещё с low-code хостингом сравните. Или с хостингом уже готового интернет-магазина, сайта, блога, который вообще на чём угодно может быть написан, просто покупайте и пользуйтесь. В два клика, без знаний какого-либо ЯП в принципе.

Сегодня уже интернет-магазины, которыми так любят хвастаться "за 3 минуты на коленке на Wordpress" уже давно уступили маркет-плейсам и готовым SaaS-решениям. Блоги тем более атавизм. Сайты-визитки? Я вас умоляю.

Весь этот дешёвый хостинг с ISP, почтовиком с каждым днём становится всё менее востребован. Даже забесплатно.

Разработку сложного ПО, если на внешнем хостинге, ведут в облаках (контейнеры), и там Go побеждает, безапелляционно. Ибо весит копейки, ресурсов ест минимально, не требует ничего, а с учётом тарифов на память и вычислительные ресурсы, это имеет серьёзный вес.

Вот пример базовый образ bitnami/php-fpm весит ~340Mb, а с далеко не самым сложным приложением легко доходит до 1Гб и выше. Базовый образ для приложения на Go, например alpine, весит... ~7Мб. Чувствуете разницу? И это не считая, что пыхе также нужен nginx, или ещё какой веб-сервер. На одном единственном экземпляре приложения может не так чувствуется, но когда идёт активная разработка CI/CD, а экземпляров много, уже ощущается неприличное давление и требовательность к ресурсам. И по времени развёртывания, и по хранению и прочее прочее.

И это не считая, что пыхе также нужен nginx, или ещё какой веб-сервер.

Формально — нет, не нужен. Можете запустить микроскопический socat и кидать соединения пыхе. Можете прямо на пыхе создать слушающий сокет и форкаться по мере поступления входящих соединений.

А чего тогда все возятся с php-fpm? Какой-то swoole или rr прикручивают, оказывается у пыхи есть свой встроенный продакшен-реди сервер? Или я что-то не понимаю? :)

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

Нет, это не так — PHP сам по себе может стать сервером, если при компиляции не вырезали поддержку POSIX-сокеточ.

А с php-fpm возятся потому, что люди любят использовать готовые решения, а не писать свои.

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

Никакого встроенного веб-сервера нет, его придётся написать.

Я нигде выше по ветви дискуссии не писал, что он есть в готовом виде. Но зато я выше по ветви дискуссии писал, что его можно написать на PHP и пришлось бы написать, если бы кто-то захотел так сделать.

Почему вы паясничаете и начинаете рассказывать про то, какие глупые вопросы вы задавали своим знакомым — мне непонятно.

Никакого встроенного веб-сервера нет, его придётся написать.

Ну строго говоря встроенный web-сервер в php всеже есть.
https://www.php.net/manual/ru/features.commandline.webserver.php

Но очевидное предупреждение как бы намекает

Внимание

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

Есть он, есть, php -S называется. Но да, использовать его - что есть суп ботинком, там правила маршрутизации определяет он сам, а не вы

$fp = fopen(__DIR__ . '/test.json', 'rb'); if ($fp === false) { echo 'Error' . PHP_EOL; return; } defer(function() use($fp) { fclose($fp); }); $result = ''; while ($line = fread($fp, 1024)) { $result .= $line; }

А вот это все разве нельзя по аналогии с golang заменить на:

$some_path_to_file = "....";

if (is_file($some_path_to_file)){

$line = file_get_contents($some_path_to_file);

}else{

throw new Exception('file not found...');

}

но я типа не сеньер... ))) Но на больших файлах и дисковых накопителей чтение по 1024 байта - может работать очень долго.

  • Показать, что PHP хороший язык программирования, на котором можно делать web-проекты

Можно и нужно - вещи разные. Это я оставлю, а то, что почти собрался писать про тесты выполняющие не написаное на тестируемых языках - опущу и перейду сразу к выводам. Для тех, кого подобное тестирование убедит что нужно выбрать PHP, PHP действительно лучший язык и его нужно выбрать. Всё хорошо.

Php убивает сам php. Самая важная фича языка - отсутствие типизации, толерантность к ошибкам в данных (сделать из числа строку или массив и работать с этим дальше - легко!) и простота языка позволяют писать то, что на других языках превращается в огромную портянку кода.

  • Разработчики взяли курс на принудительное внедрение строгой типизации.

  • Теперь нельзя вызвать count() на не-массиве потому что он, внезапно, not-countable - причем десятилетия это не было проблемой, но теперь всё падает с ошибкой. В итоге тот код, который раньше нормально переваривал любые входные данные теперь требует дополнительных приседаний, чтобы убедиться, что эти данные - корректны (т.е. получилось как во всех остальных языках).

  • Сделан очень большой упор на классы везде: причем все новые фичи языка завязаны именно на классы, при том что бОльшая часть старой кодовой базы - процедурно-ориентированная.

... и еще много всякого

В итоге php постепенно превращается в какой-то c++ на минималках, даже js уже выглядит лучше.

Ваш случай я буквально вчера описывал в соседнем топике.

Для подхода "фига-фигак и в продакшен" действительно совершенно неважно, какие там данные пришли. "У меня никаких ошибок не выдаёт".

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

$product = null;
$price = 10;
$cost = $price * $product['qty'];

До 7 версии РНР молча делал стоимость равной нулю, и это было ПОЗОРИЩЕ.

Если лопату применять для забивания гвоздей, то она почему-то гнется...

Эта фича нужна для обработки строковых данных разного формата. Причем когда формат заранее не определен и определять его, в общем-то, и нет смысла - задача в целом про другое. В итоге на каком-нибудь c# мы имеем портянку кода с кучей приседаний и объявлений переменных, чтобы не дай бог строка не полезла в int - а на php это одна-две примитивных строчки кода.

Это, повторюсь, фича языка, про которую надо знать и учитывать. Именно этим он отличается от остальных. Чем отличаются все эти новомодные языки друг от друга? Нескучным синтаксисом??

Чем отличаются все эти новомодные языки друг от друга?

Ну если мы говорим в контексте статьи, то Go как раз отличается тем, что в нём стараются минимизировать количество таких "фич". Все же мы помним вопросы с собеседований на PHP типа "что выведет код", рассчитанные на знание механизма приведения типов.

Нескучным синтаксисом?

Как раз синтаксис в Go очень скучный. Зато можно прийти с другого языка и с ходу начать понимать написанное.

Go как раз отличается тем, что в нём стараются минимизировать количество таких "фич"

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

Зато можно прийти с другого языка и с ходу начать понимать написанное.

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

Так вот, только на php это делается более-менее простым кодом.

Ну так значит, для этой задачи PHP подходит хорошо) Никто же не говорит, что PHP со всех сторон ущербен. Но это таки вполне специфическая прикладная задача. Если в вашем приложении нужно её решать часто и в больших объёмах (есть наработанная кодовая база, опять же) - для вас PHP предпочтительнее. А если такой задачи нет и надо чаще считать, например, деньги, чем парсить текст, то это слабое преимущество. Многие, я думаю, предпочтут иметь портянку кода, но быть уверенными, что лишняя копеечка никуда не улетает.

Практически все языки сегодня имеют плюс-минус одинаковый си-подобный синтаксис.

В других языках огромное количество собственных синтаксических конструкций и всевозможного сахара, который пойди пойми как работает.

Go, по сравнению с другими языками, пуст. Даже в каком-то смысле примитивен. Но благодаря этому вкатываться проще.

Проблема в том, что текущая 8ая ветка php сильно ограничивает эту свободу. А грядущие изменения ограничат её ещё сильнее. Т.е., имхо, в какой-то момент php просто станет таким же языком, как, например, c#. И зачем мне тогда его выбирать? ASP.Net, как язык со строгой типизацией, просто во всём лучше, чем такой переделанный php. И даже если они вдруг в этом будут равны - то Visual Studio с Resharper просто на несколько порядков лучше вообще любого известного мне редактора с поддержкой php.

Т.е., я повторюсь, разработчики php сейчас сами своими руками рубят уникальность php. И они выходят туда же, где тусуется куча других языков - у которых была куча времени для развития. В отличие от php. От этой конкуренции он и помрет...

Многие, я думаю, предпочтут иметь портянку кода, но быть уверенными, что лишняя копеечка никуда не улетает.

Ну так они и выберут другой язык. Например, в котором есть специальный тип Price, умеющий корректно работать с долями копеек (с чем у обычных float/double есть проблемы).

Никто ж не призывал писать всё на php)

В других языках огромное количество собственных синтаксических конструкций и всевозможного сахара, который пойди пойми как работает.

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

Намного важнее обвязка языка: библиотеки, документация, форумы. (По документации, имхо, дотнет вообще никто до сих пор не обошел. У многих просто плохо. У некоторых вообще такая беда, что не понятно как это стало популярным)

Если динамика это фича языка, может стоит усиливать эту фичу, и обходиться вообще без типов, пусть оно как-то само волшебным образом к чему надо приводится? Но в пыху тащат типизацию.

Недавно у нас при интеграции с PHP приложением возник казус. Получали в ответе JSON со словарём вида { "meta": { "prop1": "value1", "prop2": "value2" } } и всё было хорошо, пока всё внезапно не сломалось. По бизнесу словарь может быть пустой, в таких случаях ожидается вот такое { "meta": { } }, но пыха прислала { "meta": [ ] }. Стандартная сериализация при отсутствии явной типизации. Бизнес-процесс пострадали и был простой. Кто виноват? Глупые типизированные платформы, которые должны были догадаться, что [ ] это { }? :)

Если динамика это фича языка, может стоит усиливать эту фичу, и обходиться вообще без типов, пусть оно как-то само волшебным образом к чему надо приводится? Но в пыху тащат типизацию.

Ну вот и я про то же. Лучше б они синтаксис системных функций единообразным сделали, а то без документации никогда не угадаешь, где в функции будет haystack, а где needle (позиция этих двух переменных в вызове функции для каждой новой функции явно выбирается разработчиками php подбрасыванием кубика)

жидается вот такое { "meta": { } }, но пыха прислала { "meta": [ ] }

Так для php уже много лет массивы с [] и {} - одинаковое. Версии с седьмой, кажется (я по-прежнему предпочитаю старый синтаксис, поэтому не помню когда по-новому стали делать). Не, ну т.е. на самом-то деле это разное даже в php, но когда программируешь, разницу эту просто не чувствуешь - она слишком глубоко закопана.

С позиции enterprise разработки, когда бизнес-объектная модель состоит из десятков тысяч типов и множества слоёв логики, отсутствие максимально строгой типизации превращается просто в ад. Вплоть до того, что даже для таких значений как ИНН, ОГРН и т.п. создаётся отдельный доменный тип, на которым уже навешаны: валидация, парсинг, сериализация, куча расширений и нельзя вот так какую-то рандомную строку сунуть как параметр функции, т.е. перепутать ИНН и ОГРН физически компилятор не даст. Если честно, за всю практику работы в типизированной среде мне крайне редко доводилось кастовать строку к числу, чтобы с чем-нибудь сложить. Зачем? Число в виде строки просто тупо не появится в границах приложения. И такие случаи возникают чаще именно в интеграции с динамическими ЯП, которые без всяких Б могут прислать число строкой, вообще не запариваясь ни разу. Разработчики, получая такие "подарки" очень радуются, ну наконец-то! Расчехляем адаптивную десериализацию, обмазываем аспектами.

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

Ну так поэтому все и стараются в энтерпрайзе использовать java или c#, но не php. Под задачу и инструмент.

В общем-то да, мне тоже не очень очевидно, где я могу применить сложение числа со строкой. Но это же не специально, просто следствие механизма приведения типов в языке. Не обязательно ж на него код завязывать. Точно так же как вы постоянно помните, что один знак равно и два знака равно - это разные операции и лишний раз себя перепроверяете в if'ах.

Так для php уже много лет массивы с [] и {} - одинаковое

Оно разное, так же как и в JS. Первое массив. Второе объект.

То что json_decode в php можно (и в 90% случаев так и используется) включить associative режим, когда все JS объекты будут возвращаться как массивы - это немного другое

Оно разное

Я знаю, что оно разное, я про это написал. Но многие программисты на php их перестали различать вообще. И лепят {} всегда - благо, задачи такие, что там без разницы, на остальной код не влияет.

json_decode

А он причем, если писалось про результат encode? Тут-то вот эта дурная привычка некоторых php-шников лепить {} вместо [] к вам и вылезла боком.

Чтоб в PHP получить в json_encode {} надо налепить туда объект как-то так

// чтоб получить {} надо сговнякать объект
$a = new \stdClass();
$a->foo = 'foo';
$a->bar = 'bar';

// а "плоский" список даст []
$b = ['foo','bar'];

echo json_encode(['a'=>$a,'b'=>$b]);
{"a":{"foo":"foo","bar":"bar"},"b":["foo","bar"]}

Я, честно говоря, хз как это можно не различать и говнякать всегда {}?

// чтоб получить {} надо сговнякать объект $a = new \stdClass();

Не нужно. Достаточно написать $a={}; вместо $a=[];
И потом можно писать $b['foo']="foo"; $b['bar']="bar";

Такой синтаксис работает с 7ой версии - т.е. уже много лет.

Я, честно говоря, хз как это можно не различать и говнякать всегда {}?

Говнокодеры, сэр.

А ещё - всё хорошо, если у вас весь код перед глазами. А если этот массив/объект инициализировали в одном месте, а потом заполняют данными в совершенно других местах + код постепенно дополняли разные люди в разное время...

Совершенно не удивительно, что где-нибудь в дебрях foreach очередной программист по своей привычке влепил $data[]=[]; вместо $data[]={}; - вот у вас в json'e и получилась смесь объекта с массивом.

Самое прикольное, что после json_decode на php вы могли даже и не заметить, что там что-то не так было с форматом данных. Потому что с точки зрения синтаксиса языка foreach по объекту и массиву работают совершенно одинаково. И обращение по ключу к элементу - тоже.

Разница, повторюсь, есть - но для этой разницы нужен специальный код, который нужен ооочень редко и в проектах с очень хитрой спецификой. А остальным что там [], что {} - без разницы, на конечный код это не влияет.

Достаточно написать $a={};

Вы бредите

Действительно, я ошибся(

Проверил по-разному синтаксис и объект должен быть задан явно или через приведение типов или через new. Ну или объект незаметно вернет какая-то функция.

При этом по полям объекта тоже можно сделать цикл, как и по элементам массива:

$a=(object)['aaa'=>'bbb', 'xxx'=>array('yyy')];
foreach($a as $c)
var_dump ($c);

php.exe D:\x\x.php
string(3) "bbb"
array(1) {
[0]=>
string(3) "yyy"
}

И пока вы явно не полезете за полем через, например, $a['aaa'] - вы и не узнаете, что там объект, а не массив (или наоборот).

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

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

Извините, но вы вообще ничего не поняли в этой ветке. И пишете какую-то чушь. Как получить непустой объект в джейсоне никто и не спрашивал. Причем никакой "объект говнякать" тут не нужно, массива будет вполне достаточно. Ассоциативного.

Речь шла про json_encode и пустые массивы. Которые действительно по умолчанию кодируются в список. То есть про случай, когда ни ни foo, ни bar в массиве нет. Но поскольку принимающая сторона ждёт объект, то действительно приходится ставить костыль, принудительно кастуя ассоциативный массив в объект перед вызовом json_encode (если есть вероятность, что массив может оказаться пустым). Либо заранее используя объект вместо массива.

Собеседник ваш, впрочем, недалеко от вас ушёл, воображая что в РНР можно определять массивы в фигурных скобках, получая массив какого-то "другого" вида.

Речь шла про json_encode и пустые массивы. Которые действительно по умолчанию кодируются в список.

А что, непустые массивы кодируются во что-то другое?
В json объекты {} кодируются по-умолчанию ассоциативные массивы, простые же массивы (ок, они же и есть списки) кодируются как json списки [], так же как и пустые массивы (которые из за своей «пустоты» не являются ассоциативными).

Если уж бизнес логика @posledam желает получить в json именно пустой объект, то почему кто-то туда пихает массив? Где логика? Хотите пустой объект - пихайте пустой объект. А уж как его приготовить в php, через new \stdClass() или кастинг (object) [] не важно. Мне лично понятнее первое.

$a  = []; // пустой массив
$b  = ['m1','m2']; // не пустой массив
$c  = ['k1'=>'v1','k2'=>'v2']; // не пустой ассоциативный массив
$o  = new \stdClass(); // новый объект
$of = (object) []; // объект из массива через кастинг
echo json_encode(['a'=>$a,'b'=>$b,'c'=>$c,'o'=>$o,'of'=>$of],JSON_UNESCAPED_UNICODE);
{"a":[],"b":["m1","m2"],"c":{"k1":"v1","k2":"v2"},"o":{},"of":{}}

А что, непустые массивы кодируются во что-то другое?

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

Да. В этом и заключается весь смысл этой ветки

Увы. Смысл этой ветки в том, что люди, которым требуется объект на выходе – пихают вместо него массив, а потом говорят, что php говно.

Логика вообще полезная штука. Или Вы хотите оспорить утверждение, что ['a','b'] это «непустой массив»? Вы считаете что он «пустой» или что он «не массив»?

мы с вами

Оглянулся, я тут вроде один, не надо ко мне во множественном числе обращаться :-)

Задам такой вопрос (вернее, три вопроса):

  • Во что кодируется пустой ассоциативный массив?

  • Во что кодируется непустой ассоциативный массив?

  • Как принимающей стороне писать код, чтобы декодировать оба случая?

Для начала задайте вопрос себе: в чем отличие ассоциативного массива от обычного с точки зрения логики, а не внутреннего устройства (которое в php, помнится, одинаковое)?

  1. Пустой массив не является ассоциативным. И поэтому кодируется как список [], так же как и непустой и не ассоциативный.

  2. Непустой ассоциативный кодируется как объект {}, потому что очевидно, по другому в js его не закодировать

  3. При чем тут принимающая сторона? Писать правильный код нужно кодирующей стороне

В этой ветке неправы вообще все (включая меня). Я таки победил лень, написал демо код и проверил:

$data1 = [];
$data2 = ['aaa'=>'bbb'];

echo json_encode($data1);
echo "\n";
echo json_encode($data2);
php.exe D:\x\x.php
[]
{"aaa":"bbb"}

Потом погуглил и выяснилось, что json_encode в php по умолчанию возвращает именно квадратные скобки вместо фигурных на пустом массиве. И надо делать так:

json_encode($data1, JSON_FORCE_OBJECT);

JSON_FORCE_OBJECT - тоже не решение, потому что в таком случае будут фигурные скобки вместо квадратных там, где по схеме должен быть массив.

Ну хотя бы всё будет единообразно, а не смесь из [] и {}.

Остается, правда, открытым вопрос, как к пустым {} отнесутся другие языки программирования, где будут делать json_decode... Боюсь, там тоже будет что-нибудь нетривиальное с параметрами вызова функции.