задний план
Как говорится, где люди, там и реки и озера, а где дизайн, там и конструкция. Если вы старая птица в индустрии программного обеспечения, у вас должен быть такой опыт: на ранней стадии бизнеса можно довольствоваться обычным CRUD, а бизнес-линия тоже очень короткая.В это время все в системе выглядит очень красиво, но с непрерывной эволюцией итераций и сложностью бизнес-логики наши системы становятся все более и более сложными, модули связаны друг с другом, и никто не может даже описать каждую деталь. Когда новые требования должны изменить функцию, часто требуется много времени для анализа процесса, связанного с функцией, не говоря уже о непредсказуемом влиянии модификации. Так что RD добавил переключатель, осторожно перерезал поток онлайн и отключил переключатель, если возникла проблема.
Столкнувшись с таким сценарием, вы либо убегаете, либо проводите рефакторинг. Рефакторинг является основной силой для преодоления проблемы мешанины в эволюционном проектировании.Выполняя серию небольших рефакторингов на уровне отдельных классов и методов, мы можем легко реорганизовать независимый класс, чтобы добавить некоторую общую логику. обнаружите, что вам трудно придать ему деловой смысл, только смысл, изображаемый техническим измерением. Вы копаете ямы для будущих поколений во время рефакторинга.
DDD кажется «старой и медленной» идеей в среде Интернет-разработки, «работающей небольшими шагами, повторяющимися пробами и ошибками». Однако по мере постепенного проникновения интернет-компаний в реальную экономику и усложнения их бизнеса мы все чаще сталкиваемся с проблемами разработки программного обеспечения в традиционных отраслях.
Как решить эту проблему? На самом деле, волшебное оружие — это сегодняшняя тема, доменно-ориентированный дизайн! ! Я верю, что вы будете вдохновлены после прочтения этой статьи.
Введение в ДДД
Весь процесс DDD называется Domain-Driven Design, который по-китайски называется Domain-Driven Design и представляет собой набор методологий объектно-ориентированного моделирования для анализа и проектирования сложных программных систем.
В прошлом системный анализ и проектирование были разделены, что приводило к расхождению между требованиями и готовой продукцией. Они были относительно независимыми, что также приводило к трудностям в общении. DDD устранил этот разрыв и предложил концепцию модели предметной области для унификации анализа и проектирования. программирование, делая программное обеспечение более гибким и быстрым, чтобы следовать изменениям спроса.
(общедоступный номер: усовершенствование архитектуры)
История ДДД.
Я полагаю, что вы, должно быть, слышали о доменном управлении (DDD) более или менее раньше, будете ли вы ослеплены многочисленными концепциями? Чувствует ли абстрактная логика недостаток практической практики? Возможно, именно поэтому DDD никогда не был популярен.
Говорят, что ООП появилось в 1967 году, а ООП (объектно-ориентированный анализ и проектирование) — в 1982. Это зрелая версия ООП. Целью является решение сложных бизнес-сценариев. В 2009 году Эрик Эванс опубликовал книгу Domain-driven Design: Tackling Complexity in the Heart of Software, которая формально определила концепцию домена и положила начало эре DDD. Прошло почти 20 лет, но все не так просто, как представлял себе Эрик Эванс, DDD, кажется, был прохладным и не смог «захватить мир».
В 2013 году Вон Вернон написал книгу «Внедрение предметно-ориентированного проектирования», в которой определил направление развития DDD и дал много рекомендаций по посадке, что сделало людей на один шаг ближе к DDD.
В то же время, с появлением Интернета, старший брат Род Джонсон привлек всеобщее внимание своим легким и минималистичным Spring Cloud.Хотя модель потери крови, продвигаемая Spring, не является королевской кровью ООП, кого это волнует? Ведь упрощение стоимости разработки — это последнее слово.
Просто когда мы используем этот порт, закрывая Spring, мы понимаем серьезную проблему.Когда мы имеем дело со сложными бизнес-сценариями, Spring, похоже, не дает более разумного решения, поэтому мысли о разделении и обязательно должны иметь микросервис. прошлое, использование нескольких подприложений, и вдруг у нас не было времени разделить сервис, и реестр, предоставленный микросервисами, слитный, ограниченный поток и т. д., мы использовали Earner.
После того, как вы наступили на многие ямы разделения услуг (чрезмерное разделение приводит к взрыву услуг, необоснованное разделение приводит к реконструкции частотного разделения и т. Д.), Причина тупика начинается. Существует ли методология, которая может направить людей к более разумному разделению? -Сервисы? В толпе тысячи Baidu, но DDD находится в тусклом свете.С руководством DDD и микросервисными событиями это идеальная архитектура.
Связь между DDD и микросервисами
На заднем плане мы сказали, что под руководством DDD и событий микросервисов это идеальная архитектура.Здесь мы подробно обсудим их взаимосвязь.
Это неизбежная тенденция, что сложность системы становится все выше и выше. Причина может быть в развитии собственного бизнеса, или это может быть инновация технологии. Однако есть предел понимания сложности человек и команда, как производительность сервера.Предел тот же, решение состоит в том, чтобы разделять и властвовать, разбивать большую проблему на маленькие проблемы, и, наконец, преодолеть этот предел. Микросервисы дали теоретическое руководство и лучшие практики в этом отношении, такие как центр регистрации, автоматический выключатель и ограничение тока, но микросервисы не дали разумного решения проблемы «работы со сложными бизнес-сценариями». Это связано с тем, что в центре внимания микросервисов находится управление, а не разделение.
Все мы знаем, что при построении системы следует учитывать следующие аспекты:
- функциональное измерение
- Показатели качества (включая производительность и доступность)
- Инженерное измерение
Микросервисы преуспевают во втором измерении, но недостаточно в первом и третьем измерениях. Это дает DDD «возможность», DDD дает недостаток, заключающийся в том, что микросервисы не дают хорошего руководства по функциональному разделению. Таким образом, они дополняют друг друга при столкновении со сложными проблемами и системами построения.
С архитектурной точки зрения объем сервисов в микросервисах — это доменный уровень в шестиугольной архитектуре, поддерживаемой DDD, и уровни сущностей и вариантов использования в чистой архитектуре. Как показано ниже:
Как DDD и микросервисы работают вместе
Знать DDD и микросервисы недостаточно, нам также нужно знать, как они работают вместе.
Бизнес-сфера системы (или компании) и деятельность, осуществляемая в этой сфере, называются доменами.Домен представляет собой проблемную область, с которой приходится сталкиваться в реальной жизни и не имеет ничего общего с программными системами.Домен можно разделить на под- домены, такие как электротехника.Бизнес-домен можно разделить на поддомены товаров, поддомены заказов, поддомены счетов-фактур, поддомены запасов и т. д. В разных поддоменах разные понятия имеют разное значение, поэтому при моделировании мы должны иметь четкую границу, эту границу в DDD называется ограниченным контекстом, который является границей внутри системной архитектуры, упомянутой в книге «Путь чистоты»:
Архитектура системы определяется архитектурными границами в системе, а также зависимостями между границами, независимо от того, как вызываются компоненты в системе. Сама так называемая услуга - это просто форма разделения поведения приложения с немного более высокой стоимостью, чем метод вызова функций, и не имеет ничего общего с архитектурой системы.
Поэтому первым элементом сложносистемного разделения является разделение внутренней архитектурной границы системы, то есть разделение контекста, и выяснение отношений между ними, что соответствует первому измерению (функциональному измерению), упомянутому ранее, и тут на помощь приходит ДДД. Во-вторых, мы рассматриваем только то, как разделить измерения на основе нефункций, и именно здесь вступают в игру преимущества микросервисов.
Предположим, мы делим сервис на три контекста ABC:
Мы можем развернуть одно приложение в процессе или выполнить вызовы функций с помощью удаленных вызовов. Это текущий метод микросервиса. Чаще всего мы представляем собой смесь двух методов, таких как A и B, в одной единице развертывания. C развертывается отдельно, это связано с тем, что C очень важен, или параллелизм относительно велик, или требования часто меняются.В настоящее время независимое развертывание C имеет несколько преимуществ:
- C Независимое развертывание ресурсов: ресурсы более разумны, а мощность можно расширять и заключать контракты независимо друг от друга.
- Эластичный сервис: повторная попытка, автоматический выключатель, переход на более раннюю версию и т. д. обеспечили изоляцию сбоя.
- Независимость от стека технологий: C может быть написан на других языках и больше подходит для персонализированных стеков командных технологий.
- Команда независима: могут нести ответственность разные команды.
Архитектура может развиваться, поэтому при разделении необходимо учитывать этапы архитектуры. На ранней стадии больше внимания уделяется границам бизнес-логики. На более поздней стадии необходимо учитывать больше аспектов, таких как объем данных, сложности и т.д., но даже при такой политике часто бывают разные мнения, и никто не может сразу определить границу права, на самом деле тут вообще нет четкого правильного или неправильного.
Даже если границы четко не определены, совокупный корень гарантирует, что мы можем развить более подходящий контекст.В контексте контекста концепции предметной области моделируются сущностями и объектами-значениями.Набор сущностей и объектов-значений принадлежит совокупному корню.
Согласно ограничениям DDD:
- Во-первых, агрегируйте корни, чтобы обеспечить правильность внутренних правил сущностей и непротиворечивость данных;
- Во-вторых, внешние объекты могут ссылаться на корень агрегата только по идентификатору и не могут ссылаться на объекты внутри корня агрегата;
- В-третьих, транзакция базы данных не может быть разделена между корнями агрегатов, и согласованность данных между ними должна быть гарантирована согласованностью в конечном итоге.
С агрегированным корнем и на основе этих ограничений относительно легко обновить агрегированный корень до контекста или даже разделить его на микросервисы по мере необходимости в будущем.
Связанные термины и основные понятия DDD
После обсуждения концепций макросов, давайте познакомимся с некоторыми концепциями DDD.Я нашел для вас концепцию сопоставления, разработанную режимом Spring для каждой концепции, которая удобна вам для понимания, но ее следует использовать только для понимания, а не слишком зависимый.
Кроме того, здесь вам может понадобиться несколько раз комбинировать следующий код, чтобы понять его, чтобы интегрировать в реальную работу.
поле
Концепция сопоставления: Sharded Services.
Сфера — это масштаб. Точка охвата – это границы. Основная идея предметной области состоит в том, чтобы разделить проблему по уровням, чтобы уменьшить сложность бизнеса и системы, что также является ядром обсуждения DDD.
Поддомены
Концепции отображения: подсервисы.
Домены могут быть дополнительно разделены на поддомены, известные как поддомены. Это дизайнерская идея для работы с очень сложными областями, она пытается разделить сложность технической реализации. Это разделение встречается во многих архитектурах, таких как C4.
основной домен
Концепции сопоставления: основные службы.
В процессе разделения доменов субдомены будут непрерывно делиться, а субдомены будут разделены на три категории в зависимости от их важности: основной домен, общий домен и домен поддержки.
Субдомен, который определяет основную конкурентоспособность продукта, является основным доменом, и персонализированных требований не так много.
Примеры персиковых деревьев, шесть поддоменов, таких как корни, стебли, листья, цветы, плоды, семена, разные люди понимают основной домен, например, в саду основной домен является основным доменом, в парке основной домен Это это цветок. Иногда для питания основного домена он также отсекает универсальные домены и вспомогательные домены (стебли, листья и т. д.).
общий домен
Концепции сопоставления: сервисы промежуточного программного обеспечения или сторонние сервисы.
Универсальная функция, используемая несколькими поддоменами, — это общий домен без многих корпоративных функций, таких как авторизованная проверка подлинности.
домен поддержки
Концепции картирования: корпоративные общественные услуги.
Он должен существовать для функции, но он не влияет на основную конкурентоспособность продукта и не содержит общих функций.Он имеет характеристики предприятия и не имеет общности, такой как цифровая словарная система кодов данных.
единый язык
Концепции картирования: объединение концепций.
Определите, что означает контекст. Его ценность в том, что он может устранить коммуникационные барьеры, независимо от того, какую роль вы играете в RD, PM, QA и т. д., позволяя каждой команде использовать единый язык (концепцию) для общения и даже более читаемый код.
Общий язык содержит сценарии принадлежности и вариантов использования и может быть отражен непосредственно в коде.
В случае шторма (встречи) язык может быть унифицирован, даже сопоставление между китайским и английским языками, сопоставление между бизнес-моделями и моделями кода и т. д. Для записи можно использовать таблицу.
ограниченный контекст
Концепции картирования: границы служебных обязанностей.
Определите границы контекста. Модели предметной области существуют в определенных границах. Одно и то же понятие в разных контекстах имеет разное понимание, например, товар называется товаром на этапе продажи, а товаром — на этапе транспортировки.
Теоретически границы ограниченных контекстов — это границы микросервисов, поэтому понимание ограниченных контекстов очень важно при проектировании.
полимеризация
Концепции отображения: пакеты.
Концепция агрегации аналогична концепции пакета, как вы ее понимаете. Каждый пакет содержит класс сущностей или поведений. Это помогает распределить сложность системы. Это также абстракция высокого уровня, которая упрощает понимание модель домена.
Все разделенные объекты не могут быть размещены в одном сервисе, который включает в себя разделение, поэтому, если есть разделение, будет агрегация. Агрегация предназначена для обеспечения согласованности между объектами в домене.
При определении агрегатов должны соблюдаться инвариантные ограничения:
- Какая информация должна находиться в границах агрегата, без чего его нельзя назвать действительным агрегатом;
- Состояние некоторых объектов в агрегате должно удовлетворять определенному бизнес-правилу:
- Агрегат имеет только один агрегатный корень, и этот агрегатный корень может существовать независимо.Другие сущности или объекты-значения в агрегате зависят от агрегатного корня.
- Доступ извне возможен только к корню агрегата, а корень агрегата поддерживает внутреннюю согласованность агрегата.
Совокупный корень
Концепции отображения: пакеты.
Контекст может содержать несколько агрегатов, каждый агрегат имеет корневую сущность, называемую корнем агрегата, а агрегат имеет только один корень агрегата.
организация
Концепция сопоставления: Домен или сущность.
В книге «Шаблоны проектирования, принципы и практика, управляемые предметной областью» упоминается, что сущность — это понятие предметной области, обладающее идентичностью и согласованностью. Можно видеть, что сущность на самом деле представляет собой особую предметную область. баллы: уникальный идентификатор (identity), преемственность. Оба незаменимы.
Как вы понимаете, статьи могут быть сущностями, как и авторы, поскольку у них есть идентификатор в качестве их уникального идентификатора.
объект значения
Концепция сопоставления: Домен или сущность.
Чтобы лучше показать взаимосвязь между моделями предметной области, сформулированный объект по существу является сущностью, но по отношению к сущности он не имеет состояния и идентичности, и его цель состоит в том, чтобы представлять значение, обычно используя значение. Объекты представлены в форма передачи количества.
Например, деньги, очевидно, неразумно иметь идентификатор, и вы не можете запрашивать деньги по идентификатору.
Определение объектов значения должно быть основано на различии конкретных сценариев.Вы даже можете рассматривать Автора в статье как объект значения, но должно быть ясно, что когда Автор существует независимо, он является сущностью, или, если вы хотите используйте Автора для сложной бизнес-логики, затем Автор также обновился до совокупного корня.
Наконец, приведено изображение, взятое из Интернета, которое является относительно полным и просто скопировано напрямую, чтобы вы могли просмотреть соответствующие концепции DDD в макроскопическом виде:
Четыре режима домена
Помимо неясных понятий, самое сложное для нас принять может быть использование моделей.В мышлении Spring Домен является только носителем данных, и все поведения инкапсулированы в Сервис с использованием Домена.Поток, в то время как ООП обращает внимание на объектное измерение для выполнения бизнеса, поэтому объекты в DDD используют поведение (это очень важно понимать).
Здесь я обобщил все четыре шаблона домена, чтобы вы могли их различить и понять:
- модель кровопотери
- Модель анемии
- модель гиперемии
- Модель отека крови
задний план
Позвольте мне сначала объяснить предысторию примера.Поскольку проект компании не может быть просочился, я смоделирую здесь систему управления статьями (эта система относительно проста, теоретически DDD нельзя использовать, здесь только пример), бизнес требования: публикация статей, изменение статей, поиск и отображение статей по классификации и т. д.
При разработке с помощью Spring вы должны иметь в виду следующий код.
Категория статьи: Статья
public class Article implements Serializable {
private Integer id;
private String title;
private Integer classId;
private Integer authorId;
private String authorName;
private String content;
private Date pubDate;
//getter/setter/toString
}
Класс DAO: ArticleDao/ArticleImpl
public interface ArticleDao extends BaseDao<Article>{
//...
}
Repository("articleDao")
public class ArticleDaoImpl implements ArticleDao{
//...
}
Класс обслуживания: СтатьяОбслуживание
public interface ArticleService extends BaseService<Article>{
//...
}
@Service(value="articleService")
public class ArticleServiceImpl implements ArticleService {
//...
}
Класс контроллера: опущен.
Примеры четырех режимов
модель кровопотери
Объект домена имеет только чистый класс данных с методами получения/установки свойств, и вся бизнес-логика полностью выполняется бизнес-объектом.
public class Article implements Serializable {
private Integer id;
private String title;
private Integer classId;
private Integer authorId;
private String authorName;
private String content;
private Date pubDate;
//getter/setter/toString
}
public interface ArticleDao {
public Article getArticleById(Integer id);
public Article findAll();
public void updateArticle(Article article);
}
Модель анемии
Проще говоря, объект домена содержит логику домена, которая не зависит от сохраняемости, а логика домена, зависящая от сохраняемости, отделена от уровня службы.
public class Article implements Serializable {
private Integer id;
private String title;
private Integer classId;
private Integer authorId;
private String authorName;
private String content;
private Date pubDate;
//getter/setter/toString
//判断是否是热门分类(假设等于57或102的类别的文章就是热门分类的文章)
public boolean isHotClass(Article article){
return Stream.of(57,102)
.anyMatch(classId -> classId.equals(article.getClassId()));
}
//更新分类,但未持久化,这里不能依赖Dao去操作实体化
public Article changeClass(Article article, ArticleClass ac){
return article.setClassId(ac.getId());
}
}
@Repository("articleDao")
public class ArticleDaoImpl implements ArticleDao{
@Resource
private ArticleDao articleDao;
public void changeClass(Article article, ArticleClass ac){
article.changeClass(article, ac);
articleDao.update(article)
}
}
Обратите внимание, что этот шаблон не зависит от DAO на уровне предметной области. Работа по настойчивости также должна выполняться в DAO или Service.
Плюсы и минусы этого
Преимущества: Каждый слой односторонне зависим, а структура ясна.
недостаток:
- Постоянная логика домена, тесно зависящая от объекта домена, разделена на уровень службы, что недостаточно для объектно-ориентированного подхода.
- Сервисный уровень слишком тяжелый
модель гиперемии
Модель перегрузки аналогична второй модели. Разница заключается в разделении бизнес-логики. Большая часть бизнес-логики размещается в домене. Сервис представляет собой тонкий слой, который инкапсулирует небольшое количество бизнес-логики и не имеет отношения к DAO:
Сервис (инкапсуляция транзакции) —> Объект домена DAO
public class Article implements Serializable {
@Resource
private static ArticleDao articleDao;
private Integer id;
private String title;
private Integer classId;
private Integer authorId;
private String authorName;
private String content;
private Date pubDate;
//getter/setter/toString
//使用articleDao进行持久化交互
public List<Article> findAll(){
return articleDao.findAll();
}
//判断是否是热门分类(假设等于57或102的类别的文章就是热门分类的文章)
public boolean isHotClass(Article article){
return Stream.of(57,102)
.anyMatch(classId -> classId.equals(article.getClassId()));
}
//更新分类,但未持久化,这里不能依赖Dao去操作实体化
public Article changeClass(Article article, ArticleClass ac){
return article.setClassId(ac.getId());
}
}
Вся бизнес-логика находится в Domain, а управление транзакциями также реализовано в Item. Плюсы и минусы этого действия заключаются в следующем.
преимущество:
- Более соответствует принципам ООП;
- Уровень службы очень тонкий и действует только как фасад и не имеет отношения к DAO.
недостаток:
- DAO и объект домена образуют двунаправленную зависимость, а сложные двунаправленные зависимости могут привести ко многим потенциальным проблемам.
- Как разделить логику сервисного уровня и логику доменного уровня очень неоднозначно, в реальных проектах из-за различий в уровне дизайна и разработчиков вся структура может быть хаотичной и беспорядочной.
Модель отека крови
Основываясь на третьем недостатке модели гиперемии, некоторые студенты предложили отменить уровень службы, оставив только слои объекта домена и DAO и инкапсулировав транзакцию в логике домена объекта домена.
Объект домена (инкапсуляция транзакций, бизнес-логика) DAO
Кажется, что Ruby on rails — это именно эта модель, она даже объединяет как Domain Object, так и DAO.
Плюсы и минусы этого:
- Упрощенное наслоение
- Также в соответствии с ОО
Недостатки этой модели:
- Многие логики службы, которые не являются логикой домена, также принудительно помещаются в объект домена, вызывая нестабильность модели объекта домена;
- Объект домена предоставляет веб-слою слишком много информации, что может вызвать неожиданные побочные эффекты.
Модернизация существующих устаревших системных практик с помощью DDD
Если вы руководитель группы или архитектор, когда вы берете на себя задачу поддержки и рефакторинга старой системы, как вы ее трансформируете? Вы чувствуете, что что-то не так, но не можете начать из-за незнакомого вам делового познания? Фактически, здесь я могу научить вас набору методов решения этой дилеммы.
Что вам нужно сделать, это примерно следующее:
1. Примерно разберитесь с отношениями вызовов между системами через общедоступную платформу (как правило, компании выше среднего и выше имеют отношения вызовов RPC и HTTP, и вы можете запрашивать системы одну за другой, не задумываясь), рисунок может быть грязным, или он может быть относительно ясно, но это статус-кво.
2. Назначьте каждого члена команды на несколько проектов, чтобы разобраться в взаимосвязях измерений проектов, включая подробные описания внешних интерфейсов, взаимодействий, вариантов использования, MQ и т. д. Отдельные базовые системы могут создавать внутренние объекты или совокупные корни.
3. Группа встречается для рассмотрения бизнес-концепций каждой системы по очереди для достижения единого языка внутри группы.
4. В соответствии с приведенной выше информацией вы можете увидеть, какие необоснованные отношения вызовов (такие как циклические вызовы, нерегулярные вызовы и т. д.) и даже необоснованное расслоение.
5. По основному направлению бизнеса сегментация сверху вниз и в ограниченном контексте. Этот процесс может перевернуть предыдущее разделение системы.
6. В зависимости от сложности бизнеса укажите модель предметной области и выберите модель анемии или перегрузки. Лучше всего внедрить единую привычку внутри команды, чтобы избежать чрезмерных затрат на передачу.
7. Разделите работу по разработке и установите крайние сроки. Обратите внимание: не устанавливайте один крайний срок, а установите промежуточное время проверки. Например, крайний срок — 20 января, и необходимо установить два времени проверки, чтобы сообщить стиль кода и границы ответственности. соответственно, чтобы избежать продления срока.
Идеальное сочетание DDD и семейства Spring
Также, используя вышеупомянутую систему управления статьями, я объясню вам суть разработки DDD.
Модуль
Модуль (Module) — это средство управления ограниченным контекстом, явно упомянутое в DDD, В нашем проекте мы обычно пытаемся использовать модуль для представления ограниченного контекста предметной области.
Как показано в коде, организация пакетов в общем проекте такова: {компания.название компании.организационная структура.бизнес.контекст.*}, такая организационная структура может четко определять контекст внутри пакета.
import com.company.team.bussiness.counter.*;//计数上下文
import com.company.team.bussiness.category.*;//分类上下文
import com.company.team.bussiness.comment.*;//评论上下文
Что касается организационной структуры в модуле, мы обычно определяем ее в соответствии с организационными методами, такими как объекты домена, службы домена, библиотеки ресурсов домена и антикоррозийные слои.
import com.company.team.bussiness.cms.domain.valobj.*;//领域对象-值对象
import com.company.team.bussiness.cms.domain.entity.*;//领域对象-实体
import com.company.team.bussiness.cms.domain.aggregate.*;//领域对象-聚合根
import com.company.team.bussiness.cms.service.*;//领域服务
import com.company.team.bussiness.cms.repo.*;//领域资源库
import com.company.team.bussiness.cms.facade.*;//领域防腐层
доменный объект
Важной проблемой, которую должны решить драйверы домена, является решение проблемы анемии объектов, и объекты домена самым непосредственным образом отражают эту способность.
Для иллюстрации мы можем определить сводные корни (статьи) и объекты-значения (счетчики). Совокупный корень содержит идентификатор статьи и данные счетчика статьи. Причина, по которой счетчик указан как объект значения, а не атрибут сущности, заключается в том, что счетчик состоит из нескольких частей, таких как фактические объем чтения, объем чтения по продвижению и т. д.
В объекте домена статьи нам нужно определить метод для получения количества статей для отображения на странице.Эта логика может быть очень сложной, включая такие факторы, как популярные статьи, уровень обозревателя и время публикации.
package com.company.team.bussiness.domain.aggregate;
import ...;
public class Article {
@Resource
private CategoryRepository categoryRepository;
private int articleId; //文章id
...
private ArticleCount articleCount; //文章计数器
//getter & setter
//查询计数显示数量,这里简化一些逻辑,甚至是不符合实际业务场景,这不重要,这里只为直观表达意思
public Integer getShowArticleCount() {
if(this.articleCount == null){
return 0;
}
return this.articleCount.realCount + categoryRepository.getCategoryWeight(this.category) + (this.articleCount.adCount * DayUtils.calDaysByNow(this.articleCount.deadDays));
}
}
В отличие от предыдущих бизнес-объектов только с геттерами и сеттерами, у доменных объектов есть поведение, и объектов больше. В то же время, по сравнению с написанием этой логики в сервисах (таких как Service), связь доменных функций сильнее, а обязанности определены более четко.
Библиотека ресурсов
Объекты предметной области требуют хранения ресурсов, а под библиотекой ресурсов можно понимать DAO, но она шире, чем DAO, и средства хранения могут быть разнообразными.Наиболее распространенными из них являются базы данных, распределенные кэши, локальные кэши и т.д. Роль репозитория заключается в унифицированном управлении хранением и доступом к домену.
В системе мы организуем репозиторий следующим образом.
import com.company.team.bussiness.repo.dao.ArticleDao;//数据库访问对象-文章
import com.company.team.bussiness.repo.dao.CommentDao;//数据库访问对象-评论
import com.company.team.bussiness.repo.dao.po.ArticlePO;//数据库持久化对象-文章
import com.company.team.bussiness.repo.dao.po.CommentPO;//数据库持久化对象-评论
import com.company.team.bussiness.repo.cache.ArticleObj;//分布式缓存访问对象-文章缓存访问
Общий внешний доступ к библиотеке ресурсов обеспечивается репозиторием, который агрегирует информацию о данных каждой библиотеки ресурсов, а также выполняет логику хранения ресурсов (например, механизм обновления кэша и т. д.).
В библиотеке ресурсов мы блокируем прямой доступ к базовому призовому фонду и призовым фондам и вместо этого управляем только управлением ресурсами агрегированного корня статьи. Метод получения ресурсов (наиболее распространенный шаблон Cache Aside Pattern) показан в примере кода.
package com.company.team.bussiness.repo;
import ...;
@Repository
public class ArticleRepository {
@Autowired
private ArticleDao articleDao;
@AutoWired
private articleDaoCacheAccessObj articleCacheAccessObj;
public Article getArticleById(int articleId) {
Article article = articleCacheAccessObj.get(articleId);
if(article!=null){
return article;
}
article = getArticleFromDB(articleId);
articleCacheAccessObj.add(articleId, article);
return article;
}
private Article getArticleFromDB(int articleId) {...}
}
По сравнению с предыдущей практикой размещения управления ресурсами в службах, библиотека ресурсов управляет ресурсами с более четкими обязанностями, а код более удобочитаем и удобен в сопровождении.
антикоррозийный слой
Также известен как адаптационный слой. В контексте иногда необходимо получить доступ к внешнему контексту, и понятие антикоррозионного слоя обычно вводится, чтобы избежать доступа к внешнему контексту.
Существует несколько ситуаций, в которых может рассматриваться вопрос о нанесении антикоррозионного слоя:
- Необходимо перевести модель во внешнем контексте в модель, которая понимает контекст.
- Для отношений командного сотрудничества между различными контекстами, если это отношения преданных, рекомендуется ввести антикоррозийный слой, чтобы избежать эрозии этого контекста внешними изменениями контекста.
- Этот доступ широко используется в этом контексте, чтобы избежать изменений, затрагивающих слишком большую область.
package com.company.team.bussiness.facade;
import ...;
@Component
public class ArticleFacade {
@Resource
private ArticleService articleService;
public Article getArticle(ArticleContext context) {
ArticleResponse resp = articleService.getArticle(context.getArticleId());
return buildArticle(resp);
}
private Article buildArticle(ArticleResponse resp) {...}
}
Если несколько внутренних контекстов нуждаются в доступе к внешнему контексту, подумайте о том, чтобы поместить их в общий контекст.
Доменные службы
В приведенном выше примере мы инкапсулируем поведение домена в объект домена, поведение управления ресурсами — в библиотеку ресурсов, а поведение взаимодействия внешнего контекста — в антикоррозийный слой. На этом этапе, когда мы оглядываемся назад на доменную службу, мы можем обнаружить, что обязанности, которые несет сама доменная служба, более ясны, то есть путем соединения поведения объектов в ряде доменов, таких как объекты домена, библиотеки ресурсов. и антикоррозийные слои. Предоставляет интерфейс для взаимодействия с другими контекстами.
package com.company.team.bussiness.service.impl
import ...;
@Service
public class CommentServiceImpl implements CommentService {
@Resource
private CommentFacade commentFacade;
@Resource
private ArticleRepository articleRepo;
@Resource
private ArticleService articleService;
@Override
public CommentResponse commentArticle(CommentContext commentContext) {
Article article = articleRepo.getArticleById(commentContext.getArticleId());//获取文章聚合根
commentFacade.doComment(commentContext);//增加计数信息
return buildCommentResponse(commentContext,article);//组装评论后的文章信息
}
private CommentResponse buildCommentResponse(CommentContext commentContext, Article article) {...}
}
Можно видеть, что после исключения некоторой защитной логики (обработки исключений, оценки нулевого значения и т. д.) логика доменной службы достаточно ясна.
Структура демонстрационного пакета
рефлексивное мышление
DDD Слой предметной области разбит, DDD является относительно самым большим светлым пятном фреймворка MVC.
DDD может это сделать, главным образом потому, что DDD подразделяет уровень предметной области.Например, объекты предметной области включают сущности, агрегации, действия и операции, называемые службами предметной области, а возможности называются возможностями предметной области и т. д., в то время как архитектура MVC не реализует бизнес-элементы. Разделенные, все предприятия являются службами, что затрудняет определение технических ограничений для уровня контроллера и уровня службы.Поскольку они оба являются службами, вы не будете знать, используется ли служба для описания объекта или бизнес-операции.
Для будущего расширения бизнеса обновление совокупного корня до контекста или даже разделение его на микрослужбы также является важным средством решения сложных проблем.
Сущности и объекты-значения — это самые большие изменения в существующих привычках программирования, но не стоит слишком сосредотачиваться на отношениях между объектами предметной области.
DDD сам по себе является методологией и предоставляет теоретическое руководство, поэтому не ожидайте, что он даст вам демонстрацию, как это делает Spring, и я надеюсь, что читатели задумаются после прочтения.
(общедоступный номер: усовершенствование архитектуры)