Перейти к содержимому

Объектно-ориентированное проектирование

Когда предметная область уже описана, возникает вопрос: какие объекты должны быть представлены в модели системы и какую ответственность они несут. Здесь появляется объектно-ориентированное проектирование.

Объектно-ориентированное проектирование начинается не с выбора языка программирования. Его смысл в том, чтобы представить систему как совокупность объектов, у которых есть состояние, поведение и ответственность. Такой подход удобен для информационных систем, потому что многие предметные понятия естественно имеют жизненный цикл и правила: заказ создаётся, оплачивается, доставляется; заявка подаётся, согласуется, отклоняется или закрывается; документ создаётся, подписывается, публикуется или архивируется.

В идеальном мире в этих этапах участвуют не только разработчики и менеджеры, но и эксперты предметной области. Они могут не знать внутреннего устройства ИС с точки зрения программной архитектуры, но способны указать на полезные и неочевидные моменты: исключения, регламенты, реальные документы, устойчивые термины, состояния объектов и правила переходов.

На раннем этапе важно отличать предметный анализ от технического проектирования. Если мы описываем “заявку”, “исполнителя”, “услугу” и “согласование”, речь идёт о предметной модели. Если появляются “контроллер”, “репозиторий”, “DTO” и “адаптер”, мы уже перешли к технической модели.

Ответственность класса — центральная идея. Класс не должен быть просто контейнером данных, если в предметной области с ним связаны важные правила. Но и перегружать один класс всей логикой процесса нельзя. Если операция затрагивает несколько объектов или внешнюю систему, может понадобиться сервис, координатор или адаптер.

Пример распределения ответственности:

ЭлементПодходящая ответственностьНеподходящая ответственность
Заказзнать свои позиции и статусотправлять HTTP-запрос в платёжную систему
Позиция заказахранить товар, количество и ценууправлять всем процессом доставки
Сервис оформлениякоординировать создание заказахранить внутреннее состояние заказа вместо объекта
Репозиторийзагружать и сохранять заказпринимать бизнес-решение об отмене
Адаптер платежейизолировать внешний платёжный APIопределять правила предметной области

ОО-проектирование не требует, чтобы каждый объект был “умным” до предела. Важно, чтобы правила не терялись и не размазывались случайно. Если правило принадлежит предметной области, его нужно разместить там, где оно будет понятно и проверяемо. Если действие является координацией сценария, оно может принадлежать сервису приложения. Если действие связано с внешней системой, его лучше изолировать техническим адаптером.

Таким образом, объектно-ориентированное проектирование — это не механический перенос существительных в классы, а поиск осмысленного распределения ответственности между элементами будущей программной модели.

Ответственность можно проверять через вопрос “кто лучше всего знает данные, необходимые для решения?”. Если объект заказа знает свои позиции и статус, логично разместить часть правил заказа рядом с ним. Если решение требует данных нескольких объектов и внешнего сервиса, это уже кандидат на сервис или координатор. Такой подход помогает избегать как анемичной модели, где все объекты только хранят поля, так и монолитного класса, который делает всё.

В учебной модели достаточно показать принцип распределения ответственности, а не проектировать промышленную архитектуру. Важно, чтобы технические элементы были объяснимы: зачем нужен сервис, почему появился репозиторий, что изолирует адаптер и какие предметные правила сохраняются в модели.