Command пакує намір разом з усіма даними в обʼєкт, щоб виконати його зараз, пізніше, повторно або з іншої точки входу. Command bus додає одне місце, через яке проходять усі команди: він знаходить обробник за класом команди й загортає виконання в middleware для транзакцій, логування й валідації. Queued job у Laravel - це команда й обробник в одному класі з доставкою через чергу, а Symfony Messenger тримає повідомлення й обробник окремо і вирішує, синхронно чи через транспорт, у конфігу `routing`.
Архітектура для Senior: питання на співбесіду
9 питань рівня Senior з теми Архітектура з розгорнутими відповідями, порадами та перевіркою.
За кодом їх не відрізнити: обидва реалізують той самий інтерфейс і тримають посилання на справжній обʼєкт. Декоратор додає поведінку (кеш, лог, повтори) і складається шарами там, де збирають обʼєкт, а проксі керує доступом до справжнього обʼєкта: відкладає його створення, перевіряє права або пересилає виклик кудись далі. Кешувальна обгортка репозиторію працює, лише якщо інвалідація живе в тій самій обгортці й спрацьовує після коміту.
DDD має сенс там, де складність саме в домені: багато правил, які часто змінюються, і потрібна спільна мова з бізнесом; для CRUD-адмінки чи інтеграційного сервісу агрегати й репозиторії додають шарів без вигоди.
Модулі й сервіси розділяє не код, а межа процесу: усередині моноліта виклик модуля — це синхронний метод у спільній транзакції, між сервісами — мережа з таймаутами, частковими збоями й eventual consistency. Тому за замовчуванням беруть модульний моноліт із твердими межами, а окремий сервіс виділяють лише там, де є конкретна причина — незалежний профіль навантаження, окремий цикл релізу під окрему команду або інший рантайм — і платять за неї розподіленими транзакціями та експлуатацією.
Outbox pattern прибирає проблему подвійного запису: подію зберігають рядком у таблиці `outbox` тією ж транзакцією, що й зміну стану, а окремий процес-релей уже після коміту читає ці рядки й публікує в брокер. База і подія стають атомарними, ціною чого є доставка at-least-once — споживач зобовʼязаний бути ідемпотентним.
Агрегат - це найменша група об'єктів, яку доводиться читати й писати разом, щоб гарантувати бізнес-правило: межа проходить там, де є інваріант, який мусить виконуватися після кожного коміту. Корінь агрегату - єдина точка входу, одна транзакція змінює один екземпляр, а зв'язки з іншими агрегатами тримаються за ідентифікатором; що більший агрегат, то більше конкурентних записів він серіалізує.
Версія - це ярлик на контракті, а сумісність визначається поведінкою: ламає не номер, а звужений тип, нове значення enum, суворіша валідація чи змінений статус-код. Робочий підхід - additive-зміни всередині версії, нова major лише на справжній злам, машиночитані заголовки Deprecation і Sunset плюс телеметрія по клієнтах перед вимкненням.
Межа контексту проходить там, де слово змінює значення і де змінюється склад людей, які замовляють зміни, а не там, де закінчується таблиця. Спільні дані розвʼязуються правилом одного власника факту: решта контекстів читають через контракт або тримають власну проєкцію, спільний код лишається мікроскопічним ядром без бізнес-правил, а чужа модель заходить усередину тільки через антикорупційний шар.
Клієнт передає idempotency key, сервер зберігає його разом із результатом операції під унікальним індексом і на повторний запит повертає збережений результат замість другого платежу.