Объектно-ориентированное проектирование
Когда предметная область уже описана, возникает вопрос: какие объекты должны быть представлены в модели системы и какую ответственность они несут. Здесь появляется объектно-ориентированное проектирование.
Объектно-ориентированное проектирование начинается не с выбора языка программирования. Его смысл в том, чтобы представить систему как совокупность объектов, у которых есть состояние, поведение и ответственность. Такой подход удобен для информационных систем, потому что многие предметные понятия естественно имеют жизненный цикл и правила: заказ создаётся, оплачивается, доставляется; заявка подаётся, согласуется, отклоняется или закрывается; документ создаётся, подписывается, публикуется или архивируется.
В идеальном мире в этих этапах участвуют не только разработчики и менеджеры, но и эксперты предметной области. Они могут не знать внутреннего устройства ИС с точки зрения программной архитектуры, но способны указать на полезные и неочевидные моменты: исключения, регламенты, реальные документы, устойчивые термины, состояния объектов и правила переходов.
На раннем этапе важно отличать предметный анализ от технического проектирования. Если мы описываем “заявку”, “исполнителя”, “услугу” и “согласование”, речь идёт о предметной модели. Если появляются “контроллер”, “репозиторий”, “DTO” и “адаптер”, мы уже перешли к технической модели.
Ответственность класса — центральная идея. Класс не должен быть просто контейнером данных, если в предметной области с ним связаны важные правила. Но и перегружать один класс всей логикой процесса нельзя. Если операция затрагивает несколько объектов или внешнюю систему, может понадобиться сервис, координатор или адаптер.
Пример распределения ответственности:
| Элемент | Подходящая ответственность | Неподходящая ответственность |
|---|---|---|
| Заказ | знать свои позиции и статус | отправлять HTTP-запрос в платёжную систему |
| Позиция заказа | хранить товар, количество и цену | управлять всем процессом доставки |
| Сервис оформления | координировать создание заказа | хранить внутреннее состояние заказа вместо объекта |
| Репозиторий | загружать и сохранять заказ | принимать бизнес-решение об отмене |
| Адаптер платежей | изолировать внешний платёжный API | определять правила предметной области |
ОО-проектирование не требует, чтобы каждый объект был “умным” до предела. Важно, чтобы правила не терялись и не размазывались случайно. Если правило принадлежит предметной области, его нужно разместить там, где оно будет понятно и проверяемо. Если действие является координацией сценария, оно может принадлежать сервису приложения. Если действие связано с внешней системой, его лучше изолировать техническим адаптером.
Таким образом, объектно-ориентированное проектирование — это не механический перенос существительных в классы, а поиск осмысленного распределения ответственности между элементами будущей программной модели.
Ответственность можно проверять через вопрос “кто лучше всего знает данные, необходимые для решения?”. Если объект заказа знает свои позиции и статус, логично разместить часть правил заказа рядом с ним. Если решение требует данных нескольких объектов и внешнего сервиса, это уже кандидат на сервис или координатор. Такой подход помогает избегать как анемичной модели, где все объекты только хранят поля, так и монолитного класса, который делает всё.
В учебной модели достаточно показать принцип распределения ответственности, а не проектировать промышленную архитектуру. Важно, чтобы технические элементы были объяснимы: зачем нужен сервис, почему появился репозиторий, что изолирует адаптер и какие предметные правила сохраняются в модели.