[PHP] Какой могла бы быть Standard PHP Library

Автор Сообщение
news_bot ®

Стаж: 6 лет 9 месяцев
Сообщений: 27286

Создавать темы news_bot ® написал(а)
04-Апр-2021 21:31

Каждая статья с критикой PHP, следом за объяснением почему «$» в обозначении переменной портит синтаксис, обязательно расскажет вам о том, как плохо организовано именование функций в ядре и расширениях. И если «$» останется в стандарте языка и наших сердцах навсегда (хотя бы просто как напоминание о старом-добром PHP), то с именованием функций давно пора что-то делать.TLDR; Автор предлагает свои правила именования функций ядра PHP и распределение их по пространствам имен.Standard PHP LibraryПрежде всего, расскажу немного о той терминологической путанице, которую я намеренно ввожу в данной статье.Standard PHP Library (SPL) уже существует в качестве отдельного расширения. SPL предоставляет структуры данных, исключения, итераторы и многое другое, но к базовым функциям, например к функциям для работы со строками, никакого отношения не имеет. Они, на мой далёкий от устройства интерпретатора PHP взгляд, просто существуют где-то в ядре и являются как бы частью стандарта языка.Я считаю, что базовые функции следует выделить в отдельное расширение и самым подходящим для него названием стало бы именно Standard PHP Library.ПроблемыНедостатков в именовании функций и, в целом, в их организации много. Хрестоматийным примером являются функции для работы со строками, поэтому  далее рассматривать буду именно их.Наиболее заметные проблемы:
  • одновременно существуют несколько подходов к именованию: с префиксом «‎str_» (str_split), с префиксом «‎str» (strrev), с префиксом «‎substr_» (substr_compare), без какого-либо префикса (trim);
  • однородные функции имеют аргументы с разными именами, например, в strncmp два аргумента: «‎str1» и «‎str2», в strnatcasecmp: «‎string1» и «‎string2», а в substr_compare: «‎haystack» и «‎needle»;
  • однородные функции имеют разный порядок следования однородных же аргументов — все помнят историю про порядок аргументов в implode и explode;
  • совершенно нечитаемые и непроизносимые имена функций: strtr, strncmp, strpbrk, strrchr и т.д.;
  • некоторые функции могут менять тип возвращаемого значения в зависимости от типов переданных им аргументов, например, substr_replace непринужденно жонглирует массивами и строками;
  • зачастую функции возвращают false в случае ошибки или неверно заданных аргументов, например, strrpos;
  • некоторые функции выглядят довольно экзотично и используются крайне редко: soundex, levenshtein и т.д.
ПричиныНе берусь утверждать, что я точно знаю чем это вызвано. Хотя уверен, что мое предположение будет недалеко от истины. Все ошибки на проектах, застигнутых внезапной лавинообразной популярностью, объединяет одна причина — «‎так исторически сложилось».Никто не мог предположить, что продвинутый html-шаблонизатор станет едва ли не самым популярным языком для создания сайтов. А когда это все же случилось, то оказалось, что экосистема в десятки миллионов строк кода с большой неприязнью относится к изменениям интерпретатора, ломающим обратную совместимость.Я прекрасно понимаю, что функции есть и они успешно работают в огромном множестве проектов, а эстетика написания кода — дело десятое. Более того, я понимаю, что взять на себя ответственность за решение, которое, вероятно, оттолкнет от PHP часть старых и новых пользователей, довольно сложно. Так есть ли шансы? Я вижу некоторые робкие шаги в этом направлении, но пока нет ничего, что попало бы в релиз.Как бы это сделал я.
  • PHP 8.2 — создать и принять новый регламент об именовании функций и их аргументов;
  • PHP 8.3 — добавить новые функции согласно регламента, старые оставить в качестве псевдонимов, выпустить инструмент, который преобразует старые вызовы в новые;
  • PHP 9 — объявить старые функции deprecated, вынести новые и старые функции в отдельные расширения, при этом legacy расширение по умолчанию не будет идти в составе сборки,
  • PHP 10 — end of life для legacy расширения.
Учитывая, что между 7 и 8 версиями пролетело каких-то 5 лет, я думаю, что 10 лет экосистеме хватит на переход.Что я предлагаюВыделить функции из состава ядра в отдельные расширенияОтдельные расширения проще тестировать и их релизы можно выпускать отдельно от больших релизов языка. Здесь я ничего нового не скажу — преимущества модульности давно известны.Добавить пространства имен для расширенийДа, пространства имен нужны и для ядра, и для расширений. Довольно странно создавать стандарты, которые будут различаться для пользовательского кода и кода, предоставленного создателями языка. И если для ядра я еще могу представить корневое «‎\», то для расширений без них никак не обойтись. Я не буду выдумывать что-то новое и просто использую PSR-4. В качестве имени вендора очевидно следует использовать «‎Php», а дальше добавить имя расширения. Таким образом, будущие функции стандартной библиотеки будут в пространстве имен «‎Php\Spl».Договориться о правилах именования функций и аргументовСнова предлагаю существующие стандарты: частично использовать PSR-12 и частично правила именования функций от дядюшки Боба.
  • Имена функций не должны содержать какого-либо явного префикса расширения, в котором определены. Иными словами, не должно быть никаких  «‎str_» или «‎str», для этих целей служит пространство имен.
  • Имена функций и аргументов должны быть заданы в lowerCamelCase.
  • Имена функций должны быть читаемыми и содержать в себе явное описание выполняемого действия. Уместно использовать для этого некий глагол, а для функций возвращающих значения булева типа — префикс is.
  • Имена аргументов также должны быть читаемыми и содержать в себе явное описание передаваемых данных. Уместно использовать в качестве имен аргументов существительные.
  • Порядок и имена аргументов для однородных функций, например для функций сравнения строк, должны совпадать.
Включить строгую проверку типов данныхТут давно пора навести порядок. Например sscanf может возвращать массив, целочисленный результат или null. Я уверен, что взрослый язык может позволить себе согласовать типы аргументов и возвращаемых значений для функций стандартной библиотеки.Я во многом полагаюсь на  подсказки IDE и на статический анализ, а непредсказуемые типы сильно этому мешают и создают дополнительный шум в виде явных кастов или условных выражений.
  • Функции стандартной библиотеки должны использовать строгую проверку типов аргументов и возвращаемых значений.
  • Для аргументов и для возвращаемых значений должны быть явно указаны типы. Использование «‎mixed» недопустимо.
  • Для аргументов допустимо использовать union-типы и nullable-типы.
  • Возвращаемое значение должно иметь один явный тип или быть «‎null» там, где это оправданно.
  • В случае исключительной ситуации или неверно заданных аргументов функция должна выбрасывать одно из стандартных исключений с четким описанием проблемы или ошибки.
Практическая реализацияВ качестве proof of concept я создал библиотеку, которая следует всем правилам, указанным выше, и предлагает новые имена функций для работы со строками — https://github.com/marvin255/php-spl-proposal/blob/master/src/StringUtilities.php.Первый и главный вопрос реализации — использовать отдельные функции в пространстве имен или статические методы класса.Я решил использовать статические методы класса. Возможно, это не очень изящное решение, зато крайне удобное в быту: весь набор функций импортируется одной короткой строкой, с помощью IDE можно с легкостью посмотреть весь список функций только для работы со строками, механизм наследования пригодится для переопределения методов в фрэймворках и cms.Пара примеров для ознакомления.
strnatcmp(“test1”, “test2”);
// заменяется на
StringUtilities::compareUsingNaturalOrder(“test1”, “test2”);
str_contains(”test”, “t”);
// заменяется на
StringUtilities::isContain(”test”, “t”);
Символов стало больше и это может показаться минусом, но, на мой взгляд, в современном интерпретируемом языке читаемость метода важнее мнимой экономии. Соглашусь, что имена новых функций не везде подобраны удачно, но не судите строго — в конце концов это одна из главных проблем программирования.Интересно, что первоначально я использовал json файл, задающий соответствия между новыми именами и старыми, и специальный генератор для создания статических методов. К сожалению, он превратился в жуткого монстра, который молит о рефакторинге — так много было различных исключений и условий при конвертации. Решил его не публиковать.Вместо заключенияСтатья не претендует на какую-либо объективность. Более того, очевидно, что я не смог за пару вечеров исправить один из коренных недостатков PHP. Я вижу как данную проблему из релиза в релиз обходят стороной в погоне за новыми фичами и синтаксическим сахаром. Не подумайте, я не имею ничего против изменений, введенных в PHP 7 и 8, но и для возвращения технического долга нужно найти время.Своей статьей я хотел лишь спровоцировать диалог и заронить семена сомнений. Кто-то должен этим заняться и я уверен, что именно сообщество должно подтолкнуть мэйнтейнеров к мысли о неизбежности этих изменений.
===========
Источник:
habr.com
===========

Похожие новости: Теги для поиска: #_php, #_php, #_codestyle, #_php
Профиль  ЛС 
Показать сообщения:     

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

Текущее время: 22-Ноя 14:17
Часовой пояс: UTC + 5