Бизнес-код и технический код

задняя часть Архитектура

У большинства программистов есть обычный опыт: когда вы меняете сложный кусок кода, вы открываете запись коммита, жалуясь на то, какой маленький милашка написал этот кусок кода, похожий на комок *, и с удивлением обнаруживаете, что я написал это 3 месяца назад!

Вроде бы простое дело, но почему программный код пишется так сложно? Над этим вопросом, вероятно, задумываются все программисты.

«Дизайн, ориентированный на предметную область», претендует на то, чтобы решить проблему сложности программного обеспечения. Его основная идея заключается в разработке программного обеспечения с точки зрения бизнеса и попытке отделить техническую сложность от сложности бизнеса. Но проект, управляемый предметной областью, был предложен 20 лет назад.В то время технические проблемы и техническая сложность, с которыми сталкивалось программное обеспечение, отличались от сегодняшних, и некоторые правила могли быть неприменимы.

Почему программа сложная? Некоторое время назад я прочитал книгу старшего Чжан И "Деконструкция предметно-ориентированного дизайна", в которой есть очень подробное объяснение по этой теме. Я думаю, что он довольно хорошо подвел итог. Вот краткое изложение, которым я хочу поделиться с вами:

Проще говоря, сложность программного обеспечения делится на два измерения. С точки зрения понимания, чем больше масштаб программного обеспечения, тем более хаотичной будет структура и тем более сложным будет программное обеспечение. С точки зрения предсказательной способности программное обеспечение может быть слишком дорогостоящим и сложным для изменения, поскольку оно плохо адаптируется к будущим изменениям.

Мы можем использовать некоторые концепции разработки, чтобы соответствовать этим измерениям, например, масштаб соответствует количеству строк кода и количеству микросервисов, структура соответствует иерархическому дизайну кода и вызывающим отношениям сервисов, чрезмерное проектирование. относится к дизайну программного обеспечения Это слишком общее, что приводит к сложному дизайну кода и снижению читабельности; недостаточный дизайн - это много жестко запрограммированного кода, что приводит к явлению «неизменяемости» при изменении бизнеса.

Итак, каково решение для предметно-ориентированного проектирования? —— Разбивая поле, разделяй и властвуй, чтобы достичь «масштаба контроля».; через разумную структуру«Чистая структура кода»; путем абстрагирования подходящей модели предметной области, высокой связности и низкой связанности«Как справиться с изменениями»**.

Среди них, в части ясной структуры, мы должны попытаться различать «деловую сложность» и «техническую сложность». Например, в бизнесе заказов основное внимание уделяется проверке заказа, расчету суммы заказа, отправке заказа и потоку последующего статуса всего заказа. С технической точки зрения основное внимание уделяется правильному выполнению заказов, обеспечению правильности, непротиворечивости и стабильности данных, а если быть более конкретным, например, как предотвратить повторную отправку, как предотвратить перепроданность, как бороться с высокими ценами. параллелизм, зависание нижестоящих служб или базы данных. Что делать, а также ряд технических проблем.

Итак, давайте в качестве примера возьмем бизнес по «отправке заказа», чтобы увидеть, какие коды будут во всем процессе, какие бизнес-коды, какие технические коды и как они должны быть организованы.

Давайте сначала посмотрим на упрощенную версию диаграммы вариантов использования отправки заказа, реальная ситуация может быть намного сложнее, чем эта.

Эта диаграмма вариантов использования не кажется очень сложной, всего шагов 6. Давайте разберем ее шаг за шагом.

шаг разложения

1 Отправить заказ

В связи с размещением заказа бизнес не считает слишком много. Однако технически из соображений безопасности нам может потребоваться проверить правильность некоторых параметров, таких как идентификатор отправленного продукта, который не может быть пустым списком, а количество отправленных продуктов должно быть больше 0.

Эти коды обычно записываются на самом внешнем уровне нашего приложения, и их необходимо проверять, как только они поступают. Некоторые языки (например, Java) могут иметь более элегантное решение, например, использование аннотации Validation.

Так что **"проверка параметров здесь чисто технический код"**.

2 Проверить и занять инвентарь

На самом деле, с точки зрения бизнеса, этот шаг следует называть только «проверкой запасов», то есть проверкой наличия товара на складе.Если запаса недостаточно, процесс следует вовремя прервать, чтобы напомнить пользователю, что запас недостаточен.

Но по техническим соображениям это может быть не просто проверка. Нам также необходимо «забрать» запасы, чтобы предотвратить явление перепроданности. Например, в сцене seckill есть 100 запасов определенного товара, но 10 000 человек раскупают его одновременно, и все раскупают почти одновременно. очень вероятно, что это подтвердят гораздо более 100 человек.Проходя, процесс идет в обратном направлении, и только когда пользователь платит, инвентарь оказывается недостаточным, что приносит пользователю плохой опыт, который не допускается в бизнесе.

Я предпринял этот шаг вместе, который называется «проверка и занятый запас», но это могут быть два интерфейса, когда я на самом деле проектирую, или интерфейс.

Таким образом, ** «Проверка здесь — это бизнес-код, а профессия — это технический код»**. Но занятость также необходима для улучшения бизнес-опыта и корректировки бизнес-данных, поэтому некоторые команды рассматривают занятость как бизнес-код.

3 Запросить цену товара

Фактически, с точки зрения бизнеса важна только общая стоимость заказа. Логика расчета также очень проста: это сумма цены * количества каждого товара в заказе.

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

В целях безопасности система заказов будет обращаться к товарной системе для запроса данных.

Таким образом, вопрос в том, что делать, если определенный продукт не может быть найден (ниже по течению или данные неверны), или продукт был снят с полки/нарушил правила?

В это время, если продукт не может быть найден из-за того, что нисходящий поток завис или данные неверны, это техническая проблема, и процесс должен быть прекращен, а пользователь должен быть уведомлен. А если товар сняли с полки/нарушение, то это вопрос бизнеса. Конечно, процесс также должен быть завершен, а пользователю должна быть предложена соответствующая копия.

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

Так вот вопрос, что делать, если откат не удался?

Вот вопрос,«Наша ценность не стоит для этой «мини-вероятностной сцены» делать набор программ».?比如占用超时释放?

Из-за соображений стоимости, я думаю, большинство команд не будут очень строгими, и на самом деле идеально решить эту задачу невозможно, ведь идеального решения может и не быть вообще. Если это произойдет, большинство людей могут выбрать регистрацию журнала ОШИБОК, активировать сигнал тревоги и проверить его вручную.

4 Рассчитайте общую стоимость заказа

Ну и наконец в область чистого бизнеса. Расчет общей стоимости заказа кажется достаточно простым, просто умножьте его и сложите.

Тогда одноклассники по бизнесу говорят вам, что это не проблема для прямого расчета сейчас, но нам, возможно, придется позже заняться полной редукцией, которая делится на оценки. Больше 100 минус 10, больше 200 минус 25, больше 500 минус 80...

И для участников есть скидки, VIP 1 - скидка 9,2%, vip 2 - скидка 9,7%...

В период акции у нас также может быть купонная кампания, пользователи могут использовать различные купоны…

Самое страшное, вероятно, повышение спроса на продукт, когда студенты не говорят ничего из перечисленного с вами, а за спиной упоминают о необходимости перемен.

Ну, это бизнес-код. Он может измениться в любое время.

После расчета информация об этом заказе должна быть сохранена в БД для формирования документа. Но бизнесу на это наплевать, это технический код.

5 Подтвердить вычет запасов

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

Поэтому лично мне кажется, что "подтверждение вычета инвентаря" больше похоже на технический кодекс.

6 Формировать платежные документы

Я думаю, что это бизнес-код. Но также будет ряд технических проблем, описанных выше, например, что делать, если генерация не удалась, как спроектировать идемпотентность, предотвратить повторные отправки и так далее.

код поля

Предположим, у нас есть система, разделенная по доменам. Затем у нас есть поле заказа, поле инвентаря, поле товара и поле платежа. Для сценариев электронной коммерции все они могут быть основными областями в нашей системе (возможно, не в области платежей, это зависит от стратегии компании).

В бизнесе пользователя, отправляющего заказ, поле заказа должно генерировать модель «заказа», завершать расчет заказа и генерировать документ заказа. Среди них шаг завершения расчета заказа — это чистая бизнес-логика, и он же самый сложный, и его следует размещать внутри модели предметной области. Но это не всегда так.Когда правила сложны и в определенной степени изменчивы, мы можем использовать «механизм правил», и ответственностью модели заказа становится «вычислить сумму, применяя правила, считанные из механизма правил. ".

В поле инвентаризации код основного поля должен указывать на то, что инвентарь занят.

В области товаров этот шаг не включает изменения состояния поля, а только запросы информации о продукте. В соответствии с архитектурой CQRS (разделение чтения-записи), поддерживаемой в конструкции драйвера предметной области, сектор продукта предоставляет только интерфейс запроса, поэтому он не включает соответствующий код модели предметной области.

В области платежей, но также генерируйте «единый платеж», логика здесь проста.

технический код

Вы, очевидно, чувствуете, что если вы полагаетесь только на код домена, в принципе невозможно успешно правильно завершить бизнес-операцию «отправка заказа».

Например, если инвентарь занят, его необходимо заблокировать, чтобы он не был переполнен. Не говоря уже об откатах и ​​подтверждениях. Например, проверка параметров и идемпотентный дизайн не являются частью бизнес-кода.

Давайте посмотрим на «коммуникацию на основе событий» между двумя доменами, поддерживаемую дизайном, ориентированным на домены.В этом бизнесе события не могут быть полностью использованы для коммуникации. Поле заказа должно вызывать интерфейс поля инвентаризации в режиме реального времени, чтобы обеспечить строгую согласованность.

отражение

Итак, давайте вернемся назад и подумаем, может ли доменно-ориентированный дизайн решить эту проблему? Можно ли разделить бизнес-код и технический код?

Очевидно, что в поле заказа простая модель заказа уже не может связать всю логику. Итак, как насчет добавления службы обработки заказов? На самом деле это теоретически возможно. Организация кода, вероятно, такова:

public String submitOrder(SubmitOrderCommand command) {
    stockAdapter.checkAndOccupyStock(command.getCommodityInfos());
    try {
        Commodities = commodityAdapter.Getcommodities(command.getCommodityInfos());
        Order order = OrderFactory.generateOrder(command);
        order.computeTotalAmount();
        orderRepository.save(order);
     stockAdapter.confirmOccupyn(command.getCommodityInfos());
    } catch(Throwable t) {
        logger.Error("提交订单失败。", t)
        stockAdapter.rollbackOccupy(command.getCommodityInfos());
    }
    paymentAdapter.submitPayment(order.getPaymentInfo())
}

Видно, что приведенный выше код охватывает все шаги с 2 по 6 (шаг 1 не включен, поскольку проверка параметров обычно выполняется на внешнем уровне). Но ясно, что мы по-прежнему **"неизбежно смешиваем технический код с бизнес-кодом"**. Такие как сохранение базы данных, подтверждение занятия и т. д. Но мы также постарались перенести технический код в реализацию адаптера и репозитория, а просто вызвали интерфейс на доменном уровне. По сравнению с традиционным кодом вызова службы в стиле спагетти гораздо понятнее использовать доменные службы и объекты домена.

Вернемся к проблеме чрезмерной и недостаточной инженерии. Это фактически проверяет уровень понимания и размышлений программиста о бизнесе. Если очевидно, что в будущем будут очевидные изменения (например, упомянутые в статье изменения правил расчета), то в начале проектирования следует проектировать более гибко. И если понимание будущих изменений неясно или определено, то этого достаточно для удовлетворения текущих потребностей бизнеса.Если архитектура разумна и код понятен, стоимость изменений не так уж велика. Здесь рекомендуется, чтобы разработчики как можно больше общались с экспертами в предметной области (такими как бизнес-персонал или менеджеры по продуктам), чтобы лучше понять будущее направление кода.

попросить поддержки

Я Ясин, блогер, который настаивает на технической оригинальности. Мой публичный аккаунт в WeChat:запрограммировал программу

Я видел все это здесь Если вы считаете, что моя статья хорошо написана, вы можете поддержать ее.

Статья будет опубликована на официальном аккаунте впервые, и опыт чтения будет лучшим, и все желающие могут обратить на это внимание.

Каждый ваш ретвит, подписка, лайк и комментарий — это самая большая поддержка для меня!

Есть также обучающие ресурсы и внутреннее продвижение ведущих интернет-компаний.