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

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

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

до java/c# пока что очень далеко

ВНЕЗАПНО не строго типизированный язык

конечно, не дотягивает до java/c#/typescript


Антон, так пишите на Java или C#, кто же вам запрещает-то?

Статья — прекрасный образец самой настоящей демагогии.

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

Я никогда не понимал — как можно быть «руководителем отдела разработки» на языке, который тебе так не нравится? Расскажите, Антон, пожалуйста, как вы планерки проводите?

Примерно так: «Парни, начинается новая неделя и нам всем снова предстоит писать код на этом ненавистном PHP, будь бы он неладен… Когда же это кончится уже?»
Я же написал: «Повторюсь, не дотянется именно с точки зрения системы типов, в остальных вещах возможны предпочтения в ту или иную сторону.»
А нужно дотягиваться?
Зачем вообще принципиально слаботипизированному языку с динамической «рантайм» системой типов дотягиваться до языков со статической типизацией?
Кто такую цель поставил для PHP? Вы?
Ну php же явно идет в эту сторону. Type hinting-и усложняются с каждой версией. strict_types и т.д. Но в то же время у этого процесса есть ограничения, потолок возможностей, что я и показал в этой статье. Просто это не всем очевидно.
Я не уверен, что вы верно понимаете, в какую сторону идет PHP. И более того — не уверен, что цель этого движения именно «строгая типизация» в вашем понимании.
Цель-то достаточно очевидная у нынешних владельцев zend — отжимать рынок у java/c#/typescript. Это предопределяет кучу стратегических решений по развитию языка. Так что не зарекайтесь от «строгой типизации».
Вполне допустимо повторение ошибок, подобных php6. Тогда всё исходило из идеи что в java же utf-16, значит и в php надо.
К большому сожалению само ядро php имеет относительно слабое комьюнити и ограниченные ресурсы. Плохая сторона — зависимость от zend с плохо продуманной стратегией, хорошая — очень тщательно выбираемые изменения не ломающие BC каждые пять лет и дающие максимальный профит тактически.
Не надо так агриться на статью, я не хотел никого обижать )
Я бы не «агрился» так, если бы не очевидный вред от таких статей.

Вы своё собственное несовпадение «идеального языка» и реального PHP почему-то считаете проблемой последнего. Да еще и называете «фатальным недостатком»

Если бы не подобная тональность статьи — никаких отрицательных эмоций в вашу сторону не было бы.
Какая тональность? В какой фразе? Система типов хуже, чем у java — ну извините, это медицинский факт, а не тональность.
Кроме этого факта я ничего плохого про php не сказал. Более того, я на нем сам пишу.
О проблемах надо говорить, а не замалчивать. Тогда возможно появятся какие-то решения. К примеру для javascript появился typescript. Чем не решение? И строгие типы, и возможность использоваь либы на ванильном Js
Можно я чуть-чуть «сагрюсь» еще? Ну совсем немножко?

Система типов хуже, чем у java — ну извините, это медицинский факт, а не тональность.

Вот здесь у вас фатальная ошибка и недостаток. У вас, а не в PHP. Ошибка в том, что вы пытаетесь личное субъективное выдать за объективное сравнение несравнимых величин. Пресловутые «килограмм» с «километром»

Система типов в PHP не «хуже» или «лучше» — она другая. Она построена на иных принципах и решает иные задачи, нежели в Java.

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

Но если совсем коротко, то успешно решаемые задачи в PHP стоит свести к нескольким важнейшим пунктам:
— автоматический динамический кастинг скалярных типов
— реализация понятия «практической эквивалентности»
— стандартизация всех i/o хэндлеров в едином типе resource
— решение всех проблем, которые возникают в других языках с динамическими массивами
— реализация класс-ориентированного подхода
— контроль типов времени исполнения
— контроль типов времени компиляции

Постарался расположить по степени важности
— автоматический динамический кастинг скалярных типов

Да, когда-то целью php это было. Но ввели declare(strict_types=1). Это для чего?
По-моему чтобы избавиться от неявного, разве нет?

— реализация понятия «практической эквивалентности»

Не могли бы вы пояснить?

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

Каких проблем?

— контроль типов времени компиляции

в php почти нет этого
Да, когда-то целью php это было. Но ввели declare(strict_types=1). Это для чего?
По-моему чтобы избавиться от неявного, разве нет?

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

Причем тут ваши фантазии о «явном» и «неявном» — я не знаю.

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

Я про неявное приведение типов.

function myFunc(int $val) {
   print $val;
}

myFunc("1.99999999");


выдаст единицу. Молча, неявно преобразовав тип.

с decrlare(strict_types=1) придется явно написать

myFunc((int) "1.99999999");


иначе будет выдана ошибка. Вот про это явное указание (int) я и говорил.

И не надо, пожалуйста, рассказывать о «целях PHP». В вашем исполнении это звучит как минимум странно.


Почему в моем исполнении странно? Может именно в вашем странно?
Я просто высказываю свое мнение, наблюдая за changelog ом языка.
выдаст единицу. Молча, неявно преобразовав тип.


Как же «неявно», если вы сами написали «int»? Что тут неявного?
Как же «неявно», если вы сами написали «int»? Что тут неявного?

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


Явное преобразование — это когда программст, когда передаёт параметр сам пишет, что его надо преобразовать в int.

Вот да, достаточно просто погуглить по фразе «неявное преобразование типов»
Практическая эквивалентность это
1 == '1' == true
0 == '0' == '' == false == []

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

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

Не пишите на PHP. Он вам не нравится, и, как результат — вы его не понимаете.
Последнее утверждение крайне спорно. Я 9 лет писал на джаве, я думаю что понимаю её глубже чем многие. Но я прям далеко не фанат. И как только появилась внятная альтернатива в лице котлина — с радостью перешёл на него. Не нравится ≠ не понимаю.
Практика показывает что те, кому язык не нравится, не изучают его в должной мере. И, следовательно, не понимают.

Изучение же, приводя к пониманию, затем убирает это странное «не нравится». Ну или человек уходит на другую платформу.
Позвольте вас дополнить.
В целом обсуждение сводится к той ситуации, когда есть два напильника — плоский и круглый, и, автор, взяв в руки круглый напильник, рассказывает нам, как же плохо им выравнивать плоскую поверхность — то он соскальзывает, то канавки в поверхности делает, то вообще очень медленно точит! И, говорит, неплохо бы этому круглому напильнику грани сделать — тогда и с плоскими поверхностями намного удобнее будет работать! У автора то уже есть один удобный плоский напильник, тот то хорошо плоскости обрабатывает, значит надо к этому стремиться, сделать все напильники плоскими. Автор просто редко занимается округлыми поверхностями, но в те редкие моменты, когда это все же происходит, он тихим шепотом сыплет проклятия тому, кто ему подсунул эти неплоские поверхности, возможно даже изредка подумывая о круглом напильнике…
Если уж на то пошло, то php (personal home page) изначально предназначался для простых сайтиков

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

Множество гигантских систем написны на php и страдают от недостатчной строгости язык

Посмотрите современные фреймворки.
Вот вы сами и ответили на свои же, скажем так, «вопросы».
Время шло, «фейсбуки превращались», «напильники перестали подходить», но вместо того, чтобы брать для работы другие, более подходящие напильники (треугольные, квадратные, и другие разные инструменты), мы продолжаем мужественно стачивать грани у круглого напильника, превращая его во всё более плоский…
Блин.
Расскажите мне, какие аргументы приводить начальству, чтобы уговорить их потратить пару человеколет на то, чтобы переписать всё на другой язык?

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

Т.е. выбора-то нет на самом деле.

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

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

В вашем комментарии вы правильно используете аналогию с напильником — значит я верно донес мысль.
В данном случае напильник — это инструмент, а каждый инструмент предназначен для выполнения предназначенных этому инструменту действий. И поэтому топором мы рубим, а отверткой закручиваем, а не наоборот. И мы не стараемся из отвертки сделать топор, а из топора отвертку. И если у нас нет отвертки, то мы идем в магазин и покупаем ее (ну или у кого то берем и др.)
А в случае, обозначенном автором, как раз и усматривается ситуация, когда человек не хочет использовать подходящий по ситуации применения инструмент, а хочет подогнать инструмент под применение. К примеру, нет отвертки для вкручивания шурупа. Что делаем? Правильно, молоток! Несколько ударов — и шуруп вкручен! Наверняка каждый из нас хоть раз, но делал так. Так и в случае автора — есть PHP, который был сделан для веба, и причем сделан давно, и он был сделан под тот, старый веб, а не современный, который и чисто вебом назвать уже нельзя, т.к. веб трансформировался уже в нечто большее и глобальное. Да, PHP доделывают, совершенствуют, улучшают. Но эти улучшения более косметические, чем принципиальные. А автор пытается сравнивать PHP с современными языками либо с языками другого назначения и применения. А зачем это делать? Если автору нужна строгая типизация, так пусть берет Java и пользуется на здоровье. Зачем тащить фичи из одних языков в другие, когда можно брать уже готовый нужный язык и пользоваться им? На то они и разные языки, чтобы быть разными! Или автор хочет из PHP сделать Java? Сейчас столько языков, на любой вкус и цвет — пользуйся, не хочу. Я никогда не понимал, когда хают один язык, а другой восхваляют. Это — не профессионально! У каждого языка есть свои плюсы и свои минусы, и зачем тащить одни в другие, не понимаю. Сейчас все языки в одинаковой категории по производительности примерно равны, по памяти ограничений почти нет, и нет смысла холиварить на тему лучше-хуже, надо просто пользоваться тем, что удобнее для тебя и все. Вот как-то так…

P.S. Есть опыт использования разных языков, в том числе PHP и Java.

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


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

Вот именно в такой интерпретации я с вами полностью согласен. Но, как мне показалось, автор имел ввиду несколько другое. Не то, что инструмент можно улучшить за счет каких-то правильных дополнений, а то, что в целом сам инструмент плохой, даже если добавить ему эти отсутствующие дополнения.
По поводу заимствования — это прекрасно, что оно имеет место быть, но все должно быть в разумных пределах. К примеру, некоторые экстравагантные инженеры приделывают к автомобилю крылья и винты, и у некоторых это чудо инженерной мысли даже летает, но с практической точки зрения получившееся поделие ухудшило свойства автомобиля, и так и не стало самолетом. К чему я — надо улучшать и заимствовать то, что относится к изначальной целевой применимости сущности, а не просто потому что какая то фича есть у другой сущности, эта фича удобная и привычная, значит ее надо пихать во все другие сущности, хотя может быть там это совсем не к месту и сильно изменит саму эту сущность. Пример — любые паттерны программирования, которые суют везде, где надо и не надо. В общем, я думаю так — машине крылья не нужны! Если хотите крылья — делайте самолеты!
P.S. И кстати, по поводу типизации PHP был лишь пример, а не именно причина для обсуждения. Я имел ввиду абстрактную ситуацию в целом относительно языков.
> что в целом сам инструмент плохой, даже если добавить ему эти отсутствующие дополнения.

Ситуацию можно исправить, если сделать аналог typescript для js.
Там были те же проблемы, и решение нашлось ведь
Ну так исправляйте, кто мешает то?
Из двух высказываний типа:«Смотрите, как я решил проблему типизации в PHP, как здорово получилось!», или
«В PHP нет нормальной типизации, в Java намного лучше, PHP отстой!»
вам что больше по душе?

С одной стороны, да, практика показывает, что сложно удачно совмещать два целевых назначения каких-то вещей. Как говорится, гибриды обычно удачно комбинируют недостатки предков. С другой, гибриды могут (не должны, но могут) оказаться рациональным выходом для тех, для кого обе функциональности важны, а иметь специализированные инструменты для каждой по каким-то причинам нерационально. Ну, например, в случае летающего автомобиля, можно представить себе ситуацию: живешь за городом достаточно далеко от города, где работаешь, по прямой в км, а с учетом направлений, состояния и(или) загруженности дорог ещё дальше. Летающий автомобиль, способный взлетать и садиться практически везеде, может оказаться вполне разумным выходом для сценария: взлетел от дома, долетел по прямой до окраин города, приземлился и поехал в центр. Да, это медленнее получится, чем лететь на полноценном самолете, оптимальном для перемещения 1-2 человек на такие расстояния, и пересесть на автомобиль оптимизированный для города, но даже не обращая внимание на цену приобретения и самолета, и автомобиля (а ещё желательно иметь машину дома), такой сценарий может оказаться затруднительно реализовывать из-за отсутствия мест, где можно без проблем оставить на день самолёт и на ночь машину, то есть выбирать самолет или машину использовать нужно по принципу "исключающего или". И вот тут "автолёт" выигрывает по совокупности факторов и у нормального самолёта, и у нормального автомобиля.


Примерно то же и с языками происходит. Допустим есть язык А по совокупности факторов больше всего подходящий для какого-то применения, например для создания простых веб-сайтов :) и слабо подходящий для описания сложных бизнес-процессов (например, по причине отсутствия ООП) и, допустим, есть язык Б больше всего подходящий для создания сложных бизнес-моделей, но значительно уступающий языку А в обработке веб-запросов (например, способный работать в вебе только в режиме CGI). Основная задача у нас была создать простой (с точки зрения бизнес-процессов) сайт. Технико-экономический анализ первоначальной задачи с учётом роста бизнеса на 10% процентов в год на протяжении 10 лет без особого изменения бизнес-процессов показал, что оптимальным будет язык А. Написали сайт, допустим за год, запустили, но постепенно стало выясняться, что оценки роста оказались слишком пессимистичными, а пользователям нужны более сложные бизнес-процессы. Может быть даже оказалось, что в фактических, а не прогнозируемых условиях, сразу надо было писать на языке Б. Но уже есть работающий и приносящий деньги сайт на А. Ресурсов на то, чтобы переписать сайт целиком или, хотя бы, бизнес-модель, на язык Б, не останавливая развития работающего сайта, нет. Пилим сложные бизнес-процессы на языке А и плачем. А тут оказывается, что какой-то энтузиаст из чисто академического интереса портировал некоторые фичи языка Б в язык А, пускай и не полноценно, с учётом "родовых травм" языка А, но портировал, значительно упрощая (читай — удешевляя) бизнес-моделирование на языке А. Мы должны проигнорировать эту возможность, или всё-таки начать её использовать?

Рациональный подход в реальной жизни не только может, но и должен быть! И я ничего не имею против «гибридов» и сращивания технологий и других сущностей, но я о другом говорю.
Я против негативного отношения к тому, чем приходится пользоваться в силу различных обстоятельств, в данном случае PHP. Посмотрите на это с другой стороны — то, что у PHP есть недостатки, которые остались с прошлого и которые со временем стали все сильнее мешать, это не вина языка, это недоработка тех, кто принимает решения по разработке проектов и использованию конкретных инструментов. Это они неправильно или не вовремя приняли решение об использовании необходимых инструментов и технологий, это они не позаботились и не предусмотрели текущие проблемы с языком PHP, хотя знали про них ранее. Поэтому говорить о том, что язык PHP плохой, что у него нет того то, что он не умеет то то — в корне неверно. А чем думали раньше?? Это, к примеру, как переходить через большую яму по узкой досочке — если туда бухнешься, то кто виноват — узкая досочка, по которой решил перейти «умный человек», зная что вероятность падения более 90%?? Ах да, "… проект достался от предыдущих разработчиков, вот если бы я начинал с нуля, то..." — через некоторое количество времени ситуация бы снова повторилась.
Поэтому, будет правильным, как мне кажется, спокойно относится к недостаткам текущей реализации языка, по возможности добавлять сторонние «костыли» для расширения возможностей, а когда «костылирование» перейдет черту рациональности — просто поменять инструментарий со всеми вытекающими. Но не хаять то, с чем вы работаете. Ибо работа должна приносить удовольствие, тогда и результат будет соответствующий.

В этом плане, да, негативное отношение к инструменту в духе "уроды, не могли сделать по-человечески" ничего положительного никому не несёт.


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

Чего я там не понимаю? На php пишу 100500 лет.

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

Замкнутый круг.

Попробуйте ответить на самый простой вопрос для самых-самых начинающих — а зачем вообще в PHP
empty('0') === true;
?
Какой практический смысл в таком?

С точки зрения любого не-PHP программера ересь же. Непустая строка пустая?
НЛО прилетело и опубликовало эту надпись здесь
empty($x) — это фактически сокращенная запись ( isset($x) && $x == false)
А '0' в php — это false

Это не то, чтобы ересь, просто нейминг немного путает людей
empty($x) — это фактически сокращенная запись ( isset($x) && $x == false)

Да ну? то есть для несуществующих переменных (isset($x) = false) empty должна вернуть false?
Вы не ответили на вопрос «зачем оно так»
ну, чтобы меньше кода писать. Вместо двух условий одно

НЛО прилетело и опубликовало эту надпись здесь
AlexLeonov намекает, что в http-протоколе есть только строки, других типов нет. И удобно брать строки из $_GET и тд и сразу начинать сравнивать и складывать с чем нибудь, не приводя вручную к типу

На самом дделе этот аргумент не совсем верен.
Учитывая, что PHP работает далеко не только с $_GET, $_POST и иже с ними, не уверен в корректности этого аргумента как такового. Но, надо же привести что-то в защиту ¯\_(ツ)_/¯
В сложных приложениях все равно приходится тщательно валидировать и санитизировать входные данные.
Одна ручная операция по преобразованию типа роли бы не сыграла.

В сложных приложениях получение данных из GET и POST — вершина айсберга, причем самая простая. Дальше идет бизнес логика и т.д., где цена ошибки слишком высока, и хочется не надеяться слепо, что php как-то сам закастит данные по своим магическим правилам. Делать все явно — вот, что было бы хорошо. Понятный с одного взгляда неизменный тип переменной -это было бы супер. Но увы
И я о том, но ведь «мы просто используем инструмент не по назначению», как тут многие выражаются(С удовольствие использовал бы подходящий инструмент, да вот поди объясни бизнесу, что у них кодовая база не на том написана). Я с Вами во всем солидарен. Времена, когда PHP заходил с его слабой динамической типизацией канули в лету, теперь скорее источник ошибок, нежели полезная фича.
mysql тоже строки возвращает как результаты выборки, независимо от типа в базе. Так что основная причина подобных приведения — именно упрощение разработки в среде, где почтм всё представлено в строках технически, но имеет семантику не только строк, но и чисел, булевых и т. д.
В защиту: для проверки с учётом типа есть ===
НЛО прилетело и опубликовало эту надпись здесь
Каких проблем?

— создание в рантайме массива
— динамическое добавление и удаление элементов массива
— возможность иметь неплотное и немонотонное множество ключей
— упорядоченность массива, отдельная от упорядоченности ключей
— нетипизированность массива

Поверьте, не каждый язык это всё умеет.
Да, на уровне конструкции языка этого часто нет. Но обычно в этом случае есть в виде стандартной библиотеке.
Это всё классно, но

$requiredParams = array_slice($params, 0, 9);
$baseUrl = Router::createLink('analys', 'index', $requiredParams);

Видите ошибку? А она есть.
НЛО прилетело и опубликовало эту надпись здесь
Включая статические гарантии не выхода за границы? Или как проблемы-то решаются?


Покажите мне практический пример «выхода за границы» для массивов в PHP — и тогда обсудим вопрос про гарантии.

На самом же деле постановка вопроса не имеет смысла, поскольку «массивы» в PHP это не массивы с фиксированным размером элемента и смещением, а что-то вроде hashmap (тоже неверно, но ближе к истине)
НЛО прилетело и опубликовало эту надпись здесь
Запрос элемента с несуществующим ключом приведет к выбросу предупреждения (можно проигнорировать) и возврату null значения.
Но поскольку в языке есть явная конструкция проверки существования элемента — проблема не имеет смысла.
НЛО прилетело и опубликовало эту надпись здесь

C?

НЛО прилетело и опубликовало эту надпись здесь

Если PHP претендует на OOP с SOLID, тогда почему они немогут реализовать нормальное ковариантное наследование как в других языках. Вместо этого зачем-то делают костыли в виде нарушения принципа Лисков. Можно еще ознакомится с этим PR и отношением PHP сообщеситва к таким изменениям.

Можно ссылочку на документацию, где указано, что цель развития PHP — соблюдение принципов SOLID?

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

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

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

Но расширение типа в наследниках позволяет использовать их во всех случаях, где использовался базовый класс — на мой взгляд, никакого нарушения нет.
НЛО прилетело и опубликовало эту надпись здесь
Ковариантность: если у вас в базовом классе Base есть метод, возвращающий некоторый BaseRet, то вы по факту говорите, что объект каждого класса Derived, унаследованного от Base, возвращает из этого метода BaseRet. Если вы в конкретном Derived возвращаете DerivedRet, унаследованный от BaseRet, то вы всё равно возвращаете BaseRet (потому что DerivedRet is-a BaseRet), и все действия, которые клиент вашего метода может сделать с возвращённым ему (по контракту базового класса) BaseRet, он может сделать и с возвращённым из конкретного метода DerivedRet.

Если вкратце: возвращаемые типы сужать можно, расширять нельзя.

Если под расширением типов вы подразумеваете
B extends A {...}
то разве из первого абзаца не следует прямо противоположное — что возвращаемые типы расширять можно?
НЛО прилетело и опубликовало эту надпись здесь
Вы не представляете, как я радовался declare(strict_types=1). Как ребенок.
Но потом я внезапно осознал, что в эту сторону большого развития не будет из-за того, что всё проверяется в рантайме. И опечалился.
Собственно, об этом и статья.

Когда будет JIT, вероятно, проблемы рантайма должны будут уменьшится.
Даже opcache, по словам Дмитрия Стогова уже использует тайпхинтинг для оптимизаций.

У меня такие же чувства. Но если честно, то первый комментарий абсолютно верен. Нам с вами надо писать на Яве и сишарпе :) там все в разы приятнее. Особенно с типами :)
А так… я пока тоже пишу на PHP. Мне это приносит больше денег :)
Меня вполне устраивают типы.
Есть конечно моменты которые стоит доработать, но их уже предложили и рассматривают.
К примеру хотят добавить скалярный тип.
Еще бы хотелось иметь возможность создавать собственный тип.
(type Test = ...)
Ну да, соглашусь.
Пожалуй не хватает только конструктора кастомных типов.
Что-то вроде
type iterable = array | \Iterator, но в своем коде
Можно любить, признавая недостатки в тех или иных областях. Движения в сторону строгости типизации подтверждает, что слабая типизация создаёт проблемы в некоторых случаях типового по нынешним временам использования PHP, не только по мнению части сообщества, но и по мнению разработчиков самого языка. Пойдёт ли движение дальше в сторону ещё большей строгости, вряд ли кто сейчас скажет наверняка, но исключать, что PHP станет ещё ближе к Java/C# в плане строгости типизации, нельзя.
странная статья, странные предъявы,

сравнивать типы и ооп в рнр с java, etc… вы серьезно?

… в рнр много вредных возможностей, например:

$Obj = new \stdClass;
$Obj->first = "First";
$Obj->second = "Second";

$a = "first";

print($Obj->$a);



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

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

и всякое такое…

это как автомобили сравнивать… что говно что не говно… говорю, любое авто хорошее, если им по назначению пользоваться и вовремя обслуживать, а не лезть паркетником в гавно\глину и жаловаться «джип с недостатками».
  1. Особенно удивляет, что javascript ругают меньше

    Откуда вы взяли про больше/меньше? Получается java/c# совсем не ругают?


    По моим ощущениям, ругают одну только джаву (чего только это стоит — как же её не ругать?), и ощущение складывается от того, что эта платформа моя основная сфера деятельности.


  2. релизы php7 (с нормальным ООП и строгим тайпхинтингом)

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


Не понимаю, почему все накинулись на автора, еще и с аргументами, аля «пишите на своих джаве, сях и прочем, если не нравится», это сродни «я художник, я так вижу». Но тут-то все-таки комьюнити не гуманитарное, думается мне.

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

2 моих последних проекта на PHP, это мой основной рабочий язык, он неплохой, он очень простой, в этом его плюс и минус. И если это плюс на старте, то чем дальше в лес, тем больше понимаешь, какой же он в некоторых моментах уродливый и как же не хватает тех фич `b` из тех самых других языков. Я не говорю, что PHP плохой язык, упаси боже, у него действительно свои цели и своя ниша, в которой он чертовски неплох. Но давайте будем честны, как только он делает хоть шаг за границы возможного, он мгновенно теряет весь свой шик перед упомянутыми «тру-языками». #nohate
НЛО прилетело и опубликовало эту надпись здесь
Он имел в виду статическую типизацию, по контексту. Их почему-то все путают, Python-у вон никто не мешает иметь динамическую строгую типизацию, а C статическую слабую)
в php и не статическая, и не строгая
Я обратного и не утверждал. Только строгость типизации никак не связана с проверкой во время компиляции/выполнении. Си, внезапно, тоже является нестрого типизированным.
НЛО прилетело и опубликовало эту надпись здесь
Что значит «js не подходит для сложных программ»? Масштабные 3D игры явно посложнее чем какая-нибудь cms. И нейросети на нём давно реализованны, есть библиотека. Ооп и типы этому никак мешать не могут, всё зависит лишь от программиста
Ну не то, чтобы совсем не подходит, но на typescript гораздо легче писать сложные программы. Быстрее понимаешь код и допускаешь меньше тупых ошибок. Angular не зря его выбрал как дефолт
Поначалу тоже плевался от нестрогой типизации. А теперь вообще не представляю как без нее можно жить. Откуда я знаю что там в ответе от АПИ приходит? 0 как число? 0 строка? null? А что если один единственный метод этого апи писал другой автор и написал «пустой ответ» вообще как то по другому? В ПХП очень низкий порог вхождения, надо учитывать что тут говнокод прет просто со всех щелей и со строгой типизацией будет только хуже.
По началу не представлял как можно жить без нестрогой типизацией. А теперь вообще не представляю, как с ней можно жить.
В этом и суть. Со строгой типизацией таких вопросов, о том, что же придет в начале, не возникло бы, все было бы явно и понятно
С чего вдруг? Как строгая типизация помешает говнокодерам с другой стороны в одном месте вернуть 0 числом, а в другом строкой? Никак. Или вы рассчитываете, что они будут ограничены интерфейсами или чем то вроде того? Скорее всего они даже не знают, что это такое.
С того, например, что если бы типизация была статической, или хотя бы, строгой динамической, компилятор еще на этапе компиляции сказал бы,(ну или хотя бы понимал в рантайме) что тут приходит не то, что нужно, а не тихонечко кастовал величины к тайпхинтам. Эта вседозволенность как раз таки и приводит к говнокоду, просто потому, что так проще, а никто не запрещает. Вы точно работали на хоть сколько-нибудь крупных проектах в PHP? Без этого поддержка и разработка оных становится болью ниже спины, я не знаю, как тут можно спорить. Если в плюсах, джавах, шарпах и т.д. можно выстрелить себе в ногу в некоторых случаях, то это точно не относится к таким вещам, как типизация, которая как бы является фундаментальной вещью, ибо есть суть представления информации. У PHP в этом вопросе как будто читы на оружие, можешь отстрелить все что угодно, просто из-за того, что тебе вместо 0 — «0» вернулся, а вкупе с дизайном его API так это вообще стрелковая фиеста.
Я не говорил, что участвовал в чем то крупном :). ПХП это в первую очередь не для крупных проектов. Если у вас там потребность лезть аж в компилятор, будьте добры возмите чтото другое. А если не можете, то это не проблема ПХП уже. Как выше писали аналогию с напильником — вы взяли не тот инструмент, а теперь ругаете инструмент, что он плохо работает.
Ну вот как появится опыт разработки проектов покрупнее, я уверен, мнение о крутости слабой динамической типизации очень быстро рассеется. Я думаю, тут никто не говорит об кейсах аля «бложик на 200 строк».
Выше также писали, что приходится работать с тем что есть, и что никто под нас, разработчиков подстраиваться не будет, просто потому что, нам видите ли неудобно так.

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

Нет никакой «строгой типизации» в PHP. Есть контроль типов в рантайме.
И да, у вас есть возможность его использовать либо не использовать. Что прекрасно, имхо.

Контроль типов — это и есть типизация. А в рантайме она или в каком-то компайлтайме — разница между динамической и статической типизацией. Вот в python типизация строгая, но динамическая. Хотя в каких-то моментах она теперь менее строгая, чем в PHP.

А откуда вы знаете, что в API 0 (число) — это пустое значение, а не валидное полноценное? Банальный индекс элемента в коллекции, например. Собственно, даже в документации функций типа strpos постоянно выделяют предупреждения, что результат false надо проверять строго, что if (strpos($s1, $s2)) не означает "если подстрока найдена".

У самого основной хлеб — PHP, но частично согласен с автором.
Как писали в PHP: фрактал плохого дизайна:
PHP обширно черпает вдохновение из других языков, при этом ему удаётся быть непонятным для тех, кто эти языки знает.
Чем больше проверок в рантайме, тем больше тормозов. Поэтому слишком сложные проверки навряд ли вообще когда-нибудь появятся. Многослойные дженерики и callable с callable аргументами просто положат рантайм. Также будут тормозить рантайм введение типов для членов класса и в других местах.

Не нагнетайте, в PHP5 это работает даже быстрее, чем strlen($str), а в PHP7 вообще без разницы.

Странности тайпхинтинга и типа возврата в связке с наследованием


Здесь получаем ошибку, что findById не совместим с findById из абстрактного класса. Такой же пример в java нормально компилируется:

В Java findById будет возвращать Entity же, а не User? Если это действительно так, то странности не у PHP.
В Java findById будет возвращать Entity же, а не User?

Не, вернёт User. A Entity в Java вообще нет, если только самому не сделать класс с таким именем.

Конкретный пример из статьи:
interface Entity {}

class User implements Entity {};

abstract class Repository {
    abstract public Entity findById();
}

class UserRepository extends Repository {
    public User findById(){
        return new User();
    }
}

Мне нужен юзер и я пишу, что-то типа:
Repository repository = new UserRepository();
        Entity user = repository.findById();

Если объявить переменную user типом User, то получим ту же ошибку, что и в php (о несовместимости типов).
Конечно, можно объявить переменную repository типом UserRepository, но тогда не имеет никакого значения, указание типа возвращаемого значения у абстрактного findById.
> Конечно, можно объявить переменную repository типом UserRepository, но тогда не имеет никакого значения, указание типа возвращаемого значения у абстрактного findById.

Почему не имеет никакого значения? Мы заставляем наследников абстрактного класса возвращать тип, соместимый с Entity
А почему бы тогда не описывать в конкретной реализации метода, что возвращаемый тип совместим с Entity? т.е.
public Entity findById(){
        return new User();
    }

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

Но клиенты могут (и наверно, должны) сами решать, нужен им конкретный экземпляр User или достаточно Entity. И если нужен User, то можно воспользоваться привидением типа.
PS Простите если туплю.

Если нужен User, наверное лучше сразу заюзать UserRepository .

не дотягивает до java/c#/typescript, и навряд ли когда-нибудь дотянется


Фанат тайпскрипта детектед. Зачем вы сравниваете языки программирования с какой-то оберткой над Javascript'ом? TypeScript понимается каким либо браузером? Может быть есть компилятор под какую-нибудь ось? Чтобы работать с вашим тайпскриптом, приходится использовать тонну либ, конвертеров в JS.

Язык программирования — это не компилятор, а описание языка и синтаксиса. На языке программирования пишут программы, а компьютер может их исполнять посредством "либ и конвертеров". Даже машинные коды типа CD 03 F8 не исполняются сами по себе, а каким-то конвертером (я такой даже на тумблерах делал) преобразуются в наличие или отсутствие зарядов и связанных/схожих с ними физических величин в устройствах памяти, которые потом другие устройства интерпретируют.

суть в том, что все мнимое удобство типизации в тайпскрипте ниверлируется тем, что этот язык приходится с трудом запускать через всякие примочки к джаваскрипту. Имел возможность поработать с тайпскриптом, который в проекте был языком для бекенд приложений на NodeJS. Так вот чтобы такая связка работала, приходилось «поставить одну либу, а вот тут еще одну нужно, а вот для этого еще нужно поставить вот эту либу такой-то версии, вот тут в конфиге прописать пару строчек, а для юнит тестов нужно скачать дубликат для Тайпскрипта стандартного набора тестовых библиотек для JS» и все это запускать вот с такими-то ключами и молится чтобы завелось. А если не заведется, то вам выдается «прекраснейший» стак трейс из 100500 либ/строк джаваскрипта с вызовами из анонимных функций.

Конфиги делаются один раз, одним членом команды.

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

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

В ангуларе ts из коробки сразу ок работает :)

Сломанный детектор детектед.
А PHP понимается каждым сервером? А может это всего лишь надстройка над C? Или все таки ставится интерпретатор на него? Или все таки это двойственность стандартов?

Воу, целых одну на каждый тип импорта? (tsx -> jsx/ts -> js etc)
Сейчас сам юзаю связку tsx -> jsx -> js -> js_bundle, минификатор по вкусу, один раз установил все конфиги и забыл. Написал сценарий билда проекта, кодишь, все билдится автоматом, сидишь наслаждаешься жизнью. Если это дюже трудно, есть пакеты в сети, деплой проекта со всеми зависимостями и стандартными либами одной npm командой.
Мы смотрим на эту php-функцию filterUsersByAge и сходу не понимаем, массив чего нам пришел. Что именно за array? В java можно было бы написать List&ltUser&gt, и мы бы понимали, что к нам пришел список объектов User. Или Set&ltUser&gt, и мы бы сразу видели, что это список без повторов, т.е. только разные объекты.

Вообще-то можно написать function someAction(User ...$listOfUsers) и вызывать ее someAction(...$users), в плане тайпхинтинга это удобно. Имхо, конечно.

Иногда можно и так, да. Но большие ограничения на такой способ — ...$listOfUsers должен быть последним и единственным с этим синтаксисом. Какую-то merge(User[] $dst, User[] $src) уже не написать. Ну и накладные расходы довольно велики.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации