Шутки про PHP — уже отдельный жанр в различных сообществах программистов. Некоторые не любят PHP, потому что {lang_name}
намного лучше. А кого-то он вполне обоснованно расстраивает.
Я же PHP люблю. Не смотря на его косяки. Этот язык был создан для конкретной цели и решает он свою задачу хорошо. Схема "принял — обработал — отдал — умер" очень эффективна и решает проблему небольших утечек памяти.
В моей работе PHP используется постоянно. Так сказать, это основной backend язык, используемый в моих проектах. За время работы у меня появились некоторые пожелания и замечания. Решил поделиться с обществом. Кому интересно, добро пожаловать под кат.
Традиционный дисклеймер
Этот пост вряд ли изменит мир. Да и не об этом он. Пост, скорее, о наболевшем. Много субъективных моментов из разряда "я так считаю" или "я так хочу". Предупреждаю заранее, чтобы все были готовы.
1. Неявное временное преобразование примитива в объект
Проще объяснить на примере. В JavaScript мы можем обращаться к строке и массиву как к объекту.
let str = "1,2,3";
let arr = str.split(",");
arr = arr.map(_ => _ * 2);
console.log(arr); // [2, 4, 6]
Благодаря таким конструкциям, код выглядит чище, логичнее, есть возможность создавать цепочки вызовов и п.р.
В JavaScript, насколько мне это известно, массив уже является полноценным объектом, а строка хранится в виде примитива. И при необходимости, строка преобразуется в объект String
, происходит вызов необходимого метода.
Почему бы в PHP не сделать что-то похожее?
$str = '1,2,3';
$arr = $str->explode(',');
$arr = $arr->map(function ($i) {
return $i * 2;
});
var_dump($arr);
// Или даже так:
$str = '1,2,3';
$arr = $str
->explode(',')
->map(function ($i) {
return $i * 2;
});
var_dump($arr);
Десятки функций, связанных со строками и массивами можно было бы убрать в классы String
и Array
. Написание кода в функциональном стиле не был бы столь мучительным процессом.
$arr->keyExists(...);
$arr->map(...);
$arr->filter(...);
$arr->keys(...);
$arr->push(...);
$arr->pop(...);
$arr->exists(...); // in_array
$str->repeat(...);
$str->join(...);
$str->trim(...);
$str->replace(...);
Другая сторона этого вопроса: объектная реализация примитивов может имплементировать различные интерфейсы. Что нам это дает? Можно свободно избавляться от таких функций, как is_iterable
, is_numeric
, is_countable
, и переходить на иcпользование instanceof
\Countable
, \Traversable
и п.р. Ну разве не прекрасно?
2. Дженерики
Впервые с дженериками я познакомился, когда изучал Java. Мощь дженериков сложно переоценить. Они могут использоваться в DI контейнере, когда указываем тип объекта, который хотим получить:
$service = $container->get<SomeService>();
Они полезны при реализации различных коллекций, а также репозиториев (Yii2 Query или Doctrine).
Еще, какую пользу могли бы принести дженерики, это type hinting массивов объектов (этого уж очень не хватает). Опять же, проще объяснить не примере:
public function getItems(): Array<Item>
public function setItems(Array<Item>): void
Выглядит уже инетересно, согласитесь? Теперь и мы уверены, что всегда получим массив объектов определенного класса, и IDE точно знает, что подсказывать без всяких PHPDoc блоков. Но мы ведь можем не только массивы передавать, но и свои коллекции:
public function getItems(): Collection<Item>
public function setItems(Collection<Item>): void
Хотя синтаксис массива объектов как PHPDoc мне нравится больше (SomeObject[]
), этот вариант тоже хорош. В любом случае это лучше, чем то, что есть сейчас (либо array
, либо ничего).
3. Аннотации или декораторы
В Java аннотации используются с версии 1.6 (придуманы они были еще раньше). Доступны они через рефлексию. (Java знаю плохо, поэтому исправьте, если где-то не прав)
В JavaScript существует похожий механизм — декораторы (не уверен, что они являются частью стандарта, но уже повсеместно используются благодаря Babel).
А что есть в PHP? В PHP есть PHPDoc блоки, которые созданы сугубо для документирования. И разработчики выжимают из этого все, что могут. Примерами служат такие замечательные библиотеки, как Doctrine и PHP-DI.
Я об аннотациях задумался, когда подключил компонент Symfony Event Dispatcher. Когда я создаю класс-подписчик, который реагирует на события в системе, я должен имплементировать метод getSubscribedEvents
, который возвращает массив, где в качестве ключа — идентификатор события, а в качестве значения — имя метода, реагирующего на событие в этом классе. Это простой и эффективный способ решения проблемы. Эффективный, но не удобный. Почему? У меня идентификаторы событий хранятся в константах классов. Если я хочу найти подписчиков на какое-то событие, я произвожу поиск по коду, который использует константу-идентификатор, меня перекидывает в метод getSubscribedEvents
, где я беру название метода(ов), и ищу этот метод(ы) в классе. Если мне нужно узнать, на какое событие реагирует какой-либо метод, то мне нужно проделать ровно то же самое, только в обратном порядке. Слишком много шагов для столь простого действия. Опять же, если я хочу переименовать метод-подписчик, я не могу просто взять и воспользоваться возможностями IDE (поиск по тексту — функция редактора, а не IDE). Это придется делать вручную.
Но как оно могло бы быть, если бы существовали аннотации:
@EventSubscriber(ItemEvents::CREATE)
public function itemCreated(ItemEvent $event)
Как по мне, это очень удобно. Производя поиск по константе, я сразу увижу, какой метод его использует. Без всяких дополнительных действий. И наоборот: мне не нужно куда-то еще лезть, чтобы увидеть, на какое событие среагирует этот метод.
Из плюсов сразу хочется отметить поддержку IDE, если это будет внедрено в язык. Аннотации можно импортировать также, как и обычные классы, что избавляет от необходимости писать namespace'ы.
Это только то, что пришло в голову мне. А как преобразились бы библиотеки, о которых я говорил ранее, если подобный механизм будет внедрен...
4. Короткий синтаксис функций.
До знакомства с JavaScript при любых действиях с массивом (фильтрация, маппинг и п.р.) я использовал императивный подход:
$input = [...];
$output = [];
foreach ($input as $i => $item) {
// logic
$output[$i] = $item;
}
После изучения ReactJS + Redux мне больше понравился функциональный подход к решению подобных задач:
let output = input.map(item => {
// logic
return item;
});
Но мне не нравится, как это выглядит в PHP:
$output = array_map(function($item) {
// logic
return $item;
}, $input);
А теперь давайте объединим первую идею с этой:
$output = $input->map(($item) => {
// logic
return $item;
});
Вот согласитесь, в PHP не хватает чего-то, что заменило бы function($item) {}
на что-то более чистое и эллегантное. И совсем не обязательно, чтобы это что-то отличалось по функционалу от обычной записи (как это есть в JS). Главное, чтобы оно занимало меньше места и не создавало шум для глаз разработчика. Об этом уже говорилось ранее не мной. И даже есть такой RFC. Но это актуально, не так ли?
5. Асинхронность
Я не говорю про многопоточность. Вот в JavaScript есть Promise. Я запустил несколько задач асинхронно, дождался окончания их работы и пошел работать дальше.
В PHP может быть множество задач, которые хотелось бы сделать асинхронно, не дожидаясь окончания выполнения. На ум сразу же приходят работа с большими БД запросами и HTTP запросами. Чтобы составить большой отчет, приходится либо долго ждать, либо пользоваться сторонними решениями, типа очередей. В моем случае, в проекте в большом количестве используются Slack уведомления и Mailgun оповещения. За один клиентский запрос может быть отправлено около десятка HTTP запросов. Почему бы не запустить это все на фоне, а клиенту уже отдать страничку? Это возможно. Но простого решения из коробки нет.
Знаю про существование расширения PThreads, но насколько это просто решение из коробки? К тому же, это про настоящую многопоточность, которую нужно уметь готовить.
6. Использование выражений везде
Например в значениях параметров по умолчанию:
class Money {
__constuct($currency = new Currency('RUB')) {...}
}
Или даже в свойствах класса:
class Money {
private $currency = new Currency('RUB');
public function setCurrency(Currency $currency) {...}
}
А чтобы не засорять память, создавать объект при необходимости, первом обращении к свойству или если не был передан аргумент.
На самом деле, это всего лишь сахар, который чуть-чуть уменьшит объем кода в некоторых случаях, потому что можно сделать так:
class Money {
private $currency;
__constuct(Currency $currency = null) {
$this->currency = $currency ?? new Currency('RUB');
}
}
Использование выражений на создании объектов налету не заканчивается. Вместо этого можно было бы подставить любое выражение:
public function someMethod($value = $this->defaultValue): void
public $statuses = SomeClass::getStatuses();
Мне было бы очень удобно.
7. Указание типа переменным
Тут много написать не получится, так как (1) и так все понятно, (2) и так всем известно. Хочу сказать только то, что из PHP не обязательно делать язык со строгой типизацией. Достаточно только дать такую возможность. А дальше пусть каждый решает сам, как ему пользоваться этим. Но для тех, кто пришел с языков со строгой типизацией, PHP станет более привлекательным.
8. Убрать function
Не совсем понимаю необходимость ключевого слова function
в указании методов класса.
public function someMethod()
// Или
public someMethod()
Это чисто субъективный момент. Но в тех языках, которые я знаю помимо PHP, а именно Java и JavaScript, я этого не наблюдаю. Действительно, а зачем? Семантически это слово никакой роли не играет. Я и без того пойму, где функция, а где свойство. Но кажется, что убрав лишние 9 символов, будет немного больше места для аргументов и меньше визуального шума. А это небольшой, но плюс.
9. Навести порядок
Беспорядок, пожалуй, самый весомый аргумент против языка. Сложно отрицать, что в PHP много странных непоследовательных решений, в отношении названия функций, порядка аргументов и п.р. Всё понимаю: обратная совместимость, "исторически сложилось", влияние других языков. Но нужно двигаться дальше!
Как вариант, можно большинство функций перенести внутрь объектов, как я описал в самом первом пункте, остальные реализовать в качестве статических методов этих классов (например Array::method()
), а все остальное пометить как deprecated
. А в следующей версии повыкидывать все!
Как по мне, PHP неплохо развивается как ОО язык, и большинство функций, констант и п.р. можно переместить в классы (json_encode -> Json::encode
, cUrl
).
Если бы кто-нибудь сделал расширение, которое решает эти проблемы, переносит все функции в статичные методы классов, написал полифил, если вдруг расширение не установлено, и для Codesniffer написал варнинги при использовании старых функций… Я бы уже сейчас стал использовать его. Мне кажется, что не только я. Вопрос только в том, что это должно быть именно расширение, которое максимально эффективно прокидывает аргументы из метода в нативную функцию.
Вместо заключения
Легко рассуждать, сидя за диваном (компьютерным столом) и жалуясь на недостатки языка, который помогает мне зарабатывать на жизнь. Но я не жалуюсь. Я очень благодарен всем тем, кто вкладывается в развитие языка и его экосистемы. Но ничто не мешает мне высказывать свои мысли и пожелания. Как я уже говорил, я люблю PHP и хочу, чтобы он становился еще лучше.
Я прекрасно понимаю, что многое из того, что я описал, почти невозможно сделать без серьезных проблем с производительностью, либо корневых изменений в движке. Но кто мешает хотеть?) К тому же, многое из описанного, наверняка, хочу не только я. Поэтому, есть хороший шанс увидеть все это в будущем.
Еще что хочу сказать. Это все субъективно. Это то, что хочу конкретно я. К тому же, на мое мнение повлияло изучение Java. И мне понравились некоторые возможности этого языка. Но это вовсе не говорит о том, что так надо или что это единственно верное решение.
А что Вы хотели бы увидеть или изменить в PHP?
Комментарии (188)
Gemorroj
02.05.2018 14:45+4По поводу асинхронности — давно делают файберы, но пока в ядро протащить не получается (https://wiki.php.net/rfc/fiber, https://externals.io/message/101808).
А сторонних реализаций eventloop хватает.
Да и вообще, почти по всем пунктам, уже были или попытки что-то сделать по указанным направлениям, но протащить дальше rfc не удавалось.
Alukardd
02.05.2018 15:22-2Просто, оставлю это здесь.
www.cisecurity.org/advisory/multiple-vulnerabilities-in-php-could-allow-for-arbitrary-code-execution_2018-046m0rtis
02.05.2018 17:12+2There are currently no reports of these vulnerabilities being exploited in the wild.
Ну и вообще говоря прикольно видеть ченджлог в качестве отчета об уязвимости:))
justmara
02.05.2018 16:07+2Указание типа переменным
… не обязательно делать язык со строгой типизациейснова кто-то путает строгую (сильную) и статическую типизацию
vlreshet
02.05.2018 16:16Пункт номер 1 — это было бы прекрасно. После JS очень коробит делать что-то вроде
Вместо$something = explode($list, ","); $result = []; foreach($something as $item){ $result[] = doAction($item); }
$something = $list->explode(",") ->map($item => doAction($item));
oxidmod
02.05.2018 16:28+1Гляньте на эти коллекции
Для большинства случаев они очень неплохи.SerafimArts
02.05.2018 19:18+1Лучше ларовские: laravel.com/docs/5.6/collections У них плюшек на несколько порядок больше, включая High Order Messaging и прочую дичь)
symbix
02.05.2018 23:26Если уже используется laravel или lumen, то ага. А так целый illuminate/support тащить, да еще с этими фасадами — ну как то не знаю.
Samouvazhektra
02.05.2018 23:36+1Snart
03.05.2018 14:36nayjest/collection
composer require nayjest/collectionSerafimArts
03.05.2018 15:06И всё же оригинал лучше, имхо. Это раньше он половину ядря тянул за собой, сейчас же только контракты (набор из дестяка интерфейсов), что не является фатальным.
Зато получаем поддержку километрового сообщества, актуальность и набор хелперов, которые будут использоваться 146% если знать об их существовании (например, array_first/last или class_basename).
Я согласен, что там есть и лишнее (вроде базового класса фасадов или провайдеров), но эти пяток классов — не помешают, учитывая то, что вендор любого современного фрейма и так содержит тучу неиспользуемого кода. Нет, это не призыв тянуть за собой мусор, просто меньшее зло, выбирая которое профита можно получить на несколько порядков больше.VolCh
03.05.2018 15:56+2> которые будут использоваться 146% если знать об их существовании
Знаю, но не использую, чтобы не создавать привязку к фреймворку.
Bal
02.05.2018 20:08+1Что-то типа такого?
$result = array_map(function($x) { return $x*$x;}, explode(',', '1,2,3'));
Array ( [0] => 1 [1] => 4 [2] => 9 )
springimport
02.05.2018 16:54Раз такое обсуждение пошло, то внесу и я свои пожелания.
Конструкторы и di
После работы с magento 2 стало очевидно что нужно что-то делать с конструкторами когда внедряется di. Пример класса. Возможно, использование выражений на месте, как сказано в статье, спасет ситуацию.
Наследование классов
Знаю что проблема не php, а многих языков. Так и не пришел к хорошему решению проблемы с наследниками.
1 случай: имеется класс для выборки данных который нужно закэшировать. Можно сделать наследование и заменить все методы на кэширующие. Если класс под интерфейсом, то реализацию интерфейса. В обоих случаях придется дублировать все методы. Как это решить — не понятно.
2 случай: в magento 2 есть возможность переопределять классы (preference), но переопределить класс от которого кто-то наследуются напрямую (extends /Class) — нельзя. А класс еще может быть абстрактным. В итоге получаем кучу наследников которые нужно переопределять чтобы добавить общий метод. И простого решения нет. Трейт лишь облегчит ситуацию.m0rtis
02.05.2018 17:48+1Пример класса. Возможно, использование выражений на месте, как сказано в статье, спасет ситуацию.
Я поглядел пример по Вашей ссылке и волосы на моей голове зашевелились. Я подозреваю, что такое количество аргументов конструктора может говорить о серьёзных архитектурных проблемах, а не проблемах языка.
OnYourLips
03.05.2018 07:15+1После работы с magento 2 стало очевидно что нужно что-то делать с конструкторами когда внедряется di. Пример класса.
С этой проблемой прекрасно справляются код-ревью и наймболееквалифицированных специалистов.
KAndy
03.05.2018 00:00Слегка не по теме, но на 2 случай в мадженте есть плагины
springimport
03.05.2018 15:47Как и все в мадженте, они как бы есть, но использовать можно только где-то в 20% случаях.
Добавить метод через плагин? Нельзя.
Сделать замену метода где используются приватные методы? Можно, но бессмысленно (нельзя).
Плагины не отменяют проблему с наследниками. Точно так же нужно работать с каждым по-отдельности.
symbix
03.05.2018 00:19Мне вот недавно пришлось с головой окунуться в старый индокод, с десятками global в начале функций. В этом вашем примере класса из Magento вижу по сути то же самое, только приправленное ООП.
Не-не, как раз хорошо, что инъекции через конструктор. Были бы property injections по типу
@Autowired
— было бы не так заметно, какой там ад.KAndy
03.05.2018 00:32Не то же самое, потому что как раз нет глобального состояния, и вы всегда можете поменять зависимость.
В этом и заключается беда многих фремворков/цмс не использующих DI, что реальные зависимости классов скрытыsymbix
03.05.2018 02:58Вы так уверены, что можете поменять вот такую зависимость? :-)
Не, SOLID работает, только когда все буковки сразу.
springimport
03.05.2018 15:54Я думаю что да. Просто это может потребовать кучи времени.
symbix
03.05.2018 16:21За кучу времени я и global-ы индусские переписать могу, вообще с нуля :-)
springimport
03.05.2018 16:56Мне кажется что если бы разработчики применили полноценное ddd то m2 если бы и вышла, то к концу десятилетия. Это если не смотреть сколько лет ушло на фиксы багов с 2.0…
А еще при работе с системой проходят проверку на прочность все компоненты: php, mysql, phpstorm, composer. Я вот не уверен что разработчики composer планировали что обычный проект будет грузить сотни мегабайт кода. Или в jetbrains разрабатывали phpstorm только для тех у кого ssd… Куда еще увеличивать кодовую базу.symbix
03.05.2018 17:52Да я это все прекрасно понимаю, у самого тонна криво спроектированного легаси, с которым приходится жить. Я это все к изначальному тезису про "надо что-то делать с конструкторами". Не надо. :-)
springimport
03.05.2018 18:10На надо во времена 5.6-7.0, уверен что на 7.5 вообще все перейдут на di и в каждом проекте будет вот это вот объявление параметра, занесение в конструктор, назначение в конструкторе, генерация docblock. В наследнике хочешь написать что-то в construct? Будь добр, тащи все зависимости в предок.
Запрещать подход я не предлагаю. Я за расширение: в простых случаях по-старинке, а с десятком зависимостей по-другому.symbix
03.05.2018 19:59А, в этом смысле. Тут можно позаимствовать сахарок из того же Typescript:
constructor(private foo: FooInterface, private bar: BarInterface) {}
Хотя в нормальной IDE с генерацией приватных свойств и присваиванием в конструкторе проблем нет, все делается автоматически.
Docblock, который не добавляет никакой информации, а просто дублирует сигнатуру — нафиг не нужен. Если требуется правилами оформления — IDE сгенерирует сама.
В наследнике хочешь написать что-то в construct?
Ну, это вообще не очень нормально. Composition over inheritance, Abstract or final.
uralmas
02.05.2018 19:04+1Согласен со многими пунктами. Сам собираю список того, чтобы я изменил в PHP — с кучей новых возможностей, разделением и оптимизацией стандартной библиотеки, упрощением синтаксиса, с цепочками функций стандартных функций, без оглядки на историческое наследие.
Но это получается уже новый ЯП, несовместимый с PHP, но конвертируемый в/из него.
Может, как-нибудь оформлю свои заметки в статью
VolCh
02.05.2018 19:25+1Отключение возможности неявного преобразования типов. Или, хотя бы, deprecated сообщения о его использовании.
Goodkat
02.05.2018 20:05+2А что вам мешает сделать объектные обёртки для примитивов, как в JavaScript?
ArrayObject уже давно есть.VolCh
02.05.2018 21:09Дорого и ужасно выглядит что-то вроде
(new String("1,2,3"))->explode(",")->map(function (string $item) { return (new String($item))->intval();});
Goodkat
02.05.2018 23:14Зато ж красота!
И без new, есть же __invoke(). И это же php, intval не нужен, ну или в explode вторым параметром EXPLODE_CASTING_TYPE_INTEGER — придерживайтесь стиля phр ;-)
Shamanische
02.05.2018 20:28-2Скоро линии развития PHP и Java сойдутся в одной точке пространства-времени. Но покуда жизненный цикл PHP скрипта будет 'выполнил задачу или запрос и сдох' по-насоящему лучше он не станет.
oxidmod
02.05.2018 20:32+4Для своих целей PHP is good enough.
А те вещи, которые действительно дорого поднимать можно запустить в виде демона, или вообще написать на другом, более подходящем языке.Shamanische
02.05.2018 22:38Границ у этих, так сказать, целей нет. В этом весь фокус. Достигнув простой цели, планка требований поднимется выше, потом ещё выше, и ещё… а потом бах и OutOfMemoryException, например.
Так или иначе язык ограничен (любой язык), а задачи — нет. Так может разработчикам PHP пора начать делать что-то более серьезное чем добавление сахара из других языков? Начать с таймера и многопоточности, вот тогда язык станет языком вне конкуренции, а не темой для холиваров.springimport
03.05.2018 15:59+2За несколько последних лет с миграцией с 5.5 до 7.2 получил нереальное ускорение. Это что, не прогресс?
kuftachev
03.05.2018 09:58+4В этом и есть его крутость.
Вот представь, поднять на той же Java на одном сервере 100 сайтов, или 1000, или ещё больше. В PHP если на каждой из них нет большой нагрузки все ограничено дисковыми пространством, а Java будет стартовать каждый и держать все программу в памяти.
Есть две Java (ещё C#), есть два Python (второй Ruby), а PHP реально имеет свою нишу, в которой он незаменим.
С той же многопоточностью, конечно иногда было бы круто быстро отдать ответ и запустить процесс в фоне, но это можно с помощью очереди.
В общем, нужно понимать инструмент и использовать тот, который нужен. Другое дело, что многие используют его там, где место Java и создают сете проблемы.
Shamanische
03.05.2018 12:49В PHP если на каждой из них нет большой нагрузки все ограничено дисковыми пространством
Это Вы про тот случай, когда основными источниками трафика на сайте являются фрилансеры и их заказчики? Так для таких целей PHP хорош как он есть, и без всяких улучшений!kuftachev
03.05.2018 13:02Не обязательно, если есть какая-то штука, которая может развернуться на одном сервере, но нужно, чтобы каждый клиент имел свой сайт. И в администрировании PHP прост.
Большинство веба — это по сути CRUD, узелок место — это походы в бд, а те жалкие проценты, которые мог бы ускорить компилируемый язык, редко когда нужны (ну и есть модули на Си, и вершина развития этой идеи — Phalcon).
А вот из скриптовых языков PHP на голову выше всех конкурентов, кроме Groovy(но там JVM и все прелести выяснения отношений с каким-то Tomcat). А Python и Ruby рядом не стоят.
unfapable
02.05.2018 21:11Неявное временное преобразование примитива в объект
Вы же понимаете, что это будет совершенно другой тогда ЯП? Смущает даже более формулировка "неявное временное", в Python и Ruby, скриптовых языках, к коим относится и PHP, всё представляет из себя объекты, смысл делать из PHP очередной Ruby, это противоречит его концепции? Безусловно, профит есть, но это уже полностью изменить язык, даже если учесть что это "временно"...
- Короткий синтаксис функций
RFC, указанный в статье, уже давно отклонен, вместо него есть другой, реализация стрелочных функций, что выглядит получше и довольно круто.
- Убрать function
Вот снова отсылка к JavaScript. Однако довольно странно это выглядит, в тех же упомянутых скриптовых языках, есть ключевое слово def для объявления функции, в PHP — это function. А вообще не стоит забывать, что PHP — мультипарадигмальный язык, где кроме поддержки ООП, есть и функциональная парадигма, в отличие от Java, а в JS — классы, как известно, синтаксический сахар, так что поэтому и нет лишнего ключевого слово. В общем, плохой, я бы даже назвал, рекомендацию убирать это, смотрится не очень, даже если учитывать, что это будет опциональная фишка, с целью не писать дополнительно 8 букв, находясь внутри контекста объекта...
- Навести порядок
Многое сказано правильно, но
json_encode -> Json::encode
, вообще жутко, да и представить себе сложно уже, т.к. кажется, что это пользовательский класс Json со статическим методом encode, а не что-то родное от языка. Да и опять же, статические вызовы в данном случае смотрятся ужасно.
Дженерики, декораторы асинхронность — лайк, и это реально можно, если уж не реализовать (хотя всё можно, конечно), то представить себе в контексте такого языка, как PHP, однозначно.
uralmas
02.05.2018 21:33+2На мой взгляд,
json_encode -> Json::encode
— очень хорошая замена, т.к. в стандартных библиотеках, коей является библиотека json, все функции, свойства константы идут с префиксом от наименования библиотеки, что иногда затрудняет чтение кода (не в случае json, конечно).
Зато все константы JSON_*, которые идут в этой библиотеке, можно будет вызывать не из глобального пространства, а как константы класса JSON
Вообще, как многие справедливо ругают, в PHP слишком много функций находится в глобальном пространстве. Кроме этого, данная замена позволит гибко управлять и переопределять эти функции.unfapable
02.05.2018 22:30+1Я имел в виду, что более привычно видеть обычные функции, нежели чем статические вызовы классов, если используешь встроенные возможности PHP. Возможно, я слишком привык к этому, но большое изменение, и меня смущает именно эти статические вызовы, опять-таки, скорее всего моя проблема.
rjhdby
02.05.2018 22:52Нет, это не ваша проблема.
В PHP функции стандартной библиотеки являются интринсиками (не уверен в корректности термина применительно к PHP, но по смыслу ближе всего) и работают с примитивными типами:
_zend_value{ zend_long lval; //int64_t double dval; zend_string *str; //uchar ... }
В случае объекта — это дополнительные накладные расходы на создание и хранение этого самого объекта.uralmas
03.05.2018 10:10Т.к. это расширение, данный объект создаётся 1 раз при запуске php. Расходы на хранение не такие уж и большие.
Если сравнивать варианты выполнения функции:
1.json_encode
: найти в локальном пространстве функциюjson_encode
, если в нём не найдём (что скорее всего и будет), ищем её в глобальном пространстве.
2.JSON::encode
: найти классJSON
, затем в нём найти статический методencode
.
Мне кажется, что 2-ой способ будет выполняться быстрее. Могу ошибаться, не знаток внутренностей PHP.sumanai
03.05.2018 10:14На первый вариант можно использовать \json_encode, защитит от переопределений и скажет сразу искать в глобальном пространстве, хотя производительность не замерял.
rjhdby
03.05.2018 10:32- Т.к. это расширение, то мы уже имеем увеличение вермени от получения запроса до начала его обработки, так как его надо загрузить и подготовить. Ну это я чисто придраться.
- Для
JSON::encode
разрешение имен будет идти абсолютно по такому же пути — сперва будет происходить поиск классаJSON
в локальном пространстве имен, а потом в глобальном.
uralmas
03.05.2018 10:491. Нет, загрузка расширения (и его классов) идёт всего 1 раз во время поднятия PHP (или инстансов php-fpm), а не на каждый запрос.
2. На мой взгляд, код\JSON::encode
выглядит гораздо гармоничней, чем\json_encode
. Но это чисто моё мнение.
Плюс, как я думаю, поиск в локальных/глобальных классах будет будет идти быстрее, чем в функциях, т.к. их намного меньше. Но точно этого не знаю, т.к. надо измерять.rjhdby
03.05.2018 11:05- Вот хорошая статья про жизненный цикл PHP
- Да я, собственно, не против. PHP позиционируется как мультипарадигменный язык. Кому-то нравится ООП, кому-то процедурный стиль.
Вы вполне можете сделать свой утилитный класс с красивыми методами, проксирующими к некрасивым стандартным функциям (лично я так иногда и делаю) и даже вынести его в расширение — это не так сложно делается.
uralmas
03.05.2018 10:21А чем в глобальном плане различаются «встроенные возможности» от сторонних библиотек? В самих встроенных библиотеках вообще можно найти разброд и ахтунг.
Например, встроенное расширение intl. Если зайти на страницу документации php.net/manual/ru/book.intl.php и почитать названия методов, то волосы встают дыбом — смесь CamelCase, слитное написание наименований без заглавных букв, «стандартное» наименование функций прописными буквами, разделённые нижним подчёркиванием. Плюс дублирование многих функций в процедурном стиле (функции вызываются из загруженного глобального пространства) и ООП.
В то время, как сторонние библиотеки (далеко не все, конечно) стараются держаться ООП либо вызова статических методов.rjhdby
03.05.2018 10:49А чем в глобальном плане различаются «встроенные возможности» от сторонних библиотек?
Из этой фразы стоит убрать слово "сторонних".
В PHP есть стандартная библиотека, содержащаяся вот прямо внутри исходного кода PHP, куда входит не такое уж и большое количество функций.
Все остальное подключается с помощью библиотек расширений — это то, что лежит в каталогеext
и включается вphp.ini
(библиотеки PECL отличается от "стандартных библиотек" только тем, что они не доступны "из коробки" и подключать/компилировать их нужно самостоятельно)
Глобальная же разница в том, что для работы с функциями расширений требуется подгрузить и инициализировать соответствующую библиотеку, а функции стандартной библиотеки доступны даже если вообще ни одного расширения не загружать.
uralmas
03.05.2018 11:09Под «глобальным» я имею только их выполнение, а не способ подключения.
JSON — та же библиотека, только «вшитая» в ядро. Я не про неё конкретно. Есть достаточно много таких «вшитых» библиотек, некоторые из которых можно отключить при компиляции.
Так что в глобальном плане они не отличаются от сторонних. Только образование наименований функций отличается. И это порой создаёт путаницу.
Понимаю, что это из-за наследия формирования PHP, и что это не изменить. Но такая разнородность «не красит» язык.
Всё написанное прошу считать моими «мысли вслух». Это просто тезисы моего ЯП, который я создаю на основе PHP, существующий только в моей голове.rjhdby
03.05.2018 11:42+1Видимо я не совсем понятно объяснил.
В PHP нет "вшитых" библиотек кромеstandard
, которую нельзя отключить. И, в частности, практически все функции работы с однобайтовыми строками содержатся именно в ней.
Все, что можно отключить/подключить — является библиотеками, которые довольно условно делятся на два типа — те, которые включены в поставку (например
mbstring
илиjson
) и те, которые PECL.
rjhdby
02.05.2018 21:21Многое из перечисленного уже есть на wiki.php.net/rfc в качестве предложений.
Про многопоточность в каждом еженедельном дайджесте про PHP на хабре есть отсылки.
если убрать слово `function`, то, насколько я понимаю, сильно усложнится процесс токенизации, что печально скажется на производительности. Да и не факт, что без жестко поломанной обратной совместимости не обойдется, если вдруг.
moscowman
02.05.2018 22:13Вы не против если я выскажу мысли с другой стороны баррикад. Нам это не нужно, это нужно Вам. Нужно для переписывания кода и получения очередного вознаграждения когда выйдет очередной PHP X, а поддержка старых версий на хостингах сойдёт на нет.
Samouvazhektra
02.05.2018 22:25Да, сахарка со стрелочными функциями очень хотелось бы, а если это еще приправить штукой типа https://github.com/sebastiaanluca/php-pipe-operator c поддержкой из коробки, будет совсем замечательно
Ну и про порядок с array_map/array_filter etc. и со строковыми функциями конечно тоже наболело, понятно что оберток хватает, но и нативных подвижек хотелось быSamouvazhektra
02.05.2018 22:31И еще, если не дженерики, то хотябы в phpdoc описание структуры массива
array[<string>, <int>], array[<int>, SomeClass[]]
rjhdby
02.05.2018 22:38Ну и про порядок с array_map/array_filter etc. и со строковыми функциями конечно тоже наболело
Малейший чих в сторону изменения поведения/порядка аргументов в функциях стандартной библиотеки PHP равносилен развязыванию маленькой ядерной войны — вроде и маленькая, но трясти и корёжить будет весь мир. Ситуация, конечно, очень печальная и, как мне кажется, решением может быть только создание параллельной стандартной библиотеки с постепенной (через 3-4 мажорных релиза) деприкацией старой.Goodkat
02.05.2018 23:32+1Можно было упрятать все эти старые стандартные функции в какой-нибудь namespace и пометить как deprecated и сделать им модные современные алиасы с однотипным наименованием функции и порядком аргументов.
Кто хочет пользоваться старыми для поддержки legacy, тот подключает namespace legaсу, а остальные переходят постепенно на новые, причём этот переход можно было бы почти полностью автоматизировать средствами самого языка.
Я думал, что так и сделают с введением namespace.rjhdby
02.05.2018 23:49В предлагаемом вами решении есть очень много спорного, но все это меркнет на фоне того, что оно ломает обратную совместимость практически со всем написанным на PHP коде, за все время существования языка.
Goodkat
03.05.2018 00:22Как раз не ломает же. Старые функции помечаются как deprecated, но работают.
rjhdby
03.05.2018 00:53PHP сперва ищет функцию в локальном пространстве имен, после чего, если не найдет, ищет в корневом (\).
Теперь представим, что старую стандартную библиотеку вынесли в отдельное пространство имен и добавили третий шаг в алгоритм разрешения (что само по себе костыль в ядро языка).
Тут же в проекте появится падаван, который лихо объявляет во входной точке API, в рутовом пространстве имен, что-то вроде
function strstr($a){ echo $a; }
И всё заверте…
Пример конечно утрированный, но нарушение обратной совместимости демонстрирует.Goodkat
03.05.2018 01:59Это будет уже новый код, от выстрелов в ногу везде защиту не поставишь.
И да, такое поведение иногда даже желательно, можно делать так:
`function strstr($a){
log();
return legacy\strstr($a);
}
symbix
03.05.2018 00:37Так не сделают. На php куча кода, который поддерживать вообще некому, просто работает и работает.
Имеет смысл добавить ООП-варианты вида
$array->map(...)->reduce(...)
/$string->length()
, а функции оставить как были для обратной совместимости.m0rtis
03.05.2018 10:54На php куча кода, который поддерживать вообще некому, просто работает и работает.
Тогда там и версию PHP некому будет обновить, а значит ничего не сломается:)
symbix
03.05.2018 16:22А оно с обновлениями серверов ломается. Какой-нибудь Pentium 4 с Debian Etch не вечен. :-)
Мне вот до сих пор для старого кода приходится держать PHP 5.3, например, и только потому, что придумали сломать call_by_ref в идиотской манере. Причем, если таки сделают explicit_send_by_ref, — а это именно то, как call by ref
в этом старом коде используется — можно будет сразу ставить 7.3 (или что там будет) — все должно завестись (разве что для совсем-совсем старого кода времен php4 понадобится полифилл на ext/mysql).
symbix
02.05.2018 23:29array_map/array_filter
Тут порядок легко запомнить:
- у array_map varargs, чтобы скормить несколько массивов,
- array_filter можно использовать без второго аргумента, что идентично function($v) { return !!$v; }.
Вот со строковыми функциями сложнее, впрочем, IDE всегда подскажет :-)
poxvuibr
03.05.2018 00:59По какой-то необъяснимой причине в статье отсутствует предложение убрать необходимость ставить значок доллара перед переменной. По той же необъяснимой причине ничего не сказано про то, что было бы лучше, если бы к полям объекта можно было обратиться не через два символа ->, а через какой-нибудь один символ.
А ведь, казалось бы, очевидные кандидаты на улучшение.
kuftachev
03.05.2018 03:05Конечно, меня это тоже бесит, но на счёт $ под точно проблема вылезет в том, что в строке "..." не понятно как искать переменную. Это то, что на поверхности, может ещё какие-то трудности.
А по -> — это переписать весь существующий код на PHP, и это не Java, где что-то скомпилировать можно и старым компилятором, тут вообще все умножится на ноль. В Плюсах с этим как-то живут.
yarosroman
03.05.2018 05:14В других языках как-то без $ обходятся. И в плюсах между. и -> есть разница.
kuftachev
03.05.2018 09:07+1Вообще-то я не говорил, что без этого нельзя сделать язык, я говорил, что это сломает слишком много кода.
На счёт точки в Плюсах, там она не используется для конкатенации строк.
rjhdby
03.05.2018 10:18Допустим отказались от знака доллара. Как токенизатору толковать вот такую строку?
a();
Вызов функции `a`?
Вызов метода `__invoke()` у класса, хранящегося в переменной `a`?
Вызов функции, имя которой хранится в переменной `a`?
Еще как-то?poxvuibr
03.05.2018 13:56Вызов функции
a
?
Вызов метода__invoke()
у класса, хранящегося в переменнойa
?Вызывать то, что ближе по области видимости. Если функция
a
есть в области видимости и переменная есть в области видимости — отдавать предочтение переменной или придумать другое однозначно трактуемое правило.
Вызов функции, имя которой хранится в переменной
a
?Если хочется вызвать функцию, имя которой хранится в переменной
a
, можно оставить возможность поставить перед переменнойa
знак доллара.rjhdby
03.05.2018 14:08+1или придумать другое однозначно трактуемое правило.
Например однозначное определение переменной с использованием символа
$
Вводить в язык развесистые деревья условных признаков, от которых зависит поведение кода — одно из самых деструктивных начинаний, какое только можно придумать. Особенно странно заниматься этим из-за оскорбленного эстетического чувства довольно малой части разработчиков.
poxvuibr
03.05.2018 15:18-1или придумать другое однозначно трактуемое правило.
Например однозначное определение переменной с использованием символа $Ну, то есть оставить, как сделано сейчас. Вам это, как я понимаю, кажется совершенно естественным и понятным. Именно то, что многим разработчикам это кажется совершенно естественным, меня и удивляет.
Описываемое вами поведение, когда у a() может означать вызов функции, а может означать вызов метода у объекта, который хранится в переменной
a
, присутствует в C++ и, если программистам на C++ предложить ради упрощения разруливания этого кейса ставить значок доллара перед каждой переменной, они просто покрутят пальцем у виска.
Особенно странно заниматься этим из-за оскорбленного эстетического чувства довольно малой части разработчиков.
Эстетика тут не при чём. Набирать $ перед каждой переменной объективно неудобно и в этом объективно нет необходимости.
rjhdby
03.05.2018 16:16+1если программистам на C++ предложить
Зачем вы пытаетесь сравнивать ежа и ужа?
Сходите к перловикам и расскажите, что ажно три разных префикса для переменных — это неудобно.
Сходите к дельфистам и расскажите, что:=
— это трешь.
Сходите к сишникам и объявите, что от вездесущих*
и&
в глазах рябит.
Поведайте питонщикам, что выделять блоки кода отступами — это за гранью добра и зла.
Расскажите создателям Kotlin, что типы должны быть слева, потому что вы в Java так привыкли.
они просто покрутят пальцем у виска.©
Синтаксис любого языка вырабатывается с конкретными целями. У использования доллара как префикса переменной в PHP есть конкретная цель — однозначное определение переменной в коде. А нужно это для:
- Облегчения чтения кода. Вы ведь помните, что 80% времени разработчик именно читает код?
- Ускорение работы парсера. Для PHP по сути его критично время старта.
poxvuibr
04.05.2018 23:23-1Зачем вы пытаетесь сравнивать ежа и ужа?
Я не пытаюсь делать ничего такого. Вы декларируете, что ставить доллар перед каждой переменной лучше, чем ввести правила, по которым будет определяться является
a
функцией или переменной. Я в ответ пишу, что в языке программирования, в котором фича с долларом отсутствует — никто не спешит её добавлять. Почему-то вместо этой, по вашему мнению разумной альтернативы, комитет по развитию С++ предпочитает ввести правило. Мне кажется, вы попали в ловушку рационализации недостатков инструмента, которым вы пользуетесь и хочу сказать, что в языках, в которых недостатка, который вы считаете фичей, нет — никто не спешит его добавлять. Возможно именно потому, что это недостаток.
Теперь по пунктам про приведённые вами утверждения
Сходите к перловикам и расскажите, что ажно три разных префикса для переменных — это неудобно.
Неудобно, но в перле эти префиксы хотя бы нужны для раделения типов переменных.
Сходите к дельфистам и расскажите, что := — это треш.
Тему много раз обсуждали, один символ был бы лучше, но так уж сложилось исторически. К счастью оператор присваивания в коде встречается реже, чем переменные.
Сходите к сишникам и объявите, что от вездесущих * и & в глазах рябит.
Вот тут вы собственноручно приступили к сравнению ежа с ужом. У символов * и & в Си есть смысл, убрать их просто так невозможно.
Поведайте питонщикам, что выделять блоки кода отступами — это за гранью добра и зла.
Я только что объяснял, что в лишнем символе перед переменными нет необходимости. Странно будет, если я сразу после этого буду говорить, что, хотя отступов достаточно для выделения блоков кода, обязательно надо выделить блоки чем-то ещё.
Расскажите создателям Kotlin, что типы должны быть слева, потому что вы в Java так привыкли.
Опять сравнение ужа с ежом — с какой стороны объявлять тип переменной — в основном дело вкуса. Объективных аргументов за или против тут нет.
poxvuibr
04.05.2018 23:34Синтаксис любого языка вырабатывается с конкретными целями.
И конкретной целью необходимости ставить знак доллара перед переменной в PHP было обеспечить возможность вставлять переменные в строки.
Облегчения чтения кода. Вы ведь помните, что 80% времени разработчик именно читает код?
В IDE можно подкрасить переменную любым интересным вам цветом. Также IDE подкрашивает переменные в зависимости от дополнительных факторов. Знак доллара облегчает чтение кода только если вы используете какой-то текстовый редактор типа Блокнот.
Ускорение работы парсера. Для PHP по сути его критично время старта.
Ну это даже не смешно. Во-первых, существенно на время старта наличие или отсутсвие значка доллара не влияет, во-вторых те, кому это по настоящему критично — компилируют код заранее.
rjhdby
05.05.2018 00:13+1И конкретной целью необходимости ставить знак доллара перед переменной в PHP было обеспечить возможность вставлять переменные в строки.
Позвольте не поверить и попросить предоставить пруфы.
В IDE можно подкрасить переменную любым интересным вам цветом.
А не в IDE нельзя. Вы удивитесь, когда узнаете, сколько разработчиков используют редакторы не обладающие развитыми возможностями подсветки синтаксиса.
Ну это даже не смешно. Во-первых, существенно на время старта наличие или отсутсвие значка доллара не влияет, во-вторых те, кому это по настоящему критично — компилируют код заранее.
Во-первых — повлияет.
Во-вторых — это как раз критично для всех, кроме high load (для них тоже критично, но только на прогреве). А таковых подавляющее большинство. Тут на хабре были статьи про критичность времени отклика — почитайте.
Я в ответ пишу, что в языке программирования, в котором фича с долларом отсутствует — никто не спешит её добавлять.
А в языках, где присутствует — никто не спешит убирать. Вам не кажется, что это прямо про притчу о своем уставе в чужом монастыре?
Почему-то вместо этой, по вашему мнению разумной альтернативы, комитет по развитию С++ предпочитает ввести правило.
А мантейнеры PHP, почему-то, предпочитают оставить доллар. При этом они не лезут в комитет по развитию С++ с предложением все переделать как у них. Странно, правда?poxvuibr
05.05.2018 00:51Позвольте не поверить и попросить предоставить пруфы.
Ну вот, например.
Вы удивитесь, когда узнаете, сколько разработчиков используют редакторы не обладающие развитыми возможностями подсветки синтаксиса.
То есть доллар перед переменными нужен тем, кто пользуется этими редакторами? А что это за редакторы? Можно поимённо? Вы, кстати, пользуетесь ими? Или в IDE пишете?
Во-первых — повлияет.
И, конечно, у вас есть результаты тестов? Или какие-то другие пруфы? Есть?
Во-вторых — это как раз критично для всех
Значит все должны компилировать код заранее. Это ускорит старт сильнее, чем доллары перед именами переменных.
А в языках, где присутствует — никто не спешит убирать.
И в каких языках нужно перед каждой переменной ставить один и тот же символ?
Вам не кажется, что это прямо про притчу о своем уставе в чужом монастыре?
Это не притча, это пословица :). И это пословица о том, что необходимо соблюдать установленные правила, а не о том, что их нельзя обсуждать.
А мантейнеры PHP, почему-то, предпочитают оставить доллар.
Так уж здесь заведено. О том, что можно по другому, почему-то мало кто задумывается.
При этом они не лезут в комитет по развитию С++ с предложением все переделать как у них. Странно, правда?
Да и члены комитета по развитию С++ не лезут к майнтейнерам PHP с предложением всё переделать как у них. Вас это тоже удивляет?
rjhdby
05.05.2018 01:36Ну вот, например.
Источник так себе, но да ладно. Вопрос на засыпку — какой процесс облегчается в результате «an ability to insert variables inside literal string values»? Не парсинг ли?
А что это за редакторы? Можно поимённо? Вы, кстати, пользуетесь ими? Или в IDE пишете?
Например vi и notepad++. Постоянно пользуюсь обоими, хотя имею опенсорсную лицензию на все продукты JetBrains. (нет, notepad++ НЕ обладает развитыми возможностями подсветки синтаксиса. vi тем более)
И, конечно, у вас есть результаты тестов?
А у вас? У меня есть опыт написания расширений к PHP, ковыряния в его коде и изучения принципов работы.
И в каких языках нужно перед каждой переменной ставить один и тот же символ?
Perl. Перед каждой переменной конкретного типа ставится фиксированный префикс. В PHP тип один — ```zend_value```
О том, что можно по другому, почему-то мало кто задумывается.
Не, ну кто бы спорил. Все вокруг дураки. Слава богу один умный нашелся и всем глаза раскрыл.
Да и члены комитета по развитию С++ не лезут к майнтейнерам PHP с предложением всё переделать как у них
Тем более странно, что лезете вы и потрясаете их комитетом.
Вишенка на торте.
Как я уже писал, надо компилировать заранее, а не затачивать синтаксис под нужды компилятора.
А что еще все должны делать?
Вам не кажется, что это несколько странное пожелание для интерпритируемого языка? (дабы избежать лишней итерации переписки — я пишу на Java, Kotlin, PHP, C, Objective C и чутка на ассемблере — для души)poxvuibr
05.05.2018 02:11Вопрос на засыпку — какой процесс облегчается в результате «an ability to insert variables inside literal string values»? Не парсинг ли?
Он самый. Но можно ставить доллар перед переменными только внутри строк. Везде их ставить необходимости нет.
(нет, notepad++ НЕ обладает развитыми возможностями подсветки синтаксиса. vi тем более)
Во-первых у vim возможности подсветки получше, чем у notepad++, а во-вторых подсветки и того и другого хватает, чтобы выделить всё, кроме собственно переменных. Для того, чтобы проблемы появились, надо использовать notepad.
У меня есть опыт написания расширений к PHP, ковыряния в его коде и изучения принципов работы.
А для доказательства вашего утверждения нужны результаты тестов, демонстрирующие, насколько отсутствие доллара замедляет разбор файла.
Perl. Перед каждой переменной конкретного типа ставится фиксированный префикс.
Этих префиксов несколько. Поэтому, что один и тот же символ нужно ставить перед каждой переменной, сказать нельзя.
Тем более странно, что лезете вы и потрясаете их комитетом.
Странно, что вас удивляет, что я написал, как можно улучшить PHP в статье про то, как можно улучшить PHP. Так же очень странно, что вы охарактеризовали мои слова как "потрясание комитетом", да и то, что вы вообще написали, что майнтейнеры не лезут с советами к комитету по развитию С++ очень странно. Создаётся впечатление, что вы воспринимаете выражение моей позиции как попытку покуситься на что-то сакральное.
А что еще все должны делать?
Ну пока что вы сказали, что все должны уменьшать время старта скриптов. Я с этим не спорил. Наибольший эффект достигается предварительной компиляцией.
Вам не кажется, что это несколько странное пожелание для интерпритируемого языка?
Кажется, но вы же сказали, что тут особый случай, потому что скрипт запускается и компилируется заново при каждом запросе. Значит надо компилировать.
rjhdby
05.05.2018 02:30Во-первых у vim… во-вторых подсветки и того и другого хватает...
Во-первых не vim, а vi.
Во-вторых — подсветки хватает, пока парсер редактора может однозначно определить переменную. Когда он этого сделать не может, то и подсветка начинает уже не помогать, а мешать. Даже у Idea бывает крышу сносит на, вроде бы, «правильных» языках, что уж говорить о других редакторах.
А для доказательства вашего утверждения
Начнем с того, что это именно вы утверждаете, что никак не скажется. Извините, но в случае парсера ЯП доказывать отсутствие импакта должен предлагающий изменения.
Поэтому, что один и тот же символ нужно ставить перед каждой переменной, сказать нельзя.
Перед каждым скаляром надо ставить $. Перед каждой хэш-таблицей надо ставить %. Перед каждым массивом надо ставить @.
Странно, что вас удивляет, что я написал, как можно улучшить PHP в статье про то, как можно улучшить PHP.
Меня удивляет, что в статье про то, как можно улучшит PHP, вы предлагаете переделать его в С++. Не более того. Спасибо — не надо. Когда мне нужен С++ — я пользуюсь им, но когда мне нужен PHP, то и беру я PHP.
Кажется, но вы же сказали, что тут особый случай, потому что скрипт запускается и компилируется заново при каждом запросе. Значит надо компилировать.
То, что мотоцикл имеет два колеса и может упасть на бок(пока не едет) не означает, что нужно приделать ему еще два и превратить его в машину.poxvuibr
05.05.2018 03:02Во-первых не vim, а vi.
Либо вы на своём компьютере по какой-то причине используете vi вместо vim, что удивительно, либо редактируете код на какой-то удалённой машине, что объясняет, например, ваше нежелание компилировать код. Вам в вашей ситуации, возможно, действительно имеет смысл именовать все переменные как-нибудь особенно, например начинать с доллара. Но делать это обязательным для всех нецелесообразно.
Начнем с того, что это именно вы утверждаете, что никак не скажется.
Началось всё с вашего утверждения о том, что скажется, причём скажется существенно.
Перед каждым скаляром надо ставить $. Перед каждой хэш-таблицей надо ставить %. Перед каждым массивом надо ставить @.
Да, перед разными видами переменных надо ставить разные префиксы. Поэтому утверждение, что в Perl перед всеми переменными нужно ставить один и тот же символ — ложно.
Меня удивляет, что в статье про то, как можно улучшит PHP, вы предлагаете переделать его в С++.
Это неправда, я этого не предлагал.
То, что мотоцикл имеет два колеса и может упасть на бок(пока не едет) не означает, что нужно приделать ему еще два и превратить его в машину.
Поясните, пожалуйста, что вы хотели этим сказать.
rjhdby
05.05.2018 03:38что объясняет, например, ваше нежелание компилировать код
:facepalm:
Вы понимаете, что PHP — это скриптовый (интерпритируемый) язык? Что он потому и подходит для решения определенного скопа задач именно потому, что его не надо компилировать?
Началось всё с вашего утверждения о том, что скажется, причём скажется существенно.
Тут было во-первых и во-вторых, но главное все же в-третьих — все равно, бремя доказательств отсутствия негативного воздействия лежит на предлагающем изменения. Изменения предлагаете вы — вам и доказывать, что они не сделают хуже.
Пока не докажете, я, основываясь на своем знании предмета буду утверждать обратное. Dixi.
Да, перед разными видами переменных надо ставить разные префиксы. Поэтому утверждение, что в Perl перед всеми переменными нужно ставить один и тот же символ — ложно.
В PHP не перед всеми переменными и не всегда надо ставить символ $. Сталобыть ваше утверждение также ложно.
Это неправда, я этого не предлагал.
Именно к этому вы и ведете. Сначала вы предлагаете убрать $, аргументируя, что С++ обходятся без него. Потом начали рассказывать про компиляцию. Это все здорово, но непонятно, причем тут PHP?
Поясните, пожалуйста, что вы хотели этим сказать.
Ровно то, что сказал. То, что для PHP критична производительность парсера не значит, что его надо превращать в компилируемый язык.poxvuibr
05.05.2018 11:16Вы понимаете, что PHP — это скриптовый (интерпритируемый) язык?
Понимаю.
Что он потому и подходит для решения определенного скопа задач именно потому, что его не надо компилировать?
Да, но с ваших слов веб к этим задачам не относится, потому что всем надо делать так, чтобы скрипт стартовал как можно скорее. Самый лучший способ это сделать — компилировать заранее.
В PHP не перед всеми переменными и не всегда надо ставить символ $. Сталобыть ваше утверждение также ложно.
То есть, если доллара нет, то нельзя точно сказать, что перед нами не переменная? И в каких случаях не нужно ставить доллар перед переменными?
Именно к этому вы и ведете.
Нет, не веду.
Сначала вы предлагаете убрать $, аргументируя, что С++ обходятся без него.
Мой аргумент — необходимости в долларе нет и другие языки прекрасно это демонстрируют. Вместо С++ можно взять какой-нибудь другой пример.
Потом начали рассказывать про компиляцию.
С ваших слов надо уменьшать время старта скрипта. Вот я и заговорил про компиляцию.
Это все здорово, но непонятно, причем тут PHP?
Необходимость ставить знак доллара перед каждой переменной — объективный недостаток PHP, необходимость компилировать скрипты на PHP следует из ваших слов о необходимости ускорять старт. Вот причём тут PHP.
То, что для PHP критична производительность парсера не значит, что его надо превращать в компилируемый язык.
Производительность парсера, с ваших слов, критична потому, что критично время старта скрипта, лучший способ него уменьшить — компилироваать скрипты. Если время старта действительно важно уменьшать — скрипты надо компилировать.
Vilgelm
05.05.2018 04:10То есть доллар перед переменными нужен тем, кто пользуется этими редакторами?
Мне нужно внести какие-то небольшие изменения в код или посмотреть на строку, в которой возникает ошибка. Я подключаюсь по ssh, ввожу nano name.php или vi name.php и читаю код. А вы мне предлагаете IDE ставить. На сервер. Который бы в консоли работал. Мне почему-то сразу хочется послать в известном направлении с такими предложениями.
rjhdby
05.05.2018 00:49Почему повлияет (не про высоконагруженные, где opcache и прочие).
Операция компиляции происходит при каждом(!) выполнении скрипта. Эта задержка, какой бы малой она не была, добавится ко времени отклика вообще каждого скрипта. Это как раз тот случай, когда экономия на спичках оправдана.
Если рассматривать средней сложности приложение с десятком подгружаемых классов — умножай на количество подгружаемых файлов.
Парсер в PHP достаточно прямолинеен. Введение правил, которые добавят в него ветвления и дополнительные проходы приведет к непрогнозируемому росту сложности и, соответственно, времени выполнения.poxvuibr
05.05.2018 00:54-1Операция компиляции происходит при каждом(!) выполнении скрипта. Эта задержка, какой бы малой она не была, добавится ко времени отклика вообще каждого скрипта. Это как раз тот случай, когда экономия на спичках оправдана.
Как я уже писал, надо компилировать заранее, а не затачивать синтаксис под нужды компилятора.
VolCh
05.05.2018 18:05> Знак доллара облегчает чтение кода только если вы используете какой-то текстовый редактор типа Блокнот.
Или просматриваете где-то на гитхабе. Или книгу читаете.poxvuibr
05.05.2018 18:59Гитхаб раскрашивает код. В книгах он зачастую тоже раскрашенный, но, если вы читаете нецветную книгу и оттенков серого для раскраски не хватило, то может быть доллары принесут какую-то пользу. Но лично я считаю, что этого недостаточно, для того, чтобы оправдать их существование.
springimport
03.05.2018 16:19Мне в js наоборот странно когда возле переменной ничего нет, а набирание постоянных let вообще напрягает.
И вообще, если $ все не замечают и никого не напрягает — значит знак выбран удачно. Конечно, кому-то может и не зайти. Я все жду когда для php появятся свой babel и тогда заживем. И вы сможете не писать $)
NickyX3
03.05.2018 16:01А в некоторых не только не обходятся с $, но еще и @# юзают… Для переменных :-)
poxvuibr
03.05.2018 13:40на счёт $ под точно проблема вылезет в том, что в строке "..." не понятно как искать переменную
Как раз в строке с двойными кавычками можно оставить необходимость ставить знак доллара перед переменной. Тут понятно для чего он нужен и почему без него будет менее удобно.
А по -> — это переписать весь существующий код на PHP, и это не Java, где что-то скомпилировать можно и старым компилятором, тут вообще все умножится на ноль
Я бы предложил оставить старый код как есть, а в файлах с новым кодом добавить директиву, наподобии "use strict" в javascript. При использовании этой директивы для получения поля объекта надо было бы использовать точку, а для конкатенации какой-нибудь другой символ. Можно даже ->, лично у меня возражений нет :). Но лучше, конечно, какой-нибудь один символ.
Но всё это технические детали, сначала нужно хотя бы сойтись во мнении, что, если бы волшебным образом в PHP не надо было ставить доллары перед переменными и можно было бы использовать точку для доступа к полям объектов — это было бы хорошо. Но, как демонстрируют комментарии, такого единодушия среди программистов нет.
kuftachev
03.05.2018 18:09Мне кажется, что единодушие есть )))
Есть просто и понимание к каким проблемам это может привести.
Goodkat
03.05.2018 09:14+1Вы, наверное, и переменные называете a, b и с, чтобы сэкономить?
poxvuibr
03.05.2018 13:50Нет, не называю :). Когда экономия создаёт объективные проблемы — лучше не экономить. Но значок доллара перед каждой переменной смысловой нагрузки не несёт и, если его убрать, хуже не станет.
Банально проще писать код, если перед каждой переменной не надо набирать символ, без которого можно обойтись и для ввода которого нужно зажать шифт.
m0rtis
03.05.2018 11:00+1Лично мне (подчеркиваю эти два слова) знак доллара перед именем переменной гораздо удобнее — и с точки зрения читаемости, и с точки зрения всяких фишек типа подстановки значения переменной в строках в двойных кавычках. Не вижу ни малейшего смысла знак доллара убирать.
А вот насчет точки вместо стрелочки — оно можно, но ничего хорошего (в отличие, например, от дженериков) в язык это не принесет. А вот с конкатенацией и оператором ".=" будут проблемы. Так что пусть уж лучше будет привычная стрелочка:)poxvuibr
03.05.2018 13:58Лично мне (подчеркиваю эти два слова) знак доллара перед именем переменной гораздо удобнее — и с точки зрения читаемости
Если есть IDE, она подсветить переменные каким-нибудь цветом. Если без IDE, то знак доллара действительно приносит определённую пользу.
и с точки зрения всяких фишек типа подстановки значения переменной в строках в двойных кавычках
Эту функцию знака доллара можно оставить.
dmitryklerik
03.05.2018 11:41+3Значок $ перед переменными это очень удобно для того чтобы отличать переменную от функции и это как раз выгодно отличает php от многих других языков
IvanNochnoy
03.05.2018 14:25Да, пользователи других языков очень страдают по этому поводу, даже придумали хак: договорились начинать все переменные с $. Все так делают… потому что удобно.
sumanai
03.05.2018 14:30На JS походу так делают только для объектов JQuery, на остальных и вовсе не замечал.
yarosroman
03.05.2018 02:15В C# все это давно есть.
m0rtis
03.05.2018 11:08+1А в бейсике нужно нумеровать строки десятками. И что, какое это отношение имеет к будущему PHP?
vlreshet
03.05.2018 11:51Разве не любыми числами? По-моему, десятками было просто общепринято, типа кодстайл)
m0rtis
03.05.2018 12:00Разве не любыми числами? По-моему, десятками было просто общепринято, типа кодстайл)
Да, Вы правы. Подойдет любое число. Десятками нумеровали, чтобы была возможность добавить ы последующем строки в программу без тотальной перенумерации:)
rjhdby
03.05.2018 12:02Да и не в любом бейсике нумерация нужна, если уж на то пошло.
Десятками нумеровали для того, чтобы можно было, при необходимости, вставить строки без пересчета всех меток до конца файла.
kuftachev
03.05.2018 02:54Ещё нужно знак доллара поменять на знак евро, ну или рубля.
В общем, завязывайте со спиртным ;-)
springimport
03.05.2018 16:33+3Так и представляю: где-нибудь в php.ini
; Okay, guys, now you can choose your favorite currency ; $variable ; €variable ; ?peremennaya developer.loved_currency_symbol = $
alexkbs
03.05.2018 06:53Функции, работающие с массивами, не меняют исходный массив, за некоторым исключением. Вы считаете что методы вида
$arr->map(...)
и$arr->filter(...)
должны следовать исходной семантике, или должны менять исходный массив, на котором они вызываются?
- Если первое, то значит ли что ваше API всегда нужно будет использовать вызывая методы по цепочке?..
- Если второе, то каким образом, вы считаете, пользователь вашего API сможет сохранять исходный массив, если объекты в PHP по умолчанию передаются по ссылке? Всегда использовать
clone
при присвоении массивов?..
В том числе из-за таких вопросов мы до сих пор используем
array_map
, а не делаемcomposer install ...
и используем какую-то библиотеку, реализующую подобный функционал, даже не смотря на то, что такие библиотеки уже есть. Они просто неудобны в использовании, потому подобного функционала вы не увидите в самом языке.kuftachev
03.05.2018 09:20Ну как они могут менять? Это же элементы функционального программирования, там вообще ничего не меняется.
VolCh
03.05.2018 09:39Есть RFC о иммутабельных объектах, тут они очень в тему будут. Но, вероятно, для эффективной работы нужны будут оптимизации как раз чтобы не делать clone на каждую операцию.
alexkbs
03.05.2018 09:47Признаться честно даже если такие массивы будут иммутабельные, это нисколько не сделает PHP как язык лучше, а наоборот — сделает работу с массивами ещё сложней и запутанней, чем она уже есть.
Например, сейчас ты вызываешь функцию и получаешь результат. Плохая или хорошая функция, всё очень понятно и однозначно.
В отличии от старых функций, с таким новым API типа как у объектов нужно будет в голове держать кучу контекстов: что это и не настоящий объект, и что он не меняется, и что нужно обязательно сохранять результат в какой-то другой переменной. Стоит ли такое новое API таких новых требований — я не уверен.
VolCh
03.05.2018 09:53С результатом сейчас не всё однозначно, даже если ограничиться семейством функций array_*.
alexkbs
03.05.2018 09:54Не обязательно однозначно, но предсказуемо. Достаточно запомнить как работает конкретная функция, не нужно держать в голове ещё какие-то концепты.
VolCh
03.05.2018 11:32Тут достаточно будет запомнить одно правило: применение оператора -> к скаляру или массиву всегда будет возвращать новое значение, а не менять существующее.
alexkbs
03.05.2018 11:48Не просто запомнить, а наложить это новое знание на все другие знания о методах обычных объектов, у которых как правило противоположное поведение. Тут сразу появляется широкое поле для всевозможных ошибок.
T-362
03.05.2018 12:29В принципе, можно используя немножко черной магии сделать как-то так уже сейчас:
$b = Array::asort($a, SORT_REGULAR); // получаем новый массив $a->asort(SORT_REGULAR); // меняем имеющийся массив
Правда даже хуже чем уродливый код будет отсутствие возможности сделать нормальные подсказки для IDE, или я чего-то не знаю о возможностях докблоков.springimport
03.05.2018 16:39Всегда выше переменной можно написать пояснение:
/** @var \Class $item */ $item->get();
impwx
03.05.2018 11:12+2Внутренняя несогласованность в PHP вызвана тем, что язык долгое время развивался людьми, который не имели четкого представления о дизайне языка, а зачастую вообще не понимали, что они делают. Автор статьи продолжает эту традицию.
Язык может быть востребован по нескольким причинам: он предлагает уникальное решение для некой задачи, или же имеет большую кодовую базу. Изначально PHP опирался на первый пункт и был самым простым языком для написания веб-страниц, но тогда веб был совсем другим: никто не заботился о безопасности и поддерживаемости, важнее всего была возможность что-то слепить по-быстрому. Именно поэтому в языке изначально были такие секьюрити-дыры, как register_globals и magic_quotes_gpc. Теперь же удобных для бэкенда языков не меньше дюжины, но у PHP остается преимущество в виде огромного числа написанных на нем приложений и специалистов разного уровня.
Автор многократно упоминает в статье, что «любит PHP», но если «навести порядок» и «перенести функции в классы», в результате это будет уже не PHP, а какой-то новый язык, лишенный основного преимущества в виде кодовой базы и не дающий никаких преимуществ для привлечения новых пользователей по сравнению с конкуретами.
В отличие от фронтенда, где исторически существует только JS, на бэкенде есть огромный выбор. Почти всем пожеланиям автора отвечают, например, уже существующие Typescript/C#/Java 8. Не стоит зацикливаться на одном инструменте, когда требуемую задачу лучше решает другой.VolCh
03.05.2018 11:37Ну, у PHP останется, как минимум, его модель выполнения в самом популярном случае использования. Да и изменения можно вводить постпенно, не ломая BC сразу, а делая некоторые фичи сначала просто нерекомендуемыми, потом deprecated, а уж потом выпиливать совсем. Например, в 8.0 добавить новое, а существующее на уровне документации объявить нерекомендуемым, в 9.0 сделать deprecated, в 10.0 выпилить.
vtvz_ru Автор
03.05.2018 13:03Можно старые функции оставить, пометить как deprecated, а новое по-человечески запихивать в namespace'ы, а не в глобальную область видимости
rjhdby
03.05.2018 16:26Про пространства имен — не самая лучшая идея. При всех своих недостатках, функции стандартной библиотеки используются очень часто. Представьте себе, в какую кашу превратится код, если для каждой элементарной функции указывать ее пространство имен.
private static function parseMethodName($token): string { return trim(strrchr(rtrim($token, "\n\r\t */"), ' ')); }
Превратится в такое, например :)
private static function parseMethodName($token): string { return standard\string\trim(standard\string\strrchr(standard\string\rtrim($token, "\n\r\t */"), ' ')); }
VolCh
03.05.2018 17:20github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/Mapping/DefaultEntityListenerResolver.php#L7 обратите внимание на импорт функций.
impwx
03.05.2018 14:49Такими темпами «наведение порядка» растянется лет на десять. И что конкретно вы подразумеваете под «моделью выполнения»?
VolCh
03.05.2018 14:52Ну на каждый минорный релиз можно.
mod_php для apache и(или) php_fpm для fastcgiimpwx
03.05.2018 15:04Ну и получится, что новая версия — это другой язык, и портировать под него существующий софт мало кто захочет.
Чем эта модель исполнения принципиально лучше других? Как я понимаю, вы считаете преимуществом то, что под каждый запрос стартует отдельный процесс, который убивается после его обработки?VolCh
03.05.2018 17:16Новый процесс не стартует на самом деле обычно, но для пользовательского кода это так выглядит. Есть похожая по удобству (в случае интерпретируемых языков) модель CGI, но она заметно медленнее, как раз потому что новый процесс.
impwx
03.05.2018 18:08Так практически в любом MVC-фреймворке такой же подход: для пользователя важно только то, что на каждый запрос к серверу будет создан класс-контроллер и вызван метод-действие. Более того, можно легко сделать статический кеш объектов (если очень нужно и понимаешь, что делаешь). Не вижу тут преимущества PHP.
sumanai
03.05.2018 18:35Не вижу тут преимущества PHP.
Автоочистка всех созданный ресурсов по завершению обработки запроса. В других моделях можно забыть закрыть дескриптор или ещё чего и получить утечку.impwx
03.05.2018 19:02+1Для меня это скорее недостаток, и он очень в духе PHP. В данном случае у вас в логике явный баг, но система не помогает вам его найти и исправить, а наоборот маскирует его неявным поведением — до поры, до времени.
Знаете про принцип fail fast? Если в двух словах, то он звучит так: надежное приложение при ошибке падает и ничего не делает. PHP же всегда старается сделать хоть что-то, зачастую неправильно и, что еще хуже, молча — так вы можете потерять данные и даже не заметить этого. Там даже есть специальный оператор управления ошибками, который «затыкает» ошибки, возникающие во время вычисления выражения!
Буквально вчера у меня был случай, когда используемый уже много лет скрипт на PHP молча потёр мои данные. Скрипт выглядел примерно вот так:
$data = json_decode(file_get_contents($cache), true); update($data); file_put_contents($cache, json_encode($info, JSON_PRETTY_PRINT));
Оказалось, что скрипт был запущен в PHP 5.3, а флагJSON_PRETTY_PRINT
появился только в PHP 5.4. В результатеjson_encode
молча вернулNULL
, и даже вjson_last_error
ничего не было, а данные пропали.sumanai
03.05.2018 19:36Для меня это скорее недостаток, и он очень в духе PHP.
Ну значит вам для ваших задач PHP не подходит.
Буквально вчера у меня был случай
В вашем примере банальное отсутствие проверки наличия результата (если вы ничего не опустили), пенять на язык тут не нужно.impwx
03.05.2018 21:57пенять на язык тут не нужно
Ничего подобного. Была проверка на ошибку, но в данной ситуации не было ни ошибки, ни результата. Такую ситуацию я не предусмотрел, и моя претензия именно к принципиальной возможности ее возникновения.
Скрипт был изначально невалиден как минимум по двум причинам. Во-первых, идентификаторJSON_PRETTY_PRINT
не был объявлен, что даже в весьма либеральном JS считаетсяReferenceError
, но PHP предпочел молча превратить его в строку. Во-вторых,json_encode
на вход был передан аргумент неправильного типа, а он молча вернулNULL
. В документации, кстати, сказано, что в случае ошибки возвращаетсяfalse
. В обоих случаях не было даже notice!
Люди ошибаются. Поэтому строители носят каски, а альпинисты используют страховку. И только бесстрашные программисты продолжают писать на языках с неявными эффектами :)oxidmod
03.05.2018 22:00Если говорить откровенно, то PHP бросает notice при обращении к неизвестной константе.
impwx
03.05.2018 22:18Любопытно. У меня на сервере даже с
error_reporting(E_ALL)
полная тишина. Правда, я использую IIS — возможно, дело в этом.symbix
04.05.2018 02:35А error_log вообще включен? :)
Вообще, стандартная практика, используемая во всех современных фреймворках — на каждую ошибку, включая notice, выбрасывать исключение. Да и без фреймворков тоже стандартная, делается в 5 строк кода.
sumanai
04.05.2018 06:31Была проверка на ошибку
Никогда не помешает проверить и результат на корректность. Что NULL, что false не являются корректными данными для JSON.
Плюс в скрипте не указана минимальная версия для запуска.impwx
04.05.2018 10:16В итоге мы сошлись во мнении, что для написания надежного кода на PHP необходимо все обмазывать параноидальными проверками. Странно, что выводы из этого мы делаем абсолютно разные.
oxidmod
04.05.2018 11:09Нет, мы приходим к тому, что надо использовать composer с указанием необходимых минимальных требований к платформе (версия пхп, екстеншены и прочее)
impwx
04.05.2018 11:25Как это решает проблему возможной опечатки в константе?
oxidmod
04.05.2018 11:34Как любой другой интерпретируемый язык спасет вас от опечатки?
Ну а глобально — вменяемая IDE, тесты.
В этом случае константа была корректная, но не зафиксирована версия пхп. Композер тут как раз помог быimpwx
04.05.2018 11:44Все остальные языки кидают ошибку при обращении к неизвестной переменной \ константе.
Python:
a = b // NameError: name 'b' is not defined
Javascript:
a = b; // ReferenceError: b is not defined
Ruby:
a = B // uninitialized constant B
sumanai
04.05.2018 11:56Причём тут вообще PHP? Для написания надёжного кода на любом языке нужен параноидальный код.
impwx
04.05.2018 12:06Просто попробуйте несколько других языков и сравните, где надежный код получается проще и лаконичнее.
sumanai
04.05.2018 12:09Например С, ASM?
Если уж говорить о надёжности, то нужно использовать Ada, но знаете, работу с этим языком искать трудно, всё больше JS требуют, где с этим ничем не лучше PHP.
kuftachev
03.05.2018 18:15"Внутренняя несогласованность в PHP вызвана тем, что язык долгое время развивался людьми, который не имели четкого представления о дизайне языка, а зачастую вообще не понимали, что они делают."
Хорошо, что в отличии от авторов JS они хоть наркоту не употребляли ))))
dmitryklerik
03.05.2018 11:51Основная претензия автора — это многословность PHP как языка программирования. Но тут ничего не поделаешь — так язык задуман изначально. И добавление разных способов объявления функций это будет ужасно, нет ничего хуже чем смещение стилей и парадигм
impwx
03.05.2018 14:58Язык никто не задумывал многословным — просто у него очень плохо описана грамматика. Я еще помню времена, когда можно было применять индексатор только к переменным, а не произвольным выражениям — но это со временем поправили. Весь сахар из статьи довольно легко реализуется в нормальном парсере, не вызывает неоднозначностей или ощутимого замедления разбора.
Смешение парадигм тоже может быть вполне оправдано — например, элементы функционального программирования в императивных языках сейчас прижились повсеместно. Нужно смотреть на конкретные реализации.
mr_avi
03.05.2018 11:55Как по мне, PHP неплохо развивается как ОО язык, и большинство функций, констант и п.р. можно переместить в классы (json_encode -> Json::encode, cUrl).
Можно по-быстрому набросать преобразование вызова статического метода в вызов стандартной функции, вроде этого:
github.com/uavn/artwrap/blob/master/Art/Wrapper/Hash.php
1Tiger1
03.05.2018 12:24+1PHP может стать еще лучше если из него сделать JS? как то так я увидел в статье, с примесью java и scala. Спасибо, не надо ассинхроности, и магии по минимуму. PHP хорош как раз своей относительной простотой, низким порогом входа и прозрачностью. Нужна простая параллельность — запускайте процессы и синхронизуйте их если надо, хоть очередями хоть другими инструментами. Нужна гибкая паралельность — не натягивайте сову на глобус, пожалейте птичку, возмите тот инструмент что вам нужен, хоть scala хоть go, с функционалной записью та же история, PHP не функциональный язык, и им не будет, подход у него не тот. Хотите JS на сервере — ноду вам в руки.
Странная эта мания превращать один инструмент в другой, потому что привыкли или потому что удобная фишечка. Комбинируйте инструменты а не затачивайте молоток что-бы получить отвертку.
«В PHP может быть множество задач, которые хотелось бы сделать асинхронно, не дожидаясь окончания выполнения. На ум сразу же приходят работа с большими БД запросами и HTTP запросами. Чтобы составить большой отчет, приходится либо долго ждать, либо пользоваться сторонними решениями, типа очередей. В моем случае, в проекте в большом количестве используются Slack уведомления и Mailgun оповещения. За один клиентский запрос может быть отправлено около десятка HTTP запросов. Почему бы не запустить это все на фоне, а клиенту уже отдать страничку? » потому что «Этот язык был создан для конкретной цели и решает он свою задачу хорошо. Схема „принял — обработал — отдал — умер“ очень эффективна и решает проблему небольших утечек памяти.». Не только кстати утечек памяти.VolCh
03.05.2018 13:23> Странная эта мания превращать один инструмент в другой, потому что привыкли или потому что удобная фишечка.
Ничего странного. «Привыкли» ещё ладно, но «удобная фишечка» по сути основной стимул что-то менять.
xobotyi
03.05.2018 13:10Меня в PHP до состояния «аштрисёт» доводят только три вещи (по убыванию бесячести):
- Доступ к элементам объектов через
->
, которое ну очень часто получается как_>
ну или-.
(рукопопы как я, которые имеют рассинхрон между руками, поймут). Вот что угодно лучше служебного оператора из двух символов, один из которых по шифту вводится.. - Инициализация значений именованного массива через
=>
(ну какого черта не:
?) - Ну и как уже сказал автор — нельзя использовать выражения везде. Да даже если бы можно было хотя бы в строках делать было бы уже хорошо:
вместо$a = "Hello ${$b?:'hell'}";
$a = "Hello " . ($b?:'hell') . "!";
oxidmod
03.05.2018 13:23По поводу второго — автодополнение от IDE очень даже помогает
По поводу третьего
$a = sprintf('Hello %s!', $b?:'hell')
xobotyi
03.05.2018 13:29Оверхед по написанному не находите? =)
Все что я описал — банальная экономия на символах, с сохранением функциональности.
Правда, по поводу автодополнения на инициализации массива — не понял… PHPStorm вроде не позволяет такого.oxidmod
03.05.2018 13:48Вы правы, я имел ввиду первый пункт (->)
Бес попутал.
А вот оверхед ли? Большую часть времени вы читаете код, а не пишите. sprintf или даже просто конкатенация читаются куда как проще. Вы в свой вариант добавьте еще двойных кавычек внутрь строки и будет вообще нечитаемый треш с экранированием.
rjhdby
03.05.2018 15:36По третьему пункту.
$a='a'; $b='b'; echo "Hi $a! I`m $b";
Раскладывается на такие токены
1: T_OPEN_TAG = <?php 2: T_VARIABLE = $a 2: = 2: T_CONSTANT_ENCAPSED_STRING = "a" 2: ; 2: T_WHITESPACE = 3: T_VARIABLE = $b 3: = 3: T_CONSTANT_ENCAPSED_STRING = "b" 3: ; 3: T_WHITESPACE = 4: T_ECHO = echo 4: T_WHITESPACE = 4: " 4: T_ENCAPSED_AND_WHITESPACE = Hi 4: T_VARIABLE = $a 4: T_ENCAPSED_AND_WHITESPACE = ! I`m 4: T_VARIABLE = $b 4: T_ENCAPSED_AND_WHITESPACE = . 4: " 4: ;
Обратите внимание, что строка в
echo
по сути разбита на элементарные составляющие из констант и переменных, для которых, в последствии, произойдет последовательная конкатенация.
опкодopcode op1 op2 result ZEND_ASSIGN $a 'a' x4 ZEND_ASSIGN $b 'b' x4 ZEND_ROPE_INIT 'Hi ' $_tmp_4294967290 ZEND_ROPE_ADD $_tmp_4294967290 $a $_tmp_4294967290 ZEND_ROPE_ADD $_tmp_4294967290 '!I'm ' $_tmp_4294967290 ZEND_ROPE_END $_tmp_4294967290 $b $_tmp_4294967290 ZEND_ECHO $_tmp_4294967290 ZEND_RETURN 1
caballero
03.05.2018 14:23+1Лично мне не хватает нормальных аннотаций. Но следует учитывать что все подобные вышеперечисленным вещи усложняют грамматику языка и даже могут сделать ее неоднозначной (потому и не убирается function). Усложнение грамматики — усложнение компилятора. А значит сложнее становится генерация оптимизированого кода. Но в подавляющем числе проектов на PHP никаких особых наворотов не нужно. Гораздо важнее простота, скорость и надежность.
achekalin
03.05.2018 14:24Хочется сказать классическое: «легким движением руки брюки превращаются… превращаются...»
Впрочем, как из MySQL 3.x вырос MySQL 8.x, так и из PHP постепенно вырастет…
Но — я бы язык тогда переименовал, а то выражение «умеешь ли писать на PHP» с годами будет означать очередную, новую итерацию языка, во многом отличную от старых — это создаст путаницу. А если подумать (а как без этого?) о совместимости со старым кодом, которого, все же, вагон и маленькая тележка (скажем прямо — из-за него про PHP и помнят), то нужен либо режим совместимости (в php.ini писать «mode=5.5», не к обеду будет PHP5.5 помянут), либо, и правда, язык назвать чем-то вроде NewPHP.sumanai
03.05.2018 14:32+1Зачем? PHP до версии 3 отличается от 4, 5 отличается от 7, и ничего, никаких новых названий не нужно, кроме факапа с 6 версией.
achekalin
03.05.2018 14:36кроме факапа с 6 версией
Ну вы же сами себе и противоречите. Впрочем, раз в 3 мажорные версии можно и потерпеть пару лет, как скажете. Шутка, лично мне это неприятно.
Другое дело, что в "новом", расширенном языке что делать — тянуть различия с третьей ветки (я про совместимость), или так и жить в режиме "у вас какая версия того, что вы называете PHP?" Минимум сбивает.sumanai
03.05.2018 15:15Ну вы же сами себе и противоречите.
Так название языка всё то же, просто версия, на которую возложили слишком много, получалась настолько плохой, что от неё решили отказаться заранее.
или так и жить в режиме «у вас какая версия того, что вы называете PHP?»
Я не вижу проблем в обслуживании кода на любой версии, а написание нового в любом случае лучше делать под последнюю.
FSA
03.05.2018 17:57Хочу сказать только то, что из PHP не обязательно делать язык со строгой типизацией. Достаточно только дать такую возможность.
А это не оно?
declare(strict_types=1);
Не знаю точно версию языка, где это появилось, но точно после 7.0
nezdhanov
04.05.2018 09:36Статья в принципе дает неплохую почву для собственных внутренних рассуждений по вечерам перед сном. Но хотел бы отдельно высказать свое мнение по поводу 9 пункта: на мой взгляд есть вещи исторические, те, которые придают языку свою элегантность, отличают его от других языков, делают неповторимым. Именно такие вещи на мой взгляд, как function, знак доллара перед переменной (или даже два знака доллара), его строки с двойными кавычками, и heredoc'и в которых может происходить мистика на первый взгляд неосвещенного человека, все это и многое другое и делает его именно тем языком, который мы знаем. И исчезновение подобных конструкций, зарезервированных слов и т. д. может смешать языки в одну массу, где в конце концов возможно будет выделяться один Brainfuck и то мало вероятно.
- Доступ к элементам объектов через
m03r
Вам сюда:
wiki.php.net/rfc/howto
php.net/get-involved.php
vtvz_ru Автор
Было бы все просто, если было бы все просто. RFC писать без предварительной реализации и без тестов не имеет особого смысла (там так и сказано). Я бы с удовольствием поддержал проект кодом. Но сколько времени займет изучение языка C и исследование внутренностей проекта, прежде чем я смогу написать что-то толковое? С учетом полной рабочей занятости, на это могут уйти годы...
Fesor
обычно на это предлагают скинуться толпой и нанять сишника что бы тот запилил. И в целом предложение весьма дельное, вот только основная проблема в том что бы пропихнуть фичу дальше. И тут не надо винить мэйнтейнеров — вы там наплодите много сишного кода а им мэйнтейнить это дело еще годами. потому каждая новая штука должна быть важна.
Но давайте вспомним почему в php нет вещей в статье:
->
для операций над скалярами) — нет и не будет потому что заведомо проигрышная штука. Она в разы проигрывает тому же pipe оператору в плане гибкости и сложности реализации. А то что люди "привыкли" — это вопрос к тому что нужно правильно людям подать идею что бы они забросили мертвые концепты. PHP на js, там нет прототипного наследования, манкипатчинг в php никто не хочет (и правильно делает), так что нечего.вот pipe оператор дело другое:
дженерики: сложна, существует RFC и даже существуют люди которые чето пилят и обещают нам дженерики в 8-ой версии. Но есть нюансы с описанием поведения дженериков (RFC не доконца проработана и уже слишком большая) + есть целая гильдия противников подобных вещей в php. Ну и главная проблема — то что php единственный язык из тех что я знаю который делает подобные проверки в рантайме. Это глупо и в целом только по этой причине реализация тех же дженериков усложняется на порядки (потому например мы не имеем тайпхинтинга для пропертей — была реализация но сделать без сущенственного оверхэда на рантайм не вышло).
Аннотации (а точнее это больше походит на атрибуты) — основная причина по которой несколько RFC загнулись — либо расхождение во взглядах (кто-то хочет декораторы а кому-то достаточно атрибутов), расхождения в поведении (влияние на рантайм), ну и просто очень плохо проработанная RFC и плохая подача в комьюнити. Ну и так все заглохло.
короткие функции напоролись на ограничения парсера. Символ
=>
уже занят в выражениях, как и->
, варианты из Hack (==>
) никому не понравились, вариантыfn($x) => $x **2
не нравятся потому что новый кейворд + нарушение обратной совместимости (кто-то уже может юзать функциюfn
). Ну и последние варианты опять же уперлись во вкусовщину.Было обсуждение ввести в php stackless корутины но вы можете юзать их и так через экстеншен. Да и решений для асинхронности полно.
С другой стороны среднестатистический php разработчик понятия не имеет как работает сборщик мусора и в целом весьма сильно полагается на модель "а оно потом умрет и все будет ок" что плохо совместимо со всей этой культурой. Все это делает фичи в духе асинхронности мало востребованными, ибо те кто хотят и так могут. Просто не так красиво и удобно.
Невозможно. Просто в силу того как реализован php. Ну то есть не то что бы невозможно, но сложно. Да и не очень то и нужно.
Тайпинг для переменных и пропертей — была даже реализация но как я писал выше — из-за любви к проверке типов в рантайме никто ради этой фичи не стал жертвовать 30% оверхэдом по рантайму.
наследие лет и ограничения лексера/парсера языка. Вроде как сейчас я не вижу особо проблем с тем что бы делать этот кейворд обязательным.
p.s. я не то что бы говорю что php обречен, а скорее предлагаю перестать ныть и надеяться на то что php станет тем языком который нам хочется видеть.
Есть проекты вроде preprocess.io которые решают все озвученные проблемы (либо минимизируют эффект), есть анализаторы вроде psalm, есть куча крутых решений проблем, есть language server в конце концов и возможность писать свои DSL и синтаксисы с транспайлом в php и совместимостью. Но нет, всем надо просто и из коробки.