隔离域逻辑

在一个设计模式类中,我对建模域逻辑进行了有趣的讨论。 具体来说,它与隔离域逻辑有关 。 应用程序通常分为三个部分:

  1. 演示(例如桌面GUI,浏览器,Web服务)
  2. 域逻辑
  3. 基础架构(例如持久性存储,电子邮件)

该类发现有趣的是,依赖性箭头指向域逻辑部分。 他们问:“该图是否故意弄错了? 域逻辑部分不应该依赖于持久性存储吗?” 这是一个很大的问题。 我想在这里分享和发布讨论和解释。

经常被误解

大多数开发人员通常都会想到这种误解。

这种误解在很大程度上是由于操作顺序。 它通常以表示层中的触发器(例如,用户单击按钮或链接)开始,然后在域逻辑层中调用某些内容,然后在基础结构层中调用某些内容(例如,更新数据库表记录)。

尽管这正确的操作顺序,但是域逻辑层的实现方式还是有些微妙的。 这与依赖倒置有关。

依赖倒置原则

域逻辑层可能需要基础结构层提供的某些内容,例如某种从持久性存储中检索的访问形式。 通常的模式是:DAO和存储库。 在这里我不会解释这两种模式。 相反,我要指出的是,接口定义位于域逻辑层中,而其实现则位于另一个单独的层中。

将(DAO和存储库)接口定义放在域逻辑层中意味着它是由域逻辑层定义的。 它决定了需要哪种方法,以及期望哪种返回类型。 这也标志着域逻辑的边界。

接口和实现之间的这种分离可能是微妙的,但很关键。 仅放置接口定义就可以使域逻辑部分不受基础结构细节的影响,并允许对其进行单元测试而无需实际实现。 在单元测试期间,接口可以具有模拟实现。 这种细微的差异在快速验证(开发团队对业务规则的了解)方面有很大的不同。

这种分离是经典的依赖倒置原理 。 域逻辑(高级模块)不应依赖DAO和存储库实现(低级模块)。 两者都应依赖抽象。 域逻辑定义了抽象,而基础结构实现则依赖于这些抽象。

我见过的大多数新手团队都将DAO和存储库接口以及其特定于基础结构的实现放在一起。 例如,假设我们有一个StudentRepository及其特定于JPA的实现StudentJpaRepository 。 我通常会发现新手团队将它们放在相同的程序包中。 这样做很好,因为应用程序仍将成功编译。 但是这种分离已经消失了,领域逻辑也不再分离。

现在,我已经解释了域逻辑部分为何以及如何不依赖于基础结构部分,我想谈一谈表示部分是如何意外地与域逻辑纠缠在一起的。

分开的演讲

我在新手团队中经常看到的另一件事是,他们最终如何将自己的领域逻辑与他们的演示结合在一起。 这导致这种讨厌的循环依赖关系。 这种循环依赖性比物理依赖性更逻辑。 这使得检测和预防变得更加困难。

我不会在这里使用丰富的GUI演示示例,因为Martin Fowler已经在它上面写了一篇很棒的文章 。 相反,我将使用基于Web浏览器的演示作为示例。

大多数基于Web的系统都会使用Web框架进行演示。 这些框架通常实现某种形式的MVC(模型-视图-控制器)。 通常使用的模型直接来自领域逻辑部分。 不幸的是,大多数MVC框架都需要一些有关模型的知识。 在Java世界中,大多数MVC框架都要求模型遵循JavaBean约定。 具体来说,它要求模型具有公共零参数构造函数,getter和setter。 零参数构造函数和设置器用于将参数(来自HTTP POST)自动绑定到模型。 吸气剂用于在视图中渲染模型。

由于演示文稿中使用的MVC框架暗含要求,因此开发人员将向其所有域实体添加公共零参数构造函数,getter和setter。 他们会证明这是必需的。 不幸的是,这妨碍了实现域逻辑。 它与演示文稿纠缠在一起。 更糟糕的是,我发现域实体被发出HTML编码的字符串(例如,带有小于和大于符号HTML编码HTML代码)和XML的代码污染了,这仅仅是因为表现形式。

如果可以将您的域实体实现为JavaBean,则可以直接在演示文稿中使用它。 但是,如果域逻辑变得更加复杂,并且要求域实体失去其JavaBean风格(例如,不再有公共的零参数构造函数,没有更多的设置器),那么建议域逻辑部分实现域逻辑,并通过创建另一个JavaBean对象满足其MVC需求来使表示部分适应。

我经常使用的一个示例是用于验证用户身份的UserAccount 。 在大多数情况下,当用户希望更改密码时,也需要旧密码。 这有助于防止未经授权的密码更改。 下面的代码清楚地显示了这一点。

public class UserAccount {...public void changePassword(String oldPassword, String newPassword) {…}
}

但这并不遵循JavaBean约定。 而且,如果MVC表示框架无法与changePassword方法配合使用,那么天真的方法将是删除错误的方法并添加setPassword方法(如下所示)。 这削弱了域逻辑的隔离性,并导致团队的其他成员在各处实现它。

public class UserAccount {...public void setPassword(String password) {…}
}

对于开发人员而言,理解表示取决于域逻辑很重要。 而并非相反。 如果演示文稿有需求(例如JavaBean约定),则它不应具有域逻辑。 相反,演示文稿应创建具有相应域实体知识的其他类(例如JavaBean)。 但是不幸的是,我仍然看到许多团队仅仅因为表示而迫使他们的域实体看起来像JavaBeans,或者更糟的是,让域实体创建JavaBeans(例如DTO)用于表示目的。

安排提示

这是安排您的应用程序的提示。 将域实体和存储库保存在一个程序包中。 将您的存储库和其他基础结构实现保存在单独的程序包中。 将与演示文稿相关的类放在自己的程序包中。 请注意哪个程序包取决于哪个程序包。 最好将包含域逻辑的包放在所有组件的中心。 其他一切都取决于它。

使用Java时,程序包将如下所示:

  • com.acme.myapp.context1.domain.model
    • 将您的域实体,值对象和存储库(仅限接口定义)保留在此处
  • com.acme.myapp.context1.infrastructure.persistence.jpa
    • 将基于JPA的存储库和其他与JPA持久性相关的实现放在此处
  • com.acme.myapp.context1.infrastructure.persistence.jdbc
    • 将基于JDBC的存储库和其他与JDBC持久性相关的实现放在此处
  • com.acme.myapp.context1.presentation.web
    • 将您的Web / MVC演示组件放在此处。

请注意,我使用了context1 ,因为在给定的应用程序(或系统)中可能有多个上下文(或子系统)。 我将在以后的文章中讨论有关具有多个上下文和具有多个模型的信息。

目前为止就这样了。 我希望这个简短的解释可以为那些想知道为什么他们的代码以某种方式排列和拆分的人提供一些启示。

感谢Juno Aliento在这场有趣的讨论中为我的课堂提供了帮助。

节日快乐!

翻译自: https://www.javacodegeeks.com/2017/01/isolating-domain-logic.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/351884.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2.基础

时间:2018年12月7日18:45:59 ----------------------------------------------------------------------------------- 1.字面常量:指数字或文本字符串,值不能被改变 (1)数字:整数,浮点数&…

vsco怎么两个滤镜叠加_PS插件 VSCO滤镜137款预设安装使用教程

文末获取资源VSCO是大名鼎鼎的手机滤镜,以其逼真的胶片文艺复古风爆红,vsco滤镜甚至被誉为照片调色界的业界良心(没有之一)。不过vsco滤镜虽然很好用但苦于一直没有电脑版本,许多摄影爱好者还会用手机调色后放进PS精修。VSCO面板可以在PS上完…

Tensorflow笔记(一)

1.交叉熵 在tensorflow中用:tf.nn.sigmoid_cross_entropy_with_logits()来表示跟sigmoid搭配使用的交叉熵。tf.nn.softmax_cross_entropy_with_logits()来表示跟softmax搭配使用的交叉熵。转载于:https://www.cnblogs.com/fzth-gfh/p/10123182.html

甘特图 知乎_如何使用 Excel 绘制甘特图?

————看了上面几张甘特图,基本上只实现了『计划』和『百分比进度』这两个概念,只有在理想化的一切按照计划发展的情况下才有参考价值。但是实际上执行会提前、也可能延期,进度实时都可能变更,我们应该分开考虑计划图和进度图的…

Kali 2.0 采用ssh连接登陆

Kali GNU/Linux 2.0 \n \l 安装完kali2.0 采用ssh远程连接尽然会出现“无法连接”的情况,下面就此情况来解决问题 第一步:编辑ssh配置文件 rootrslinux:~# vim /etc/ssh/sshd_config 第二步:重新启动ssh服务 rootrslinux:~# /etc/init.d/ssh …

3.运算符与表达式,控制流

时间:2018年12月8日14:56:25 -------------------------------------------------------------------------------------------- 表达式包括运算符与操作数 1、运算符 2、求值顺序 控制流(3种) 1、if语句 number 23 guess int(input…

英语口语练习系列-C37-服饰-询问年龄-沁园春-长沙

服饰 clothes or jewelryyour favorite clothes or jewelryjewelrynecklacebraceletearringsgolddiamondbeadbroochbanglecrystalfashionfashionablesuittrendstylishboutiqueuniquepersonalityinterestuniformoccupationindividualitycasual wearcomfortable clothestradition…

因此,甲骨文杀死了java.net

好吧,还没有……但是他们宣布要在2017年5月之前关闭java.net和 kenai。JohnK . Waters 在ADTmag的Kenai和java.net的“日落”一文中接受了我的采访。 由于Oracle几乎没有提供有关已经托管在java.net上的关键项目会发生什么情况的信息,因此本文中编写的大…

snmp的使用

freebsd7.1安装snmp cd /usr/ports/net-mgmt/net-snmp make make install net-snmp相关资料 http://www.net-snmp.cn/ Snmp分2种角色:SNMP管理站(manager,我们的本机127.0.0.1)和SNMP代理(agent,我们…

1个ieee1394端口_请问IEEE1394端口有什么作用?

匿名用户1级2007-07-31 回答IEEE1394标准是一种非专用的、高速的串行总线输入输出标准。它提供了一种连接数字设备的方法,包括个人计算机和用户电子硬件。它独立于平台,可以升级(可扩展),并在支持对等连接方面很灵活。IEEE1394标准无需将数字…

jsoup 获取html中body内容_Java 进阶 利用Jsoup获取HTML页面的各分页中的标题信息...

简单介绍一下JsoupJsoup是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于Xpath,jQuery的操作方法来取出和操作元素和数据。使用Jsoup,需要导入Jsoup所需Jar包&a…

在Windows下如何安装Tomcat服务器搭建

Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选服务器。 在Windows下安装Tomcat服务器的方式有两种,一种是直接安…

剑指offer-3(替换空格)

题目: 实现一个方法,把一个字符数组里面的空格全部替换为“20%”。 思路: 首先呢,要先获取字符数组中有多少个空格以及字符数组中字符的长度,计算出替换后的长度;然后,让一个虚拟指针indexOfNew…

5.模块

时间:2018-12-9 13:40:04 ---------------------------------------------------------- 1、方法 可以创建一个包含函数与变量的py文件 可以用C语言等编写python模块,编译后,在python中使用 import sys#通过import导入sys模块print(The co…

javaee 设计模式_JavaEE重新审视设计模式:装饰器

javaee 设计模式去年的这个时候,我写了一系列有关JavaEE设计模式实现的博客文章。 大约一年后,我意识到我错过了我最喜欢的图案装饰器。 装饰器模式基本上是通过装饰其他对象来扩展对象功能的方法,其他对象可以包装目标对象并为其添加行为。…

echarts label加边框_echarts 添加自定义label标签

1.echarts 自定义标签注:当设置visualMap的后,给覆盖regions单独定义的值(如果data 中没有regions的地区 则无妨,我这个是从data中删除青岛,但是lable 无法正常显示了,如有哪位大神有好的方法,请赐教)initC…

【15】docker

docker 一种容器技术,相当于 java 一侧编译多个场所运行的技术 ,简单理解为一个盒子,盒子里面包裹着一个操作系统及其配置 docker 语法 #查看容器 docker ps -a #查看镜像docker images # 创建 dockerdocker run image #启动docker并且…

解析URI与URL之间的区别与联系

URI就是一种资源定位机制,它是比较笼统地定位了资源,并不局限于客户端和服务器,而URL就定位了网上的一切资源,只要是网上的资源,都有唯一的URL 今天在看STRUTS配置的时候,发现一个问题,就是在看…

6.数据结构

时间:2018年12月9日20:08:43 --------------------------------------------------------------------------------------- 0.四种:列表,元组,字典,集合 1.列表 可变数据类型(可以添加,移除&…

为什么要关心均值和哈希码

等于和哈希码是每个Java对象的基本元素。 它们的正确性和性能对于您的应用程序至关重要。 但是,我们经常看到甚至有经验的程序员也忽略了类开发的这一部分。 在本文中,我将介绍一些与这两种非常基本的方法有关的常见错误和问题。 合同 提到的方法至关重…