Язык php часто ругают, обычно необоснованно. Особенно удивляет, что javascript ругают меньше. Зачастую это делают люди, которые писали на нем 10+ лет назад, когда язык был действительно чертовски плох, да и разработчики в те времена не задумывались над качеством кода. Посмотрите хотя бы на код wordpress, который до сих пор вызывает шок.
Ругают необоснованно, но проблемы у языка, конечно же, есть, и они серьёзные. Разуметеся, если сравнить последние релизы php7 (с нормальным ООП и строгим тайпхинтингом) и php4, то разница будет колоссальная. Однако и в последних версиях языка не всё гладко, и до java/c# пока что очень далеко. Более того, берусь утверждать, что будущее php тоже довольно сомнительно (с точки зрения типов).
Другими словами, давайте рассмотрим предметно, что хорошо и что плохо в php с точки зрения типизации.
Тайп хинтинги
Для начала давайте разберемся, для чего вообще нужны тайпхинтинги в php, чтобы ни у кого не осталось вопросов а ля "зачем эта лишняя писанина".
Немного отвлечемся и посмотрим кусок кода на javascript:
function filterUsersByAge(users, age) {
// тут какой-то код
}
Что мы можем сказать об этой функции? Она берет каких-то пользователей и фильтрует их по возрасту. Но этого мало, потому что сразу возникают вопросы:
Что такое users? Массив? Или какой-то хитрый объект-коллекция?
Возраст задан как целое число или может быть дробным?
Может ли возраст быть null?
Возвращает ли эта фунция значение или же меняет переданный массив users?
Чтобы всё это понять, надо прочесть код функции, а также вызовы этой функции. Ошибки будет отловить сложно, потому что язык не будет ругаться ни на какие аргументы, а будет пытаться их как-то привести к нужному типу.
Как известно, программист тратит больше времени на чтение и понимание кода, чем на написание нового, поэтому отстутствие подсказок в коде является затармаживающим фактором.
Для сравнения код на последних версиях php:
function filterUsersByAge(array $users, ?int $age) : array {
// ...
}
Тут мы видим, что на входе массив пользователей, возраст может быть null, возвращается также массив. Гораздо яснее, не так ли? Если же в нужных местах указать declare(strict_types=1)
, то при попытке пихнуть дробное число в качестве возраста, мы получим ошибку.
Вроде всё супер, но есть нюансы.
Нет дженериков
Мы смотрим на эту php-функцию filterUsersByAge и сходу не понимаем, массив чего нам пришел. Что именно за array? В java можно было бы написать List<User>
, и мы бы понимали, что к нам пришел список объектов User. Или Set<User>
, и мы бы сразу видели, что это список без повторов, т.е. только разные объекты. (Вообще, array в php — это странноватая смесь массива и HashMap, но это тема для отдельной статьи)
Нет уточнений для типа callable.
Вот пример функции:
function reduce ( array $array, callable $callback )
Что за функция идет вторым аргументом? Что в ней должно быть?
Только в комментариях к коду мы можем понять, что там должно быть, к примеру, два аргумента. Кстати, есть четыре вида лжи: ложь, наглая ложь, статистика и комментарии к коду.
В некоторых языках, например в TypeScript, можно прописать прямо в объявлении функции:
function fn(action: (a: string, b: number) => void)
Т.е. здесь в качестве аргумента action должна быть функция с двумя аргументами (строка и число), которая ничего не возрващает. Всё максимально явно, IDE и компилятор сразу скажут, если аргумент был какой-то не такой
Странности тайпхинтинга и типа возврата в связке с наследованием
<?php
interface Entity {}
class User implements Entity {}
abstract class Repository {
abstract public function findById(): Entity;
}
class UserRepository extends Repository {
function findById(): User {
return new User();
}
}
Здесь получаем ошибку, что findById не совместим с findById из абстрактного класса.
Такой же пример в java нормально компилируется:
interface Entity {}
class User implements Entity {};
abstract class Repository {
abstract public Entity findById();
}
class UserRepository extends Repository {
public User findById(){
return new User();
}
}
в TypeScript тоже можно:
interface Entity {}
class User implements Entity {}
abstract class Repository {
public abstract findById(): Entity;
}
class UserRepository extends Repository {
public findById(): User{
return new User();
}
}
На это дело время от времени появляются баг репорты, возможно будет исправлено когда-нибудь:
Фатальная проблема
Самая большая проблема в том, что php проверяет типы во время выполнения, а не во время компиляции. Потому что, не смотря на strict_types и type hintings, это ВНЕЗАПНО не строго типизированный язык
Отсюда следует два вывода:
1) Чем больше проверок в рантайме, тем больше тормозов. Поэтому слишком сложные проверки навряд ли вообще когда-нибудь появятся. Многослойные дженерики и callable с callable аргументами просто положат рантайм. Также будут тормозить рантайм введение типов для членов класса и в других местах.
2) Ошибки выявляются только во время запуска. Т.е. всегда будут ситуации, когда в какой-то хитрой ситуации пользователь сделает что-то не предусмотренное тестами, и всё повалится
Вместо выводов
Хотя (с точки зрения типов и ООП) на мой взгляд php на голову выше, чем javascript, и подходит для написания сложных программ, но при этом, конечно, не дотягивает до java/c#/typescript, и навряд ли когда-нибудь дотянется (см "Фатальная проблема"). Повторюсь, не дотянется именно с точки зрения системы типов, в остальных вещах возможны предпочтения в ту или иную сторону.
Поэтому в по-настоящему сложных приложениях надо обязательно всё обкладывать тестами. Также, возможно, что phpdoc добавит поддержку сложных callable с параметрами, и IDE научатся их понимать.
Комментарии (90)
KirEv
18.01.2018 14:11странная статья, странные предъявы,
сравнивать типы и ооп в рнр с java, etc… вы серьезно?
… в рнр много вредных возможностей, например:
$Obj = new \stdClass; $Obj->first = "First"; $Obj->second = "Second"; $a = "first"; print($Obj->$a);
эти вещи добавляют неочевидности, и несколько скриптов в сотни строк каждая из таких конструкций способны голову сломать…
… но эти вещи порой удобны и спасают положение когда быстро что-то откуда то достать и т.п., не заморачиваясь с архитектурой…
и всякое такое…
это как автомобили сравнивать… что говно что не говно… говорю, любое авто хорошее, если им по назначению пользоваться и вовремя обслуживать, а не лезть паркетником в гавно\глину и жаловаться «джип с недостатками».
CyberSoft
18.01.2018 15:57Особенно удивляет, что javascript ругают меньше
Откуда вы взяли про больше/меньше? Получается java/c# совсем не ругают?
По моим ощущениям, ругают одну только джаву (чего только это стоит — как же её не ругать?), и ощущение складывается от того, что эта платформа моя основная сфера деятельности.
релизы php7 (с нормальным ООП и строгим тайпхинтингом)
Тут надо начать с "какое оно, нормальное ООП?", а вообще, чтобы понять, откуда взялось ООП в PHP, нужно ответить на вопрос для чего он создавался и как потом росла сложность проектов. Отсюда такое развитие
tehSLy
18.01.2018 20:07+3Не понимаю, почему все накинулись на автора, еще и с аргументами, аля «пишите на своих джаве, сях и прочем, если не нравится», это сродни «я художник, я так вижу». Но тут-то все-таки комьюнити не гуманитарное, думается мне.
Система типов в пхп очень неплоха для скриптового языка(и то, в том же питоне она объективно лучше), для того, чтобы писать скрипты, только вот сфера применения языка из написания скриптов для домашних страничек явно переросла начальные цели, а инструмент для достижения этих целей двигается существенно медленней. Да, во многом из-за необходимости поддерживать ВС, но это не оправдывает язык как таковой. Это оправдывает решения по выбору фич, реализациям фич в данном контексте, но не самих фич.
2 моих последних проекта на PHP, это мой основной рабочий язык, он неплохой, он очень простой, в этом его плюс и минус. И если это плюс на старте, то чем дальше в лес, тем больше понимаешь, какой же он в некоторых моментах уродливый и как же не хватает тех фич `b` из тех самых других языков. Я не говорю, что PHP плохой язык, упаси боже, у него действительно свои цели и своя ниша, в которой он чертовски неплох. Но давайте будем честны, как только он делает хоть шаг за границы возможного, он мгновенно теряет весь свой шик перед упомянутыми «тру-языками». #nohate
0xd34df00d
18.01.2018 20:32Самая большая проблема в том, что php проверяет типы во время выполнения, а не во время компиляции. Потому что, не смотря на strict_types и type hintings, это ВНЕЗАПНО не строго типизированный язык
Строгость типизации и статичность/динамичность типизации — это два разных измерения.
Corpsee
19.01.2018 04:43Он имел в виду статическую типизацию, по контексту. Их почему-то все путают, Python-у вон никто не мешает иметь динамическую строгую типизацию, а C статическую слабую)
cliff_5
19.01.2018 10:44Что значит «js не подходит для сложных программ»? Масштабные 3D игры явно посложнее чем какая-нибудь cms. И нейросети на нём давно реализованны, есть библиотека. Ооп и типы этому никак мешать не могут, всё зависит лишь от программиста
varanio Автор
19.01.2018 10:47Ну не то, чтобы совсем не подходит, но на typescript гораздо легче писать сложные программы. Быстрее понимаешь код и допускаешь меньше тупых ошибок. Angular не зря его выбрал как дефолт
Mabusius
19.01.2018 11:55Поначалу тоже плевался от нестрогой типизации. А теперь вообще не представляю как без нее можно жить. Откуда я знаю что там в ответе от АПИ приходит? 0 как число? 0 строка? null? А что если один единственный метод этого апи писал другой автор и написал «пустой ответ» вообще как то по другому? В ПХП очень низкий порог вхождения, надо учитывать что тут говнокод прет просто со всех щелей и со строгой типизацией будет только хуже.
tehSLy
19.01.2018 12:48+1По началу не представлял как можно жить без нестрогой типизацией. А теперь вообще не представляю, как с ней можно жить.
В этом и суть. Со строгой типизацией таких вопросов, о том, что же придет в начале, не возникло бы, все было бы явно и понятноMabusius
19.01.2018 15:09С чего вдруг? Как строгая типизация помешает говнокодерам с другой стороны в одном месте вернуть 0 числом, а в другом строкой? Никак. Или вы рассчитываете, что они будут ограничены интерфейсами или чем то вроде того? Скорее всего они даже не знают, что это такое.
tehSLy
19.01.2018 15:56С того, например, что если бы типизация была статической, или хотя бы, строгой динамической, компилятор еще на этапе компиляции сказал бы,(ну или хотя бы понимал в рантайме) что тут приходит не то, что нужно, а не тихонечко кастовал величины к тайпхинтам. Эта вседозволенность как раз таки и приводит к говнокоду, просто потому, что так проще, а никто не запрещает. Вы точно работали на хоть сколько-нибудь крупных проектах в PHP? Без этого поддержка и разработка оных становится болью ниже спины, я не знаю, как тут можно спорить. Если в плюсах, джавах, шарпах и т.д. можно выстрелить себе в ногу в некоторых случаях, то это точно не относится к таким вещам, как типизация, которая как бы является фундаментальной вещью, ибо есть суть представления информации. У PHP в этом вопросе как будто читы на оружие, можешь отстрелить все что угодно, просто из-за того, что тебе вместо 0 — «0» вернулся, а вкупе с дизайном его API так это вообще стрелковая фиеста.
Mabusius
19.01.2018 17:29Я не говорил, что участвовал в чем то крупном :). ПХП это в первую очередь не для крупных проектов. Если у вас там потребность лезть аж в компилятор, будьте добры возмите чтото другое. А если не можете, то это не проблема ПХП уже. Как выше писали аналогию с напильником — вы взяли не тот инструмент, а теперь ругаете инструмент, что он плохо работает.
tehSLy
19.01.2018 17:35+1Ну вот как появится опыт разработки проектов покрупнее, я уверен, мнение о крутости слабой динамической типизации очень быстро рассеется. Я думаю, тут никто не говорит об кейсах аля «бложик на 200 строк».
Выше также писали, что приходится работать с тем что есть, и что никто под нас, разработчиков подстраиваться не будет, просто потому что, нам видите ли неудобно так.
michael_vostrikov
19.01.2018 14:13Суть не в том, чтобы везде нестрогую заменить на строгую, а чтобы была возможность использовать то или другое.
AlexLeonov
19.01.2018 15:02Нет никакой «строгой типизации» в PHP. Есть контроль типов в рантайме.
И да, у вас есть возможность его использовать либо не использовать. Что прекрасно, имхо.VolCh
19.01.2018 15:06Контроль типов — это и есть типизация. А в рантайме она или в каком-то компайлтайме — разница между динамической и статической типизацией. Вот в python типизация строгая, но динамическая. Хотя в каких-то моментах она теперь менее строгая, чем в PHP.
michael_vostrikov
19.01.2018 15:26Сильная и слабая типизация
PHP еще есть куда двигаться в сторону контроля типов, как его ни называй.
VolCh
19.01.2018 15:03А откуда вы знаете, что в API 0 (число) — это пустое значение, а не валидное полноценное? Банальный индекс элемента в коллекции, например. Собственно, даже в документации функций типа strpos постоянно выделяют предупреждения, что результат false надо проверять строго, что if (strpos($s1, $s2)) не означает "если подстрока найдена".
JTG
19.01.2018 18:06У самого основной хлеб — PHP, но частично согласен с автором.
Как писали в PHP: фрактал плохого дизайна:
PHP обширно черпает вдохновение из других языков, при этом ему удаётся быть непонятным для тех, кто эти языки знает.
Sannis
22.01.2018 18:49Чем больше проверок в рантайме, тем больше тормозов. Поэтому слишком сложные проверки навряд ли вообще когда-нибудь появятся. Многослойные дженерики и callable с callable аргументами просто положат рантайм. Также будут тормозить рантайм введение типов для членов класса и в других местах.
Не нагнетайте, в PHP5 это работает даже быстрее, чем strlen($str), а в PHP7 вообще без разницы.
AlexLeonov
Антон, так пишите на Java или C#, кто же вам запрещает-то?
Статья — прекрасный образец самой настоящей демагогии.
Берем язык А, в котором нет фичи b, поскольку она не нужна или реализована иначе.
Берем язык B, в котором фича b в наличии
Намеренно опускаем момент, что это принципиально разные языки и сравниваем килограмм с километром, делая вывод, что «А не дотягивает до B»
Я никогда не понимал — как можно быть «руководителем отдела разработки» на языке, который тебе так не нравится? Расскажите, Антон, пожалуйста, как вы планерки проводите?
Примерно так: «Парни, начинается новая неделя и нам всем снова предстоит писать код на этом ненавистном PHP, будь бы он неладен… Когда же это кончится уже?»
varanio Автор
Я же написал: «Повторюсь, не дотянется именно с точки зрения системы типов, в остальных вещах возможны предпочтения в ту или иную сторону.»
AlexLeonov
А нужно дотягиваться?
Зачем вообще принципиально слаботипизированному языку с динамической «рантайм» системой типов дотягиваться до языков со статической типизацией?
Кто такую цель поставил для PHP? Вы?
varanio Автор
Ну php же явно идет в эту сторону. Type hinting-и усложняются с каждой версией. strict_types и т.д. Но в то же время у этого процесса есть ограничения, потолок возможностей, что я и показал в этой статье. Просто это не всем очевидно.
AlexLeonov
Я не уверен, что вы верно понимаете, в какую сторону идет PHP. И более того — не уверен, что цель этого движения именно «строгая типизация» в вашем понимании.
sam002
Цель-то достаточно очевидная у нынешних владельцев zend — отжимать рынок у java/c#/typescript. Это предопределяет кучу стратегических решений по развитию языка. Так что не зарекайтесь от «строгой типизации».
Вполне допустимо повторение ошибок, подобных php6. Тогда всё исходило из идеи что в java же utf-16, значит и в php надо.
К большому сожалению само ядро php имеет относительно слабое комьюнити и ограниченные ресурсы. Плохая сторона — зависимость от zend с плохо продуманной стратегией, хорошая — очень тщательно выбираемые изменения не ломающие BC каждые пять лет и дающие максимальный профит тактически.
varanio Автор
Не надо так агриться на статью, я не хотел никого обижать )
AlexLeonov
Я бы не «агрился» так, если бы не очевидный вред от таких статей.
Вы своё собственное несовпадение «идеального языка» и реального PHP почему-то считаете проблемой последнего. Да еще и называете «фатальным недостатком»
Если бы не подобная тональность статьи — никаких отрицательных эмоций в вашу сторону не было бы.
varanio Автор
Какая тональность? В какой фразе? Система типов хуже, чем у java — ну извините, это медицинский факт, а не тональность.
Кроме этого факта я ничего плохого про php не сказал. Более того, я на нем сам пишу.
О проблемах надо говорить, а не замалчивать. Тогда возможно появятся какие-то решения. К примеру для javascript появился typescript. Чем не решение? И строгие типы, и возможность использоваь либы на ванильном Js
AlexLeonov
Можно я чуть-чуть «сагрюсь» еще? Ну совсем немножко?
Вот здесь у вас фатальная ошибка и недостаток. У вас, а не в PHP. Ошибка в том, что вы пытаетесь личное субъективное выдать за объективное сравнение несравнимых величин. Пресловутые «килограмм» с «километром»
Система типов в PHP не «хуже» или «лучше» — она другая. Она построена на иных принципах и решает иные задачи, нежели в Java.
Не понимаете? А как вы тогда руководите разработкой?
Впрочем, этот вопрос я вам уже задавал, ответа не последовало.
varanio Автор
Не могли бы вы мне объяснить, какие именно задачи решает система типов в php? Чтобы я мог лучше руководить разработкой? А может и вообще стёр вредную статью?
AlexLeonov
Если вы всерьез задаете этот вопрос, то нет, не смог бы в одном кратком комментарии. Это тема целого цикла статей или учебного курса.
Но если совсем коротко, то успешно решаемые задачи в PHP стоит свести к нескольким важнейшим пунктам:
— автоматический динамический кастинг скалярных типов
— реализация понятия «практической эквивалентности»
— стандартизация всех i/o хэндлеров в едином типе resource
— решение всех проблем, которые возникают в других языках с динамическими массивами
— реализация класс-ориентированного подхода
— контроль типов времени исполнения
— контроль типов времени компиляции
Постарался расположить по степени важности
varanio Автор
Да, когда-то целью php это было. Но ввели declare(strict_types=1). Это для чего?
По-моему чтобы избавиться от неявного, разве нет?
Не могли бы вы пояснить?
Каких проблем?
в php почти нет этого
AlexLeonov
Нет.
Эта директива компилятора просто запрещает кастинг скаляров в рантайме в строго определенных случаях (ровно в двух), заменяя кастинг на строгий контроль типа с выбросом исключения. Всё.
Причем тут ваши фантазии о «явном» и «неявном» — я не знаю.
И не надо, пожалуйста, рассказывать о «целях PHP». В вашем исполнении это звучит как минимум странно.
varanio Автор
Я про неявное приведение типов.
выдаст единицу. Молча, неявно преобразовав тип.
с decrlare(strict_types=1) придется явно написать
иначе будет выдана ошибка. Вот про это явное указание (int) я и говорил.
Почему в моем исполнении странно? Может именно в вашем странно?
Я просто высказываю свое мнение, наблюдая за changelog ом языка.
AlexLeonov
Как же «неявно», если вы сами написали «int»? Что тут неявного?
poxvuibr
Ну вот так, неявно. Если функция принимает int, ей передают строку и эта строка автоматом преобразуется в int — это назвается неявным преобразованием.
Явное преобразование — это когда программст, когда передаёт параметр сам пишет, что его надо преобразовать в int.
varanio Автор
Вот да, достаточно просто погуглить по фразе «неявное преобразование типов»
AlexLeonov
Практическая эквивалентность это
1 == '1' == true
0 == '0' == '' == false == []
что с трудом достигается в строго типизированных языках с контролем типов времени компиляции
На практике же такая эквивалентность необходима просто в силу того, что так устроен HTTP и CLI.
varanio Автор
Да, это было одной из целей языка изначально. Однако это сомнительный плюс, если честно. Столько нюансов с этими магическими штуками, вы и сами знаете наверняка
AlexLeonov
Не пишите на PHP. Он вам не нравится, и, как результат — вы его не понимаете.
asm0dey
Последнее утверждение крайне спорно. Я 9 лет писал на джаве, я думаю что понимаю её глубже чем многие. Но я прям далеко не фанат. И как только появилась внятная альтернатива в лице котлина — с радостью перешёл на него. Не нравится ? не понимаю.
AlexLeonov
Практика показывает что те, кому язык не нравится, не изучают его в должной мере. И, следовательно, не понимают.
Изучение же, приводя к пониманию, затем убирает это странное «не нравится». Ну или человек уходит на другую платформу.
OlegOleg1980
Позвольте вас дополнить.
В целом обсуждение сводится к той ситуации, когда есть два напильника — плоский и круглый, и, автор, взяв в руки круглый напильник, рассказывает нам, как же плохо им выравнивать плоскую поверхность — то он соскальзывает, то канавки в поверхности делает, то вообще очень медленно точит! И, говорит, неплохо бы этому круглому напильнику грани сделать — тогда и с плоскими поверхностями намного удобнее будет работать! У автора то уже есть один удобный плоский напильник, тот то хорошо плоскости обрабатывает, значит надо к этому стремиться, сделать все напильники плоскими. Автор просто редко занимается округлыми поверхностями, но в те редкие моменты, когда это все же происходит, он тихим шепотом сыплет проклятия тому, кто ему подсунул эти неплоские поверхности, возможно даже изредка подумывая о круглом напильнике…
varanio Автор
Если уж на то пошло, то php (personal home page) изначально предназначался для простых сайтиков
Но время шло, сайтики превращались в фейсбуки, и старый напильник перестал подходить
Множество гигантских систем написны на php и страдают от недостатчной строгости язык
Посмотрите современные фреймворки.
OlegOleg1980
Вот вы сами и ответили на свои же, скажем так, «вопросы».
Время шло, «фейсбуки превращались», «напильники перестали подходить», но вместо того, чтобы брать для работы другие, более подходящие напильники (треугольные, квадратные, и другие разные инструменты), мы продолжаем мужественно стачивать грани у круглого напильника, превращая его во всё более плоский…
varanio Автор
Блин.
Расскажите мне, какие аргументы приводить начальству, чтобы уговорить их потратить пару человеколет на то, чтобы переписать всё на другой язык?
Напильники, фигильники. Многие компании в заложниках у тех технологий, на которых они построены. И зачастую это навсегда.
Т.е. выбора-то нет на самом деле.
VolCh
Потратить на портирование пару человеко-лет ещё можно как-то убедить, но вот убедить, что на несколько месяцев развитие текущего проекта остановится точно нельзя.
VolCh
Аналогия с напильником не очень хорошая. Напильником сделал продукт и больше он от напильника не зависит. Следующий продукт можно делать другим напильником, более подходящим под него. Единственное препятствие — новый напильник очень дорогой и денег на него нет, тогда модернизируем старый.
varanio Автор
Чего я там не понимаю? На php пишу 100500 лет.
Вообще, нравится/не нравится — дело десятое. Мне важно, где он применим, где нет, какие нюансы есть, куда развивается язык.
AlexLeonov
Не понимаете главного — зачем этот язык. От непонимания идет нежелание его изучать. От нежелания изучать — недостаток знания и понимания.
Замкнутый круг.
Попробуйте ответить на самый простой вопрос для самых-самых начинающих — а зачем вообще в PHP
empty('0') === true;
?
Какой практический смысл в таком?
С точки зрения любого не-PHP программера ересь же. Непустая строка пустая?
Crandel
Так в чем же цель php?
varanio Автор
empty($x) — это фактически сокращенная запись ( isset($x) && $x == false)
А '0' в php — это false
Это не то, чтобы ересь, просто нейминг немного путает людей
WebSpider
Да ну? то есть для несуществующих переменных (isset($x) = false) empty должна вернуть false?
varanio Автор
Да, ошибся. Я имел в виду !isset($x) || $x == false
AlexLeonov
Вы не ответили на вопрос «зачем оно так»
varanio Автор
ну, чтобы меньше кода писать. Вместо двух условий одно
0xd34df00d
Но… Зачем? Как HTTP и CLI требуют этого?
varanio Автор
AlexLeonov намекает, что в http-протоколе есть только строки, других типов нет. И удобно брать строки из $_GET и тд и сразу начинать сравнивать и складывать с чем нибудь, не приводя вручную к типу
На самом дделе этот аргумент не совсем верен.
tehSLy
Учитывая, что PHP работает далеко не только с $_GET, $_POST и иже с ними, не уверен в корректности этого аргумента как такового. Но, надо же привести что-то в защиту ?\_(?)_/?
varanio Автор
В сложных приложениях все равно приходится тщательно валидировать и санитизировать входные данные.
Одна ручная операция по преобразованию типа роли бы не сыграла.
В сложных приложениях получение данных из GET и POST — вершина айсберга, причем самая простая. Дальше идет бизнес логика и т.д., где цена ошибки слишком высока, и хочется не надеяться слепо, что php как-то сам закастит данные по своим магическим правилам. Делать все явно — вот, что было бы хорошо. Понятный с одного взгляда неизменный тип переменной -это было бы супер. Но увы
tehSLy
И я о том, но ведь «мы просто используем инструмент не по назначению», как тут многие выражаются(С удовольствие использовал бы подходящий инструмент, да вот поди объясни бизнесу, что у них кодовая база не на том написана). Я с Вами во всем солидарен. Времена, когда PHP заходил с его слабой динамической типизацией канули в лету, теперь скорее источник ошибок, нежели полезная фича.
VolCh
mysql тоже строки возвращает как результаты выборки, независимо от типа в базе. Так что основная причина подобных приведения — именно упрощение разработки в среде, где почтм всё представлено в строках технически, но имеет семантику не только строк, но и чисел, булевых и т. д.
dekameron
В защиту: для проверки с учётом типа есть ===
0xd34df00d
А вручную ничего не надо приводить. Ну вот как тут, в quick start-примере.
quiet
имеет типBool
,enthusiasm
— вообщеInt
, и вместе с тем никаких ручных приведений.AlexLeonov
— создание в рантайме массива
— динамическое добавление и удаление элементов массива
— возможность иметь неплотное и немонотонное множество ключей
— упорядоченность массива, отдельная от упорядоченности ключей
— нетипизированность массива
Поверьте, не каждый язык это всё умеет.
varanio Автор
Да, на уровне конструкции языка этого часто нет. Но обычно в этом случае есть в виде стандартной библиотеке.
JTG
Это всё классно, но
Видите ошибку? А она есть.
0xd34df00d
Должен сразу сказать, что последний раз я трогал PHP, когда он был четвёртой версии, и с тех пор моя жизнь круто поменялась, но у меня к вам есть пара вопросов.
А это хорошо?
Включая статические гарантии не выхода за границы? Или как проблемы-то решаются?
AlexLeonov
Покажите мне практический пример «выхода за границы» для массивов в PHP — и тогда обсудим вопрос про гарантии.
На самом же деле постановка вопроса не имеет смысла, поскольку «массивы» в PHP это не массивы с фиксированным размером элемента и смещением, а что-то вроде hashmap (тоже неверно, но ближе к истине)
0xd34df00d
Я сразу написал, что в PHP не особо разбираюсь. Собственно, именно поэтому мне и интересно, как он решает эти проблемы. Если через возврат нулевых-пустых-неопределенных значений, то это, в принципе, решение. Если через утверждение, что «на практике таких проблем не возникает», то это, в принципе, тоже решение, да.
Потом, конечно, можно начинать говорить, насколько такие решения подходят для задач, отличных от написания личных домашних страниц, но это неблагодарный разговор.
AlexLeonov
Запрос элемента с несуществующим ключом приведет к выбросу предупреждения (можно проигнорировать) и возврату null значения.
Но поскольку в языке есть явная конструкция проверки существования элемента — проблема не имеет смысла.
0xd34df00d
Хорошее решение, спасибо!
А ради интереса, есть языки, где нет проверки существования элемента в массиве или индекса в массиве?
VolCh
C?
0xd34df00d
Ну, если не сохранять размер выделенного блока памяти, то да.
hack3p
Если PHP претендует на OOP с SOLID, тогда почему они немогут реализовать нормальное ковариантное наследование как в других языках. Вместо этого зачем-то делают костыли в виде нарушения принципа Лисков. Можно еще ознакомится с этим PR и отношением PHP сообщеситва к таким изменениям.
AlexLeonov
Можно ссылочку на документацию, где указано, что цель развития PHP — соблюдение принципов SOLID?
И не кажется ли вам, что соблюдать эти принципы должен программист, как разумное существо, а не язык, как набор инструментов?
Это всё равно что сказать, что нож нарушает уголовный кодекс.
greatkir
Прошу прощения, но искренне не понимаю, где в вашем примере нарушение принцпа Лисков.
Если бы речь шла о сужении типа, то да, типы в наследуемых классах не соответствовали бы базовому типу, и это было бы нарушением принципа Лисков (кстати, именно запретом такого поведения почему-то не доволен автор статьи в подзаголовки «Странности тайпхинтинга...»).
Но расширение типа в наследниках позволяет использовать их во всех случаях, где использовался базовый класс — на мой взгляд, никакого нарушения нет.
0xd34df00d
Нет. Наследование ковариантно по возвращаемым типам и контравариантно по принимаемым.
Ковариантность: если у вас в базовом классе
Base
есть метод, возвращающий некоторыйBaseRet
, то вы по факту говорите, что объект каждого классаDerived
, унаследованного отBase
, возвращает из этого методаBaseRet
. Если вы в конкретномDerived
возвращаетеDerivedRet
, унаследованный отBaseRet
, то вы всё равно возвращаетеBaseRet
(потому чтоDerivedRet
is-aBaseRet
), и все действия, которые клиент вашего метода может сделать с возвращённым ему (по контракту базового класса)BaseRet
, он может сделать и с возвращённым из конкретного методаDerivedRet
.Если вкратце: возвращаемые типы сужать можно, расширять нельзя.
Контравариантность, как подсказывает название, работает в обратную сторону: когда вы объявляете функцию, принимающую
DerivedIn
, вы говорите, что ваша функция умеет работать со всеми объектами, реализующими так или иначе интерфейсDerivedIn
. Если вы теперь в наследнике объявите функцию, принимающуюBaseIn
, то унаследованный от негоDerivedIn
она уж точно принять сможет!Если вкратце: принимаемые типы расширять можно, сужать нельзя.
sergyx
Если под расширением типов вы подразумеваете то разве из первого абзаца не следует прямо противоположное — что возвращаемые типы расширять можно?
0xd34df00d
Я имею ввиду теоретико-множественное расширение (где тип, упрощая, это множество принадлежащих ему значений). Множество объектов класса
B
, очевидно, является подмножеством (и чаще всего собственным) множества объектов классаA
.varanio Автор
Вы не представляете, как я радовался declare(strict_types=1). Как ребенок.
Но потом я внезапно осознал, что в эту сторону большого развития не будет из-за того, что всё проверяется в рантайме. И опечалился.
Собственно, об этом и статья.
Gemorroj
Когда будет JIT, вероятно, проблемы рантайма должны будут уменьшится.
Даже opcache, по словам Дмитрия Стогова уже использует тайпхинтинг для оптимизаций.
Adelf
У меня такие же чувства. Но если честно, то первый комментарий абсолютно верен. Нам с вами надо писать на Яве и сишарпе :) там все в разы приятнее. Особенно с типами :)
А так… я пока тоже пишу на PHP. Мне это приносит больше денег :)
YaRobot
Меня вполне устраивают типы.
Есть конечно моменты которые стоит доработать, но их уже предложили и рассматривают.
К примеру хотят добавить скалярный тип.
Еще бы хотелось иметь возможность создавать собственный тип.
(type Test = ...)
AlexLeonov
Ну да, соглашусь.
Пожалуй не хватает только конструктора кастомных типов.
Что-то вроде
type iterable = array | \Iterator
, но в своем кодеVolCh
Можно любить, признавая недостатки в тех или иных областях. Движения в сторону строгости типизации подтверждает, что слабая типизация создаёт проблемы в некоторых случаях типового по нынешним временам использования PHP, не только по мнению части сообщества, но и по мнению разработчиков самого языка. Пойдёт ли движение дальше в сторону ещё большей строгости, вряд ли кто сейчас скажет наверняка, но исключать, что PHP станет ещё ближе к Java/C# в плане строгости типизации, нельзя.