V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ctrlaltdeletel
V2EX  ›  程序员

关于业务分层的疑惑: 贫血模型 or 领域模型 or 都是扯淡?

  •  1
     
  •   ctrlaltdeletel ·
    cadl · 2016-08-18 01:42:23 +08:00 · 6019 次点击
    这是一个创建于 2808 天前的主题,其中的信息可能已经有所发展或是发生改变。

    LZ 是一个 Python 开发者,在公司做 Python Web 开发。

    公司的业务变得越来越复杂,团队也越来越大,感觉“ fat Active Record ORM Model ”的模式有点力不从心: Model 越写越臃肿、有的逻辑不明确应该放在哪里、依赖关系有点混乱、测试困难等等等。

    现在觉得需要对业务进行一些分层处理,类似 Java 开发中常见的区分出 DAO 和 service 。

    我理解的 DAO 即是只处理数据操作,隔离底层数据操作和逻辑。 service 处理逻辑。

    在我的理解里,其中又有两种实现方式:

    1. “贫血模型”。数据对象简单,逻辑实现在类似过程式的“事务脚本”中,操作 DAO 进行数据处理。能想到的缺点是可能仍要写一些 service 间重复的逻辑。
    2. “领域模型”。对业务对象抽象为一个 domain object ,处理自身相关逻辑。上层 service 协调各个 domain object 处理逻辑。对业务理解和抽象的要求更高,感觉 service 和 domain object 在结构的组织上也比较麻烦。

    貌似 Rails 开发也有类似的 Service Object 概念,来抽象业务模型间的逻辑。

    LZ 对 Java 基本不懂,仅限大学时候“ Hello world ”水平。现在这套分层实践起来并不是很顺手,对于命名和结构都比较模糊。 service 的参数、返回值,以及实现方式也是跟着感觉走。对以上的理解也是来自网上东拼西凑,乱说一气,感觉有时间应该翻来 Martin Fowler 的书看看。

    大家有类似的经验、什么好的实践、建议吗?或者有其它的方式解决现在遇到的问题?

    10 条回复    2021-05-27 19:32:01 +08:00
    msg7086
        1
    msg7086  
       2016-08-18 02:56:04 +08:00
    和 Java 应该关系不大吧。
    可以看看设计模式,然后用你上面提到的关键词去爬谷歌 /帖子去,应该会学到不少经验。
    davisz
        2
    davisz  
       2016-08-18 04:01:31 +08:00   ❤️ 1
    如果只是解决 FAT ORM 的问题可以用两层 Model 来处理,例如 User 表有 UserActiveRecordModel 、 UserModel , AR 一般是框架自动生成后不再任何修改,逻辑写在 UserModel ,如果处理表单校验等逻辑还可以加入 UserFormModel 。

    一家之言,仅供参考。
    kitalphaj
        3
    kitalphaj  
       2016-08-18 09:00:24 +08:00   ❤️ 2
    你说的这个问题在 Rails 里面挺常见的,特别是 Rails 的 Model 已经默认实现了数据库的一些基本操作不需要你再自己写。这种时候你就只需要考虑到底是把业务逻辑(Business Logic)放在 Service 层还是放在 Model 层。

    一种思路是完全把逻辑放在 Service 里面, Model 仅仅是存数据。这种方法的好处是 Model 层会比较轻,就算是以后某个 Model 变了,比方说以前是 FullName ,现在你需要换成 FirstName 和 LastName ,那对于 UI 层的 Controller 或者 View 来说,这个变化是透明的,只需要 Service 里面把获取名字的函数调整一下就好了。但是这个设计的问题也很明显,就像你说的, Service 层会写很多重复代码,比如明明可以直接 Model.Name 的你就需要用 Service 的方法包装一层。

    我个人觉得设计模式从来都不是绝对的,对于某些系统来说这种设计可能很适用,但是对别的系统这种设计很可能就太累赘。比如上面提到这种设计,如果你觉得现在系统处于项目早期,很多 Model 都有可能会进行变化,那么你完全可以把易变的那些逻辑在 Service 里面封装,其它一些你觉得长时间都不会变的,比如某个时间的本地化处理,那么完全可以在 Model 层里面实现。

    总之一句话总结就是,程序架构没有绝对,只有适合,一定要根据你目前的项目来决定。而且一开始你可以对这些决定拿捏不准,没有关系,因为经历还浅,就算是高级架构师也不可能设计出永久不变的架构。等你以后做的设计多了,架构多了就知道,哦这种逻辑很可能会变要抽象出来,哦这种逻辑不太可能变化等等。一开始要有自信,敢去设计敢去实现,就算是后面要改也不要怕,改了说明你学习了进步了!
    feiyuanqiu
        4
    feiyuanqiu  
       2016-08-18 09:26:28 +08:00 via iPhone   ❤️ 2
    企业应用架构模式那本书对 ddd 开发并没有写得很清楚,很多概念其实在日常开发中,在使用 orm 中已经接触并实践过了,看它收获不大

    最近在看 implementing domain driven design 这本书,内容挺丰富的


    以下是个人的一些牢骚

    我之前非常纠结的是采用 DataMapper 类型的 orm 之后,因为会给每个表建立一个对应的实体,我有点不清楚业务逻辑该放在哪好了,普遍推荐的是实体就仅仅是个做数据映射的 pojo ,数据持久化操作放到 repository 里面,领域逻辑放到 service 里面,业务流程逻辑放到 controller 里面…但因为我用的是 php ,在网上找到的一些资料又说 weak object 是种反模式,比如 doctrine 的作者之一,在他的 doctrine 最佳实践的 ppt 里就说,实体应该要有行为,不然和数组有什么区别…

    然后找了一些 php 的 ddd 开发实例观摩,发现似乎过于复杂了,几乎把业务里所有东西都对象化了, id 这些不可变元素要做成 value object ,把它的行为都扔到 vo 里面,但是实际上很少会对 id 这些东西有什么复杂的操作,同样还有对 repository 的抽象,单独建了 instruction 这么一层来存放不同的数据存储,但是实际工作中很少会出现更换数据库这种事吧?有必要吗

    我觉得像 php , python 这种语言,并不需要全盘地采纳 ddd 的思想,不然还不如直接用 java 算了
    tianshiyeben
        5
    tianshiyeben  
       2016-08-18 09:49:38 +08:00   ❤️ 1
    1>首先,团队越来越大是好事情

    2>我是做 java 的,大多数项目都是采用你说的 贫血模型

    一般架构根据依赖关系从下到上分为, dao->service>controller->view(页面)
    ctrlaltdeletel
        6
    ctrlaltdeletel  
    OP
       2016-08-18 14:10:12 +08:00
    @kitalphaj 多谢回答,很棒。
    @feiyuanqiu 已标注想读。的确应该是以解决问题为目的出发,单纯模仿就有些过了。
    ihuotui
        7
    ihuotui  
       2016-08-19 04:38:17 +08:00 via Android   ❤️ 1
    把充血模型当作微服务化就差不多了,把每个方法都是一个微服务,只是这个微服务是在单个应用里面的,而真正的微服务是面向分布式的,记住类似就行了。
    chaleaochexist
        8
    chaleaochexist  
       2019-03-07 09:34:30 +08:00
    大佬有很多体会吗?遇到了类似的问题.
    waibunleung
        9
    waibunleung  
       2021-05-27 19:31:41 +08:00
    我有了同样的疑问,看这个帖子还是没有很好地得到解决呀...题主方便交流一下吗?
    waibunleung
        10
    waibunleung  
       2021-05-27 19:32:01 +08:00
    @ctrlaltdeletel 我有了同样的疑问,看这个帖子还是没有很好地得到解决呀...题主方便交流一下吗?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1058 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 22:18 · PVG 06:18 · LAX 15:18 · JFK 18:18
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.