逻辑建模与物理建模

在讨论用于建模域逻辑(例如事务脚本,表模块,域模型)的PoEAA模式时,我注意到人们对域模型模式是最好的印象(尽管印象不对)。 因此,他们开始将其应用于所有内容。

不配领域模型模式

让我们成为现实。 大多数子系统都是基于CRUD的。 系统的仅特定部分需要域模型实现模式。 或者,换句话说,应用程序的某些部分仅需要数据上的表格和一些验证逻辑(例如,必填/必填字段,数字的最小/最大值,文本的最小/最大长度)。 对于这些,领域模型是不值得的。

对于这些,也许贫血领域模型会很好地适合。

贫血领域模型并不像听起来那样糟糕

贫血领域模型并不像听起来那样糟糕。 在那儿,我说了(至少在我的博客文章中如此)。

但是看起来怎么样?

package com.acme.bc.domain.model;
...
@Entity
class Person {@Id ... private Long id;private String firstName;private String lastName;// ...// getters and setters
}
...
interface PersonRepository /* extends CrudRepository<Person, Long> */ {// CRUD methods (e.g. find, find/pagination, update, delete)
}
package com.acme.bc.infrastructure.persistence;
...
class PersonRepositoryJpa implements PersonRepository {...
}

在表示层中,控制器可以访问存储库。 该存储库负责提取持久性详细信息。

package com.acme.bc.interfaces.web;@Controller
class PersonsController {private PersonRepository personRepository;public PersonsController(PersonRepository personRepository) {...}// ...
}

在这种情况下,将Person类暴露给表示层是完全可以的。 表示层可以直接使用它,因为它具有一个公共的零参数构造函数,获取器和设置器,而视图很可能需要这些构造器。

那里有。 一个简单的基于CRUD的应用程序。

您还需要服务层吗? 否。您还需要DTO (数据传输对象)吗? 不需要。在这种简单的CRUD情况下,您不需要其他服务或DTO

是的,此Person看起来像域实体。 不过,这并不包含逻辑,并且只是用来传输数据。 因此,它实际上只是一个DTO。 但这没关系,因为它可以完成保存持久性存储和检索的数据的工作。

现在, 如果业务逻辑开始变得更加复杂,则最初贫乏的领域模型中的某些实体可能会变得更加富有行为。 如果是这样的话,这些实体可以值得一个领域模型模式。

贫血领域模型的替代品

作为贫血领域模型(如上所述)的替代方法,可以将这些类移出领域逻辑层并移入表示层。 而不是命名
PersonRepository ,现在命名为
PersonDao

package com.acme.bc.interfaces.web;@Entity
class Person {...}@Controller
class PersonsController {private PersonDao personDao;public PersonsController(PersonDao personDao) {...}// ...
}interface PersonDao /* extends CrudRepository<Person, Long> */ {// CRUD methods (e.g. find, find/pagination, update, delete)
}
package com.acme.bc.infrastructure.persistence;class PersonDaoJpa implements PersonDao {...
}

太多分层

我认为,如果您必须通过不增加价值的强制性应用程序服务,那将是一个过大的杀伤力。

package com.acme.bc.interfaces.web;
...
@Controller
class PersonsController {private PersonService personService;public PersonsController(PersonService personService) {...}// ...
}
package com.acme.bc.application;
...
@Service
class PersonService {private PersonRepository personRepository;public PersonService(PersonRepository personRepository) {...}// expose repository CRUD methods and pass to repository// no value add
}

将存储库保留在domain.model包中。 将存储库实现放置在另一个包中(例如, infrastructure.persistence )。 但为什么?

domain.model包是定义存储库的位置。 域模型中的元素指示存储库接口定义中需要哪些方法。 因此,存储库定义放置在domain.model包中。 存储库实现需要遵循添加的新方法(或删除未使用的方法)。 此包装遵循依赖关系反转原理。 infrastructure.persistence程序包取决于domain.model程序包,而不是相反。

交易申请服务

那么,什么时候应用服务合适? 应用程序服务负责驱动工作流程和协调事务管理(例如,通过使用Spring中的声明性事务管理支持)。

如果您发现简单的CRUD应用程序需要在表示层控制器中启动事务,那么将它们移至应用程序服务中可能是一个好兆头。 当控制器需要更新多个不具有单个根的实体时,通常会发生这种情况。 这里通常的示例是在银行帐户之间转移金额。 需要进行交易以确保借方和贷​​方都成功或都失败。

package sample.domain.model;
...
@Entity
class Account {...}
...
interface AccountRepository {...}
package sample.interfaces.web;
...
@Controller
class AccountsController {private AccountRepository accountRepository;...@Transactionalpublic ... transfer(...) {...}
}

如果看到了这一点,那么最好将其(从表示层)移至应用程序层服务。

package sample.interfaces.web;
...
@Controller
class AccountsController {private AccountRepository accountRepository;private TransferService transferService;...public ... transfer(...) {...}
}
package sample.application;
...
@Service
@Transactional
class TransferService {private AccountRepository accountRepository;...public ... transfer(...) {...}
}
package sample.domain.model;
...
@Entity
class Account {...}
...
interface AccountRepository {...}

复杂逻辑的域模型模式(仅)

我将以重复输入记帐为例。 但我敢肯定,还有更适合的复杂逻辑。

假设我们将日记帐分录和科目建模为域实体。 该帐户包含余额(金额)。 但这并不是一个简单的设定。 需要创建日记帐分录。 过帐日记帐分录时,它将影响指定的帐户。 然后,该帐户将更新其余额。

package ….accounting.domain.model;
...
/** Immutable */
@Entity
class JournalEntry {// zero-sum items@ElementCollectionprivate Collection<JournalEntryItem> items;...
}
...
/** A value object */
@Embeddable
class JournalEntryItem {...}
...
interface JournalEntryRepository {...}
...
@Entity
class Account {...}
...
interface AccountRepository {...}
...
@Entity
class AccountTransaction {...}
...
interface AccountTransactionRepository {...}

现在,在这种情况下,一个简单的实现将有一个表示层控制器创建一个日记帐分录对象,并使用一个存储库来保存它。 并且在某个时间点(或如果使用自动过账),将创建相应的帐户交易,并更新帐户余额。 所有这些都需要汇总成一个事务(即全有或全无)。

同样,此事务理想地移至应用程序服务。

package ….accounting.application;@Service
@Transactional
class PostingService {...}

如果需要允许用户浏览日记帐分录和帐户交易,则表示层控制器可以直接使用相应的存储库。 如果域实体不适合于视图技术(例如,它不遵循JavaBean命名约定),则表示层可以定义适合于视图的DTO。 小心! 不要仅仅为了满足表示层的需求而更改域实体。

package ….interfaces.web;@Controller
class AccountsController {private AccountRepository accountRepository;private AccountTransactionRepository accountTransactionRepository;private PostingService postingService;...
}

即将结束...

所以你有它。 希望这篇文章可以阐明何时(以及何时不)使用域模型模式。

现在我想我要感冒了。

翻译自: https://www.javacodegeeks.com/2016/10/architectural-layers-modeling-domain-logic.html

逻辑建模与物理建模

逻辑建模与物理建模_架构层和建模域逻辑相关推荐

  1. 亚太数学建模竞赛优秀论文_全国大学生数学建模竞赛介绍

    大学生数学建模全国大学生数学建模竞赛介绍 全国大学生数学建模竞赛始于1992年每年一届,目前已经成为全国高校规模最大的基础性学科竞赛,也是世界上规模最大的数学建模竞赛,竞赛不分专业,但分为专科和本科两 ...

  2. 3d建模电脑配置要求_专业3d动画建模需要什么配置 运行Blender的电脑配置推荐

    今天我们为大家带来一款专业级的3D动画建模配置单.在我以前推荐的一些关于3D设计渲染的配置中,大都是强调cpu的性能,而这款配置却有所不同.随着nvidia RTX光追和DLSS深度学习超级采样技术的 ...

  3. (软考笔记) —— 系统架构设计师 - UML建模与架构文档化

    文章目录 UML建模与架构文档化 UML 现状与发展 UML起源 UML 体系结构演变 UML 的应用与未来 UML基础 概述 用例和用例图 交互图 类图和对象图 状态和活动图 状态图 活动图 构件图 ...

  4. 程序阅读_全面详解LTE:MATLAB建模仿真与实现_自学笔记(1)调制与编码_程序阅读

    程序阅读_全面详解LTE:MATLAB建模仿真与实现_自学笔记(1)调制与编码_程序阅读 在粗浅地掌握了LTE知识后,从今天开始对<全面详解LTE:MATLAB建模仿真与实现>一书的学习. ...

  5. 数据架构与数据库建模

    一.数据架构与数据模型 在数据资产化浪潮汹涌而来的时候,数据平台,数据中台,数据湖等平台也成为了企业的数据资产化建设的的'基建项目',数据模型是这个基建项目的核心内容之一,贯穿了整个数据架构. 数据模 ...

  6. 内外网逻辑隔离物理隔离_隔离域逻辑

    内外网逻辑隔离物理隔离 在一个设计模式课程中,我对建模域逻辑进行了有趣的讨论. 具体来说,它是关于隔离域逻辑的 . 一个应用程序通常分为三个部分: 演示(例如桌面GUI,浏览器,Web服务) 域逻辑 ...

  7. [4G5G专题-56]:L2 MAC层-逻辑信道到物理信道的映射、MAC层包或PDU格式、MAC层复用与解复用

    目录 第1章  L2 MAC层的架构 1.1 RAN的架构 1.2 L2 MAC层的架构 1.3 MAC层的帧调度功能 第2章 逻辑信道到物理信道的映射 2.1 映射示意图 2.2 逻辑信道 2.3 ...

  8. 程序阅读_全面详解LTE_MATLAB建模仿真与实现_自学笔记(2)OFDM_程序阅读

    程序阅读_全面详解LTE:MATLAB建模仿真与实现_自学笔记(2)OFDM_程序阅读 本章详细阅读 LTE 标准中的 OFDM 帧结构和实现,讨论 OFDM信号的时-频映射和多种适应信道带宽的资源元 ...

  9. xml建模包括以下_为什么要进行建模仿真?

    没有"模型"作为基础的话,很多当今的前沿概念将无法真正落地! 今天,数字孪生.人工智能.工业互联网.边缘计算这些概念在整个产业里非常的火热,但是,要知道,如果这些概念没有" ...

最新文章

  1. Iar环境c语言调用汇编函数,如何在IAR EWARM中通过内联汇编程序在另一个模块中调用C函数?...
  2. 数据结构-王道-树和二叉树
  3. Linux2.6--Linus电梯
  4. OmniPeek与Sniffer比较区别
  5. 【Linux】一步一步学Linux——dpkg-trigger命令(276)
  6. 远程办公也可以很高效
  7. ubuntu16.04下安装mysql详细步骤
  8. linux yum的用法【ZT】
  9. 盒子模型代码_果冻公开课第五课:五分钟理清盒模型的前世今生
  10. laplacian,degree,adjacency and oriented incidence matrix, differential and laplacian coordinates
  11. 常见linux服务器系统异常问题
  12. mysql econnreset_javascript - 节点Js mysql(和mysql2)ECONNRESET - 堆栈内存溢出
  13. Spark将数据写入Mysql
  14. oracle开发的小技巧(原创)
  15. 线程结束后会自动关闭_多线程学习之如何中断线程
  16. hadoop 权威指南 HIVE
  17. matlab图例使用技巧
  18. Mac Yapi 内网安装保姆级步骤
  19. 微信小程序如何使用SCSS
  20. 【Lintcode】1880. Largest Number X Which Occurs X Times

热门文章

  1. jzoj3910-Idiot的间谍网络【倍增,dfs】
  2. P1160-队列安排【链表】
  3. vijos1197-费解的开关【递推,枚举,位运算】
  4. 2021牛客暑期多校训练营2 B-Cannon(组合+推式子)
  5. [ZJOI2005]午餐(贪心+dp)
  6. 一文带你了解Java Agent
  7. IntelliJ IDEA 2018.2 发布,支持 Java 11
  8. 什么是CPU密集型、IO密集型?
  9. 上学的你,是不是最怕老师给家长打电话……
  10. 第四章使用jQuery操作DOM元素