在成为软件开发人员之前,我们是人-因此是习惯的养成。 一个人很难改变自己的习惯,一个人很难改变别人的习惯-对我们中的某些人来说,甚至更难。
本周,在进行代码审查时,我偶然发现了这种结构:
publicclassMyStructure{
privateStringmyProp1;
privateStringmyProp2;
// A bunch of other String properties
publicMyStructure(StringmyProp1,StringmyProp2/* All other properties here */){
this.myProp1=myProp1;
this.myProp2=myProp2;
// All other properties set there
}
publicStringgetMyProp1(){...}
publicStringgetMyProp2(){...}
// All other getters
publicvoidsetMyProp1(StringmyProp1){...}
publicvoidsetMyProp2(StringmyProp2){...}
// All other setters
}
注意:看起来像JavaBean,但这不是因为没有无参数的构造函数。
查看代码,我发现我们的代码中从未使用过setter,这使它成为不可变数据结构的不错用例-并节省了大量代码行:
publicclassMyStructure{
privatefinalStringmyProp1;
privatefinalStringmyProp2;
// A bunch of other String properties
publicMyStructure(StringmyProp1,StringmyProp2/* All other properties here */){
this.myProp1=myProp1;
this.myProp2=myProp2;
// All other properties set there
}
publicStringgetMyProp1(){...}
publicStringgetMyProp2(){...}
// All other getters
}
在这一点上,人们意识到String
本身是不可变的,这导致了第二个提议,该提议又节省了更多代码行:
publicclassMyStructure{
publicfinalStringmyProp1;
publicfinalStringmyProp2;
// A bunch of other String properties
publicMyStructure(StringmyProp1,StringmyProp2/* All other properties here */){
this.myProp1=myProp1;
this.myProp2=myProp2;
// All other properties set there
}
}
假定属性是final且Java String
是不可变的,则该类仍然可以防止不必要的更改。 请注意,它之所以起作用是因为Java中的String
根据定义是不可变的。 使用Date
属性,由于Date
是可变的,因此无法使用。
对于无状态服务,需要从子类访问的嵌入式服务也可以做到这一点。 不需要吸气剂:
publicclassMyService{
// Can be accessed from children classes
protectedfinalEmbeddedServiceanotherService;
publicMyService(EmbeddedServiceanotherService){
this.anotherService=anotherService;
}
}
请注意,该方法与Spring或CDI依赖注入100%兼容。
现在,您无法想象此简单评论引起的来回评论数量。 为什么? 因为即使从编码的角度来看这很有意义,但它与我们通常所做的完全不同。
在这种情况下,懒惰和IDE不能很好地为我们服务。 后者使创建访问器太容易了。 我很确定,如果我们必须手动编写getter和setter的代码,上述建议将更受欢迎。
这篇文章很容易被标题为“不要让习惯让你得到最好的”。 这里的课程是定期挑战您的编码方式,即使是简单易用的东西。 毕竟可能会有更好的选择。
翻译自: https://blog.frankel.ch/immutable-data-structures-java/