Одне слово, дві моделі
Слово «проєкт» на PHP Ukraine має два значення. У вітрині проєктів це робота розробника: посилання на сайт чи репозиторій, стек, роль автора, рівень довіри. У заявці для команди розробки це задача клієнта, про яку відомо лише стан («тільки ідея», «працює погано») і посилання. Один клас Project для обох мав би половину полів порожніми в кожному випадку. дозволяє тримати дві моделі, кожну у своїй межі.
Усередині контексту діє : ті самі слова в розмові, коді й інтерфейсі. На межі слова перекладають. Як контексти повʼязані між собою, хто від кого залежить і хто чию модель перекладає, показує .
Межу контексту проводять там, де змінюються мова й правила. Часто контекст збігається з модулем у коді, як у PHP Ukraine, де кожна папка в src/ має свій простір імен. Якщо один контекст бере модель іншого як є, межа стирається. Шар, що перекладає чужу модель на свою, називають .
«Проєкт» у двох контекстах
- Projects (проєкт: робота розробника) містить: Project, Trust, ProjectLink.
- Development (проєкт: задача клієнта) містить: Lead, ProjectState.
- Project використовує Trust.
- Project використовує ProjectLink.
- Lead використовує ProjectState.
- Lead не може змінювати Project напряму, лише через корінь.
- 1Слово означає одне в межах контексту. Якщо значення змінилося, ви перетнули межу.
- 2Кожен контекст має власну модель, навіть коли назви збігаються.
- 3Між контекстами ходять ID і прості значення, а не сутності.
- 4Чужу модель перекладають на межі: публічний вхід, DTO чи anti-corruption layer.
Проєкт і компанія в заявці на розробку
Заявка в контексті Development згадує і проєкт, і компанію, але жодне з цих слів не означає тут того, що в інших контекстах. Проєкт клієнта зведено до стану й посилання, тоді як у Projects це агрегат Project з довірою й підтвердженням авторства. Компанія тут просто рядок з форми, а в Hiring це агрегат Company з верифікацією, тарифом і привʼязкою до вакансій. Development не імпортує класів ні з Projects, ні з Hiring.
Як контексти зливаються
Одна модель на всю систему
Клас Company обслуговує каталог, найм, оплату й заявки. Поля множаться, половина з них null, а зміна правила для найму ламає оплату.
Натомість: кожен контекст тримає свою модель зі своїми полями. Спільним лишається ID.
Контексти за таблицями
Контекст на кожну сутність: UsersContext, OrdersContext, ProductsContext. Межі не збігаються з мовою, і кожна дія ходить через три контексти.
Натомість: шукайте місця, де змінюється значення слів і правила. Там проходить межа.
Чужа модель без перекладу
Модуль пошуку PHP Ukraine читає Eloquent-моделі вакансій, статей і проєктів напряму. Перейменування колонки в Hiring ламає пошук.
Натомість: беріть дані через публічний вхід іншого контексту чи будуйте власну проєкцію, переклавши чужу модель на межі.
Чи потрібен окремий контекст
- Bounded context
- Явна межа, всередині якої модель і її слова мають одне значення. В іншому контексті те саме слово може означати інше.
- Ubiquitous language
- Спільна мова команди й людей предметної області всередині одного контексту. Її видно в назвах класів і методів: Lead, withdraw(), ProjectState.
- Карта контекстів
- Схема контекстів і звʼязків між ними: хто постачає дані, хто споживає, де стоїть переклад.
- Anti-corruption layer
- Шар на межі контексту, який перекладає чужу модель на власну, щоб чужі назви й правила не просочувалися всередину.
Питання зі співбесід
Контекст це межа мови й моделі, поняття з DDD. Модуль це спосіб організувати код. Зручно, коли вони збігаються, як у PHP Ukraine, але один контекст може займати кілька модулів або окремий сервіс.
У назвах класів, методів і значень: Lead, ProjectState::WorksBadly, withdraw(). Якщо в коді setStatus(3), а люди кажуть «кандидат відкликав відгук», мова розійшлася.
Через публічний вхід іншого контексту, який віддає власні DTO, через інтеграційні події або через anti-corruption layer, що перекладає чужу модель на свою. Межу перетинають ID і прості значення, а сутність одного контексту в іншому не живе.