简单来说 controller service dao 三层。
controller 和 service 之间的分层相对比较清晰, 业务逻辑和显示逻辑的拆分, 譬如 MQ/http/RPC 和业务分离。
service 和 dao 的区分我有点搞不懂。主要是因为分不清什么是存储逻辑(非业务逻辑)什么是业务逻辑。 尤其是加入了 manager 层之后。
因为是 python 后端, 所以很自然的将业务逻辑加到 Model 上。 (我理解这里的 Model 是指业务 Model ) UserModel.is_super() 带业务的查询。
或者
UserModel.objects.all() 原生将 permissons,groups ,Commany,等等一起都带过来了。
或者
UserModel.*** 做一些跨表的操作。
我的问题:
什么是业务逻辑, 什么是非业务逻辑。
我的理解是,客户看不到的逻辑都算非业务逻辑, 譬如
1.1 表结构,表关联关系等。
UserManager.delete()和DepartmentManager.delete() 这俩可以同时包含删除关联关系表( UserDeptModel )的能力。不是二取一。 同理 save 也是。 如果没有 manager 层, 那么我的理解 Dao 是可以做连/跨表操作的,只要这个跨表操作和业务无关,没必要在 service 调用两次 dao 。
class UserManager:
def delete():
UserDao.delete()
UserDeptDao.delete()
class DepartmentManager:
def delete():
DepartmentDao.delete()
UserDeptDao.delete()
1.2 密码加盐。
用户最多只需要知道你的密码是不明文保存就可以了。 加盐动作可以放在 DAO/Manager 层处理。
class UserDao:
def make_password(passwd):
return salt(passwd)
def save():
passwd = self.make_password(passwd)
self.passwd = passwd
super.save()
1.3 DAO 层的方法命名和设定
是否可以类似get_super_user 这种带有非业务逻辑(假设这个 super 与业务逻辑无关),但是具有明显语义的方法名?还是只能get_user_by_type("super")
1.4 http 请求也可以封装层 dao. 譬如后端有一些依赖(另一个 team 提供支持), 我可以将这些依赖封装成 dao, 而不是 service.
2. 在 django/flask 中, 很容易实现 django filter 的功能。 https://www.django-rest-framework.org/api-guide/filtering/
https://django-filter.readthedocs.io/en/stable/
甚至于在 ModelViewSet 中直接集成了 filter, https://github.com/encode/django-rest-framework/blob/master/rest_framework/mixins.py#L33 如果用 python 做三层架构且想实现类似 django filter 功能的话, 那么 DAO 中一定需要传入 request 参数。且层层穿透。在没有 spring 这种自动注入框架的帮助下,如何处理类似的问题? java 中是如何实现类似 django filter 类似功能的?
3. 什么是数据实体? 是否 controller service dao 是一一对应的,如果不是, 能否举几个例子。 主要是 DAO 和 service.
三层架构和 DDD 的优缺点建议不再本贴讨论。担心歪楼。 谢谢大家啦!
dao 也可以叫做 repository,直接操作 数据源(数据库 或 第三方系统), 可以分为:接口 及其 实现层。
同样,服务层(业务逻辑) 也要有 接口 及其实现。
service 会调用 多个 dao 层的实现,此时,要做 分布式事务 处理了。
service 会调用 多个 dao 层的实现,此时,要做 分布式事务 处理了
这和分布式有什么关系...
@chaleaoch:
的确超出本文讨论范畴了。
@快乐的凡人721: service 会调用 多个 dao 层的实现,此时,要做 分布式事务 处理了。
是说在实际业务中可能遇到输出的业务逻辑涉及不同数据来源的问题嘛。分布式事务常见简单的有2PC 3PC XA协议 TCC事务等。 这块大佬你实际使用中哪些场景推荐哪种处理方式?
@戒吧老哥助我一臂之力:
没用过,也没深入研究过呢。
只是知道有这么回事,基础认知到了。
随手一搜的博文:Spring如何支持分布式事务
https://www.cnblogs.com/myitnews/p/13558785.html
@快乐的凡人721: 好的谢谢你
“那么 DAO 中一定需要传入 request 参数。”
为什么不能在controller中将请求数据提取出来,放到XXRequest类中,再进行传递呢?
对于当前系统来说,不管是提供http接口,还是订阅MQ,亦或是被任务调度系统触发,都只是外部与我这个系统的一个交换,我应该把具体的交互方式屏蔽,不管你从什么方式来找我,无非就是给我数据,我再给你数据。
所以转成DTO之后,就可以传到service层,它可不管你是怎样来的,这样就与接入层进行解耦了。
原问题中是我没有说清楚, 不见得一定要传入request, 现实情况是,可以组装一个你说的类似XXRequest类中, 但是依然要层层传递, python中没有spring那么好用的依赖注入的库。还是挺烦的。
大佬你的回答不像机器人, 能多指导两句吗?
@chaleaoch: 在spring中通常管理单实例类,但你的场景是数据传输类,肯定不是单实例的,所以注入肯定是不合适的。
为什么会产生数据传输类(DTO),其实还不是为了便于在各个层之间传输数据,在面向对象语言中用类来承担数据,在其它语言中用结构体,甚至当数据简单时直接用基本类型。
所以这个透传的过程是不可避免的,只能说怎么简化这个过程,即让各个层之间复用对象,这就好比DDD中的领域对象,接收到数据后转换成领域对象,之后做业务逻辑的时候,始终拿领域对象取值、赋值,在资源库中保存时也是拿这个在操作,当然最终写入数据库时会转成具体的XXEntity,把响应结果返回给调用端时,也是从领域对象中生成响应对象。
但上面其实还是出现了三类对象,接收外部数据和响应数据的XXRequest、XXResponse对象,以及XX领域对象,与数据库对象的XXEntity对象,如果不只是关系型数据库,可能还要有其它的对象。
理解三层架构(Controller、Service、DAO)以及业务逻辑与非业务逻辑的区分是一个重要而有挑战性的任务。让我逐一回答你提出的问题:
业务逻辑 vs. 非业务逻辑:
业务逻辑:指与业务需求直接相关的处理,比如用户权限、订单处理、商品管理等。这些逻辑通常由 Service 层处理,因为它们需要对业务进行逻辑分析和处理。
非业务逻辑:指与业务需求无关的处理,比如数据存储、加密、连接管理等。这些逻辑通常由 DAO 层处理。
Manager 层的作用:
Manager 层可以看作是 Service 层和 DAO 层之间的衔接,它可能包含了一些既非纯业务逻辑又不完全是数据访问逻辑的处理。
在你的例子中,UserManager 和 DepartmentManager 可以处理业务逻辑(如删除用户和部门)以及与之相关的数据访问逻辑(如删除用户与部门的关联关系)。
DAO 层的方法命名和设定:
方法名应该尽量清晰地反映其功能,如果一个方法不是严格的数据访问操作,而是包含一些逻辑处理,那么可以考虑以明显的语义命名,如 get_super_user。
但要注意,过于复杂的方法名可能会使代码难以理解和维护,需要权衡。
HTTP 请求封装在 DAO 层的情况:
如果某些 HTTP 请求是与数据存取相关的,可以考虑将其封装在 DAO 层。这样可以使 DAO 层更加通用,并且使服务层与外部依赖解耦。
类似 Django Filter 功能的实现:
在没有像 Django 那样自动注入的框架中,可以通过在 Service 层接受传入的参数,然后根据参数的不同调用不同的 DAO 方法来实现类似的功能。
在 Java 中,Spring 框架提供了类似的功能,你可以通过注解和依赖注入来实现类似的功能。
数据实体的概念:
数据实体是指业务领域中的实际对象,比如用户、订单、商品等。在三层架构中,Controller、Service、DAO 通常都会涉及到对数据实体的处理,但它们并不是一一对应的关系。
举例来说,一个订单可能会在 Controller 层接收到用户的请求,然后在 Service 层进行逻辑处理,最后在 DAO 层进行数据存取操作。
通过清晰地定义每个层的责任和关注点,以及良好的命名和代码组织,可以帮助你更好地理解和维护三层架构的代码。
在国内Java应用方面,阿里应该是权威。在阿里《Java开发规范》中有一个推荐的分层。
开放 API 层: 可直接封装 Service 接口暴露成 RPC 接口; 通过 Web 封装成 http 接口; 网关控制层等。
终端显示层:各个端的模板渲染并执行显示的层。当前主要是 velocity 渲染,JS 渲染,JSP 渲染,移
动端展示等。
Web 层:主要是对访问控制进行转发,各类基本参数校验,或者不复用的业务简单处理等。
Service 层:相对具体的业务逻辑服务层。
Manager 层:通用业务处理层,它有如下特征:
1) 对第三方平台封装的层,预处理返回结果及转化异常信息,适配上层接口。
2) 对 Service 层通用能力的下沉,如缓存方案、中间件通用处理。
3) 与 DAO 层交互,对多个 DAO 的组合复用。
DAO 层:数据访问层,与底层 MySQL、Oracle、Hbase、OB 等进行数据交互。
第三方服务:包括其它部门 RPC 服务接口,基础平台,其它公司的 HTTP 接口,如淘宝开放平台、支
付宝付款服务、高德地图服务等。
外部数据接口:外部(应用)数据存储服务提供的接口,多见于数据迁移场景中。
分层领域模型规约:
从java规范拷出来的?
controller service dao
controller 我理解是对接外部暴露的接口层内容
service 是服务接口的业务层逻辑
dao 是对应业务模型的持久化层相关的逻辑
如果是贫血模型的话整体是弱Model强service的接口
在贫血模型中一般感觉Model更贴近业务数据的持久层存储一些。
如果是充血模型的话整体我理解是强Model弱Service的结构。
在充血模型中和model紧密相关的部分部分业务逻辑应该是和Model在一块而不是放入Service中。引用相关Model就可以使用Model对应的相关业务操作。而Model相关的定义应该优先贴近业务模型,并屏蔽相关业务无关的内容。
不成熟的思考,欢迎大佬斧正。
我个人觉得简单点,如果没有dao层的话,那么在service层就会出现相互引用等问题,保持代码的整洁吧
个人理解service与dao是这样的。其实任何的程序或者其他编程,本质都是在操作数据,而数据只有增,删,改,查。这几项操作类似于数学中的加,减,乘,除。
而service层是应用层,本质对应当前应用程序的一些功能,模块,例如XX项目有N个模块,每个模块有N个功能。N个功能在你细化分之后,会发现是某几个表的增,删,改,查。
这么说吧,三层架构,前后端分离是解耦;现在是啥情况;全栈、全干;前后端架构分离,人不分离;都是一个人写的,你还按照三层去做,很多无用代码,我说前期的事情,后期?老板花钱让你写代码,你还考虑个后期,后期就跑路,谁还管啊。