09 | 可变的数据:不要让你的代码“失控”
满天飞的 Setter
- 深入了解
- 翻译
- 解释
- 总结
可变数据在软件开发中可能引发不可控的变化和并发问题,本文提出了解决方案。作者建议使用行为封装和不变类来限制数据变化,以避免可变数据带来的问题。文章强调了封装数据变化的重要性,介绍了函数式编程中的不变性概念,并指出越来越多的语言引入值类型以限制可变性。总之,文章呼吁限制可变数据,提倡使用不变类和值对象来解决可变数据带来的挑战。
《代码之丑》,新⼈⾸单¥59
全部留言(20)
- 最新
- 精选
- crtmsvchttps://immutables.github.io/ Java 用這個,好用 :)
作者回复: 多谢分享
2021-02-2813 - 陈文昕对象如果需要构造的参数太多了怎么办? 我能想到的就是用builder模式来重构
作者回复: 正解
2021-01-1913 - 刘大明前段时间,领导交代了一个任务。任务是将某某前端传进来的字段,存储到数据库里面。当时领导说这么简单的一个功能,就给你一天的时间解决。我足足花了两天时间。我后来复盘了一下,任务延期的原因就是可变的数据,失控的代码,需要修改的代码点里面逻辑,而且充斥着各种set,当我在我自以为某个地方set了该字段之后,发现在代码的后面又有一个地方set了,在往后面又有地方set,那种感觉,真的酸爽。 学习了这篇文章之后,我自己后面一定要避免这种问题,如果不改,说不定后面坑到的还是我自己。
作者回复: 那种痛,经历过才懂。
2021-01-1949 - 源泉这些算是基于充血模型的吗?可我做过的项目全是类似贫血模型
作者回复: 你说得对,贫血模型本来就不是一个好的设计,只算把数据放到一起,谈不上封装。
2021-02-2536 - sean77我们项目用mybatis-plus, 由mybatis-plus-generator生成model, 原则上自动生成的代码不应手动修改, 但是按此文讲的要去除setter方法, 那自动生成的model基本都要大改了, 这个悖论该怎么解决呢
作者回复: 针对代码生成工具,如果它生成的是一个算法,比如编译器生成器,我可以去用,因为我只要关注接口,不需要关注细节。如果生成的是模型,我倾向于不用它,因为我要关注其中的细节。如果封装它,可能就失去了代码生成的意义。 我常常说到软件设计的品位,生成大量 setter 代码的工具,本身就是设计品位不佳的体现。基于一个品位不佳的工具谈改进,这可能不是我关注的方向。
2021-08-2545 - Jxin1.现实情况下,@Setter这个我去不掉啊。毕竟很多框架(dozer,mapstruct)都是基于生成set方法操作数据的。去掉的话,兼容性会受影响,开发工作量和风险也会增加(需要手动去维护新增字段的初始化)。 2.基于idea,我声明的变量都会带上final。这一度倍受挑战,因为带上final代码自然就变长了,可读性算是变差了吧,毕竟有时因为多个final就得换行;包括jdk函数库在内,大部分好demo的代码部分都不会带上final,所以当小伙伴拿这些例子质疑时挺无奈。 3.为什么声明要带上final,因为我也认为缺省变量应该是不可变的。只是受限于java语法特性,所以采用这种曲线的方式。 4.提到final就谈谈不可变对象。一个对象一旦声明,内部的数值结构就不可变,任何对内部值的变更操作都会生成新的对象。这个其实我一直在想,如果语言层面提供一个备忘录模式或许会挺好的。使用者做变更时不用手动新建对象,回退时也可以基于his版本对象无需重新创建。并且我们也有回滚到变更前一个状态或者前多个状态的诉求,也会有打印出所有变更操作的诉求。
作者回复: 用了 setter,习惯 setter,setter 才是去不掉的。 程序库中优秀的地方也许就是潜在的语言特性,这在《软件设计之美》讲程序库的时候提到过:程序库设计就是语言设计,语言设计就是程序库设计。
2021-01-2465 - Peterclass Book { public void approve() { this.reviewStatus = ReviewStatus.APPROVED; } } 有一个小小的疑问 就是采用这种方式this.reviewStatus = ReviewStatus.APPROVED; 有点像写死hardcode的感觉,万一这个reviewStatus可以存在其他状态,那不是又要增加一个设置函数了,反倒使用setter就不会有这种问题,不知道是不是我没有领悟这个方法的精髓,希望老师指点下
作者回复: 这个 reviewStatus 就是可以保存不同的状态啊,使用 setter 的话,就等于你把实现细节暴露给其他人了,人家想怎么用就怎么用,而封装了之后,别人必须把自己的意图告诉你,比如这里,他必须说,我要审核通过。
2021-07-0824 - 孙隽璐嵌入式C程序员表示眼馋这些其他语言直接提供的封装方法……
作者回复: 其实,C 语言也是可以把代码写得很好的,我在《软件设计之美》中用过一个 Linux 文件系统的例子。只不过,花的精力比较多,很多人不愿意这么做而已。
2021-01-273 - 桃子-夏勇杰我的理解使用不变性限制了大家一起改同一份数据的混乱,但同时又会引发多份副本数据的混乱,郑老师见过这样的情况么?
作者回复: 难道数据不存回去,只在内存里吗?那就得考虑事务性内存了。😄
2021-01-193 - adang在 Rust 中变量默认是不可变的,要想使其可变,需要在变量名前加 mut 关键字。这样不仅可以改变变量的值,而且也在告诉阅读代码的人,这个值在某个地方会被改变。 另外,它的所有权机制和对可变引用的规则限制,会减少很多可变的数据这种坏味道的发生。对 Rust 理解的不深,不知道这样的理解对不对。
作者回复: 所有权机制,目的不是这个吧?
2021-01-2122