Современный PHP — прекрасен и продуктивен

    Почти 8 месяцев тому назад я пересел с проектов python/java на проект на php (мне предложили условия от которых было бы глупо отказываться), и я внезапно не ощутил боли и отчаяния, о которых проповедуют бывшие разработчики на ПХП. И вот что я думаю по этому поводу.



    Что есть что


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

    Python. Когда речь заходит о проектах на python (чаще всего на Django), мы получаем платформу, которая позволяет достаточно удобно и просто наращивать функционал, строить rest-api сервера, проводить шардирование системы и прочее. Логика работы фреймворка очень понятная и прямолинейная. Даже совсем зеленый разработчик может за пару часов набросать небольшой бложик с админкой. Плюс документация Django – одна из самых качественных, что я видел. К этому всему добавляется синтаксический сахар python, который помогает реализовывать определенные паттерны весьма элегантно. Если мы отходим от Django в сторону Tornado/aiohtpp/Twisted/Flask итд – то там начинается боль, ибо код в них писать гораздо неприятней, чем в Django.

    Java. Если мы говорим про Java, например, Spring – то это системы, которые вызывают анальную боль тем, что заставляют тебя конфигурировать все, что можно конфигурировать. Порог вхождения очень высокий, огромное число нюансов, которое нужно держать в голове, плюс сам синтаксис Java заставляет тебя писать весьма объемные конструкции (правдиво для всех проектах на шестой Java). Но в качестве награды мы получаем весьма надежные и гибкие системы, которые могут пережить не один десяток программистов с весьма посредственными руками.

    Что же касается PHP


    Перед началом работы я прочитал книгу: Мэтт Зандра – PHP объекты, шаблоны и методики программирования, и убедился, что PHP в общем-то без особой боли позволяет реализовывать те или иные паттерны разработки. Т.е. в PHP можно писать правильный код, который будет не сильно отличаться от того, что мы получаем на Python/Java.

    Zend Framework 1


    Проект внутреннего сервиса меня встретил Zend Framework 1 на PHP 5.3. Скажу сразу, что многие решения на данной платформе выглядят весьма спорно, а язык PHP 5.3 имеет ограничения на установление типа возврата функций (методов), тем не менее, достаточно быстро понимаешь, где что лежит, как что прокидывается, а как что формируется.

    Например, если мы рассматривает Zend Forms, то они практически под копирку делают то, что делают классические формы в Django. Синтаксис построения запросов в ДБ Zend DB Table – не вызывает какого-то негатива, и весьма очевидно работает.

    Т.е. буквально за 2-3 дня я смог полноценно разбираться и стал писать код, который делал то, что от него требовалось вполне адекватным способом.

    Symfony 3.4


    Спустя 3 месяца меня перевели на другой проект на Symfony 3.4 и PHP 7.1 – и вот это просто бомба. У меня откровенно было ощущение, что мне дали в ручки Django, куда добавили надежность системы из Java.

    • Шаблонизатор Twig – полный клон Jinja от Django.
    • Doctrine ORM – аналог Hibernate
    • Аннотации Symfony – аналог декораторов из Python
    • Auto-wiring Symfony – даже работает очевидней, чем DI в Spring
    • Очевидные конфигурации секрьрности
    • Удобное построение rest-APi клиентов.
    • Удобное написание джоб для крона (в данном случае в симфонии они называются консольные команды)
    • Удобный дебагер и консольный помощник.

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

    Единственный жирный минус – это недостаточная документация. Т.е. в документации указываются самые простые кейсы, а все что интересней, уже требует копания в исходниках symfony, ну и фреймворк на удивление не так популярен в Гугле, как бы того хотелось.

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

    А есть ли разница


    Также хочу отметить такой момент, что после того, как ты поработал на 3-4 современных веб-фреймворках, тебе приходит понимание, что все везде работает схожим образом. Отличаются названия и реализации, а общие концепции 1 в 1. Поэтому, скажем, если вы работали на Django, то пересесть на php Symfony / .Net CORE MVC – можно без особо труда за пару месяцев.

    P.S.: если я все же слеп и глуп, прошу в комментарии.

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

    Нравится ли вам работать с symfony?

    Поддержать автора
    Поделиться публикацией

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

      +1
      Doctrine ORM – аналог Hibernate

      Хотя я не разрабатываю реальные проекты на на Symfony, но могу сказать что Doctrine ORM имеет по крайней мере две фичи которые не повторила ни одна crm
      1) Автогенерация миграций, которые потом можно дополнятть своим кодом. При этом текущее состояние программного кода сравнивается с текущим состоянием базы данных. Аналоги есть. Но там такие варианты
      — автомиграции в стиле sync nodejs-siquelize — когда не управляешь ничем и orm частично изменяет на лету структуру базы данных
      — автомиграции в стиле go-kallax — когда генерируется некоторая промежуточная структура данных в которой делается слепок текущего состояния струкуры базы данных. И миграция генерируется не от текущего состояния базы данных а от этого состояния снимка базы данных, которое может и не на все 100% соответствовать текущей структуре базы данных
      — автомиграцми в стиле liquibase-hibernate — когда сравнивается текущее состояние базы даных и текущая схема данных, но генерируется не программный код а документ xml. То есть миграция изменит схему но нет возможности кастомизировать миграцию свое йлоггико миграции

      2) локализованные текстовые поля. Для локализации достаточно задать в схеме аннотацию что поле переводимое и все. Дальше модно работать как юудто бы с плоской таблицей но поле будет переведено на нужную локаль.

      Некоторое время назад недоставало инструментов для быстрого создания админок (типа Django) но на сегодняшний день они уже есть.
        +4
        Автогенерация миграций, которые потом можно дополнятть своим кодом.

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

          +4
          И миграция генерируется не от текущего состояния базы данных

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


          локализованные текстовые поля

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

            0
            Doctrine ORM имеет по крайней мере две фичи которые не повторила ни одна crm

            1) Автогенерация миграций, которые потом можно дополнятть своим кодом.

            2) локализованные текстовые поля


            Ну это вы зря. В нашей компании, например, для Java разрабатывают CUBA.platform. К ней есть Studio в виде плагина к Intellij IDEA, которая и миграции позволяет генерировать/менять, и поля локализировать.

            Если что, не реклама. Я к созданию/поддержке фреймворка отношения не имею. Работаю в другом бизнес-подразделении.
              –1
              CUBA это жалкая попытка портировать 1С на яву ))
                0
                CUBA.platform насколько я понимаю это уже не бесплатно хотя возможно и хорошо. Что касается платных продуктов (или же закрытых внутрикорпоративных продуктов например то что использует у себя внутри Google или Facebook и никому не продает за деньги) то я вполне допускаю что могут быть и более продвинутые решения.
                  0
                  CUBA.platform насколько я понимаю это уже не бесплатно


                  Нет, на самом деле, совершенно наоборот. Многое из того, что раньше было платно, стало бесплатным. Значительная часть функционала студии сейчас бесплатна, независимо от величины проекта. Также сделали бесплатным многие плагины (например, гугл-карты, чарты) и выложили их source code на гитхаб.
                +4

                На счёт миграций, EntityFramework же, умеет все и по-всякому...

                  +7
                  Тссс, тут люди радуются возможности указывать тип возвращаемого значения, а вы им про всякую строготипизируемую ересь вещаете…
                    +1
                    Кстати, EntityFramework Core уже взял все фичи от оригинального EntityFramework или еще есть пропасть по функционалу?
                      0
                      Ну, для средней работы всё давно на месте, но бывают фичи, которые были и до сих пор не перенесены. Помнится, я ждал выхода ef core 2.? ради какой-то штуки, которая понадобилась и как назло не было. Ни в 2.1 не было, ни в 2.2, поэтому так и остался воркэраунд.

                      А вообще — сильно зависит от того, что вам нужно в вашем проекте. Почитайте например здесь changelog docs.microsoft.com/ru-ru/ef/core/what-is-new/ef-core-2.2 и лог предыдущих версий.
                        0
                        Некоторые редкоиспользуемые фичи все еще отсутствуют — например, связь «много ко многим» без промежуточной таблицы. В целом же EF Core 2.2 вполне «взрослый» и готовый к продакшену.
                      0
                      > не программный код а документ xml

                      1) миграция производится не для 1 конкретной базы данных, а для всех-всех-всех. Синтаксис SQL может и будет отличаться. Из XML генерится разный SQL в зависимости от ситуации.

                      2) свой SQL в Liquibase писать можно. Хотя это боль и унижение, потому что смотри пункт 1 — оно будет непортируемо между разными БД
                        0
                        свой SQL в Liquibase писать можно, но будет непортируемо между разными БД

                        Свой sql писать придётся, потому что понадобятся фичи, специфичные для используемой СУБД.

                          0
                          В doctrine генерится не sql а php поэтому кастомизируктся миграция средствами orm и поэтому переносимая между базами данных
                            0
                            Вы, наверное, плохо смотрели содержание файлов миграций. Генерируется SQL-код, который завязан на вашу текущую платформу. Для того, чтобы было портируемо на другие платформы — нужны дополнительные действия: либо шаманить с генерацией под несколько платформ, либо вручную дописывать в каждый файлик самому ;-)
                        +42
                        Как мне кажется, больше всего хейтят PHP те, кто ушёл с него где-то на 4 версии, максимум с 5.2. Или те, кто в основном работал в єкосистеме WordPress и Joomla. Собственно оба варианта почти одно и то же, пускай и во втором формально последний PHP сейчас поддерживается.

                        P.S. А аналог Doctrine (DataMapper ORM) появился? Или всё разновидности ActiveRecord?
                          +9

                          Вы так мастерски объяснили почему хейтят php и так лицемерно сделали то же самое с двумя популярными cms.
                          Php хейтят по инерции, причем в основном те, кто его не использует и те, кто его использует, но не знает толком. На хабре периодически появляются статьи вида "ухожу из пхп потому что он не очень" от ребят, которые толком не знают о чем пишут.
                          А про джумлу — будьте добры, изучите хоть немного то, о чем говорите. А то получается что вы осуждаете людей за собственные ошибки и не видите этого. Есть масса отличных разработчиков, которые пишут под джумлу и масса хреновых, которые используют {подставить имя} фреймворк, а вы сейчас всех под одну гребёнку, неприятно, знаете ли. Почему вы считаете что если человек пишет не под ту систему, во вам нравится, то он априори не очень?

                            +1
                            А где в комментарии выше высказывание, что те, кто пишут под джумлу и wp не очень? Там конкретно про эти фреймворки написано. Я не работал под Joomla, а проекты на wp обходил стороной, весьма не приятные воспоминания он оставил в последний раз, когда я с ним работал. Если я правильно понял посыл автора предыдущего комментария, то в этот ряд можно так же добавить ещё и Bitrix, в котором globals повсеместно использовались ещё года так 2-3 назад и проблемы с поддержкой 7х версий были, не знаю как сейчас, благо ушёл с него и забыл как страшный сон. И я бы тоже хэйтил PHP, если бы знал только про Bitrix, потому что нормальным программированием там не пахнет: SOLID, DI — это не сюда.
                              +3
                              Bitrix, в котором globals повсеместно использовались ещё года так 2-3 назад

                              Там и сейчас без globals никуда (
                                –1
                                вы не поверите, но клиентам все равно что вам нравится глобалс или нет. А кушать эту каку всегда есть кому когда за нее неплохо платят.
                                +4
                                Достаточно глянуть исходники WordPress чтобы понять какое это г-но. Популярным он стал потому что альтернатив быстро запустить свой сайт в свое время не было, а сейчас многим дешевле и дальше с ним с кривыми плагинами мучиться, чем переписать всё под фреймворк. Вот если б они его полностью с нуля переписали. Показатель — хотя бы количество проектов на Upwork, где у заказчиков проблемы с WP (в моей ленте это где-то 30-40% от всех). Насчет Joomla не знаю.
                                  +3
                                  Это не так. Он развивался в среде когда слева была джумла, справа modx, сверху ещё что-то, внизу тоже. CMS был зоопарк! Выбирать точно было из чего. Выстрелил он потому что думал об удобстве для потребителя, а не соблюдении паттернов ради паттернов.

                                  Архитектурные ошибки именно и тянутся что о пользователе продолжают думать, чтобы не ломать обратную совместимость. Нет зоопарка версий. Есть строгие предупреждения перед обновлением, что сломается что-то такое. Пресс давно поддерживает json API, а его кривую архитектуру абстрагируют реактом. У меня подозрение, что в будущем однажды подменят ядро воссоздав идентичный API.
                                  Там есть вещи дико выбешивающие меня, например, создание нового размера изображений заставит все загруженные файлы обрезаться в копию. Отсюда тонны лишних не используемых изображений.
                                    +1
                                    альтернатив быстро запустить свой сайт в свое время не было

                                    Да ну? Всяких CMS всегда было много. В том числе с минимальными требованиями и удобными установками.
                                      0

                                      У WordPress была чёткая ниша — блоги. В ней он и выстрелил. А потом уже обросло всё плагинами.

                                    +3
                                    Так а почему бы их не хейтить? В отличие от PHP, их качество никуда не выросло, как был там жуткий говнокод под капотом, так и остаётся.
                                      0
                                      Наверное потому что речь о «тех, кто в основном работал в єкосистеме WordPress и Joomla» именно в том контексте что эти люди больше всего хейтят пхп, а не про качество кода самих CMS?
                                      Не скажу про вп, я один раз посмотрел на его код и больше никогда к нему не возвращался. Но под ждумлу я пишу последние два — два споловиной года, не только под нее, конечно, zf3, laravel, yii2 тоже использовал.
                                      У джумлы есть проблемы только с доками из-за чего под нее сложно начать писать нормально. Но сам ее код не так уж и плох, вполне себе читается и дебажится. Проблемы есть, разумеется, но они со временем уходят.
                                        +1

                                        И как показывает практика, доля wp растет. Как растет Битрикс тоже страшно. При всем при этом первому прастительного ибо он бесплатный.

                                      +2
                                      Я лишь констатировал факт, что встречавшиеся мне продакшен-системы на WordPress и Joomla, которые пытались мне спихнуть на поддержку или развитие были написаны в стиле PHP4, если вообще не PHP3. PHP 5 и 7 в них поддерживались (хорошо если логи не засорялись depricated), но их фичи не использовались.
                                        0
                                        Возможно тут что-то типа «ошибки выжившего» — может быть нормальные адекватные системы на PHP 7 просто не «спихивают» на поддержку?
                                        «У нас есть легаси код 15 лет, давайте починим баги в нем? — Свят-свят, лучше спихните какому-нибудь фрилансеру за любые деньги!»
                                          0

                                          Ну вот на Symfony, Zend и даже на pure PHP5.3+ "спихивают" нормальные адекватные, а на WordPress и Joomla нет. Понятно, что выборка ограниченная у меня очень, но как-то сомнения возникают, что на WordPress и Joomla в принципе можно написать что-то в соответствии с принципами и практиками типа SOLID и DRY.

                                            0
                                            А, в такой формулировке, наверное, соглашусь с вашим выводом.
                                      +9
                                      PHP хейтится за уровень разработчиков, за низкий порог входа. Это до сих пор так. Но в тот же Symfony порог входа весьма высок и средний уровень разработчиков на нём сильно выше, чем в среднем по PHP.
                                        –1
                                        Ага, и стоимость этих разработчиков уже такая же как на Java / .Net. После чего возникает вопрос, и нафига собственно использовать инструмент, когда есть «оригинал» энтерпрайзного уровня, который на голову выше по всем статьям?
                                          +2
                                          Пока ещё не такая :( процентов 5 отставания навсидку.

                                          Не по всем. Есть отличия между PHP и Java / .Net, которые нельзя назвать абсолютными плюсами или минусами: есть ситуации и метрики, где PHP «с эмуляцией настоящего ООП и эмуляцией строгой стат типизации» лучше чем «оригиналы».
                                            –3
                                            В чем разница:

                                            При работе с .net/java ты отбираешь себе джунов и мидлов среди студентов, и стажеров.

                                            При работе с php, ты отбираешь себе джунов и мидлв из тех, кто раньше писал на cms и не может в ООП, Паттерны и чистый код=)
                                              +1
                                              А что мешает для php отбирать из студентов и стажеров?
                                                –3
                                                ну давайте говорить честно.

                                                Если студент перспективный, то он будет писать либо на .net/java/python — ибо в универах чаще всего на этом преподают, а всякие финтех/гос компании и прочие яндексы охотно берут студентов именно на эти технологии. Да и зп там повыше, чем в основном в среднем на ПХП.

                                                Рынок php-разработчиков — это чаще всего самоучки, либо люди из регионов, которые учат пхп, тупо по тому, что у них в регионе нет работы под другой стек.

                                                Например, большая часть «звезд» в пхп команде, это ребята, которых мы привезли из Барнаула, Читы, Благовещенска и прочих городов сибири, ДВ и Поволжья.
                                                  +1
                                                  Если студент перспективный, то, по-моему, ему всё равно на чём писать. Что в вузе давали — это лишь малозначимая деталь. Малозначимая и для него, и для его работодателя, пока у этого студента нет опыта реального программирования.
                                              0
                                              Пока ещё не такая :( процентов 5 отставания навсидку.

                                              От человека, который собеседует и нанимает и тех, и других, я слышал цифру в 16%. Даже чуть больше. Но всё равно это мизер, это даже не в 2 раза. Притом что скорость разработки и отлова багов, имхо, эту разницу нивелирует с лихвой. Что сходу в голову приходит: например, в PHP коде вызов функции на объекте, пришедший от процедуры, отдающий mixed. Вы вообще не знаете, что именно это за объект, и вам надо хотя бы интерфейсом его проаннотировать, чтобы вам IDE хотя бы примерно подсветила, куда эта функция ведёт. А если интерфейса нет, или возвращаемых типов может быть 50 штук, а дальше вы грепаете по коду и у вас в коде есть 300 таких функций в разных классах? Начинается дебаг, на который убивается часа 4. Что за объект, откуда пришёл, какой тип, какая функция вызвалась… В то время как в Java вы в 95% случаев пройдёте по вызову процедуры в сааамом худшем случае на интерфейс. И аннотировать вам ничего не надо, потому что до того в обязательном порядке написали тип этой переменной (покажите мне PHP разработчика, который хотя бы все методы в классе аннотирует и пишет, какие типы принимаются и какие возвращаются).
                                              И тому подобное. В транзакции например вам не надо всё руками заворачивать, за вас это сделает Spring, достаточно поставить одну аннотацию.

                                              есть ситуации и метрики, где PHP «с эмуляцией настоящего ООП и эмуляцией строгой стат типизации» лучше чем «оригиналы».

                                              Скорее всего вы имеете в виду проекты такого рода, когда у вас например заранее неизвестна структура БД, или приходит куча разных данных отовсюду, или например есть json сильно меняющегося формата. Ок, согласен, что-то такое на PHP или Python это закодить сильно проще. Ну а если у вас обычное бизнес-приложение, где такого практически не бывает? Если вы тянете данные из хорошо извесных и документированных API (или даже из внутренних, где можно напинать соседу васе за внезапный выплывший пустой объект в json'е вместо пустого массива)? Или если например вам надо банально выводить 100 объектов типа пользователь, тысячи раз в секунду, при этом пользователи частично отсортированы, и php'шная быстрая сортировка вам подвешивает всё нахрен именно в этом месте? Или когда вам тупо завтра понадобится настоящее дерево в памяти, а не хешмап?

                                              Ответ на ваш вопрос ниже о том, почему нельзя отбирать из студентов и стажёров: потому что студенты и стажёры не хотят на РНР. Они учили в универе алгоритмы, структуры данных и ещё много всего, они хотят таких проектов, где всё это есть на практике. А если не хотят, то вы сами не захотите таких стажёров, потому что они не будут развиваться.
                                                +1
                                                Притом что скорость разработки и отлова багов, имхо, эту разницу нивелирует с лихвой.

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


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

                                                Посмотрите на меня. У нас єто в целом обязательное требование. Причём аннотации запрещены если можно объявить тип в коде а-ля sum(int $a, int $b): int


                                                И тому подобное. В транзакции например вам не надо всё руками заворачивать, за вас это сделает Spring, достаточно поставить одну аннотацию.

                                                Так надо аннотации или нет? :) На самом деле последний раз управлял транзакциями ручками года два назад, когда не смог отстоять мнение, что мы сильно делаем что-то не так, если на одно дерганье ендпоинта нам нужно две транзакции.


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

                                                А вот не согласен. Я предпочитаю брать студентов, у которых алгоритмы и структуры данных от зубов отскакивают (и на бумажке могут много чего написать по ним), но которым они осточертели и они хотят автоматизировать реальные бизнес-процессы, думая об "О большом" только получив задачу на оптимизацию, а не доказывая мне, что бенчмарк и профайлер что-то неправильно считают, раз O(N*logN) медленнее O(N^3) на N=3 или что проблема N+1 запроса не проблема, потому что сложность всё равно O(N), а так как они написали граф зависимостей проще.

                                                  0
                                                  Причём аннотации запрещены если можно объявить тип в коде а-ля sum(int $a, int $b): int

                                                  А почему запрещены? Я пишу сначала типы в коде, а потом по ключевому /** VSCode с плагином генерирует PHPDoc комментарий с этими же типами, где я могу дополнить описанием принимаемых параметров. Зачем это запрещать?
                                                    +3
                                                    Дублирующаяся информация, за синхронизацией которой надо следить. В аннотациях только то, что нельзя нативными типами выразить: string|int, User[] (array нативный + уточняющая информация), resource|false и т. п.

                                                    Не запрещены ещё если есть полноценные описания, а не пустые или очевидные. Но приоритет у понятного имени параметра/функции.
                                                    +1
                                                    Как по мне, то в компилируемых языках со строгой статической типизацией скорость разработки и отлова багов (...) ниже.

                                                    Если не трудно, можете пояснить, откуда у сторонников слабой типизции такое мнение? Для меня всегда это было загадкой. Можете привести конкретный пример, когда строгая типизация мешает? Спасибо.
                                                      0
                                                      Я приведу большой конкретный класс примеров: необходимость приводить или проверять типы вручную там, где встречаются несколько типов. Либо вырождать типы до object или вообще any, там где в языке со слабой типизацией мы доверились бы спецификации приведения типов.

                                                      Ещё большой класс: сами типы могут быть очень сложными и нечитаемыми и в виду своей нечитаемости вообще непонятно что гарантирующими или допускающими. Особенно второй случай «интересен», когда тратятся часы, а то и больше на то, чтобы привести код, который вроде должен проходить тайпчекинг, к коду, который его проходит.

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

                                                      Ну и чисто субъективно инфраструктура разработки на языках типа C+/C#/Java гораздо сложнее обычно (я прежде всего о веб-разработке) чем на JS или PHP.
                                                        +1
                                                        там где в языке со слабой типизацией мы доверились бы спецификации приведения типов

                                                        О, да, помню, как мне в метод из формы приходила 1 вместо числа — какое бы число я не передавал, всегда на входе 1! Всего часик отладчике, и я обнаружил, что вместо чила передавался массив с этим числом внутри, а PHP услужливо конвертировал мне его в int. Доверился, называется.

                                                        Я не понимаю. Вот у меня функция getFruit(), она может вернуть Apple или Banana. Каким образом приведение типов (автоматическое?) поможет? Или, погодите, кажется, начинаю понимать: Вы говорите о примитивных типах, типа, кастануть string в int, да? Тогда так: во-первых существует перегрузка методов (ничего общего с, так называемой, лютой перегрузкой в PHP), во-вторых, входные данные автоматчески приводятся к нужному типу фреймворком на внешней границе, а внутри системы такой кастинг не нужен.

                                                        Ну и чисто субъективно инфраструктура разработки на языках типа C+/C#/Java гораздо сложнее

                                                        Человек, который может руками настроить WebPack, уступает только Чак-Норрису.
                                                          –2
                                                          PHP услужливо конвертировал мне его в int. Доверился, называется.

                                                          Это было для вас неожиданное поведение? Даже будь PHP весь из себя такой строго типизированный скорее всего у $_POST тип бы был mixed[].


                                                          Вы говорите о примитивных типах, типа, кастануть string в int, да?

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


                                                          Тогда так: во-первых существует перегрузка методов

                                                          Это про кучу методов типа add(int a), add(float a), add(double a)? Если так, то об этом я и говорю, что типизированный язык замедляет разработку.


                                                          во-вторых, входные данные автоматчески приводятся к нужному типу фреймворком на внешней границе, а внутри системы такой кастинг не нужен.

                                                          А фреймворк откуда знает нужный тип? Ну вот что-то вроде findEntityById(string EntityClassName, int|string|Guid entityId). Для одних id числовой, для других строковых, а для третьих зависит от настроек коннекшена к базе. К чему там на внешней границе будет приводиться?


                                                          Это не говоря о том, что фреймворк тоже надо разработать.

                                                            0
                                                            Это было для вас неожиданное поведение?

                                                            Я и сейчас в шоке, если честно. Я не могу понять, какой смысл в преобразовании array(13) в 1?

                                                            Даже будь PHP весь из себя такой строго типизированный скорее всего у $_POST тип бы был mixed[].

                                                            Если бы PHP был типизированный, то Вы могли бы указать модель в виде класса с нужными свойствами и нужными типами и гарантированно получили бы этот класс заполненным данными из POST запроса, либо получили бы ошибку и отправили юзер-агенту 400 Bad Request. Либо всё, либо ничего. При этом не надо думать, какой у Вас там тип — какой указали, такой и получите.

                                                            Это про кучу методов типа add(int a), add(float a), add(double a)? Если так, то об этом я и говорю, что типизированный язык замедляет разработку.

                                                            Ну это легкий пример, я имел ввиду что-то вроде add(int productId), add(Product product).

                                                            А фреймворк откуда знает нужный тип? Ну вот что-то вроде findEntityById(string EntityClassName, int|string|Guid entityId). Для одних id числовой, для других строковых, а для третьих зависит от настроек коннекшена к базе.

                                                            1. Дженерики
                                                            2. Перегруженные методы
                                                            3. Типы-объединения
                                                            4. Размеченные объединения
                                                            5. Перегрузка операторов приведения типа

                                                            Способов много, но Вы все равно скажете, что это замедлет разработку. Что ж… замедлять-то, может и замедляет, но зато ускоряет поддержку. Мне просто интересно, сколько времении потратит программист, который увидит метод с такой сигнатурой findEntityById($EntityClassName, $entityId), на то, чтобы понять, какие именно аргументы передавать в метод? Число? GUID? Строку? Пёс его знает.
                                                              0
                                                              Мне просто интересно, сколько времении потратит программист, который увидит метод с такой сигнатурой findEntityById($EntityClassName, $entityId), на то, чтобы понять, какие именно аргументы передавать в метод? Число? GUID? Строку? Пёс его знает.

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

                                                              Но с другой стороны у меня специфичный опыт работы — всегда использовал только фреймы, всякие CMS в глаза не видел, а код у первых на порядки качественнее CMS.
                                                                0
                                                                Я и сейчас в шоке, если честно. Я не могу понять, какой смысл в преобразовании array(13) в 1?

                                                                Каюсь, это undefined behavior, скорее всего со смыслом преобразованием сначала к bool, а потом к int. Причём встречался на практике с кодом явно это использующим, типа подсчёта количества непустых массивов в цикле типа $count += $curArray; И понятно было, и мысли об UB не возникло. Кажется, пора перечитать всю документацию где есть undefined behavior. Спасибо за стимул.

                                                                  0
                                                                  Каюсь, это undefined behavior, скорее всего со смыслом преобразованием сначала к bool, а потом к int.

                                                                  А программист точно именно это имел в виду? А если там будет явное приведение к bool, а потом к int, то читаемость и поддерживаемость что, ухудшится?

                                                                    0

                                                                    Ну, тесты с тремя кейсами (пустой, один и два элемента) им написанные проходят.


                                                                    Для улучшения поддерживаемости только что закоммитил $count += (bool)$current;

                                                                +1
                                                                А фреймворк откуда знает нужный тип?

                                                                Из схемы данных, которые ожидает ваше приложение.

                                                              0
                                                              Я приведу большой конкретный класс примеров: необходимость приводить или проверять типы вручную там, где встречаются несколько типов. Либо вырождать типы до object или вообще any, там где в языке со слабой типизацией мы доверились бы спецификации приведения типов.

                                                              Либо взять адекватные языки с ADT, или тайпклассами, или экзистенциальными типами. Да мало ли.


                                                              Ещё большой класс: сами типы могут быть очень сложными и нечитаемыми и в виду своей нечитаемости вообще непонятно что гарантирующими или допускающими.

                                                              Без типов было бы лучше?


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

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

                                                                –1

                                                                Я говорю обічно о мэйнстрим языках. В данном случае о строго статически типизированных С#, Java, TypeScript плюс строго динамически типизированном Python в сравнении с PHP и JavaScript


                                                                Без типов было бы лучше?

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

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

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

                                                                    +1

                                                                    Вы так часто говорите про брутфорс тайпчекера (в каждой дискуссии на эту тему, по впечатлениям) — а могли бы привести пример, когда это нужно делать?


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

                                                                      0
                                                                      Да банальный вызов какой-то функции jQuery может превратиться в квест.

                                                                      А если есть фатальные недостатки архитектуры, то что, увольняться?
                                                                        +1

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


                                                                        то что, увольняться?

                                                                        Конкретно по jQuery — можно попробовать для начала поменять заголовочные файлы, в смысле сделать пожестче. Выделить другие типы, вот это всё.


                                                                        банальный вызов какой-то функции jQuery

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


                                                                        Просто если это всё не описывать, то разговор получится беспредметный.

                                                                          –1
                                                                          Тут какое дело: без статической типизации всё работает. Глазами я вижу, что тип передаваемых параметров соответствует всегда ожидаемому в рамках нашей системы. Кейсы, что в будущем какой-то разработчик начнёт писать что-то не то — не рассматриваем. Кейсы, что какой-то пользователь начнёт, например, менять DOM и по селектору будет приходить div вместо input или прсто null — не рассматриваем.

                                                                          Трудность заключается в том, что в какой-то момент формально теряется информация о типе данных и то, что мы знаем и в чём уверены на 100% здесь и сейчас — нужно формально доказать компилятору на все возможные кейсы в будущем, чтобы он пресекал попытки несанкционированного использования без изменения сигнатур вызываемых функций или без явного приведения в вызывающем.Или вот мой «любимый» хак: function isSomeType(obj): is SomeType (return true).

                                                                          Конкретный пример мне сейчас сложно привести — нужно рыться в истории гита и обфуцировать найденное. Как встретится в текущих задачах — скину.
                                                            +1
                                                            Что сходу в голову приходит: например, в PHP коде вызов функции на объекте, пришедший от процедуры, отдающий mixed. Вы вообще не знаете, что именно это за объект, и вам надо хотя бы интерфейсом его проаннотировать, чтобы вам IDE хотя бы примерно подсветила, куда эта функция ведёт. А если интерфейса нет, или возвращаемых типов может быть 50 штук, а дальше вы грепаете по коду и у вас в коде есть 300 таких функций в разных классах? Начинается дебаг, на который убивается часа 4.


                                                            То что вы описали может быть и в джаве. Когда все аргументы и возвращаемые значения типа Object. Но в джаве вы бы сказали, что это говнокод и не надо так писать. Возможно я вас удивлю, но в мире PHP это тоже говнокод и не надо так писать.
                                                            Все мы знаем о море легаси и просто говнокода рожденного толпой студентов и индусов на фрилансе, который приходится саппортить спустя года. Да, это боль и страдание, но это не значит, что на PHP всегда пишут так.
                                                              +1
                                                              Начинается дебаг, на который убивается часа 4. Что за объект, откуда пришёл, какой тип, какая функция вызвалась…

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


                                                              В то время как в Java вы в 95% случаев пройдёте по вызову процедуры в сааамом худшем случае на интерфейс.

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

                                                                0
                                                                Ну, положим, в дебаггере будет видно, какой именно класс реализует интерфейс в данной отладочной сессии.
                                                                  0
                                                                  Ну так о том и речь, приемы отладки везде одинаковые. Особенно если возвращаемых типов 50 штук.
                                                                    0
                                                                    Вау, примеры?
                                                                      0
                                                                      Про типы было в комментарии, на который я отвечал, сам я с таким не сталкивался)
                                                                        0
                                                                        Ну это хз, это долбодятлом надо быть чтоб метод/функция могли возвращать over 5000 типов :D Опять же C — там в указателе можно вернуть всё что угодно/неугодно, и потом проверяй. Да и в Java, тут же вроде писали, вернуть Object — раз плюнуть.
                                                                +1
                                                                > А если интерфейса нет, или возвращаемых типов может быть 50 штук
                                                                значит это говнокод который можно написать на любом языке даже на таком казалось бы клёвом языке как Котлин, и конкретно к php не имеет отношения. Не удивительно что говнокод сложно поддерживать.
                                                                >покажите мне PHP разработчика, который хотя бы все методы в классе аннотирует и пишет, какие типы принимаются и какие возвращаются
                                                                Я например так делаю. Да и вобщем-то большинство людей придерживающихся общепринятым стандартам. Особенно в Symfony коммъюнити.
                                                                > В транзакции например вам не надо всё руками заворачивать, за вас это сделает Spring, достаточно поставить одну аннотацию.
                                                                Ну за вас это сделает спринг, а за меня доктрина ровно тем-же способом.
                                                                >php'шная быстрая сортировка вам подвешивает всё нахрен именно в этом месте?
                                                                Серьёзно? Что за умозрительная ситуация. Ровно с той-же достоверностью можно заявить что Java тормозит настолько, что с ней вообще невозможно работать. Но это же не так. Вы просто фантазируете.
                                                          +2
                                                          Ну я застал проекты еще на PHP3 :|
                                                          И не то чтобы прямо хейт такой, просто открывая любой код на PHP, я всегда вспоминаю всю ту боль. Особенно в сравнении с другими ЯП.
                                                            +5
                                                            Я тоже застал, но теперь открывая современный код на современном PHP испытываю удовольствие. Я закрыл психическую травму, нанесенную PHP3 :)
                                                            +1
                                                            Так после 5.6 у него был тот самый прорыв на 7ку, а в итоге — ничего, опять стагнация какая-то
                                                            пхп хейтят за его стремление сесть на оба стула в попытке «погони» (очень громкое слово, самому смешно) и за новыми фичами и за обратной совместимостью, в итоге получается что то среднее между ежом и ужом, вроде уже и не так колется, но все еще противно.
                                                            (Баги, висящие на багтрекерах годами, причем достаточно весомые, инертность языка, отсутствие конвенций в именованиях, очередности аргументов, все то, что уже проговорено 1000 и 1 раз)
                                                            ((Сам сейчас веду проект на пхп, Laravel, все bleeding-edge версий, как был простым как палка, так и остался, за попытку отстрелить себе ногу никто ничего не скажет))
                                                              –5
                                                              Хз после js я вообще не могу больше писать на синхронных языках. Так же в php напрягает то что при наличии автоприведения типов есть разные операторы сложения и конкатенации, а еще больше бесит, это разные операторы доступа к элементам объекта, массива и статическим методам.
                                                                +11
                                                                разные операторы сложения и конкатенации

                                                                Странно слышать это от JSсника. Это же божественно. Нет ошибкам типа
                                                                2 + '2'
                                                                22
                                                                2 - '2'
                                                                0

                                                              +8

                                                              К слову Symfony 4 намного удобнее третьей ветки. Я PHP как язык не очень люблю, но Symfony 4 просто волшебная. Рекомендую.

                                                                +6
                                                                >правдиво для всех проектах на шестой Java
                                                                Вообще-то, даже Java 8 уже legacy. Как-то странно так вот сравнивать, если вы конечно имели в виду Java SE 1.6, вышедшую в 2006 кажется году.
                                                                  +3

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

                                                                    0
                                                                    Неужели дженерики нормальные наконец завезли? Так-то в java отсутствует очень много ништяков, которые есть, например, в c#.
                                                                      0
                                                                      Дженерики «нормальные» это про что? Не испытываю проблем, что дженерики compile-time, да и есть конструкции для runtime, но на практике не возникает необходимости.
                                                                        0
                                                                        Если вы не испытываете проблем — это не значит, что их нет. Например, в проекте, над которым сейчас работаю, мы активно используем рефлексию и дженерики. Я не эксперт в java, но думаю, что в связи с type erasure повторить это на java очень сложно (если вообще возможно)
                                                                          0
                                                                          После 10 лет опыта, я встречал очень много и очень разные ситуации, чтобы сейчас сказать, что такой проблемы в большинстве случаев нет.
                                                                          И да, рефлексия это уже плохо, потому что подрывает многие концепции compile-time проверок. Рефлексия должна использоваться в редких случаях.

                                                                          Когда, в Java 1.5 вышли дженерики, кто только не говорил, что все это сделали лишь бы не менять байткод. На самом деле, байткод менять не нужно было и это сделано намерено. В Java давно существует RuntimeException TypeA[] a[0] = TypeB(); и его вполне можно отлично использовать. Так же есть Collections.checkedCollection, checkedMap… На пару проектов я использовал, но потом понял, что снижает performance и никаких багов в принципе не ловится, так что отказался.

                                                                          Ответ один, лучше всего когда ошибки видны, чем раньше, тем лучше, а именно compile-time. Отлавливать что-то runtime моветон и в Java уже существует древняя проблема NPE как раз из-за недостатка compile time checks.

                                                                          Давайте разбираться на конкретных примерах, что можно сделать лучше.
                                                                            0
                                                                            Рефлексия не обязательно означает отсутствие compile-time проверок.
                                                                            Давайте рассмотрим такой пример. Представим себе, что одному приложению необходимо генерировать и отправлять события. Получателю события уходят в формате, например, json, т. е. надо в коде как-то этот json формировать и отправлять. Событий конечное количество, но достаточно много, и периодически появляются новые и могут меняться старые. Набор атрибутов в целом у каждого события произвольный. Разные события могут обрабатываться по факту разными получателями, т. е. у них могут быть свои требования к формату значений. Типы данных значений в целом произвольные, есть вложенные структуры и коллекции.
                                                                            А теперь внимание вопрос — как обеспечить типобезопасность таких событий? Делать руками json на каждый чих очевидно не вариант, передавать куда-то словарь <string, object> тоже не лучше — рано или поздно на проект придёт новый разработчик, напишет «null» вместо null или наоборот (и это самый простой кейс) и кто-то поимеет очень много головной боли.
                                                                            А есть такой вариант — описывать события в виде контрактов (интерфейсов). Есть класс (покрытый тестами с ног до головы), который в runtime генерирует по интерфейсу реализации, умеет реализовывать коллекции (в том числе коллекции контрактов с коллекциями и тд), учитывает возможные атрибуты (которые определяют дальнейшие преобразования данных, например, формат даты/времени). Дальше такой объект передётся другому классу, который знает, что можно отправлять, а что нет, и который раскладывает объекты в нужное представление и отправляет получателю (это в первом приближении, всё гораздо более гибко). Таким образом, вы у себя в коде пишете что-то вроде
                                                                            var evt = DataContract.Create<IMySuperEvent>();
                                                                            evt.PropertyOne = 1;
                                                                            evt.PropertyTwo = "two";
                                                                            evt.PropertyThree.Add(DateTime.Now);
                                                                            ...
                                                                            
                                                                            await _tracker.Track(evt);
                                                                            

                                                                            Ничего лишнего, просто, удобно, типобезопасно, все довольны. Можно ли так сделать на java?
                                                                              +2

                                                                              Кхм. А если вот так?


                                                                              IMySuperEvent evt = DataContract.make(IMySuperEvent.class);
                                                                              evt.setPropertyOne(1); // звиняйте, пропертей не держим
                                                                              evt.setPropertyTwo("Two");
                                                                              // а это чтоб прокси колекций не делать, хотя тоже можно
                                                                              evt.addPropertyThree(LocalDate.now());
                                                                              
                                                                              /*... Somewhere in a galaxy far away */
                                                                              class DataContract {
                                                                                public static <T> T make(Class<T> cls) {
                                                                                  return Proxy.newProxyInstance(
                                                                                      cls.getClassLoader(),
                                                                                      new Class<?> []{cls},
                                                                                      new DataPropertiesImplementation()
                                                                                  );
                                                                                }
                                                                              
                                                                                private static class DataPropertiesImplementation implements InvocationHandler {
                                                                                   /* ... а вот тут ваш покрытый по самые помидоры тестами код, но на самом деле может быть и обёртка над HashMap ...*/
                                                                                }
                                                                              }

                                                                              Все методы интерфейса распознаются в соответствии с Java Beans 1.0 Spec, но в принципе реализация на усмотрение.

                                                                                0
                                                                                Неплохо вы меня уделали :) Это не совсем одно и тоже, но идея та же самая, согласен. Вообще дженерики просто первое, что в голову пришло. Вот например те же проперти или события, а точнее их отсутствие — встаёт непреодолимой преградой в освоении java. Я честно пытался несколько раз, но после C# совсем не то пальто.
                                                                                  0
                                                                                  Ну так и начинать стоило со свойств и событий, а то начали с прокси и рефлексии.
                                                                                  Причём, по моему мнению (с учётом ограниченных знаний, само собой), оба преимущества в экосистеме Java можно в определённых пределах имитировать, например, лямбдами.
                                                                                  И без свойств как таковых вполне можно обойтись — это скорее сахар над парой методов, чем именно что-то полезное до незаменимости. Хотя я вполне понимаю как такие мелочи могут портить впечатление от разработки, если уже привык. Я вот привык, что их нет, и просто делаю код. Когда их в Java добавят — порадуюсь, не добавят — ну что ж поделать, судьба такая.

                                                                                  Хотя мне и не нравятся соглашения о наименовании в C# — имя типа и имя метода должны быть различимы даже без подсветок синтаксиса, а в C# они именуются по одному и тому же шаблону; Но это вкусовщина, скорее) — я, впрочем, не буду отрицать в целом превосходство C# над Java — язык более молодой, смог учиться на ошибках и брать лучшее, плюс в раннем возрасте смог сбросить груз некоторых плохих решений в API стандартной библиотеки.
                                                                                  По этой же причине Ceylon, как я считаю, может превосходить их оба, только за счёт системы типов. Но так как я пока что не видел его подводных камней, — «может», не «превосходит».
                                                                                    0
                                                                                    То, что вы говорите, что у Generic не хватает описания конструкторов и их нельзя создать не выходя в рефлексию. Очень странно, но вот такой код распространен и дает отличный результат.
                                                                                    public <T> T newInstance(Class<T> cl) {
                                                                                         /// reflection constructor
                                                                                    }
                                                                                    
                                                                                    IMySuperEvent ie = newInstance(IMySuperEvent.class);
                                                                                    ie.setProperty(...);
                                                                                    
                                                                                    

                                                                                    Недостаток что до сих пор это нельзя сделать без полной рефлексии и с compile time проверками, то есть нельзя написать <T has constructor ()>. С другой стороны, все очевидно, что для работы коллекции или сервиса нужен Class в runtime.

                                                                                    Property — вопрос исторический, их нет и уже огромная практика по get/set генерации. К этому можно быстро привыкнуть. И ко всем классам пишешь get/set, а если не пишешь подразумеваешь, что метод чисто data-structure. То есть либо везде, либо нигде, в принципе по количеству кода получается ненамного больше, но структурирует.

                                                                                    С появлением нормальных делегатов в Java 8 и Stream API, вопрос событий можно считать закрытым, потому что их очень просто писать с помощью делегатов и Lambda.
                                                                                      0
                                                                                      то есть нельзя написать <T has constructor ()>

                                                                                      Это от того, что в вашем примере T — это интерфейс. Интерфейсы в Java не имеют конструкторов, потому что не содержат никакого состояния — они просто декларация некоего API.


                                                                                      С появлением нормальных делегатов в Java 8 и Stream API, вопрос событий можно считать закрытым, потому что их очень просто писать с помощью делегатов и Lambda.

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


                                                                                      object.event += new EventListener();

                                                                                      Это в терминах Java транслируется вот в такой код:


                                                                                      class Consumer<T> {
                                                                                         abstract void accept(T arg0);
                                                                                      
                                                                                         default Consumer<T> andThen(Consumer<T> other) {
                                                                                           return (arg0) -> { accept(arg0); other.accept(arg0); };
                                                                                         }
                                                                                      }
                                                                                      
                                                                                      /* Использование */
                                                                                      
                                                                                      if (object.event == null) {
                                                                                        object.event = new MyEventListener();
                                                                                      }
                                                                                      else {
                                                                                        object.event = object.event.andThen(new MyEventListener());
                                                                                      }
                                                                                      /* Или нужно */
                                                                                      
                                                                                      class MyObject<T> {
                                                                                        Consumer<T> event = new EmptyConsumer<>();
                                                                                        ....
                                                                                      }
                                                                                      
                                                                                      object.event = object.event.andThen(new MyEventListener());

                                                                                      Здесь совершенно явно видно, что в Java по-прежнему не хватает синтаксического сахара, чтобы аналогичный код писался насколько же "плавно" — например, для добавления делегатов в Java нужно контролировать доступ к event у объекта. И с описанным подходом делегаты вообще-то уже не удаляются (потому что оригинал не сохранён) — что значит, нужен список делегатов, а это ещё больше бойлерплейта, но уже со стороны вызова делегатов. И т.п.


                                                                                      Потому я и писал, что именно это я считаю узким местом в Java по сравнению с C#, а не рефлексивную генерацию классов.

                                                                                        0
                                                                                        T — возможный интерфейс. Шаблоны в С++ неограничены так, получается из-за интерфейсов страдают те, кто хотел использовать для обычных классов с конструкторами или передать метод конструктор.

                                                                                        По делегатам, честно говоря, не понял, вроде никогда не замечал много кода с подписчиками (в основном код пишется, где создается listener), особенно с lambda. А вот, менеджемент List можно хотя в базовый класс вынести, его же редко пишут.
                                                                                          0

                                                                                          Я был невнимателен, и подумал, что под reflection constructor вы имели в виду то же, что и я выше. Как я потом понял, на самом деле вы хотели вот так:


                                                                                          public <T> T newInstance(Class<T> cls) {
                                                                                            return findConstructor(cls).newInstance(inferArguments(cls));
                                                                                          }
                                                                                          
                                                                                          private Constructor<T> findConstructor(Class<T> cls) {
                                                                                          ...
                                                                                          }
                                                                                          private Object[] inferArguments(Class<?> cls) {...}

                                                                                          Шаблоны в С++ неограничены так

                                                                                          Возможно. При этом <T has constructor> — это duck-typing, и этого в Java нет, и пока не видно никаких предпосылок его появлению.


                                                                                          Опять же, зачем эти элементы если есть


                                                                                          • Proxy
                                                                                          • BiFunction<Arg1, Arg2, MyUberType> constructor
                                                                                                                             = MyUberType::new;

                                                                                            Ну напишете вы create(MyUberType::new) вместо create(MyUberType.class) — "по новому стилю" ещё и типы проверяются, и даже код на один символ короче со стороны вызова, плюс никто не ограничивает вас только конструкторами, это может быть и фабрика, и что угодно ещё.



                                                                                          получается из-за интерфейсов страдают

                                                                                          Вовсе не страдают — интерфейс, с точки зрения API, отделяет поведения объекта от деталей его реализации (в конкретно этом случае — от процесса получения новых экземпляров). Если чуть абстрагироваться, то class — это interface + [Constructor...]. Ну а как куда-нибудь метод передать писали и вы, и я чуть выше.


                                                                                          По делегатам, честно говоря, не понял, вроде никогда не замечал много кода с подписчиками (в основном код пишется, где создается listener), особенно с lambda. А вот, менеджемент List можно хотя в базовый класс вынести, его же редко пишут

                                                                                          Суть моего посыла в том, что делегатами в C# подписку на события сделать удобнее, чем лямбдами в Java. С# не заставляет вас делать именно список, и как-то там его "менеджерить" — есть два оператора, += подписаться, -= отписаться, и на этом всё, остальное скрыто под слоем сахара. Я даже сходу не знаю, как это устроено под капотом, кроме разве что смутной идеи, что там где-то тоже есть списки.


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

                                                                                          Я лично вообще за то, чтобы сделать "нормально", и писать эту катавасию вообще один раз, а не редко. Пусть будет, например, class Event<T>, что-то вроде такого, с поправкой на язык:
                                                                                          https://docs.sencha.com/extjs/3.4.0/source/Observable.html (там внизу файла есть класс EXTUTIL.Event)

                                                                      –1
                                                                      Вообще-то, даже Java 8 уже legacy

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

                                                                        0
                                                                        На сегодня уже доступен как пол-года новый LTS — v11. Проект, над которым работаю последние лет 5, уже на новом LTS.
                                                                        В других фирмах, где серьезные Java-проекты, тоже переползают на v11.
                                                                          +1
                                                                          Дело в том, что автор пишет про Java 6, а не 8. Тех, кто сегодня сидит на 6, можно пожалеть, но уж точно не стоило сравнивать PHP сегодняшний, 7.х, с такой старой версией.
                                                                        +14

                                                                        Symfony 4:


                                                                        • Документация местами ужасна, в том числе навигация по документации.
                                                                        • Конфиги, конфиги и ещё раз конфиги. С десяток конфиг файлов в установке с нуля. Куцая документация добавляет боли.
                                                                        • Аннотации — в сложных случаях вырождаются в программирование на комментариях.
                                                                        • Сплошная магия во всех ключевых компонентах (сериализатор, валидаторы, секьюрити) — одна не осторожная строчка в конфиг файлах, или неправильно написанная аннотация, и без пошаговой отладки уже не разобраться. И собственно сами "магические" методы, которые так ругают в других фрэймворках, их здесь кажется даже в разы больше чем в Laravel, только они спрятаны более тщательно.
                                                                          0
                                                                          Конфиги, конфиги и ещё раз конфиги. С десяток конфиг файлов в установке с нуля. Куцая документация добавляет боли.

                                                                          Напишите сходу 10 конфигов? Где их меньше? Какие альтернативы конфигам предлагаете?

                                                                          Аннотации — в сложных случаях вырождаются в программирование на комментариях.

                                                                          В каком месте Sf4 принуждает вас юзать аннотации?

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

                                                                          см п.1
                                                                            –2
                                                                            Напишите сходу 10 конфигов? Где их меньше? Какие альтернативы конфигам предлагаете?
                                                                            Convention over configuration. Можно посмотреть в том числе на lumen, или любой другой api фрэймворк.

                                                                            В каком месте Sf4 принуждает вас юзать аннотации?
                                                                            Официальная документация и инструменты (в том числе кодогенерации) по умолчанию форсят аннотации. Можно перейти с программирования на аннотациях на программирования через конфигурации, но легче от этого не станет, yml файлы ни чем не лучше аннотаций. Последний вариант — конфигурация через php код, тут хотя бы будут подсказки по коду.
                                                                              0
                                                                              тут хотя бы будут подсказки по кодa

                                                                              У меня и в Аннотациях подсказки работают, так что не вижу разницы(да и с конфигами, вродь, не возникает проблем), а если там вот такое:
                                                                              $app->get('{id}/posts/{postId}', ['uses' => 'UsersController@getUserPost', ]); — нет по сути разницы где это описывать, автокомплита ни там ни там не будет

                                                                              Официальная документация и инструменты (в том числе кодогенерации) по умолчанию форсят аннотации.

                                                                              Точно так же они форсят бездумно пихать геттеры и сеттеры в сущности, класть их все кучей в App\Entity etc., что не мешает всего этого не делать. В принципе не самый приятный момент, но тем не менее вполне неплохая кодогенерация есть, Laravel с кодогенерацией из коробки всё ж не лучше, хоть и не плох.
                                                                                +4
                                                                                тут хотя бы будут подсказки по кодa

                                                                                PhpStorm с соответствующим плагином всё нормально подсказывает.
                                                                              +1
                                                                              Аннотации — в сложных случаях вырождаются в программирование на комментариях.

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

                                                                                +2
                                                                                Конфиги, конфиги и ещё раз конфиги. С десяток конфиг файлов в установке с нуля. Куцая документация добавляет боли.

                                                                                Ровно то же самое во всех остальных фреймворках. А как иначе вы будете настраивать под свои нужды отдельные компоненты?

                                                                                  +4
                                                                                  Конфиги, конфиги и ещё раз конфиги. С десяток конфиг файлов в установке с нуля. Куцая документация добавляет боли.
                                                                                  Установка с нуля — конфигов 8 штук, а по сути 5 (3 ещё — отдельная настройка окружений dev/test). Строк не комментариев, не пустых — 35. Столько же строк — комментариев. Там всё расписано где и что означает.
                                                                                  Сплошная магия во всех ключевых компонентах (сериализатор, валидаторы, секьюрити) — одна не осторожная строчка в конфиг файлах, или неправильно написанная аннотация, и без пошаговой отладки уже не разобраться.
                                                                                  Это не магия, это скрытые под капот заморочки. Тут варианта два — либо самому обо всём этом заморачиваться, либо скрыть за слоями абстракций, но в результате, можно в редких случаях получить сложные ситуации.

                                                                                  Ну и потом. аннотации не обязательны, можно жить без них. С доктриной сложнее, а что в Symfony всё можно сделать и без аннотаций.
                                                                                  И собственно сами «магические» методы, которые так ругают в других фрэймворках, их здесь кажется даже в разы больше чем в Laravel, только они спрятаны более тщательно.
                                                                                  Ну вот это вы совсем зря.
                                                                                  Считаем
                                                                                  Laravel:
                                                                                  $ git clone git@github.com:laravel/framework.git laravel && cd laravel
                                                                                  $ grep -P 'function __(call|get|set|isset|callStatic)\(' src -R | grep -Poi '__[a-z]+' | sort |uniq -c
                                                                                       41 __call
                                                                                        6 __callStatic
                                                                                       14 __get
                                                                                        8 __isset
                                                                                        6 __set
                                                                                  # А если учесть, что там ещё магия часто вынесена в трейты, то надо добавить ещё:
                                                                                  $ grep -PR 'use .*\\(Macroable|ForwardsCalls|Fluent)' src | grep -Poi '[a-z]+$' | sort |uniq -c
                                                                                       11 Fluent
                                                                                       10 ForwardsCalls
                                                                                       33 Macroable
                                                                                  

                                                                                  Symfony:
                                                                                  $ git clone git@github.com:symfony/symfony.git && cd symfony
                                                                                  $ grep -P 'function __(call|get|set|isset|callStatic)\(' src -R | grep -v 'Tests' | grep -Poi '__[a-z]+' | sort |uniq -c
                                                                                        9 __call
                                                                                        4 __get
                                                                                        3 __isset
                                                                                        2 __set
                                                                                  

                                                                                  То есть, магии в Симфони куда меньше, а уж тем более той, с которой соприкасается юзер фреймворка — подавно. В ларавеле же вся магия она в интерфейсах, которые ближе всего к юзеру.
                                                                                    +2
                                                                                    аннотации не обязательны, можно жить без них. С доктриной сложнее, а что в Symfony всё можно сделать и без аннотаций.

                                                                                    А в чём сложности с Доктриной?


                                                                                    Там же тоже можно без аннотаций docs

                                                                                  +3
                                                                                  PHP не очень люблю, но приходится c ним работать. Так же приходится работать с Kotlin.
                                                                                  Сравнивая два этих языка могу сказать, что в мире PHP ещё очень многое предстоит сделать.
                                                                                  Мне вот, например, очень сильно не хватает:
                                                                                  • дженериков (раз уж язык начал стремиться в статическую типизацию);
                                                                                  • нормальных коллекций и мэпов;
                                                                                  • адекватного синтаксиса для лямбд;
                                                                                  • нормальных аннотаций (а не вот эти вот дурацкие комментарии);
                                                                                  • поддержка UTF-8 по дефолту для всех функций;
                                                                                  • производительность хромает, нужна производительность получше;
                                                                                  • composer ужасен, в сравнение с Gradle, по крайней мере.


                                                                                  Ну и всякого другого по мелочи.

                                                                                  В Symfony не нравится зашкаливающее количество всяких конфигураций и неочевидных моментов. В это плане Spring Framework (особенно в связке со Spring Boot) намного проще.
                                                                                    +2
                                                                                    В PHP нет никакой статической типизации и никогда не будет. Откуда?

                                                                                    Статическая типизация — определение и контроль типа значения и/или переменной при компиляции.

                                                                                    В PHP контроль типов принципиально рантаймовый. И никогда иным не был.

                                                                                    Откуда хоть вы этот миф берете, про «движение к статической типизации»?
                                                                                      0
                                                                                      Например, как вы в рантайме вернёте не string из функции ниже? Ни это ли элементы статической типизации?

                                                                                      class A {
                                                                                          function f(): string {
                                                                                              return new A();
                                                                                          }
                                                                                      }
                                                                                      
                                                                                      echo (new A())->f();
                                                                                      
                                                                                        0
                                                                                        И, кстати, скоро в свойства классов типы тоже завезут
                                                                                          +5
                                                                                          Да, только type hints != статическая типизация.
                                                                                          +8
                                                                                          Статическая типизация — это когда типы известны до запуска кода, т.е. не про рантайм. В PHP же все проверки по прежнему идут в рантайме, и если что-то не так, ошибку вы словите в уже работающей системе.
                                                                                            0
                                                                                            Точнее по умолчанию PHP молча приведёт тип к требуемому.
                                                                                              +2
                                                                                              Это уже следствия слабой(нестрогой) типизации, и не все типы конвертируются.
                                                                                                +2
                                                                                                Я вот этого не понимаю. Когда работают на С и иже с ними все страдают со строгой типизацией и пытаются постоянно менять типы. Когда переходят на языки с нестрогой типизацией — РНР или JS, начинают хаять эту нестрогую типизацию и сочиняют всякие TypeScript и подобное.
                                                                                                Не знаю, мне строгость типизации проблем не доставляла, может я уже привык просто ко всяким примочкам приведения типов, что я уже и не замечаю каких-либо неудобств
                                                                                                  0
                                                                                                  Нестрогая типизация повышает риск возникновения багов, которые на так уж и просто отловить

                                                                                                  может я уже привык просто ко всяким примочкам

                                                                                                  Хорошо если привыкли, но если пробежаться по типичным проектам можно увидеть как люди символьную строку с int сравнивают через нестрогое сравнение
                                                                                                    0

                                                                                                    del

                                                                                                      0
                                                                                                      Нестрогая типизация в интерпретируемых языках более удобна, ИМХО.
                                                                                                      Позволяет срезать углы.

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

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

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

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

                                                                                                      Как минус: без теста трудно сказать, будет ли код работать. Но для этого есть юнит-тесты.
                                                                                                      Как плюс: работающий код можно писать сразу.
                                                                                                      Написал — посмотрел какие косяки — поправил, посмотрел — поправил.
                                                                                                      Очень быстро все критичные ошибки выловил — код работает, ушел в продакшн. Потом по репортам фиксишь мелкие косяки.
                                                                                                      Более быстрая и интерактивная разработка получается: код адаптируется под задачу и вместе с задачей.
                                                                                                        +1
                                                                                                        для каждой из них написать копию метода со своими типами

                                                                                                        много почти одинакового кода

                                                                                                        Дженерики, интерфейсы и трейты — не, не слышали?

                                                                                                          +1
                                                                                                          Дженерики, интерфейсы и трейты — не, не слышали?

                                                                                                          Ну, допустим, в Go не слышали :D
                                                                                                            0

                                                                                                            Ага, я подумывал ответить что-то в стиле «Ловите гошника!», но решил воздержаться)


                                                                                                            Но в Go 2 вроде обещали какие-то дженерики (но это не точно)

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

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

                                                                                                            И например если мы изначально не угадали с типами, потом приходится переписывать большие объёмы кода. Понятно, что в больших проектах и на длинной дистанции такой подход принесёт много проблем, однако порой удобно создавать архитектуру таким вот методом проб и ошибок. На небольших одиночных проектах, которые не требуют в дальнейшем большого развития, такая быстрая разработка может быть очень удобной.
                                                                                                              0
                                                                                                              Скорее не переписывать придётся, а просто всё больше и больше типов заменять any или Object.
                                                                                                                +2
                                                                                                                С динамической типизацией можно писать код даже когда ещё не сильно представляешь архитектуру всего проекта.

                                                                                                                С сильной статической, представьте себе, тоже. И рефакторить потом одно удовольствие, можно положиться на тайпчекер.


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

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

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

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

                                                                                                              function getMessage(): string | Message | null {
                                                                                                                  return 'Hello!'
                                                                                                              }
                                                                                                              


                                                                                                              В F# можно использовать Discriminated Unions

                                                                                                              type MessageOrString = 
                                                                                                                  | M of Message
                                                                                                                  | S of string
                                                                                                              

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

                                                                                                              То есть, по-вашему это проще? Это проще для Вас, но не для тех, кто пользуется Вашим кодом.

                                                                                                              Как минус: без теста трудно сказать, будет ли код работать. Но для этого есть юнит-тесты.

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

                                                                                                              Как плюс: работающий код можно писать сразу.
                                                                                                              Написал — посмотрел какие косяки — поправил, посмотрел — поправил.

                                                                                                              Замечательно! В языках со статической (не путать со строгой) типизацией, это, до некоторой степени, можно делать. Скажем, функция Edit and Continue, часто позволяет изменить код метода без перекомиляции. Но вообще, делается не так: берется какой-нить непрерывный прогонщик тестов и спокойно пишутся тесты вообще без компиляции.

                                                                                                              Вопрос в другом: как, щьёрт побьери, менять этот код? Я понимаю, что можно куяк-куяк и продакшн, но потом вы решили что-то поменять. И? И вот 80% Ваших тестов стали красненькими и Вы не знаете, что делать. То есть, тест говорит Вам: опа стряслась! Но где и как?! И тут Вы лезете в дебаггер и сидите в нем несколько суток. Только не надо говорить, что изменять код можно мелким инкрементными частями. Не бывает так. Одно изменение может привести к повалу всго кода. А со строй типизацией, любое изменение стразу будет не только отловлено еще даже и до компиляции, но и точно указаны места, где и что надо поменять.

                                                                                                              Именно поэтому в PHP-коммунии столько говнокода: написал — уволился, написал — уволился. Код писать легко, а менять его тяжело. Поэтому новые поколения работников просто добавляют свои костыли поверх старого кода. Рефакторить никто не будет, потому как рефакториг без типов это боль. Плавали-знаем.
                                                                                                                0
                                                                                                                Не рефакторят отнюдь не из-за отсутствия типов, а из-за отсутствия задачи от менеджеров, отсутствия согласия клиентов на это. Рефакторинг сложно продать.
                                                                                                                  +2
                                                                                                                  Я почему-то думал, что решение о рефакторинге принимает программист, а не менеджер, который даже не знает, что это такое, не говоря уж о клиентах. Что ж, если цена рефакоринга настолько высока, что проще без него, то это многе объяснет.
                                                                                                                    0

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

                                                                                                                      0
                                                                                                                      Что ж, если цена рефакоринга настолько высока, что проще без него, то это многе объяснет.

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

                                                                                                                          «переписать весь проект» — разновидность рефакторинга :)

                                                                                                                    0
                                                                                                                    Последний год я работаю в смешанной среде PHP и TS, где код плюс-минус в одном стиле написан в плане SOLID и т. п. Рефакторинг PHP гораздо проще.
                                                                                                                      0
                                                                                                                      Но как?! Как Вам удается сделать так, что рефакторинг PHP гораздо проще, чем в TS? Это Ноу-хау какое-то?
                                                                                                                        0
                                                                                                                        Действия те же самые, в той же самой IDE, но вот банальное переименование класса или перенос класса с одного нэймспейса в другой приводит к куче ложных переименований в случае с TypeScript, если есть что-то похожее в других неймспейсах или у класса есть наследники. Сорри, точнее объяснить или пример дать не могу. Пытался на простейшем проекте сделать — не воспроизвелось. А куски рабочего кода NDA не позволяет. Надо «обфусцировать» как-то.
                                                                                                                +4
                                                                                                                С — язык со слабой типизацией :)
                                                                                                                  +3
                                                                                                                  Си — совсем не пример того, какой должна быть статическая типизация.
                                                                                                              +2
                                                                                                              Ошибка, конечно, случится в рантайме. Но вот шанс её возникновения будет куда ниже — ide подсветит ошибки по невнимательности
                                                                                                              –1
                                                                                                              Хм…
                                                                                                              <?php
                                                                                                              declare(strict_types = 1);
                                                                                                              
                                                                                                              class A {
                                                                                                                  function f(): string {
                                                                                                                      return new A();
                                                                                                                  }
                                                                                                                  
                                                                                                                  function __toString() {
                                                                                                                      return "5";
                                                                                                                  }
                                                                                                              }
                                                                                                              
                                                                                                              echo (new A())->f();
                                                                                                              

                                                                                                              Fatal error: Uncaught TypeError: Return value of A::f() must be of the type string, object returned in /in/OWFlL:6

                                                                                                              ok, пусть это была опечатка
                                                                                                              <?php
                                                                                                              declare(strict_types = 1);
                                                                                                              
                                                                                                              class A {
                                                                                                                  function f(): string {
                                                                                                                      return (string) (new A());
                                                                                                                  }
                                                                                                                  
                                                                                                                  function __toString() {
                                                                                                                      return "5";
                                                                                                                  }
                                                                                                              }
                                                                                                              
                                                                                                              echo (new A())->f();
                                                                                                              echo "\n\r";
                                                                                                              echo ((new A())->f()) + "2";


                                                                                                              Output for 7.3.3 | took 12 ms, 14.52 MiB
                                                                                                              5

                                                                                                              7

                                                                                                              3v4l.org/2KdVU

                                                                                                              Тайпхинтингу до статической типизации ещё жить и жить.
                                                                                                                +3
                                                                                                                Тайпхинтингу до статической типизации ещё жить и жить.

                                                                                                                Как ваши примеры связаны со статической типизацией?
                                                                                                                Автокаст типов — последствия слабой(нестрогой типизации). А типы возвращаются верные(функция возвращает строку), только опять же это не статическая типизация, т.к. типы проверяются в рантайме
                                                                                                                  0
                                                                                                                  Дык никак =_=
                                                                                                                  В комментарии выше говорится что тайпхинт — элемент статической типизации.
                                                                                                                  По факту он никак не мешает переменным менять тип в процессе исполнения и, как я понимаю, выполняет только функцию создания видимости порядка в хаосе автоприведения типов.
                                                                                                                  0
                                                                                                                  Тут есть момент,
                                                                                                                  echo ("5") + "2"
                                                                                                                  тоже выведет 7
                                                                                                                  +2
                                                                                                                  Нет, это не статическая типизация, это динамический контроль типов. Вы слегка путаетесь в терминах.
                                                                                                                    +3
                                                                                                                    Это не элементы статической типизации. Статическая типизиция подрузамевает, что все типы всех переменных известны по время компиляции в поэтому в рантайме проверять типы нет необходимости.

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

                                                                                                                    function foo(int $bar)
                                                                                                                    {
                                                                                                                        $bar = 'baz'; // упс! взяли аргумент, который объявлен как int, и положили в него строку
                                                                                                                    }
                                                                                                                  +28
                                                                                                                  composer ужасен

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

                                                                                                                    0
                                                                                                                    Если придираться, то он довольно медлителен. А вообще да, с появлением composer жизнь стала сильно лучше.
                                                                                                                      0
                                                                                                                      он довольно медлителен

                                                                                                                      Медленный там только composer update (потому что реализован по уму и там внутри настоящий SAT Solver), но update нужен раз в полгода. Все остальное весьма шустро.

                                                                                                                        0
                                                                                                                        Вы не работали с yii2, когда он требовал bower-asset… Как я понимаю там получался приличный список пакетов/зависимостей, обработка которого и сжирала тонну времени.
                                                                                                                          +1

                                                                                                                          Не работал и не собираюсь. :-)


                                                                                                                          Это уже вопрос к разработчикам yii2. Управлять фронтенд-зависимостями через composer, а тем более через давно мертвый bower — это, гхм, странное решение.

                                                                                                                            0
                                                                                                                            А это уже, наверное, вызов `npm install/update` который действительно медлителен, не говоря уже о «черной дыре» node_modules.
                                                                                                                      +5
                                                                                                                      Я вот тоже пишу на пхп и котлине. Да конечно котлин как язык поприятнее пхп, но вот сравнивать композер и грэдл по меньшей мере странно. Композер это менеджер пакетов, притом очень хороший, а грэдл это таск менеджер, там и установка пакетов и билдскрипты и линтеры и еще куча всякой всячины.
                                                                                                                        0
                                                                                                                        composer ужасен, в сравнение с Gradle, по крайней мере.

                                                                                                                        А в чём их кардинальная разница? Я совсем немного знаком с Gradle, поэтому интересно.

                                                                                                                          0

                                                                                                                          Выше уже ответили)

                                                                                                                          +1
                                                                                                                          И… что в итоге должно получиться?

                                                                                                                          Очередная джава, плюсЫ или шарп? -Постой-ка, так они уже есть…
                                                                                                                            0

                                                                                                                            Как это "не люблю, но приходится работать"? Насильно заставляют?

                                                                                                                            +22

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

                                                                                                                              +22
                                                                                                                              Шел 2019 год. Люди начали понимать, почему все пишут на пыхе
                                                                                                                                +1
                                                                                                                                > все пишут на пыхе
                                                                                                                                Смелое заявление :)
                                                                                                                                  0
                                                                                                                                  Если брать область веба, то 80%. Довольно значительная часть.
                                                                                                                                    0
                                                                                                                                    Откуда статистика?
                                                                                                                                      0
                                                                                                                                        0
                                                                                                                                        Вот вам цитата:
                                                                                                                                        According to W3Techs’ data, PHP is used by 78.9% of all websites with a known server-side programming languagе

                                                                                                                                        Т.е. это данные по «веб-сайтам» которые сканирует W3Tech. В таком же стиле можно утверждать что 99.9% сайтов используют javascript, поэтому он перспективнее.
                                                                                                                                        В общем с реальным положением дел имеет мало общего.
                                                                                                                                        Для более наглядной картины («все пишут на пыхе») лучше посмотреть рынок вакансий (нормальных вакансий) в сфере веб-раразботки, там пхп далеко не 80%
                                                                                                                                          0
                                                                                                                                          В таком же стиле можно утверждать что 99.9% сайтов используют javascript, поэтому он перспективнее.

                                                                                                                                          JS замены нет, нет конкуренции языков, отсюда и результат. У PHP море конкурентов.
                                                                                                                                            0
                                                                                                                                            Мой комментарий не про это был, а про то что статистика не убедительная.
                                                                                                                                      –1
                                                                                                                                      Если брать область Веба, то из этих 80% сайтов на Пыхе, 90% — это бложики на Wordpress с посещяемостью 1 человек в месяц, т. е. фактически одна программа, растиражированная миллионными экземплярами. Судя по той же статистике, Java вообще в заднице со своими 2-3%, одако эти 2-3%, собирают у себя больше посещений, чем все сайты на Пыхе вместе взятые. Сто раз уже говорил, что смотреть нужно не по количеству сайтов, а по количеству рабочих мест.
                                                                                                                                        +1
                                                                                                                                        одако эти 2-3%, собирают у себя больше посещений, чем все сайты на Пыхе вместе взятые

                                                                                                                                        VK и Facebook так или иначе используют PHP, не зря же оба пишут свои инструменты для него. А как там у них с посещаемостью? А то я соцсетями не пользуюсь.
                                                                                                                                          +1
                                                                                                                                          Вот не надо. Не бложиками едиными.

                                                                                                                                          Из мирового топ-20 алексы навскидку Wikipedia, FB, VK достоверно используют php как основной язык.
                                                                                                                                          Badoo, кстати, к поднятому выше вопросу о нормальных вакансиях: tech.badoo.com/ru/vacancies
                                                                                                                                          Запилить малый/средний/крупный интернет-магазин на чём-то кроме php, с точки зрения бизнеса выглядит той ещё авантюрой.
                                                                                                                                          Ну и конечно, наш всеми любимый уютный Хабр)

                                                                                                                                          Так что с трафиком все нормально.

                                                                                                                                          По количеству рабочих мест, можете посмотреть сами тоже всё в порядке.
                                                                                                                                          Можно убедиться в этом посмотрев кол-во вакансий на любом ресурсе. Не забывайте, что в языках где рабочих мест будто бы больше (java например), не только веб, и сменить специализацию порой сложнее чем язык. А php — исключительно веб.
                                                                                                                                    –5
                                                                                                                                    Шел 2019 год, а сообщество PHP до сих пор не обновили PHP.net и не написал нормальную документацию.
                                                                                                                                      0
                                                                                                                                      Пару лет назад на ZendCon Сара Големон не особо скрывала, что в документации дыры и волонтеры для их починки *очень* приветствуются. По-простому говоря, если есть руки и знание языка — ради бога приходите. Возможно все же есть какой-то сравнительно жесткий входной ценз для волонтеров.
                                                                                                                                        –4
                                                                                                                                        Меня больше удивило, что обсуждение разработки ведется через рассылку по email всем кому надо и не надо. И отдельно существует веб-интерфейс к этим письмам. Самый популярный язык для веб-разработки, можно же было какой-нибудь форум сделать с подпиской на конкретные темы.
                                                                                                                                          +1
                                                                                                                                          Я просто оставлю это здесь: habr.com/ru/post/314084
                                                                                                                                            –4

                                                                                                                                            Ну я бы наверно согласился, что для Linux это в некоторой степени оправдано, но блин для языка веб-разработки?)

                                                                                                                                        –4
                                                                                                                                        Обожаю Симфони 4.
                                                                                                                                        Но если ты попадаешь на стэковерфлоу с вопросом о связи двух и более Entity, то разбор превращается в ад.
                                                                                                                                        В итоге ты скролишь огромные простыни с описанием сущностей.
                                                                                                                                          +6
                                                                                                                                          В документации Doctrine есть хорошие примеры и сложные случаи, обычно их хватает. Не хватает — можно и на StackOverflow.
                                                                                                                                          +24
                                                                                                                                          У меня есть полдесятка знакомых сеньоров с 5+ годами опыта в своей области (не-PHP), которые немного не в курсе выхода версии 7.0 (некоторые про 5.0 не слышали). Когда говорю, что у меня 90% работы на РНР — сочувствующая усмешка. Потом они слышат о наличии вещей типа интерфейсов, жесткой типизации и встроенной крипты, и отвисшие челюсти можно снимать на видео. Контрольный в голову — «а еще на РНР было рассчитано 40+ тысяч операций на глазах, и ни один не пострадал» (было у меня как-то несколько проектов по медицине). Удивляет, что современные профессионалы продолжают высказывать безапелляционное мнение при отсутствии адекватной информации о сути дела.
                                                                                                                                            +4
                                                                                                                                            Встроенная крипта — это вы про вызовы сишных либ?
                                                                                                                                            Жесткая типизация — это про тайп хинты?
                                                                                                                                            Интерфейсы — это те которые определяют только имя метода и кол-во аргументов, но не их типы?
                                                                                                                                            Про расчет — позабавили. Я погуглил про 64 битные числа, и оказывается что на PHP 5 на винде они вообще недоступны, а на линуксе необходима 64битная машина (!). Потом я прочел совет использовать BCMath, и увидел в сигнатурах функции сложения чисел в аргументах строки, Карл! Еще в 7 классе многие писали длинную арифметику на паскале на массивах (байтов, либо кто покруче интов). А тут строки.

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

                                                                                                                                            Как способ быстро добиться результата (http ответа с html, либо с json на базе ответа из БД), наверное PHP удобен, но не потому что язык хорош, а потому что одну и ту же задачу на нем решали миллионы раз и написали понятных оберток. Как язык (да, тут подразумевается язык общего назначения) — это мусор какой-то и писать на нем расчет медицины (что бы это не значило) не стоит.
                                                                                                                                              +6

                                                                                                                                              Интерфейсы с типами же. Типы аргументов и тип возвращаемого значения, просто не все делают строгие интерфейсы

                                                                                                                                                +6
                                                                                                                                                Ну вот опять.

                                                                                                                                                Встроенная крипта — это вы про вызовы сишных либ?

                                                                                                                                                Большая часть функциональности программ в user mode — это вызовы либ (начиная от glibc на GNU), это если вы конечно не хотите изобретать велосипеды. Я не столько про это, сколько про sodium в PHP 7.2. В отличие от упомянутого ниже (и удаленного из 7.2) mcrypt:

                                                                                                                                                1. Sodium куда проще правильно готовить. Он не позволяет использовать многие нестойкие / ослабленные режимы типа AES-ECB — от чего страдал mcrypt. Огромная часть атак на методы шифрования выполняется на некорректное их использование, а не на основополагающие алгоритмы. При этом большая часть разработчиков не заморачивается деталями, и использует первый же метод из документации. При этом если голова на месте — пожалуйста, используй openssl и шифруй так, как заблагорассудится. По факту имеем систему, более подходящую для разработчиков, не имеющих базовых знаний по криптографии.

                                                                                                                                                2. Sodium влит в ядро. Я только что проверил — на том же EasyApache нет опции, чтобы его отключить (на mcrypt — есть), на основной платформе (Linux) он отключается только опцией компиляции (а не строчкой в конфиге). Это дает основания ожидать, что он будет доступен на подавляющем большинстве хостингов, в отличие от mcrypt — что заставляло городить тот же AES/Rijndael в нативном режиме.

                                                                                                                                                Жесткая типизация — это про тайп хинты?

                                                                                                                                                Намек: hint на английском — намек. На данный момент это уже не намек, а декларация: «Type declarations were also known as type hints in PHP 5.» — это что касается аргументов функций / методов. Декларативное объявление типа аргумента выбросит исключение при вызове с несовместимым аргументом. Несколько моментов:

                                                                                                                                                1. Формально это не жесткая типизация на уровне хранения данных. Во многих других ЯП это куда строже — однако здесь на уровне исходного кода получается то же самое как минимум в контексте вызова методов / функций.

                                                                                                                                                2. Типы переменных пока декларировать нельзя, декларацию типов свойства объектов добавят в PHP 7.4. При этом никто не мешает повесить getters/setters на свойства и типизировать их аргументы.

                                                                                                                                                Интерфейсы — это те которые определяют только имя метода и кол-во аргументов, но не их типы?

                                                                                                                                                Уже давно определяют (при желании). Несовпадение по типам в реализующем классе дает исключение.

                                                                                                                                                Я погуглил про 64 битные числа, и оказывается что на PHP 5 на винде они вообще недоступны

                                                                                                                                                Простите, и что? При разработке приложений обычно ориентируются на наиболее массовые системы. 1. PHP на Windows — точно не самая массовая система. 2. Поддержка PHP 5 даже на уровне обновлений безопасности прекращена в прошлом году.

                                                                                                                                                а на линуксе необходима 64битная машина (!)

                                                                                                                                                1. Насколько вы знакомы с современным рынком хостинга? Тот же RHEL/CentOS с версии 7 поддерживает только 64-битную архитектуру как минимум на Интелах, процессора имеют 64-битные расширения уже много лет.

                                                                                                                                                2. Почему обязательно использовать 64-битные числа — на всякий случай?

                                                                                                                                                Потом я прочел совет использовать BCMath, и увидел в сигнатурах функции сложения чисел в аргументах строки, Карл!

                                                                                                                                                Это декларация аргумента — просто чтобы загнать в движок число произвольной длины (arbitrary precision). Да, вы можете запихать туда нечисленное значение — не надо этого делать. Альтернатива — использовать указатели на блок памяти (небезопасно, их в PHP просто нет в обычном понимании), или другие методы работы с памятью. Строки в PHP при этом вполне работоспособны для переноса числовых данных, и не только их.

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

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

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

                                                                                                                                                1. «Расчет медицины» бывает разный. В моем случае (расчет интраокулярных операций) стандартной точности PHP (сейчас не помню дефолты в 5-й версии, ЕМНИП 12 или 14 знаков после запятой, в 7.3 — 14) было более чем достаточно. BCMATH приходилось использовать лишь в единичных случаях — в остальных с лихвой хватало обычных float.

                                                                                                                                                2. После любых изменений подобного кода в обязательном порядке прогоняются регрессионные тесты. В моем случае они выполнялись на нескольких десятках (сотнях) тысяч расчетных кейсов, описывающих оптико-биологические параметры человеческого глаза. Результаты должны совпадать с контрольными расчетами (мы использовали MatLab) до офтальмологической клинической значимости (плюс-минус 1/10 диоптрии). За всю свою практику расхождений по регрессионным тестам больше чем в 6 знаке после запятой я не видел — и это были пограничные кейсы. Это разница с клинической значимостью на 5 порядков… Карл. Позволю себе утверждать, что конкретные требования были более чем закрыты.

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

                                                                                                                                                4. Мы рассматривали вариант гонять вычисления напрямую на движке MatLab — но не потому, что не устраивала точность PHP, а чтобы сократить время на конверсию методик. Этот подход было признан неэффективным как с инженерной точки зрения, так и с точки зрения поддержки и развития системы.

                                                                                                                                                5. Некоторые конкурирующие системы расчетов были написаны… на Excel. При этом их точность страдала не от точности управления данными итп, а от кривых/упрощенных методик.

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

                                                                                                                                                Вывод — был выбран инструмент для решения задачи, выбор был обоснован и подтвержден многочисленными проверками, и адекватность выбора была подтверждена массой реальных кейсов. ИМХО ваша фраза про «не стоит» — это широкое утверждение, под которым я не вижу точного обоснования, подтвержденного детальными расхождениями с требованиями конкретных задач. Как результат, ваш комментарий лишь подчеркивает мой тезис о том, что прежде чем называть язык мусором, неплохо бы собрать информацию о четко описанных косяках из реальной жизни, которые вы собираетесь критиковать.
                                                                                                                                                  0

                                                                                                                                                  Позвольте полюбопытствовать почему для точных медицинских расчетов был выбран PHP?

                                                                                                                                                    +2
                                                                                                                                                    Вывод — был выбран инструмент для решения задачи, выбор был обоснован

                                                                                                                                                    Почему был выбран именно php, а не python, javascript, ruby, java, Go или C#?

                                                                                                                                                      +4
                                                                                                                                                      Попробую ответить и вам и DarkGenius.

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

                                                                                                                                                      2. Требования проекта изначально включали легкодоступный хостинг. В 2004-м году (когда начиналась разработка) таким требованиям удовлетворял в основном LAMP stack и ASP / C#, плюс Java, если лезть в enterprise — но это было бы заметно дороже. Опять же, если бы появилась необходимость — я первым голосовал бы за конвертацию исходников туда, куда необходимо, невзирая на стоимость (это медицина, все-таки) — но мы не нашли такой необходимости (см. ниже). В конечном итоге нам отдали и поддержку проекта (включая хостинг), т.е. мы могли бы туда влепить все, что угодно — но найти адекватных LAMP хостеров за вменяемые деньги тогда все равно было проще, чем на многое другое, и они были найдены (Rackspace, если кому интересно). Кроме пары косяков аппаратного толка, ни единой проблемы с инфраструктурой за более чем 8 лет не возникло.

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

                                                                                                                                                      Я там выше писал уже, что рассматривались варианты с двухзвенной системой (С/MatLab backend для расчетов, куда PHP сливал бы входные данные), но PoC оказался громоздким по инфраструктуре, сложным в поддержке, и как результат, менее надежным без доказанной необходимости.

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

                                                                                                                                                        Спасибо за развернутый ответ. Насколько сложная математика в расчетах? Достаточно сложная, чтобы рассмотреть возможность использования мощностей GPU в расчетах?

                                                                                                                                                          0
                                                                                                                                                          Рад, что смог принести что-то новое в дискуссию. Сложная ли математика — не особо, скорее многоступенчатая. В базовом варианте — арифметика первого порядка (x + y/2), потом подключается простейшая тригонометрия, в варианте «космос» — матрицы с варьируемой размерностью (позволю себе не лезть в дальнейшие детали, проприетарщина все же). Как раз таки на матрицах было бы удобно применить тот же MatLab, но для конкретных ситуаций мы довольно оперативно реализовали все, что требовалось, на PHP, и кросс-чек с матлабом никаких проблем не выявил. Конкурирующие методики были чуть проще, но идеи те же. Все на плавающей точке, конечно, но достаточно много шагов. Количество операций было таково, что (по очень старой памяти) среднее вычисление занимало от 50 до 200 миллисекунд на среднем Xeon и PHP 5 (точную минорную версию не помню, да и апгрейды проводились). Т.к. вычисления не велись каждую секунду, производительность была более чем адекватной и была сравнима с временем отклика бэкенда. Вещей типа CUDA в те времена в широкой доступности не было, и откровенно говоря, на данных задачах не было в них и необходимости.
                                                                                                                                                            0

                                                                                                                                                            Увы дело не столько в точности расчётов, вы меня очень опечалили информацией о том что за язык/экосистема используется, да я понимаю можно повесить кучу проверок, тестов и прочее, думаю у boeing их не меньше чем у вас, но результат 2 самолёта угробили всех на борту, просто экономия на разработке, ничего личного просто бизнес :(


                                                                                                                                                            И, вы вроде не писали ранее об этом, вы пишете что в расчёте много шагов, а оценивался ли алгоритм (с учётом использования float) на точность исходя из теории погрешностей?

                                                                                                                                                              +1
                                                                                                                                                              Возможно, я ошибаюсь, но мне кажется, что Вы хочете сказать, что в C/C++, C# или Java (или какой там «язык/экосистему» Вы больше предпочитаете) «оценивать алгоритм (с учётом использования float) на точность исходя из теории погрешностей» просто не нужно. Поправьте меня пожалуйста, если не так понял. Если я вообще понял, что Вы хотите сказать. В Boeing тоже PHP использовался для расчетов?
                                                                                                                                                                0

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

                                                                                                                                                                  +1
                                                                                                                                                                  Ну так насчет приведения типов вопрос вроде как решен в PHP7 (тайпхинты, да, это не статическая типизация), другое дело, насколько эффективно разработчики будут это использовать. Я к чему: говнокод можно написать даже на эльфийском языке программирования, спор в том, что какие-то языки дают больше возможностей выстрелить себе в _____ (впишите предпочтения), а какие-то — меньше. Ну так вот, C вполне позволяет отстрелить себе (и всем кому «повезло» оказаться рядом) вообще всё, и тем не менее это один из самых распространенных языков системного программирования. PHP для Web-разработки подходит вполне, практика это показывает (практика — критерий истины). Для вычислений, думаю, тоже; во всяком случае никаких проблем с этим не встречал. Чем же лучше тогда Java или C#? Они точно надежнее вычисляют? Потому что более типизированы? Если мне в метод объекта нужно передать float, я его и передам, в чем проблема? Если передам не то — это ошибка программиста, а не языка. Кстати, ведь для программ на Java тоже пишут тесты, не так ли?
                                                                                                                                                                    +1
                                                                                                                                                                    Чем же лучше тогда Java или C#? Они точно надежнее вычисляют? Потому что более типизированы? Если мне в метод объекта нужно передать float, я его и передам, в чем проблема?

                                                                                                                                                                    Что вы не поделите случайно два флоата целочисленно (или два инта целочисленно, ожидая, что они флоаты).


                                                                                                                                                                    Но вообще, опять же, лучше не C# и не Java. Лучше те языки, где необходимые ограничения (на точность, скажем) вы можете выразить на уровне типов, и где семантические ограничения модели вы тоже можете выразить на уровне типов. Тем более, если вам производительность не столь важна.


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


                                                                                                                                                                    Немного отвлечённый пример — есть языки, где в корректности процедуры, скажем, сортировки вы убеждаетесь, набросав десяток тестов на, как вам кажется, разумные граничные случаи. Есть языки, где вы берёте QuickCheck и подобные, которые генерируют тестовые примеры за вас, но это всё равно тесты. А есть языки, где вы на уровне типов выражаете понятия сортированности, и язык вам гарантирует его соблюдение для любого входного массива.

                                                                                                                                                                      0
                                                                                                                                                                      Вы никогда в PHP не поделите 2 флоата или 2 инта целочисленно, используя стандартный оператор. Но есть другая засада: вы можете передать флоат в функцию, аргумент которой помечен тайпхинтом int. Но есть и способ это контроллировать: declare(strict_types=1)
                                                                                                                                                                +1