Рефакторинг PHP-кода
с применением DDD
Виталий Чирков, FunCorp
[email protected]
2K20
Slide 2
Slide 2 text
Почему я?
• 7 лет создаю legacy в FunCorp
• Использую тактический DDD
более 5 лет
• Контрибутил в Doctrine MongoDB ODM
ради DDD
!2
Slide 3
Slide 3 text
На повестке дня
• Какие проблемы решаем
• Что такое DDD и как поможет
• Проекция общих принципов
на PHP реальность
!3
Slide 4
Slide 4 text
У вас тут старая лапша
разрослась, да еще и с
вплетением инфраструктуры
!4
Slide 5
Slide 5 text
Проблемы
• Спагетти-сервисы
• Один слой fits it all
• Божественные сущности
• Анемичные сущности
!5
Slide 6
Slide 6 text
А что делать?
!6
Slide 7
Slide 7 text
Щас все по DDD распилим!
!7
Slide 8
Slide 8 text
!8
Slide 9
Slide 9 text
2003 год
!9
Slide 10
Slide 10 text
DDD
• Техника разработки через
моделирование предметной области
• Общий язык (ubiquitous language) —
коммуникация для бизнеса и
разработки
!10
Slide 11
Slide 11 text
DDD
тактика стратегия
!11
Slide 12
Slide 12 text
Тактика
• Набор блоков для
строительства модели
предметной области
• Техники изоляции модели
!12
Slide 13
Slide 13 text
Стратегия
• Взаимодействие моделей
и команд
• Определение границ
контекстов
!13
Slide 14
Slide 14 text
DDD
тактика стратегия
!14
Slide 15
Slide 15 text
Основные блоки
Value Object объект-значение
Entity сущность
Repository репозиторий
Specification спецификация
Application and domain services сервисы
!15
Slide 16
Slide 16 text
Value Object
• Представляет собой значение
(идентификатор, цвет, деньги и т.д.)
• Сравнивается с объектами такого же
класса по значению
• Валидирует, порождает себя
!16
Slide 17
Slide 17 text
Value Object
Используем myclabs/php-enum
с добавленной логикой сравнения и
__toString.
!17
Slide 18
Slide 18 text
Value Object
!18
Slide 19
Slide 19 text
Value Object
!19
Slide 20
Slide 20 text
Entity
• Сущность доменной модели
• Конечный автомат
• Содержит поведение
(не анемична)
!20
Slide 21
Slide 21 text
Entity
!21
Slide 22
Slide 22 text
Entity
!22
Slide 23
Slide 23 text
Repository
• Имеет семантику коллекции
• Возвращает валидные сущности
• Доменно-специфичные методы
• Изолирует домен от БД
!23
Slide 24
Slide 24 text
Repository
!24
Slide 25
Slide 25 text
Repository
!25
Slide 26
Slide 26 text
Specification
• Служит для выборки сущностей
• Можно выбирать по сложным
критериям
• Разгружает контракт репозитория
Interface Segregation Principle
!26
Slide 27
Slide 27 text
Specification
• Может объединяться
со спецификациями-друзьями
• Может содержать порождающую
логику
!27
Slide 28
Slide 28 text
Specification
!28
Slide 29
Slide 29 text
Specification
!29
Slide 30
Slide 30 text
Domain service
• Не содержит состояния
• Работает с сущностями внутри домена
• Логика, которая не ложится в сущности
и VO
• Содержит доменные знания
!30
Slide 31
Slide 31 text
Domain service
!31
Slide 32
Slide 32 text
Application service
• Точка входа в домен
• Выполняет законченную
бизнес-транзакцию
• Принимает VO или более сложные DTO
• Возвращает результат в виде доменных
объектов или ошибок
!32
Slide 33
Slide 33 text
Application service
• Не содержит состояния
• Не содержит доменных знаний
цикломатическая сложность 1
• Делегирует работу доменным сервисам
или сущностям
!33
Slide 34
Slide 34 text
Application service
!34
Slide 35
Slide 35 text
Блоки: итог
Value Object Entity Repository Specification Service
➕
factory, event, command, provider,
adapter, processor, assembler, etc.
!35
Slide 36
Slide 36 text
План действий
1. Проверим язык модели
Слова контекстно-зависимы и слабы в плане
трактовки
!36
Slide 37
Slide 37 text
Проверим язык
ban
We need to deactivate user
delete
block
!37
Slide 38
Slide 38 text
Проверим язык
ban
We need to deactivate user
delete
block
!38
Slide 39
Slide 39 text
Проверим язык
We need to deactivate user
after the CRON job is over.
!39
Slide 40
Slide 40 text
Проверим язык
We need to deactivate user
after rating calculation.
!40
Slide 41
Slide 41 text
Проверим язык
• Все пользовательские сценарии
должны быть воспроизводимы на языке
предметной области
• Взаимодействие сущностей должно
быть понятно всем участникам
!41
Slide 42
Slide 42 text
План действий
1. Проверим язык модели
Слова контекстно-зависимы и слабы в плане
трактовки
2. Изолируем модель и применим DDD блоки
Транспорт и инфраструктура — отдельные слои
!42
Slide 43
Slide 43 text
Application
with DI
Изолируем модель
Domain
Infrastructure
DB, queue, FS
Transport
HTTP, CLI, Queue
interfaces
!43
Slide 44
Slide 44 text
Изолируем модель
В модели избегаем:
• MVC контроллеров с HTTP
• пользовательского интерфейса
• работы с базой данных, очередями и прочей
инфраструктурой
!44
Slide 45
Slide 45 text
Инфраструктура
• Интерфейсы для репозиториев
• Описываем хранение в слое инфраструктуры
• Оставляем домен чистым
• Иногда это непросто: спецификации,
идентификаторы
!45
Slide 46
Slide 46 text
Итоги
• выделили модель предметной
области
• провели границы между слоями
приложения
• переписали код на блоки DDD
• научили команду общим терминам
!46
Slide 47
Slide 47 text
Источники
1. Domain-Driven Design: Tackling Complexity in the Heart of Software, Eric Evans
2. Implementing Domain-Driven Design, Vaughn Vernon
3. DDD in PHP mailing list http://dddinphp.org/
4. Mathias Verraes http://verraes.net/
5. Martin Fowler on DDD
!47