手把手教你落地 DDD
钟敬
Thoughtworks 首席咨询师、数字化转型与运营团队 DDD 负责人
19697 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 45 讲
AIGC特别策划 (2讲)
结束语&结课测试 (2讲)
手把手教你落地 DDD
15
15
1.0x
00:00/00:00
登录|注册

12|代码实现(下):怎样更加“面向对象”?

你好,我是钟敬。今天咱们继续研究编码。
上节课我们学习了领域服务工厂两个模式,分别用于实现领域逻辑以及创建领域对象。今天我们考虑再增加一些面向对象的元素。
面向对象的三个特征是封装、继承和多态。其中多态我们暂时还不涉及。而上节课我们完成的添加组织功能,在封装和继承方面还不到位。
今天我们会继续开发修改组织功能,结合这个功能的开发,看看怎样运用封装和继承。

为“修改组织”功能开卡

为了完成修改组织的功能,我们再一次把产品经理老王请过来进行“开卡”,看需求的细节是否理解到位。
首先要确认的一个问题是,到底要修改组织的哪些信息。目前的 Org 对象一共有 11 个属性,我们列成一个表,和老王逐一确认。
这个表的含义是,在完成某个功能时,客户端要提供哪些数据。其中“创建”一栏是创建组织时需要哪些参数。“修改”一栏中的问号,是我们觉得在修改时需要客户提供,但需要与业务确认的。
老王轻轻一笑,眼神中的意思是“你们这些搞 IT 的还是不懂业务呀”,然后给出了后面四条意见。
1. 如果修改“上级组织”的话,实际上是在调整组织结构。一般不作为普通的修改功能,建议增加专门的“调整组织结构”功能。
2.“组织类别”不能修改,也就是说,一个开发组不能直接变成开发中心。如果真有这种需求,需要另外创建新的开发中心,把人迁移过去,然后撤销当前的开发组。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入探讨了如何更加“面向对象”地实现代码,主要围绕封装、继承和多态这三个面向对象的特征展开讨论。作者首先讨论了修改组织功能的开发,结合封装和继承的应用。随后,详细介绍了初步完成程序功能的代码实现,包括OrgService和OrgHandler的具体实现。文章还讨论了如何提高应用API的封装性,通过编写单独的参数DTO来简化入口参数的JSON格式,提高系统的封装性。此外,还提出了提高领域对象的封装性的方法,包括限制getter和setter的数量,以及用表示业务含义的接口代替简单的setter和getter。另外,文章还介绍了如何用继承消除重复,以及编程风格的回顾。总的来说,本文通过实际的代码实现和技术讨论,深入浅出地介绍了如何更好地实现面向对象的编程。 通过本文,读者可以学习如何利用封装和继承来提高代码质量。作者通过实例详细阐述了如何在API和领域对象层面实现封装,以及如何利用继承减少代码重复。此外,文章还对编程风格进行了回顾,强调根据实际情况进行权衡。读者可以通过本文学习到如何利用面向对象的编程思想来提高代码质量和可维护性,为实际项目开发提供了有益的指导。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《手把手教你落地 DDD》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(22)

  • 最新
  • 精选
  • 别天神
    置顶
    1、对于包级私有权限来增强封装我觉得是可行的,领域对象的更改我认为只能通过领域方法来做,一方面保护了领域状态的一致性,另一方面也能最大程度确保开发人员随意更改状态,所以通常我觉得 领域对象内部不应该存在set方法,取而代之的是更加“表意”的领域方法。 2、但是从存储介质进行领域对象恢复的时候,有时候又需要set方法,恢复领域对象应该无需关心业务,所以存在一些矛盾点: - 为了保护业务一致性和封装,不暴露set - 为了恢复领域对象,我们需要set,更进一步,为了使用工具类进行属性的copy还要求set必须是public的 在实际实现上,我采用了一些折中的方案, - 领域对象自身不具备set方法,有一个包级别的领域对象Builder,Builder中承载set,如@Builder(setterPrefix = "set", toBuilder = true, access = AccessLevel.PROTECTED) - 这样可以在同一个包内访问builder, 构建builder实例,同时因为setXxx是public的,还能解决属性copy问题 - builder.build()可以转换成领域对象 - 可以建一个FQN一样的包(和仓储实现同模块),里面仅存放着 持久化对象到领域对象的转换,因为包名一样,可以访问到set

    作者回复: 这个思路不错👍🏻

    2023-02-04归属地:上海
    4
  • Jaising
    还在犹豫是否要翻过墙的时候,就先把帽子丢到墙的另一边,剩下的自然会有办法。 以我切身体会仅仅迭代一学完就治好了不少DDD恐惧症,真的感谢钟老师和编辑小新的最小闭环设计,对零基础入门DDD不要太好,平时不愿记笔记的我都能跟着老钟医通过重新演绎更新了五篇——事件风暴、领域建模、数据库设计、分层架构和代码实现,小结与导航在这里:https://juejin.cn/post/7190270005072625723。 辞旧迎新,给自己的最好礼物就是持续学习,学以致用,换取职业生涯不断上台阶的可能,终身成长就有了立身之本,用来抵御各类危机。新的一年从入门DDD开始,会发现软件开发的世界照进了新的光,让我们一起加油! 祝各位兔年快乐!

    作者回复: 很佩服你的学习精神,加油!

    2023-01-20归属地:安徽
    2
    12
  • bin
    handler如果不依赖数据库,这部分业务逻辑好像也可以放到领域对象里面。有没有一个好的边界区分?

    作者回复: 目前的风格就是以是否依赖数据库来区分,参考课程中对代码风格的总结。当然,也可以制定你自己的代码规则。

    2022-12-31归属地:广东
    6
  • aoe
    原来我现在的编程风格是偏过程式的 思考题 1. 可以。这样确实可以增强封装。再疯狂一点,可以使用 Java 模块化技术,让反射都无法打破封装。 2. 没发现不应该有 getter 的属性。

    作者回复: 关于第2问,可以扩展一下。比如对于状态,如果用 isEffective(), isTerminated()之类的方法封装了,那么未必要用 getStatus()了。

    2023-01-03归属地:广东
    2
    3
  • H·H
    领域对象是否可以通过依赖注入的方式注入 仓储Repository?

    作者回复: 你是指把repository注入领域对象,从而使领域对象可以访问数据库吗?理论上可以,就看你要不要选这种编程风格。

    2023-01-30归属地:上海
    3
    2
  • 6点无痛早起学习的和尚
    一些问题: 5. 为什么在 addOrg 加事务?里面就一个 save 操作,是否没必要加@Transactional 6. 很多用@Autowired 注入的属性,有些是 final,有些不是 final,这个有什么讲究吗?

    作者回复: 加了@Transactional不会有什么坏处,如果以后逻辑更复杂了,可以避免忘掉。 @Autowired注入的属性一般都用final,我有些地方没注意,等我稍后统一改一下

    2023-01-17归属地:北京
    2
  • Breakthrough
    钟老师,DDD设计完成后的交付文档一般长啥样,是不是也要做类似设计需求说明书的WORD档。如果是,是否有相关的模板参考下?

    作者回复: 关键是有领域模型、词汇表、业务规则表,可以把这几个制品融入到目前使用的文档中。

    2023-07-17归属地:北京
    1
  • 龙腾
    老师请教一下,“第三,应用服务可以读写数据库。”这块没太明白,什么情况下读写数据库不包含领域知识呢?咱们的数据库设计不就是按照领域来划分设计的吗,只要读写都是在领域内进行的吧?

    作者回复: “调用Repository,从数据库里取出一个领域对象”这句话是不需要和业务人员谈的,因此这句话反应的逻辑不包含领域知识,

    2023-01-02归属地:广东
    1
  • 路上
    类似撤销这部分校验逻辑,目前看领域对象自己就可以校验,目前是在外层进行的校验之后调用领域方法进行状态变更 是否可以在领域对象变更状态的方法内部自己进行校验呢

    作者回复: 没错,后面就会讲到这个思路。

    2023-12-15归属地:北京
  • 末日,成欢
    老师,有一些疑问。 第一,领域对象不访问数据库。 这里的不访问数据库,是指可以在领域服务中访问,而不要在领域对象中里访问数据是吧。 第二个疑问, 修改组织信息和撤销组织, 第一步骤是查询组织是否为空, 这应该也是领域服务中的逻辑判断,应该也放在领域服务中把。这里直接放在应用服务的考虑是什么? 还有为何save方法没有放到领域服务中?这里的应该不是应用逻辑把? 第三个疑问, 事件风暴法中的第一个识别领域事件,这个领域事件维度多大呢,比如我想进行任务分解, 应该在哪个流程进行分解才合适呢? 目前代码看到这里,还是偏向过程化, 只是利用了一些软件的设计原则(比如solid),代码更业务化, 还没理解有啥好处

    作者回复: 第一:是的 第二:为了避免累赘,或者你看能否有更好的写法贡献出的? 对save的调用不算领域逻辑 第三:粒度大体相当于一个事务 本课程的的代码是偏过程式的。或许以后有时间给大家讲讲真正的面向对象编程是什么样。

    2023-06-13归属地:陕西
收起评论
显示
设置
留言
22
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部