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

实施 DDD(领域驱动设计)的好处,有没有可以量化的指标?

  •  
  •   Weixk · 2021-01-03 04:05:21 +08:00 · 4015 次点击
    这是一个创建于 1406 天前的主题,其中的信息可能已经有所发展或是发生改变。
    24 条回复    2021-01-04 16:11:44 +08:00
    lewis89
        1
    lewis89  
       2021-01-03 07:50:55 +08:00   ❤️ 3
    目前应该没有很好的量化指标,或者我个人认为 DDD 根本无法量化

    1.从战术建模层面上来讲,它那套东西本质上并不是原创,SOLID 跟设计模式里面早就有了,只不过面向对象建模对于粗制滥造的中国软件行业来讲不太适用,当然这是另外一个问题了,毕竟大部分公司活不到需要重构整个系统的那天,如果有..大多也是请人重写了,毕竟人力成本摆在那里,企业开发领域 例如 Java 生态如此之好,轮子都是现成的,搭好架子就能开始撸业务,基本上招几个老手带着一堆菜鸟重写整个系统简直是不要太便宜的一件事情了。

    所以从战术建模层面上讲,你很难按说你的模型划分清晰在长远来看就能带来多大的好处,因为大部分时候大部分场景下业务系统都是重写了,而并非重构,因为重构至少得有单元测试跟说明文档,大部分公司能保证核心业务系统代码单元测试覆盖率到 80%以上就非常不错了。

    2.从领域划分上来讲,真实世界的业务发展大多都是无序的,也并非是一个程序员能主导的,在大部分互联网公司运营比产研部门要强势很多,毕竟运营是直接给公司创造数据跟估值的部门,所以别说领域能够划分清晰,在一个系统里面想实现一个业务只有一个精确的表达都很难,因为我真就为了一个业务领导需求把一个跨部门对接的模块重新做了一遍,而且两个模块功能都是差不多的,只不过我这个模块又加了一些其它的业务属性配置维度。

    另外这两个模块的配置是相互影响的,是不正交的,配置起来差不多类似 CSS,当然没有 CSS 那么复杂,但你一旦使用,就必须得同时关注两个功能配置模块,否则就会出问题,如果测试跟运营只使用先前的模块而忘记我开发的新模块,那么很有可能在属性配置上就会产生意想不到的结果,而我评估的时候就想到了这个问题,因为大部分人很难记住一件事情需要配置两个模块,而且运营人员之间使用这个系统也大多是口口相传,并没有规范化的文档,结果就是一年的时间里面,那个地方运营测试找了我不下 10 回,我跟他们解释了不下 10 回。

    其实正交这个事情,现实中是有大量案例的,例如驾校老师跟你讲,开车遇到危险不要做除踩刹车之外任何多余的操作,除非你是开赛车的,而且像开车遇到危险这种事情还难免有些女性司机把油门当刹车踩,所以你要教导一些普通的人遇到危险还去操作方向盘简直难如同登天,还不如买个带 ABS 的车,遇到危险只管踩刹车就好,其余的事情交给上帝就好。
    cabing
        2
    cabing  
       2021-01-03 09:51:09 +08:00
    DDD 在人力有限,要保证业务迭代的情况下实现很难。
    hantsy
        3
    hantsy  
       2021-01-03 10:55:34 +08:00
    先总结下我看到 V 站的一些观点。
    1,增加了工作量,代码量明显多了
    2,大量接口,明显是过度设计
    3,没时间 DDD

    得出的结论一致,不适用。还是传统从界面到数据库一竿子捅到底,搞出来了界面就算大功造成了。
    hhhsuan
        4
    hhhsuan  
       2021-01-03 11:11:44 +08:00
    啥叫 DDD ?
    noreplay
        5
    noreplay  
       2021-01-03 11:28:05 +08:00 via Android   ❤️ 7
    @hhhsuan deadline driven development
    hantsy
        6
    hantsy  
       2021-01-03 11:30:06 +08:00
    @noreplay 这个解释不错。
    mikulch
        7
    mikulch  
       2021-01-03 11:36:05 +08:00   ❤️ 1
    我们公司是因为公司用的框架是 jpa,所以我才开始研究 ddd 的。研究了几本书,也看了很多资料,目前正在一个小项目里面实践战术设计的落地。
    就我个人的感觉的话,ddd 的精髓可能确实是在战略设计。战术设计那一块儿本质上是为战略设计服务的。但是战略设计实际上是对业务、运营、产品团队提出了要求:不能异想天开、提出需求设计功能必须有逻辑性、你的设计就是代码的工作方式。

    所以 ddd 的精髓说白了需要团队之间互相配合。国内的运营和产品,还有业务的水平大家都懂,我个人认为这个实在是太难了。
    hantsy
        8
    hantsy  
       2021-01-03 11:53:15 +08:00
    @mikulch 落地第一步需要所有的 Stakeholders 统一一种大家认可的 UL,来描述业务。有些公司就直接用 UML 代替,结果非技术人员一头雾水。

    UL ( UBIQUITOUS LANGUAGE,统一语言)实施最好用白板手绘,不同的彩笔去描述事件,实体,流程,等,比如:不同颜色的方框,圆圈,实线,虚线 箭头,等。
    hantsy
        9
    hantsy  
       2021-01-03 11:54:06 +08:00
    没有一种公共的语言去描述业务,业务人员,技术人员,管理人员怎么沟通。
    taowen
        10
    taowen  
       2021-01-03 12:02:06 +08:00 via Android
    业务架构的评价标准看三个指标。第一,自主性,需求实现过程中需要多少沟通。第二,一致性,圈定的必须保持一致的实现多大程度可以被保持。第三,反馈速度,最终的业务效果,技术故障,多快可以反馈到对应的负责团队。
    mikulch
        11
    mikulch  
       2021-01-03 12:59:07 +08:00
    @hantsy 你们公司落地战略设计了吗?希望可以一起讨论。
    mikulch
        12
    mikulch  
       2021-01-03 13:22:08 +08:00
    就像比如说,用户注册这个动作是不是应该包含在用户领域 entity 里面?如果应该包含的话,为什么呢?
    @hantsy
    @lewis89
    taowen
        13
    taowen  
       2021-01-03 13:38:28 +08:00 via Android
    @mikulch 不应该放在 user entity 里。因为这样会导致 user 这个类很大,但是你每次修改的时候只需要关心其中很小一部分,其余的强行塞进来的功能都是阅读上的噪音。从指标上来说,这么做就是降低了自主性。user entity 的负责开发经常要去开各种不想关功能的需求评审会,提高了沟通成本,降低了自主性
    tydl
        14
    tydl  
       2021-01-03 13:44:20 +08:00   ❤️ 1
    听不懂你们讲的。。。
    我只懂 CRUD
    mikulch
        15
    mikulch  
       2021-01-03 13:44:40 +08:00
    @taowen 那什么功能应该放到 user entity 里面
    如果放到 service 不就又变成贫血模型了吗?
    afewok
        16
    afewok  
       2021-01-03 13:49:47 +08:00
    一直认为没有指标,没有标准,甚至都说不清是不是的玩意,就是玩具,比如 DDD

    反过来想,如果可以根据 DDD 建立静态代码扫描和分析,然后告诉我们怎么写更合适,是不是很赞?
    vhysug01
        17
    vhysug01  
       2021-01-03 13:53:13 +08:00 via iPhone
    国情不合适 手动狗头

    实话说,现在的市场环境,我不知道一个领域专家有啥用
    taowen
        18
    taowen  
       2021-01-03 14:02:03 +08:00 via Android
    @mikulch 所有的读操作都可以放外边去,写操作中存在彼此有竞争关系的写操作放在 entity 中。例如两个操作都会修改 status 字段,把这两个写操作放同一个文件中就便于阅读。判断标准就是一次修改大概率需要同时查阅的代码放得尽可能近。
    hantsy
        19
    hantsy  
       2021-01-03 14:17:49 +08:00   ❤️ 1
    @mikulch 在分析一个流程的时候,要抽象几种东西。
    1, 状态(主要各阶段的数据, 不变性)
    2,行为动作(可以是人触发的,或者系统定时操作)
    3,状态的变化 (可以描述为事件)

    用户注册更多说法应该存在一个流程,
    1,用户注册,需要用户注册资料
    2,注册行为一个动作
    3,结果是可能失败也可能成功

    具体到代码上,如果分得足够细的话。

    1. UserRegRequest 封装用户注册请求
    2,interface UserRegister{} 封装行为过程
    3. UserReqResult 注册结果(失败或者成功)

    UserRegister 处理中,可能包括数据库的交互( Repository, Entity 抽象),与其它 Domain 的交互,比如 Register 成功的情况 raise RegisteredEvent 去通知另外一个 Notification Domain 发送一封邮件。

    具体实践过程,为了偷懒,很多时候一个类可能代表了多个角色,最常见的我们写 Spring,Entity 代替了 DomainClass (真正设计应该完全分开,Domain 类应该包括业务处理)。即使如此,也应该清楚这个类在什么地方应该充当什么角色。遗憾的是,一些开发人员,完全脱离业务,只看到一个类封装了什么字段。

    DDD 参考代码,经典的 CargoTracker 程序,DDD 原书自带的。

    https://github.com/citerus/dddsample-core (使用了 Spring 作为 Glue )

    另外,Java EE /Jakarta EE 标准也维护了一个版本。

    https://github.com/eclipse-ee4j/cargotracker

    DDD 原书没有在代码组织上过多的深挖,基本是三层结构的演变,定义了,interfaces, applicaiton, domain, infrastruture 四层结构。

    真正能够很好揣述 DDD 在代码结构上的规划,应该用后来演变出来的 Onion 和 Hexagonal 架构。第一次看到 Hexagonal 系统用 Driving 和 Driven 将整个应用体系一分为二的时候,很多东西感觉清晰了。

    https://reflectoring.io/spring-hexagonal/
    taowen
        20
    taowen  
       2021-01-03 17:27:53 +08:00 via Android
    @afewok 业务架构的目标都是优化新需求的实现过程。什么是需求,什么算新,都很难采集数据。静态扫描的问题是缺少需求,以及需求变更的记录。静态结构从业务架构来说是没有好也没有坏的,需求不变,咋写都可以。
    stupil
        21
    stupil  
       2021-01-03 19:10:19 +08:00
    ls 以及 lss 有啥 ddd 的好的书籍推荐吗
    xcstream
        22
    xcstream  
       2021-01-03 21:19:20 +08:00   ❤️ 2
    别整哪些没用的,我们需要的是 ,老板一句话立马就可以改出来的程序。
    zhaoxj58
        23
    zhaoxj58  
       2021-01-03 23:18:43 +08:00 via iPhone
    业务代码用 DDD,单元测试写起来挺爽的
    tmackan
        24
    tmackan  
       2021-01-04 16:11:44 +08:00
    @zhaoxj58 程序的可测试性更高
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2850 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 02:24 · PVG 10:24 · LAX 18:24 · JFK 21:24
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.