GRASP-паттерны в 1С: меньше хаоса, больше архитектуры.
История GRASP (General Responsibility Assignment Software Patterns) началась в середине 1990-х, когда в индустрии активно обсуждалось как правильно распределять обязанности между классами и объектами в ООП, чтобы код был понятным, гибким и расширяемым. В 1995-1996 Крейг Ларман, работая над обучением и внедрением объектно-ориентированного проектирования, заметил, что у начинающих архитекторов есть повторяющаяся проблема – «какой объект за что должен отвечать». Он начал формулировать набор простых универсальных принципов – «Шаблоны назначения обязанностей» - чтобы объяснить это без сложной теории и без привязки к конкретному языку программирования. Эти идеи Ларман воплотил в книге «Применение UML и шаблонов проектирования».
В которой он, впервые, систематизировал 9 паттернов GRASP:
- Information Expert
- Creator
- Controller
- Low Coupling
- High Cohesion
- Polymorphism
- Pure Fabrication
- Indirection
- Protected Variations
GRASP – это набор принципов распределения обязанностей между классами и объектами. Работает на архитектурно аналитическом уровне: он помогает определить кому какие обязанности давать еще до того, как начали реализовывать классы. Так как 1С предметно-ориентированный язык программирования, использование GRASP паттернов проектирования дает особенно заметные преимущества, потому что он помогает структурировать систему не на уровне «как писать код», а на уровне «как правильно разложить обязанности» между объектами конфигурации. Если говорить про SOLID – это больше про подержания написанного кода с использованием паттернов проектирования таких как Strategy, Factory, Proxy. GRASP - это про идею, как правильно реализовать приложения на уровне архитектуры.
Ключевые преимущества использования GRASP:
- Избавление от божественных модулей. (принципы Information Expert, Controller) В 1С мире часто можно встретить огромный общий модуль, который умеет все: проводить документы, осуществлять проверку заполнения объекта, выстраивать бизнес логику каких-то объектов и.т.д. Для нового программиста в проекте попытка понять, где-что происходит превращается в квест - найти нужный метод, понять логику объекта.
- Принципы Information Expert, Controller помогают понять - куда перенести обязанности. Для примера: расчет скидки в объекте, у которого есть все данные для этого расчета (Справочник Скидки). Получить список сотрудников из справочника менеджера Сотрудники. На уровне метаданных конфигурации новый программист сможет быстро найти нужный ему метод или логику объекта, тогда архитектура становится более ясной - где, что и как работает
- Принцип Low Coupling - снижение связности между объектами. Подсказывает, как сделать так, чтобы один объект конфигурации знал минимум о других. Пример плохой реализации проведения документа - заказ клиента с проверкой того, что клиент заблокирован. В модуле объекта.
Пример:
Клиент = Справочники.Клиенты.НайтиПоКоду(КодКлиента);
Если Клиент.Блокирован Тогда
ВызватьИсключение "Клиент заблокирован";
КонецЕсли;
Какие проблемы данной реализации:
- Документ «Заказ клиента» напрямую зависит от структуры и методов справочника «Клиенты».
- Любое изменение в логике блокировки клиента потребует правок в коде документа → снежный ком изменений.
Как можно было решить:
Ввести прослойку общий модуль РаботаСЗаказамиКлиента, который инкапсулирует работу с клиентом.
Для 1С это критично, потому что:
- при изменении структуры одного объекта меньше шансов “сломать” другие;
- Проще дорабатывать конфигурацию без снежного кома изменений.
- Принципы Pure Fabrication и Polymorphism - Повторное использование кода без дублирования.
Он позволяет вынести общую логику в отдельные объекты (общие модули, менеджеры) без привязки к конкретным документам или справочникам. Как пример - расчет НДС.
Пример:
Для Каждого Стр Из Товары Цикл
Стр.НДС = НДС.Рассчитать(Стр.Сумма);
КонецЦикла;
- Лучшая поддерживаемость больших конфигураций.
В 1С, особенно в больших конфигурациях, логика размазана по сотням объектов. При применении данных шаблонов проектирования упрощаются доработка, адаптация и развитие конфигураций. На уровне логического мышления становится понятно - где какие методы.
GRASP помогает:
- На этапе проектирования, решить, в каком объекте будет хранится и исполнятся логика.
- Избежать хаотичных вызовов методов между объектами.
- Ясная архитектурная карта для команды.
GRASP дает терминологию (Controller, Creator, Information Expert) общую для команды и общего понимания проектирования внутри команды.
- «Это у нас контроллер» - Общий модуль, который принимает “внешний” запрос (от формы, веб-сервиса, обмена данными, API);
- “Это эксперт” - Модуль объекта Документ.ЗаказКлиента, у которого уже есть нужные данные для выполнения определённой обязанности - рассчитать сумму документа и, именно ему, эту обязанность и стоит назначать.
Паттерны GRASP:
PS: В контексте GRASP, обязанности – это методы класса или объекта.
1. Information Expert
Идея шаблона (Information Expert)
Назначать обязанность тому объекту, у которого уже есть (или по смыслу должна быть) вся нужная информация, чтобы её выполнить.
Решение
- Логика, опирающаяся на реквизиты и табличные части конкретного экземпляра, — в модуле объекта (документа/справочника).
Пример: Документ.Реализация.ПолучитьСуммуДокумента(). - Знание, относящееся к типу целиком (поиск, статус), — в модуле менеджера.
Пример: Контрагенты.НайтиПоИНН(...).
Что решает (проблема)
Если поместить логику «не туда» (в модуль формы или случайный общий модуль), появляются дублирование, избыточная связность и высокий риск поломок при изменении структуры данных.
Пример:
Обработка «Калькулятор ипотеки» подбирает программу ипотечного кредитования для клиента. Вся логика реализована в модуле формы.
Что неправильно в таком подходе:
- UI не должен содержать бизнес-логику. Обязанность уровня интерфейса — показывать данные, принимать ввод, обновлять элементы формы.
- Переиспользование и интеграции затруднены. Поступила доработка: «Отправлять подобранные ипотечные программы на сайт». В текущей реализации сделать это быстро – сложно: логика спрятана в форме, которая не является владельцем данных и зависит от событий UI. Из-за неправильного размещения логики, задача усложняется и тянет за собой лишние изменения.
Как правильно (по Information Expert)
- Разместить логику подбора ипотечных программ в модуле объекта обработки (он владеет исходными параметрами и результатом).
- При необходимости выделить «экспертов» по данным в профильные объекты/регистры (ставки, ограничения, параметры банка).
- Интерфейсу оставить только сбор параметров и показ результата.
Пример Форма калькулятор ипотеки.
Рис-1 (Неправильно)
Пример получения суммы из документа Реализация товаров.
Рис-2 (Правильно)
PS: Information Expert чаще всего это экземпляр объекта.
Когда использовать модуль менеджера (Information Expert) — когда задача относится к типу целиком, а не к одному конкретному экземпляру или по контракту для другого слоя.
- Поиск и идентификация экземпляров типа.
Примеры: НайтиПоИННКПП(...), НайтиПоНомеру(...). - Массовые операции и выборки.
- Единый контракт для других слоёв.
Общие методы, которые стандартизируют доступ к типу:
ОсновнойУчастник(Ссылка), ПроверитьДублиПоИННКПП(...). - Получение существующих экземпляров (без создания).
Примеры: НайтиПоИННКПП, НайтиПоНомеру.
Пример Справочник Контрагенты «Метод ПроверитьДублиСправочникаКонтрагентаПоИННКПП»
Пример справочник номенклатура «Метод ЭтоАлкогольнаяПродукция»
2. Creator
Идея шаблона (Creator)
Создавать объект должен тот, кто ближе всего к нему.
Решение: назначать создание объекта тому классу/объекту, который
- агрегирует/содержит его;
- часто использует его;
- знает, как его инициализировать и сохранять;
- обладает исходными данными для корректного заполнения.
Иными словами: A создаёт B, если A — естественный “владелец” B по структуре или именно у A есть все данные для корректной инициализации.
Что решает (проблема):
Кто должен создавать объект? Без правила создание расползается по формам и “общим” модулям → дублирование инициализации, разная логика по умолчанию, жёсткая связность c UI, сложно тестировать и переиспользовать.
Пример (как не правильно):
Документ «Интерес» создаётся из разных мест:
ОбщийМодуль.гк_HTTPСервисДомилендВитрина, ОбщийМодуль.гк_HTTPСервисОбменССайтом, Документ.гк_Телемаркетинг.Форма, Обработка.гк_ПринятиеОбращения.
В каждом месте своя (или дублируемая) логика заполнения. Итог: много точек поддержки, нет единых правил и гарантий корректности.
Как исправить (по Creator):
Вынести создание и первичную инициализацию в один «создатель»:
- предпочтительно — Менеджер документа „Интерес“: Документы.Интерес.<методы>;
- если сценарии крайне разнородные — общий модуль-фабрика (Pure Fabrication), который всё равно делегирует в менеджер.
Контракт «единой точки создания»
- единый метод принимает структуру параметров, заполняет поля по правилам;
- возвращает объект или ссылку;
Рис-1 (Неправильно)
Рис-2 (Правильно)
3. Controller
Идея шаблона (Controller)
Это объект (общий модуль), который принимает запрос из формы или HTTP-сервиса и координирует выполнение сценария: проверяет входные данные, вызывает «экспертов» (менеджеры документов/регистров, сервис-модули) и формирует единый результат. Бизнес-правила остаются у экспертов — контроллер не «знает всё», он лишь организует шаги и не вмешивается во внутреннюю логику объектов.
Какие проблемы решает:
- Смешение UI и логики. Формы/HTTP-обработчики начинают валидировать, читать регистры, создавать и проводить документы — UI «распухает», код дублируется.
- Высокая связность слоёв. Формы напрямую дергают справочники/регистры/документы → любая смена модели ломает UI и интеграции.
- Плохая тестируемость и управляемость. Нет единой точки входа: сложно обернуть процесс транзакцией, централизованно обработать ошибки и протоколировать шаги.
Как решает (что делает контроллер):
- Определяет границы сценария: какие проверки выполнить, что создать/изменить, что зафиксировать (запись/проведение).
- Делегирует работу «экспертам»: обращается к менеджерам документов/регистров (Information Expert) и использует Creator там, где нужно создавать доменные объекты.
- Единообразное выполнение сценария: проверяет входные параметры; при необходимости открывает и фиксирует транзакцию, точечно включает/выключает привилегированный режим; централизованно перехватывает исключения, записывает их в журнал и преобразует в понятные сообщения.
Пример(как не правильно):
В обработке «Принятие обращения» по кнопке «Недозвон» форма:
- Создавался документ Взаимодействие
-
вытягивала реквизиты из Интереса;
-
запускала бизнес-процесс «Недозвон»
Правильно с Controller:
форма лишь собирает параметры и вызывает, например,
КонтроллерВзаимодействий.Недозвон(Парам).
Контроллер:
- валидирует вход,
- определяет вид события,
- у экспертов получает реквизиты интереса,
- через Creator создаёт/обновляет «Взаимодействие» и фиксирует транзакцию,
- запускает бизнес-процесс «Недозвон»
Рис-1 (Неправильно)
Рис-2 (Как правильно)
В данном примере по источнику заявки определяется общий модуль, где находится логика обработки http запроса.
4. Low Coupling
Идея шаблона (Low Coupling)
Сделать модули независимыми от внутренних деталей друг друга: знать контракты, а не реализации.
В 1С низкая связность означает следующее: форма остаётся “тонкой” — не делает прямых запросов к регистрам и не проводит документы; документ отвечает только за свою область (например, считает собственные суммы) и не содержит запросов и вызовов к чужим подсистемам; общий модуль работает как сервис, не завися от внутренней структуры справочников и документов. Все взаимодействия проходят через узкие, стабильные точки — менеджеры и сервисы с понятными экспортными функциями и простыми параметрами (чёткий контракт вместо знания чужих деталей).
Решение:
- Переносить логику к экспертам (Менеджеры/регистры/объекты)
- Вводить сервисы/прослойки (Indirection, Pure Fabrication) и контроллеры, как единую точку входа.
- Закрепляет стабильные экспортные контракты, изолируя детали реализации и интеграций.
Пример: Есть общий модуль, в нем определена функция «Основной участник», которая возвращает партнера из реквизита документа. Параметр функции – объект - это может быть любая ссылка или данные формы структуры.
Рис-1 (Неправильно)
Что здесь плохо:
- Сильная связность: общий модуль зависит от деталей реализации документов.
- Дублирование ответственности: логику выбора основного участника должен знать сам документ/его менеджер.
- Сложность поддержки: любой новый объект с «партнёром» заставит дописывать очередное Если ... Тогда в общий модуль.
- Трудно тестировать: нужно моделировать все возможные типы объектов.
Рис-2 (Как правильно)
Идея: В общий модуль добавить экспортную функцию «ОсновнойУчастник» с параметром «Ссылка», по этому параметру определяем ответственный объект (модуль менеджера документа) за получение результата. А в модуле менеджера реализовываем интерфейс (контракт) «ОсновнойУчастник» и реализовываем логику получения результата внутри модуля менеджера. Так мы снижаем связность и не лазим во внутренности объектов.
5. High Cohesion
Идея шаблона (High Cohesion)
Каждый модуль/класс/процедура должен заниматься одной близкой по смыслу задачей. Всё, что относится к разным задачам — выносится в отдельные функции/модули.
Решение: Один модуль — одна роль», «один метод — одна причина для изменений.
Что решает:
- Код легче читать и менять. Когда модуль про одно — быстрее понять, что в нём менять.
- Меньше багов при доработках. Меняем код в одном месте — не ломаем другое.
- Легче тестировать. Маленькие методы проще проверять.
Пример: Есть общий модуль «Сотрудники», который получает из внешнего сервиса «Список сотрудников» и создает их в информационной базе.
Рис-1 (Как правильно)
1. Каждая процедура делает только свою задачу (ОбновитьДанныеСотрудников, СоздатьНовыеСотрудники, ОбновитьКадровыеДанные).
2. Логика не размазана по всему модулю. Код как конструктор LEGO: Каждая деталь отвечает за свою часть.
3. Код легко читать и поддерживать.
4. Каждая часть изолирована в своей процедуре.
PS: Дополнительно, есть еще статья на infostart, где более подробно рассматриваются шаблоны Low Coupling, High cohesion. От автора Владимира Крючкова, ссылка Качество кода: слабое связывание и высокая сопряженность (Low coupling and High Cohesion)
6. Polymorphism
Идея шаблона (Polymorphism)
Поведение, которое меняется в зависимости от типа, должно быть реализовано самим этим типом.
Вместо длинных Если/ИначеЕсли по видам/перечислениям — вызываем один и тот же метод у разных «исполнителей», и каждый делает «по-своему».
PS: Полиморфизм в 1С ≈ одинаковое имя метода у разных менеджеров/объектов. Диспетчер получает тип по ссылке и вызывает один контракт — реализация разная у каждого типа.
Решение:
- Полиморфные методы у объектов метаданных (например, у каждого документа есть метод с одинаковым именем СформироватьПечать()/ОсновнойУчастник()).
- Полиморфные обработчики через перечисление + фабрика (каждому виду — свой обработчик в отдельном общем модуле с одинаковым контрактом).
- Полиморфизм менеджеров (вызываем метод с одинаковым именем у менеджера конкретного типа, выбранного по ссылке)
Как решается:
Вводим контракт, выносим реализацию в полиморфные обработчики (модули/менеджеры), используем фабрику/динамический вызов для выбора нужного исполнителя.
Что решаем:
- Лапша условий (Если Вид=..., ИначеЕсли Вид=...) растёт и ломается при каждом новом варианте.
- Высокая связность: один «центральный» модуль знает всё обо всех видах.
- Слабая расширяемость: чтобы добавить новый вид, нужно править текущую логику.
Пример: Есть общий модуль СотрудникиСлужебный.ОбновитьОбект. Параметры процедуры данные заполнения и объект (ссылка на справочник Сотрудники/Клиенты).
Рис-1
- Один вызов — много реализаций. Для Клиентов и Сотрудников реализован один и тот же контракт в менеджерах, напр.:Менеджер.ОбновитьДанныеСотрудника(Данные).
- Низкая связность. Процедура не знает реквизитов сущностей; она лишь делегирует по ссылке менеджеру типа.
- Расширяемость. Добавился новый тип — реализуй у его менеджера метод с тем же именем, сам диспетчер не меняется.
Пример: Еще вариант с использованием фабрики (Фабрика – это шаблон из GOF. В данной статье не рассматриваются). Есть модуль отправка сообщений, есть разные провайдеры. Провайдеры указаны в перечислениях, именам провайдера соответствуют общие модули. В пользовательском интерфейсе выбирается провайдер.
Рис-2
7. Pure Fabrication
Идея шаблона (Pure Fabrication)
Создаём “технический” модуль/класс, которого нет в предметной области, но который берёт на себя общую (сквозную) задачу, чтобы добиться:
- низкой связности (Low Coupling) между подсистемами,
- высокой связности по смыслу (High Cohesion) внутри модуля,
- повторного использования и удобного тестирования.
PS: Это служебный общий модуль, которого нет в предметной модели (не документ и не справочник), но он берёт на себя сквозную техническую работу, чтобы:
- разгрузить документы/формы от «не их» логики,
- снизить связность между подсистемами,
- повысить связность по смыслу внутри модуля,
- улучшить повторное использование и тестирование.
Решение:
- Выделяем узкий, стабильный контракт (экспортные процедуры/функции) для сквозной задачи.
- Прячем внутренние детали реализации внутри этого модуля.
- Документы/формы/контроллеры вызывают один контракт, не зная деталей.
- При необходимости — используем паттерны Фасад, Адаптер, Фабрика внутри сервиса. (Шаблоны GOF в данной статье не рассматривается)
Пример шаблона общий модуль НДС. Во многих местах конфигурации используется расчет НДС. Логика внутри модуля.
Рис-1
- Это не обязанность документа - расчет НДС. Документ «Реализация товаров» отвечает за товары, суммы, проведение. Но сам расчёт НДС по формуле — не его естественная ответственность. Логика НДС — это служебная задача, которая нужна многим объектам (документы реализации, поступления, счета, заказы).
- Вынести в общий модуль.Вместо того чтобы каждый документ хранил кусок формулы, расчёт делается централизованно — в модуле УчетНДСКлиентСервер.
- У функции простая сигнатура: (Сумма, СуммаВключаетНДС, СтавкаНДС) и предсказуемый результат.
Пример 2:
Модуль «ПроведениеСервер». В предметной модели ему нет соответствия: это технический модуль(Pure Fabrication), который централизует служебные процедуры и функции, связанные с проведением документов.
Плюсы:
- Повторное использование в десятках объектов без копипасты.
- Единое место для изменения формулы.
- Простое тестирование: можно прогнать модуль тестами, не проводя документ.
- Прозрачный контракт: без лишних зависимостей.
Как понять, когда использовать Pure Fabrication
- Логику хочется использовать в нескольких местах (формы, документы, обработки)
- В коде уже есть копипаста или «комбайн»-процедуры.
Как внедрять данный шаблон:
- Найти повторяющийся код (НДС, скидки и т. д.).
- Придумать узкий контракт.
- Вынести реализацию в общий модуль.
- Оставить в исходных местах только вызовы сервиса.
8. Indirection
Идея шаблона (Indirection)
Вставляем “прокладку” (посредник) между двумя модулями, чтобы они не зависели напрямую друг от друга. Клиент знает только контракт посредника, а посредник уже сам обращается к нужным исполнителям.
PS: Indirection — «служебный посредник», который перенаправляет вызовы от клиента к нужным исполнителям и прячет детали.
Дополнительное описание:
Шаблон Indirection похож на pure fabrication и Controler, но это разные шаблоны.
- Различие между Pure fabrication и Indirection .Pure Fabrication — служебный исполнитель, а Indirection перенаправляет вызовы
- Цель шаблона controller - реализовать сценарий: оформить реализацию, создать договор. Цель шаблона Indirection - только перенаправление вызова: нет бизнес-правил, нет сложных проверок.
Что решает: сильную связность, хрупкость изменений, дублирование, плохую тестируемость.
Решение: Узкий общий модуль-роутер + полиморфные методы у объектов/менеджеров.
Как выбрать между Controller и Indirection
- Один вызов → один исполнитель: Нужно лишь роутить → Indirection.
- Несколько шагов подряд (проверки → расчёты → создание → проведение) → Controller.
Пример: Хорошо подходит пример для демонстрации, который был описан выше ОсновнойУчастник шаблон Polymorphism. Также можно привести пример из БСП - подключаемые команды печати можно отнести к шаблону Indirection. Прослойка между формой и конкретной печатным обработчикам.
Рис-1 (Общая точка входа)
Рис-2 (Реализация)
Почему это Indirection:
- Единая точка входа. Форма обращается только к КомандыПечатиОбъекта(...) (и, при выполнении, к обёртке ВыполнитьКомандуПечати(...)), не зная, что там дальше происходит.
- Отвязка UI от реализации. Форма не знает, какие модули/процедуры формируют печать и где они находятся — она оперирует списком команд.
- Сокрытие деталей. Все нюансы — где брать команды, когда их показывать и в каком порядке — скрыты внутри модуля «УправлениеПечатью».
- Маршрутизация к исполнителям. Посредник проставляет МенеджерПечати и делегирует вызов конкретному обработчику печати.
- Расширяемость без правок формы. Новые печатные формы подключаются автоматически появляются в меню печати.
- Стабильный контракт. Внутренние изменения (добавили источники, поменяли правила) не требуют править код форм — интерфейс вызова остаётся прежним.
9. Protected Variations
Идея шаблона (Protected Variations)
Protected Variations — проектируем так, чтобы места, где «всё меняется», были спрятаны за стабильным контрактом. Клиентский код (форма, документ) зависит не от конкретной реализации, а от устойчивого интерфейса (функции общего модуля, метода менеджера). Меняются источники данных, алгоритмы — контракт остаётся тем же.
PS: защитить клиентов от изменений за счёт устойчивого контракта вокруг точки вариаций.
Что решает:
- Хрупкость при изменениях. Поменялся регистр, ставка, алгоритм → не ломаем формы/документы.
- Дублирование и «размазывание» логики. Один контракт вместо 5 похожих кусков в разных местах.
- Сильная связность. Клиентский код не знает деталей (какой регистр, какая стратегия, где хранятся настройки).
Решение:
- Задать единый стабильный контракт — экспортную функцию или метод менеджера с фиксированными именем и параметрами (сигнатура не меняется).
- Обвернуть контракт паттернами:
- Indirection — тонкая прослойка, выбирающая исполнителя и скрывающая детали;
- Polymorphism — взаимозаменяемые реализации с одной и той же сигнатурой;
- Controller — координация сценария: проверка входа → вызов контракта → единый результат.
Заключение
Использование GRASP делает архитектуру системы прозрачной, масштабируемой и предсказуемой: обязанности оказываются «у своих владельцев», снижается связность, проще тестировать и развивать. Но, чтобы раскрыть весь потенциал подхода, важно поменять способ постановки задач и опираться на Унифицированный процесс (UP) — итеративный, прецедентно-ориентированный подход к анализу и проектированию. При этом ключевая роль — не только у программиста, но и у аналитика: именно он формулирует цели и ценность изменения, собирает и нормализует требования, описывает прецеденты (основные и альтернативные потоки), строит модель предметной области и согласованный словарь терминов, выделяет точки вариаций и ограничения, фиксирует критерии приёмки. Уже на этой основе разработчик раскладывает обязанности по GRASP и реализует решение в 1С.
Что входит в UP:
- Анализ требований.
Формулируем цель и ценность для пользователя, ограничения и критерии приёмки. Вместо «добавьте ещё одну колонку в отчёт (их уже 50)» — спрашиваем: какое решение будет принято по этой информации и почему? - Прецеденты использования (Use Cases).
Описываем основной и альтернативные потоки для каждого актёра: триггеры, шаги, постусловия. Это становится «скелетом» сценариев. - Модель предметной области.
Выделяем ключевые сущности, связи и устойчивые правила (уникальности, статусы, ограничения), оформляем словарь терминов. Это база для распределения обязанностей. - Диаграммы взаимодействий (Sequence/Communication).
По ключевым прецедентам прорисовываем сообщения между объектами. Эти диаграммы подсказывают, где применять паттерны GRASP:- границы сценария → Controller,
- у кого данные и знания → Information Expert,
- кто создаёт что → Creator,
- где спрятать варианты и зависимости → Indirection/Polymorphism/Protected Variations.
- Объектная модель.
Уточняем классы/модули и раскладываем обязанности по GRASP: интерфейсы и контракты, границы модулей, точки расширения, единые правила создания и валидации.
Связка UP → GRASP на практике
- Controller рождается на границе прецедента (между актёром и системой) и координирует шаги.
- Information Expert — у владельцев данных предметной области (документы, справочники, регистры).
- Creator — у агрегирующих типов или сервисов, которые имеют все данные для инициализации.
- Indirection/Polymorphism/Protected Variations — там, где сценарии имеют варианты (скидки, печать, источники остатков): клиент видит стабильный контракт, реализация меняется «за кулисами».
Итог: сочетая UP для постановки и GRASP для распределения обязанностей, получаем систему, которая меньше ломается при изменениях, быстрее дорабатывается и легче сопровождается.
PS: Если данная статья окажется интересна сообществу, напишу вторую часть GRASP + GOF паттерны.
Вступайте в нашу телеграмм-группу Инфостарт