Как часто вы сталкиваетесь с проблемой, когда для тестирования задачи приходится менять код? Тесты отложенной отправки письма, генерации чего-то по расписанию раз в неделю и т.д.
Badoo имеет свое собственное решение, которое упрощает жизнь тестировщикам.
Все тут:
https://telegra.ph/API-dlya-QA-testiruem-fichi-bez-dostupa-k-kodu-12-01
Badoo имеет свое собственное решение, которое упрощает жизнь тестировщикам.
Все тут:
https://telegra.ph/API-dlya-QA-testiruem-fichi-bez-dostupa-k-kodu-12-01
Telegraph
API для QA: тестируем фичи без доступа к коду
Многие фичи приложения невозможно быстро протестировать, не меняя исходный код. Представьте типичную задачу, с которой может столкнуться каждый разработчик: через три дня после регистрации пользователю нужно предложить купить премиум-доступ к продукту со…
Раньше, чтобы создать nullable ValueObject из nullable примитива, приходилось писать колбасу вроде
null === $stringClientId ? null : ClientId::fromString($stringClientId).
Сегодня условные типы Psalm позволяют перенести if в статический конструктор:
/**
* @template T of ?string
* @psalm-param T $id
* @psalm-return (T is null ? null : self)
*/
public static function fromString(?string $id): ?self
{
if (null === $id) {
return null;
}
Assert::uuid($id);
return new self($id);
}
ClientId::fromString($stringClientId)
https://psalm.dev/r/ab0090be4c
null === $stringClientId ? null : ClientId::fromString($stringClientId).
Сегодня условные типы Psalm позволяют перенести if в статический конструктор:
/**
* @template T of ?string
* @psalm-param T $id
* @psalm-return (T is null ? null : self)
*/
public static function fromString(?string $id): ?self
{
if (null === $id) {
return null;
}
Assert::uuid($id);
return new self($id);
}
ClientId::fromString($stringClientId)
https://psalm.dev/r/ab0090be4c
Обработка deadlock в Doctrine
Проблему взаимных блокировок в первую очередь надо решать исходя из контекста, где они возникают. Однако если дедлоки стреляют изредка, можно предусмотреть простой retry. Удобнее всего его реализовать как middleware для command bus и там поймать Doctrine\DBAL\Exception\RetryableException.
Помните, что после ошибки EntityManager закрывается. В Symfony его можно оживить вызовом метода resetManager() на сервисе @doctrine (автовайрится по интерфейсу Doctrine\Persistence\ManagerRegistry). После этого менеджер даже в извлеченном из контейнера сервисе не кинет The EntityManager is closed благодаря замене инициализатора в прокси.
Пример такого middleware для Symfony Messenger: https://gist.github.com/vudaltsov/945291b4e8a8800f669d478c8d66e8b8
Проблему взаимных блокировок в первую очередь надо решать исходя из контекста, где они возникают. Однако если дедлоки стреляют изредка, можно предусмотреть простой retry. Удобнее всего его реализовать как middleware для command bus и там поймать Doctrine\DBAL\Exception\RetryableException.
Помните, что после ошибки EntityManager закрывается. В Symfony его можно оживить вызовом метода resetManager() на сервисе @doctrine (автовайрится по интерфейсу Doctrine\Persistence\ManagerRegistry). После этого менеджер даже в извлеченном из контейнера сервисе не кинет The EntityManager is closed благодаря замене инициализатора в прокси.
Пример такого middleware для Symfony Messenger: https://gist.github.com/vudaltsov/945291b4e8a8800f669d478c8d66e8b8
Gist
DeadlockRetryMiddleware.php
GitHub Gist: instantly share code, notes, and snippets.
Оператор new в инициализаторах
https://wiki.php.net/rfc/new_in_initializers
Не прошло и недели после стрима, как Никита Попов опубликовал обещанный RFC, разрешающий использовать new в инициализаторах.
Если его примут, то в качестве дефолтных значений статических переменных, параметров, констант и свойств можно будет использовать объекты.
Интересно, что в рамках этого предложения атрибуты тоже получат право использовать объекты. В частности, это позволит оформлять атрибутами композитные констрейнты Symfony Validator (#38503).
https://github.com/php/php-src/pull/6746
https://wiki.php.net/rfc/new_in_initializers
Не прошло и недели после стрима, как Никита Попов опубликовал обещанный RFC, разрешающий использовать new в инициализаторах.
Если его примут, то в качестве дефолтных значений статических переменных, параметров, констант и свойств можно будет использовать объекты.
Интересно, что в рамках этого предложения атрибуты тоже получат право использовать объекты. В частности, это позволит оформлять атрибутами композитные констрейнты Symfony Validator (#38503).
https://github.com/php/php-src/pull/6746
Как получить все типы значения
Для примитивов всё просто — в PHP 8 теперь есть функция get_debug_type, она возвращает тип в привычном формате.
В случае объекта помимо класса нужно вернуть список суперклассов (умное название для родительских) и интерфейсов. Проще всего их добыть встроенными функциями class_parents и class_implements.
Что касается порядка отдаваемых типов, как правило, требуется сортировка от конкретных к абстрактным. Например, при поиске обработчика значения по типу имеет смысл сначала запросить узкоспециальный обработчик, а затем — универсальный.
https://3v4l.org/DFuO8
Для примитивов всё просто — в PHP 8 теперь есть функция get_debug_type, она возвращает тип в привычном формате.
В случае объекта помимо класса нужно вернуть список суперклассов (умное название для родительских) и интерфейсов. Проще всего их добыть встроенными функциями class_parents и class_implements.
Что касается порядка отдаваемых типов, как правило, требуется сортировка от конкретных к абстрактным. Например, при поиске обработчика значения по типу имеет смысл сначала запросить узкоспециальный обработчик, а затем — универсальный.
https://3v4l.org/DFuO8
Аргумент "непустой индексный массив строк" на чистом PHP и с использованием Psalm:
function native(string $name, string ...$names): void
{
foreach ([$name, ...$names] as $name) {
// ...
}
}
/**
* @psalm-param non-empty-list<string> $names
*/
function psalm(array $names): void
{
foreach ($names as $name) {
// ...
}
}
Оба варианта по-своему интересны, выбирайте исходя из типичного контекста использования функции/метода.
Если аргументы объявляются при вызове, я советую использовать оператор ... Например, в билдере SQL запросов колонки удобнее передавать аргументами:
$db
->select('respondent_id', 'value')
->from('evaluation')
В остальных случаях передаваемое значение скорее всего уже будет "на руках" в виде списка, поэтому аргумент лучше объявить массивом.
function native(string $name, string ...$names): void
{
foreach ([$name, ...$names] as $name) {
// ...
}
}
/**
* @psalm-param non-empty-list<string> $names
*/
function psalm(array $names): void
{
foreach ($names as $name) {
// ...
}
}
Оба варианта по-своему интересны, выбирайте исходя из типичного контекста использования функции/метода.
Если аргументы объявляются при вызове, я советую использовать оператор ... Например, в билдере SQL запросов колонки удобнее передавать аргументами:
$db
->select('respondent_id', 'value')
->from('evaluation')
В остальных случаях передаваемое значение скорее всего уже будет "на руках" в виде списка, поэтому аргумент лучше объявить массивом.
Единственный правильный способ прокинуть логгер ☝️
Что не так с LoggerAware* костылями:
• LoggerAwareInterface делает дыру в сервисе методом setLogger. Да и как контракт он абсолютно бесполезен.
• В LoggerAwareTrait свойство logger, что бы ни говорил phpdoc, имеет значение по умолчанию null и, соответственно, nullable тип. Значит его либо нужно всегда проверять if ($this->logger !== null), либо как в сниппете инициализировать в конструкторе пустым логгером, только уже не в качестве фоллбэка, а превентивно. В любом случае код получится более сложным и менее очевидным.
PSR-3 я также комментировал в среду на стриме про трейты: https://youtu.be/xoEPNiMtVps?t=4069.
Что не так с LoggerAware* костылями:
• LoggerAwareInterface делает дыру в сервисе методом setLogger. Да и как контракт он абсолютно бесполезен.
• В LoggerAwareTrait свойство logger, что бы ни говорил phpdoc, имеет значение по умолчанию null и, соответственно, nullable тип. Значит его либо нужно всегда проверять if ($this->logger !== null), либо как в сниппете инициализировать в конструкторе пустым логгером, только уже не в качестве фоллбэка, а превентивно. В любом случае код получится более сложным и менее очевидным.
PSR-3 я также комментировал в среду на стриме про трейты: https://youtu.be/xoEPNiMtVps?t=4069.
Как избавиться от лишних неявных зависимостей 🧹
Рассмотрим классический пример про полифилы. Symfony Console версии 5.1 использует функцию is_countable, которая появилась в PHP 7.3. Чтобы поддерживать PHP 7.2, пакет требует полифил symfony/polyfill-php73. Поэтому когда мы устанавливаем symfony/console в проекте с PHP 7.4, мы получаем не только компонент, но и полифил PHP 7.3, который нам, очевидно, не нужен.
Чтобы его удалить, нужно в composer.json в разделе replace прописать "symfony/polyfill-php73": "*" и выполнить update. Аналогично можно убрать полифилы расширений PHP, предварительно гарантировав их наличие через require ext-<name> (см. сниппет).
ComposerRequireChecker (на страже в CI) поможет не увлечься и не удалить лишние пакеты. Он проверит, что все используемые в проекте символы (функции, константы и классы) содержатся в зависимостях, явно прописанных в require.
В сниппете фрагменты composer.json из нашего проекта в Happy Inc.
Рассмотрим классический пример про полифилы. Symfony Console версии 5.1 использует функцию is_countable, которая появилась в PHP 7.3. Чтобы поддерживать PHP 7.2, пакет требует полифил symfony/polyfill-php73. Поэтому когда мы устанавливаем symfony/console в проекте с PHP 7.4, мы получаем не только компонент, но и полифил PHP 7.3, который нам, очевидно, не нужен.
Чтобы его удалить, нужно в composer.json в разделе replace прописать "symfony/polyfill-php73": "*" и выполнить update. Аналогично можно убрать полифилы расширений PHP, предварительно гарантировав их наличие через require ext-<name> (см. сниппет).
ComposerRequireChecker (на страже в CI) поможет не увлечься и не удалить лишние пакеты. Он проверит, что все используемые в проекте символы (функции, константы и классы) содержатся в зависимостях, явно прописанных в require.
В сниппете фрагменты composer.json из нашего проекта в Happy Inc.
При помощи Generator::valid() можно проверить генератор на пустоту, не обходя его целиком.
После вызова $generator->valid() функция генератора начинает выполнение и доходит либо до первого yield (тогда valid возвращает true), либо до конца (valid возвращает false). Интересно, что в первом случае на генераторе можно вызвать rewind без каких-либо последствий, так как обход ещё не начался. Во втором случае генератор закрывается и обойти его уже нельзя.
Сравните: https://3v4l.org/LL8E9 и https://3v4l.org/jni5Y.
После вызова $generator->valid() функция генератора начинает выполнение и доходит либо до первого yield (тогда valid возвращает true), либо до конца (valid возвращает false). Интересно, что в первом случае на генераторе можно вызвать rewind без каких-либо последствий, так как обход ещё не начался. Во втором случае генератор закрывается и обойти его уже нельзя.
Сравните: https://3v4l.org/LL8E9 и https://3v4l.org/jni5Y.
Фронт для прожженного бэка
Всем привет. Данный пост подойдет новичкам, или прожженным бэкендерам, которым проще написать на го или джаве, чем на js/css. Когда вообще появилось это разделение на Front и Back? Только только у нас в команде был верстальщик, который особо и программистом то не выглядел, и вот вдруг React, Angular, TypeScript, а кто не успел - теперь Backend разработчик.
Так что делать, если ты бэкэнд до мозга костей, а пет проект, под капотом выглядящий великолепно(нет), с фронта похож на сайты из 2000х?
1. Twitter bootstrap. Содержит множество полезных симпатичных элементов из коробки. И хоть фронты сейчас начнут кидаться ссаными тапками (и тряпками), потому что бутстрап - это только скелет, лэйаут, грид, etc на котором нужно строить свое приложение, но для нас это просто палочка-выручалочка, если нужно придать человеческий вид своему детищу.
2. Vue JS Если надоело писать говнокод на jQuery для того, чтобы например показать форму редактирования прямо на строке в гриде, и после того как все заработало от одного вида этого куска кхм хочется принять валокордин - есть великолепная припарка - Vue JS.
Он выглядит так, как будто он написан бэкэндерами для бэкэндеров, чтобы последние хоть как-то могли похвастаться тем, что знают js фреймворк, и гордо называть себя full stackами. В нем нет этого бардака jquery, и нет тонн синтаксического сахара и абстракций type script. Все бесподобно просто и понятно, как php, и приправлено отличной подробной докой.
3. А для тех, кому нужно и то и то - вот bootstrap-vue.org
Сам не пробовал, но раз поддерживаются последние версии и того и другого - значит проект живой и свежий.
Эхх, за что я любил Yii 1 в лохматом 2012 - так это за коробочный неплохой внешний вид, и включение аякса на гриде одним параметром. Теперь такого не делают))
Вместо послесловия
Ну и раз зашел разговор про сервера: я давно забил на хостинги. По цене они не намного выигрывают у vds/vps а ограничений масса. Да и я считаю что каждый уважающий себя php разработчик должен уметь развернуть php+nginx+db на чистой машине, ну и прекрасно знать что такое ssh, sudo, и почему нельзя запускать nginx под рутом.
Так вот, я уже лет 7 пользуюсь digitalOcean, 5$ в месяц и все мои пет-проекты прекрасно живут на выделенной виртуалке. И по этому случаю держите реферальную ссылку https://m.do.co/c/a2a1a8f9796f , которая не только мне согреет лапу, но и даст вам 100$ на 60 дней потестить и решить, нужно ли оно вам вообще. Они зажмыдились, раньше давали 25$ навсегда (а это, на минуточку, 5 месяцев халявного пятибаксового сервера) а сейчас 100$ но всего на 2 месяца, но это ж все-таки лучше, чем ничего))
Добавил реакции, хочу получить фидбэк, полезно ли, или больше такое не писать.
Всем привет. Данный пост подойдет новичкам, или прожженным бэкендерам, которым проще написать на го или джаве, чем на js/css. Когда вообще появилось это разделение на Front и Back? Только только у нас в команде был верстальщик, который особо и программистом то не выглядел, и вот вдруг React, Angular, TypeScript, а кто не успел - теперь Backend разработчик.
Так что делать, если ты бэкэнд до мозга костей, а пет проект, под капотом выглядящий великолепно(нет), с фронта похож на сайты из 2000х?
1. Twitter bootstrap. Содержит множество полезных симпатичных элементов из коробки. И хоть фронты сейчас начнут кидаться ссаными тапками (и тряпками), потому что бутстрап - это только скелет, лэйаут, грид, etc на котором нужно строить свое приложение, но для нас это просто палочка-выручалочка, если нужно придать человеческий вид своему детищу.
2. Vue JS Если надоело писать говнокод на jQuery для того, чтобы например показать форму редактирования прямо на строке в гриде, и после того как все заработало от одного вида этого куска кхм хочется принять валокордин - есть великолепная припарка - Vue JS.
Он выглядит так, как будто он написан бэкэндерами для бэкэндеров, чтобы последние хоть как-то могли похвастаться тем, что знают js фреймворк, и гордо называть себя full stackами. В нем нет этого бардака jquery, и нет тонн синтаксического сахара и абстракций type script. Все бесподобно просто и понятно, как php, и приправлено отличной подробной докой.
3. А для тех, кому нужно и то и то - вот bootstrap-vue.org
Сам не пробовал, но раз поддерживаются последние версии и того и другого - значит проект живой и свежий.
Эхх, за что я любил Yii 1 в лохматом 2012 - так это за коробочный неплохой внешний вид, и включение аякса на гриде одним параметром. Теперь такого не делают))
Вместо послесловия
Ну и раз зашел разговор про сервера: я давно забил на хостинги. По цене они не намного выигрывают у vds/vps а ограничений масса. Да и я считаю что каждый уважающий себя php разработчик должен уметь развернуть php+nginx+db на чистой машине, ну и прекрасно знать что такое ssh, sudo, и почему нельзя запускать nginx под рутом.
Так вот, я уже лет 7 пользуюсь digitalOcean, 5$ в месяц и все мои пет-проекты прекрасно живут на выделенной виртуалке. И по этому случаю держите реферальную ссылку https://m.do.co/c/a2a1a8f9796f , которая не только мне согреет лапу, но и даст вам 100$ на 60 дней потестить и решить, нужно ли оно вам вообще. Они зажмыдились, раньше давали 25$ навсегда (а это, на минуточку, 5 месяцев халявного пятибаксового сервера) а сейчас 100$ но всего на 2 месяца, но это ж все-таки лучше, чем ничего))
Добавил реакции, хочу получить фидбэк, полезно ли, или больше такое не писать.
Digitalocean
DigitalOcean | Cloud Infrastructure for Developers
An ocean of simple, scalable cloud solutions.
Функция для получения всех типов класса
Такая функция потребовалась мне для поиска обработчика объекта по типу. Генератор здесь позволяет не рефлексировать раньше времени.
https://3v4l.org/EOPjm
Такая функция потребовалась мне для поиска обработчика объекта по типу. Генератор здесь позволяет не рефлексировать раньше времени.
https://3v4l.org/EOPjm
Вконтакте снова выложил свой движок KPHP.
Все подробности тут
https://telegra.ph/VKontakte-snova-vykladyvaet-KPHP-12-01
Все подробности тут
https://telegra.ph/VKontakte-snova-vykladyvaet-KPHP-12-01
Telegraph
ВКонтакте снова выкладывает KPHP
Привет! Сейчас будет дежавю. Мы снова выложили на GitHub наш PHP-компилятор — KPHP. Он проделал большой путь, и чтобы рассказать о нём, сначала телепортируемся на шесть лет назад. Поясню для тех, кто не в теме: платформа ВКонтакте изначально была написана…