Forwarded from Библиотека задач по PHP | тесты, код, задания
Какой признак характерен для архитектуры CQRS?
Anonymous Quiz
13%
Разделение клиентской и серверной частей
82%
Разделение команд (изменений) и запросов (чтения)
3%
Использование одного сервиса для чтения и записи
2%
Отказ от реактивщины
🥱7👍1🔥1
Стандартный ответ — «потому что in-memory». Это правда, но не объяснение. Куча баз данных хранит данные в памяти и не показывает таких цифр. Настоящий ответ в другом: каждое архитектурное решение Redis убирает конкретный источник latency.
🧵 Один поток
Redis обрабатывает команды последовательно в один поток. Никаких мьютексов, никакого context switching. Тысячи соединений при этом обслуживаются через epoll/kqueue — один поток следит за всеми сокетами через I/O multiplexing и не блокируется ни на одном из них.
📦 Адаптивные структуры
Hash с небольшим числом ключей хранится не как хэш-таблица, а как listpack — плотный байтовый массив, который влезает в один cache line. Никаких pointer chasing. Только когда данных становится много, Redis переключается на полноценную хэш-таблицу. Sorted Set — одновременно хэш-таблица и skiplist. O(1) по ключу и O(log N) для range-запросов без второго прохода.
💾 fork()
Снапшот RDB пишется дочерним процессом после fork(). Благодаря CoW основной процесс продолжает работу и не видит никакой паузы — ОС копирует только изменённые страницы памяти. AOF идёт дальше и логирует каждую команду, давая возможность восстановиться до последней записи. Точнее, но дороже — компромисс осознанный.
🧹 bounded expiry
Ключи с истёкшим TTL удаляются двумя способами: лениво при обращении и активно — каждые 100 мс Redis сэмплирует случайную выборку и чистит просроченные. Если таких больше 25%, повторяет цикл. Это не O(N) по всей базе, а предсказуемая нагрузка с жёстким потолком по CPU.
Redis — это не «база данных в памяти». Это система, где каждый выбор — однопоток, listpack, fork(), bounded expiry — существует потому, что альтернатива добавляла latency. In-memory здесь просто необходимое условие, а не причина скорости.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12👍5❤1
Классика: у тебя Value Object с readonly-свойствами, и нужно вернуть копию с одним изменённым полем. До 8.4 приходилось делать фабричный метод вручную:
class Money {
public function __construct(
public readonly int $amount,
public readonly string $currency,
) {}
public function withAmount(int $amount): static
{
return new static($amount, $this->currency);
}
}В PHP 8.4 появился clone with:
$price = new Money(1000, 'USD');
$discounted = clone $price with {
amount: 850,
};
Никаких withField() методов на каждый чих. clone with работает даже с readonly — это единственное место, где PHP позволяет их «изменить» без рефлексии.
#vardump
Please open Telegram to view this post
VIEW IN TELEGRAM
😁9👍6❤2🔥2👾1
🔥 Laravel Facades красота или костыль?
Скрытые зависимости, нарушение SRP, привязка к фреймворку через __callStatic() — звучит страшно. Но 64% PHP-девов используют Laravel и не парятся.
Как пишете вы, Facades или DI? И считаете ли, что Тейлор красиво «продал» антипаттерн?
💬 Пишите ваше мнение в комментарии
#междусобойчик
// Читаемо и быстро
Cache::get('user:' . $id);
// Явно и тестируемо
public function __construct(
private CacheInterface $cache,
) {}
Скрытые зависимости, нарушение SRP, привязка к фреймворку через __callStatic() — звучит страшно. Но 64% PHP-девов используют Laravel и не парятся.
Как пишете вы, Facades или DI? И считаете ли, что Тейлор красиво «продал» антипаттерн?
#междусобойчик
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5😁3🌚1
Forwarded from Библиотека собеса по PHP | вопросы с собеседований
Код прошёл нагрузочное тестирование. На проде деньги задвоились 👇
📦 Задание
Фича: пользователь может переводить бонусные баллы другу. Логика простая — проверить баланс, списать, начислить. Тесты зелёные, нагрузочное прогнали — всё ок. Через три дня после релиза: у нескольких пользователей баланс ушёл в минус, у других — задвоился.
// src/Bonus/BonusTransferService.php
class BonusTransferService
{
public function __construct(
private PDO $pdo,
private BonusRepository $repo,
) {}
public function transfer(int $fromId, int $toId, int $amount): void
{
$this->pdo->beginTransaction();
try {
$fromBalance = $this->repo->getBalance($fromId);
if ($fromBalance < $amount) {
throw new InsufficientFundsException();
}
$this->repo->debit($fromId, $amount);
$this->repo->credit($toId, $amount);
$this->pdo->commit();
} catch (Throwable $e) {
$this->pdo->rollBack();
throw $e;
}
}
}
// src/Bonus/BonusRepository.php
class BonusRepository
{
public function __construct(private PDO $pdo) {}
public function getBalance(int $userId): int
{
$stmt = $this->pdo->prepare(
'SELECT balance FROM bonus_accounts WHERE user_id = ?'
);
$stmt->execute([$userId]);
return (int) $stmt->fetchColumn();
}
public function debit(int $userId, int $amount): void
{
$stmt = $this->pdo->prepare(
'UPDATE bonus_accounts SET balance = balance - ? WHERE user_id = ?'
);
$stmt->execute([$amount, $userId]);
}
public function credit(int $userId, int $amount): void
{
$stmt = $this->pdo->prepare(
'UPDATE bonus_accounts SET balance = balance + ? WHERE user_id = ?'
);
$stmt->execute([$amount, $userId]);
}
}
🔹 Задачи
— Объяснить, как именно происходит race condition в этом коде
— Почему транзакция здесь не защищает от проблемы
— Исправить getBalance так, чтобы устранить race condition
Ставьте → 🔥 если нравится формат. Если нет → 🌚
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11❤4👍1
🤔 Разрабатываете ИИ-агентов, но всё ещё не уверены в их стабильности и прогнозируемости?
Мы поговорили с десятками разработчиков ИИ-агентов и сделали отдельный курс по AgentOps.
🧠 На нём вы узнаете:
– как оптимизировать траты на токены;
– как на практике оценить качество работы агента;
– как «докручивать» RAG-системы без потери качества;
– как обеспечить устойчивость агента к сбоям внешних сервисов без падения всей системы и про многое-многое другое.
📅 Старт: 19 мая.
👥 Спикеры — практики с опытом в AI и Data Science в крупных IT-компаниях, таких как Яндекс, Huawei, МТС и др.
Длительность: 6-12 недель в зависимости от тарифа.
🔗 Программа курса и другие подробности
Мы поговорили с десятками разработчиков ИИ-агентов и сделали отдельный курс по AgentOps.
🧠 На нём вы узнаете:
– как оптимизировать траты на токены;
– как на практике оценить качество работы агента;
– как «докручивать» RAG-системы без потери качества;
– как обеспечить устойчивость агента к сбоям внешних сервисов без падения всей системы и про многое-многое другое.
📅 Старт: 19 мая.
👥 Спикеры — практики с опытом в AI и Data Science в крупных IT-компаниях, таких как Яндекс, Huawei, МТС и др.
Длительность: 6-12 недель в зависимости от тарифа.
🔗 Программа курса и другие подробности
🤯 Представьте, что ваш AI-агент работает так же предсказуемо, как обычный микросервис. Звучит утопически, но это именно то, к чему должна прийти разработка в 2026 году.
Основная боль текущих реализаций — полная непредсказуемость поведения. Сегодня агент выполнил задачу за два шага, а завтра ушёл в рекурсию и потратил все лимиты.
Наш обновлённый курс «Разработка AI-агентов» научит, как приручить этот хаос с помощью
✅ Что вы получите:
— понимание того, как управлять логикой агента на уровне кода;
— навыки работы с
— готовые паттерны для обработки ошибок и галлюцинаций;
— опыт создания систем, которые реально экономят время.
Есть пара мест со скидкой до завтра, решайтесь 👈🏻
Основная боль текущих реализаций — полная непредсказуемость поведения. Сегодня агент выполнил задачу за два шага, а завтра ушёл в рекурсию и потратил все лимиты.
Наш обновлённый курс «Разработка AI-агентов» научит, как приручить этот хаос с помощью
Python и современных фреймворков. Мы не будем учить «общаться» с нейросетью, мы будем строить из неё надёжный инструмент.✅ Что вы получите:
— понимание того, как управлять логикой агента на уровне кода;
— навыки работы с
LangChain и библиотеками оркестрации;— готовые паттерны для обработки ошибок и галлюцинаций;
— опыт создания систем, которые реально экономят время.
Есть пара мест со скидкой до завтра, решайтесь 👈🏻
🥱5❤1
🐳 Фишка Docker CLI
Запустите docker stats с правильными флагами, и вы увидите всё в реальном времени.
🔹 Зачем это нужно
— Показывает live-метрики по CPU, памяти, сети и I/O для всех запущенных контейнеров.
— Критично для Java-сервисов: помогает поймать утечки памяти, GC pressure и неожиданный CPU spike прямо в момент нагрузки.
— Работает без установки каких-либо агентов.
— В отличие от top внутри контейнера видит реальные лимиты cgroup, а не ресурсы хоста.
🔹 Как использовать
— Все контейнеры в реальном времени:
— Конкретный сервис:
— Один снимок без стриминга:
— Только нужные поля:
— В JSON для скриптов:
Флаг --format принимает Go-шаблоны — те же, что и в docker inspect. Можно вывести ровно то, что нужно, и скормить в jq или свой мониторинг-скрипт.
⚠️ Если контейнер запущен без -m / --memory, JVM видит всю память хоста и выставляет heap соответственно. docker stats мгновенно покажет, есть ли лимит — колонка MEM USAGE / LIMIT.
Запустите docker stats с правильными флагами, и вы увидите всё в реальном времени.
🔹 Зачем это нужно
— Показывает live-метрики по CPU, памяти, сети и I/O для всех запущенных контейнеров.
— Критично для Java-сервисов: помогает поймать утечки памяти, GC pressure и неожиданный CPU spike прямо в момент нагрузки.
— Работает без установки каких-либо агентов.
— В отличие от top внутри контейнера видит реальные лимиты cgroup, а не ресурсы хоста.
🔹 Как использовать
— Все контейнеры в реальном времени:
docker stats— Конкретный сервис:
docker stats my-spring-app— Один снимок без стриминга:
docker stats --no-stream— Только нужные поля:
docker stats --format "table {{.Name}}\t{{.MemUsage}}\t{{.CPUPerc}}"— В JSON для скриптов:
docker stats --no-stream --format jsonФлаг --format принимает Go-шаблоны — те же, что и в docker inspect. Можно вывести ровно то, что нужно, и скормить в jq или свой мониторинг-скрипт.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤1🔥1
Пока одни продолжают спорить «нужен ли AI в разработке», другие уже автоматизируют рутину через цепочки специализированных агентов — и делают это прямо в PHP-проектах.
Свежая статья на Хабре от PHP-разработчика, который прошёл путь от «AI неудобен» до полноценного пайплайна с оркестрацией агентов в продакшене.
Что внутри:
— Почему один большой промпт не работает, и как принцип "один агент — одна ответственность" решает проблему размытия контекста
— Как выстроить цепочку: php-developer → phpstan-developer → php-test-developer → авто-фиксер — каждый в своём чистом контексте
— Specification-Driven Development на практике: спека первична, код вторичен
— Реальный опыт с Claude Code, RooCode, KiloCode — с честными плюсами и минусами
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6👍1🔥1😁1🥱1
🔥 Настройка Pest PHP
Если ты всё ещё пишешь тесты на чистом PHPUnit с setUp() и простынями $this->assert... — этот пост для тебя. Настраиваем Pest с нуля в реальном Laravel-проекте.
📦 Шаг 1 — Установка
После этого в корне появится tests/Pest.php — файл для глобальных хелперов и настроек. Не игнорируй его.
✍️ Шаг 2 — Первый тест
Забудь про классы. Pest — это функции:
🧩 Шаг 3 — Datasets (параметризованные тесты)
Вместо копипасты одного теста на каждый кейс:
⚙️ Шаг 4 — Глобальные настройки в Pest.php
Открываем tests/Pest.php и настраиваем раз и навсегда:
Теперь RefreshDatabase не нужно писать в каждом файле, а кастомные матчеры делают тесты выразительнее.
🚀 Шаг 5 — Запуск
💡 Почему Pest, а не чистый PHPUnit?
Меньше бойлерплейта, человекочитаемый вывод, встроенные архитектурные тесты (arch()) и отличная интеграция с Laravel. Команда Laravel официально рекомендует его с 11-й версии фреймворка.
Ставьте 🔥 если используете Pest.
Если ты всё ещё пишешь тесты на чистом PHPUnit с setUp() и простынями $this->assert... — этот пост для тебя. Настраиваем Pest с нуля в реальном Laravel-проекте.
📦 Шаг 1 — Установка
composer require pestphp/pest --dev
composer require pestphp/pest-plugin-laravel --dev
php artisan pest:install
После этого в корне появится tests/Pest.php — файл для глобальных хелперов и настроек. Не игнорируй его.
✍️ Шаг 2 — Первый тест
Забудь про классы. Pest — это функции:
it('создаёт пользователя через API', function () {
$response = $this->postJson('/api/users', [
'name' => 'Ivan',
'email' => 'ivan@example.com',
]);
$response->assertCreated();
expect($response->json('data.name'))->toBe('Ivan');
});🧩 Шаг 3 — Datasets (параметризованные тесты)
Вместо копипасты одного теста на каждый кейс:
it('валидирует email', function (string $email) {
$response = $this->postJson('/api/users', [
'email' => $email
]);
$response->assertUnprocessable();
})->with([
'пустой' => [''],
'без собаки' => ['notanemail'],
'только домен' => ['@example.com'],
]);⚙️ Шаг 4 — Глобальные настройки в Pest.php
Открываем tests/Pest.php и настраиваем раз и навсегда:
uses(
Tests\TestCase::class,
Illuminate\Foundation\Testing\RefreshDatabase::class,
)->in('Feature');
expect()->extend('toBeSuccess', function () {
return $this->toMatchArray([
'status' => 'success'
]);
});
Теперь RefreshDatabase не нужно писать в каждом файле, а кастомные матчеры делают тесты выразительнее.
🚀 Шаг 5 — Запуск
./vendor/bin/pest
./vendor/bin/pest --filter="создаёт пользователя"
./vendor/bin/pest --coverage # требует Xdebug или PCOV
Меньше бойлерплейта, человекочитаемый вывод, встроенные архитектурные тесты (arch()) и отличная интеграция с Laravel. Команда Laravel официально рекомендует его с 11-й версии фреймворка.
Ставьте 🔥 если используете Pest.
Please open Telegram to view this post
VIEW IN TELEGRAM
🥱11🔥6❤1👍1😁1
🐳 Фишка Docker CLI
Контейнер запустился, но ведёт себя странно — не то сетевое окружение, не те переменные, непонятно что вообще внутри? Просто запустите docker inspect, и у вас будет полная картина без лишних инструментов.
🔹 Зачем это нужно
— Возвращает полный JSON с внутренностями: переменные окружения, тома, сетевые настройки, лимиты ресурсов, entrypoint, restart policy.
— Работает не только с контейнерами — понимает образы, тома и сети.
— Незаменимо, когда нужно быстро понять, почему контейнер ведёт себя не так, как ожидается.
🔹 Как использовать
— Полный дамп:
— Только IP-адрес:
— Все переменные окружения:
— Смонтированные тома:
Флаг -f принимает Go-шаблоны — вытащите ровно то поле, которое нужно, без парсинга тысячи строк JSON вручную.
Контейнер запустился, но ведёт себя странно — не то сетевое окружение, не те переменные, непонятно что вообще внутри? Просто запустите docker inspect, и у вас будет полная картина без лишних инструментов.
🔹 Зачем это нужно
— Возвращает полный JSON с внутренностями: переменные окружения, тома, сетевые настройки, лимиты ресурсов, entrypoint, restart policy.
— Работает не только с контейнерами — понимает образы, тома и сети.
— Незаменимо, когда нужно быстро понять, почему контейнер ведёт себя не так, как ожидается.
🔹 Как использовать
— Полный дамп:
docker inspect my-container— Только IP-адрес:
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' my-container— Все переменные окружения:
docker inspect -f '{{range .Config.Env}}{{println .}}{{end}}' my-container— Смонтированные тома:
docker inspect -f '{{json .Mounts}}' my-container | jqФлаг -f принимает Go-шаблоны — вытащите ровно то поле, которое нужно, без парсинга тысячи строк JSON вручную.
❤4🔥3👍2
Forwarded from Библиотека задач по PHP | тесты, код, задания
Какова временная сложность сортировки слиянием (Merge Sort) в худшем случае?
Anonymous Quiz
17%
O(log n)
34%
O(n^2)
10%
O(n)
39%
O(n log n)
🔥3👍1🥱1
⚡️ array_walk и внешний контекст
Многие не используют третий аргумент array_walk — а зря.
Третий аргумент — проброс внешних данных прямо в коллбэк. Не нужен use, не нужна глобальная переменная.
Читается чище, зависимости явные и сразу видно, что коллбэк работает с $discounts.
🐸 Библиотека пхпшника
#vardump
Многие не используют третий аргумент array_walk — а зря.
$discounts = ['vip' => 0.3, 'regular' => 0.1];
$prices = ['vip' => 1000, 'regular' => 500];
array_walk($prices, function (&$price, $key, $discounts) {
$price -= $price * ($discounts[$key] ?? 0);
}, $discounts);
// ['vip' => 700, 'regular' => 450]
Третий аргумент — проброс внешних данных прямо в коллбэк. Не нужен use, не нужна глобальная переменная.
Читается чище, зависимости явные и сразу видно, что коллбэк работает с $discounts.
#vardump
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2👍1
🤔 Repository в Laravel: паттерн или антипаттерн?
Eloquent — это Active Record. Когда ты оборачиваешь его в репозиторий и возвращаешь User::where(...)->get(), ты не абстрагируешься от ORM. Ты просто перекладываешь Eloquent в другой класс.
Настоящий репозиторий возвращает доменные объекты, а не модели с методами ->save() и ->delete().
💬 Что думаете?
🐸 Библиотека пхпшника
#междусобойчик
Eloquent — это Active Record. Когда ты оборачиваешь его в репозиторий и возвращаешь User::where(...)->get(), ты не абстрагируешься от ORM. Ты просто перекладываешь Eloquent в другой класс.
Настоящий репозиторий возвращает доменные объекты, а не модели с методами ->save() и ->delete().
#междусобойчик
Please open Telegram to view this post
VIEW IN TELEGRAM
👏5👍3😁1
🦾 Надоело чинить «упавших» ИИ-агентов после каждого микросбоя внешних сервисов?
Анонсируем старт продаж большого курса по AgentOps. Мы собрали опыт десятков разработчиков и сделали программу, которая учит выводить ИИ в стабильный прод.
🗓 Ждем вас 28 апреля в 19:00 МСК на эфире: «Как эффективно управлять контекстным окном LLM в мультиагентных системах и не сливать бюджет на токены».
👉 Кто вещает и в чем польза?
Спикер Кирилл Кухарев (Senior AI Engineer в Raft, спикер AI Conf и Highload++). Он реализовал более 50 коммерческих проектов в GenAI и на вебинаре покажет, как взять под контроль работу нескольких агентов, чтобы они не перекидывали друг другу лишний контекст и не сжигали ваши деньги.
В прямом эфире разберем:
• Как формируется контекст в LLM при маршрутизации между агентами;
• Куда утекают лишние токены и возникает перерасход;
• Практические методы: как сжимать историю, грамотно делить задачи, лимитировать передачу контекста и собирать промпты прямо в процессе запроса пользователя.
🔥 Два способа получить максимум:
1. Приходите на вебинар 28 апреля. Дарим участникам промокод на 5.000 ₽ (работает 3 дня после эфира - это шанс забрать курс по самому низу рынка).
2. Выбирайте Инженерный трек. В подарок к нему идет полный доступ к записям и автопроверкам завершенного курса «Разработка ИИ-агентов».
👉 Занять место на вебинаре и стать профи в AgentOps
Анонсируем старт продаж большого курса по AgentOps. Мы собрали опыт десятков разработчиков и сделали программу, которая учит выводить ИИ в стабильный прод.
🗓 Ждем вас 28 апреля в 19:00 МСК на эфире: «Как эффективно управлять контекстным окном LLM в мультиагентных системах и не сливать бюджет на токены».
Спикер Кирилл Кухарев (Senior AI Engineer в Raft, спикер AI Conf и Highload++). Он реализовал более 50 коммерческих проектов в GenAI и на вебинаре покажет, как взять под контроль работу нескольких агентов, чтобы они не перекидывали друг другу лишний контекст и не сжигали ваши деньги.
В прямом эфире разберем:
• Как формируется контекст в LLM при маршрутизации между агентами;
• Куда утекают лишние токены и возникает перерасход;
• Практические методы: как сжимать историю, грамотно делить задачи, лимитировать передачу контекста и собирать промпты прямо в процессе запроса пользователя.
🔥 Два способа получить максимум:
1. Приходите на вебинар 28 апреля. Дарим участникам промокод на 5.000 ₽ (работает 3 дня после эфира - это шанс забрать курс по самому низу рынка).
2. Выбирайте Инженерный трек. В подарок к нему идет полный доступ к записям и автопроверкам завершенного курса «Разработка ИИ-агентов».
👉 Занять место на вебинаре и стать профи в AgentOps
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1😁1
Сколько среди нас
Понятно, что грейд — довольно относительная история, но примерно ваш грейд:
🔥 — Senior
👍🏼 — Middle
❤️ — Junior
😁 — Ещё учусь
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥92👍79😁19❤17👾6