在最近的快乐开发团队聚会期间,我们提出了五个要讨论的议程,然后很快就会讨论一些关于议程上没有的事情。
我们正在阅读一些代码,当我们团队中一位经验丰富的开发人员对下面的代码片段提出疑虑时。 (开发堆栈是TypeScript / Angular4),但这与讨论并不相关):
get someIsValidProperty(): Number {
return this.ruleService.runSomeRule();
}
在此实例中,模板表单上的字段引用someIsValidProperty
。在模板中看起来像是一个简单的调用某个属性,指示有效或无效的状态。在这方面,争论的焦点在于它看起来整洁而直观,并最终通过一些逻辑来调用,我们决定搬出并依赖。
然而,从单元测试的角度来看,它看起来很奇怪。正如我们断言使用期望值调用ruleService
的模拟。感觉是getter确实应该是一种方法,而且在客户端调用上下文中会更加清晰。此外,另一个论点是,getter和setter应该以某种方式暴露类/对象本身的内部状态,而不是传递给其他东西。
公平地说,我们是礼貌的,但是分歧,并决定'去看看其他团队正在做什么并复制它们®'
现在,当我回到我的办公桌时,我预计会激活谷歌,并找到一大堆狡猾的论据,以进一步激怒赋予各自阵营权力。
但是没有任何东西(我可以在我自己的短暂注意力范围内找到)。
所以,我的问题是真的,有什么理由,无论是哲学上还是其他原因,为什么我们应该避免在getter或setter中调用方法?本着避免基于意见的讨论的精神,一些明确的想法和论点将受到赞赏。
答案 0 :(得分:1)
我认为,这最终归根结底是一个美学和实践决定,而不是通用的通用准则。属性是语法糖,可以保存五个字符,您可以根据需要进行设置。我个人说,从客户的角度来看,将“似乎属于”该对象的任何东西都变成一个属性是公平的。然后,实现可以采用多种形状(从对象中的实际字段,私有字段的获取器或对另一个对象的方法的调用)。这对于测试伪造品非常实用。但是,当我说“很公平”时,我并不一定意味着我会一直这样做。团队开发的大型项目应优先考虑一致性和生产率。我认为公平地说属性可能很难测试,因此不应包含任何需要测试的逻辑。
可以从两种角度考虑这一点,以决定是否做出妥协。从模板设计者的角度(是否使用编码器)来看,属性使事情变得“更整洁”,这听起来不那么琐碎,因为更整洁的模板易于维护。从测试人员的角度来看,属性可能会使测试看起来“更糟”(再次降低了可维护性)。您拥有一个从“没有财产”到“任何财产都可以进入”的连续体,团队可以决定在哪里让所有人都感到舒适的界限,但是重要的是,这是明确的指导原则(例如“不要将逻辑放入属性中”或“记住测试属性,因为它们可能包含逻辑”。
一种可能的“两全其美”的解决方案是制定一条规则,例如“属性只能获取/设置私有字段或调用getter / setter方法”。所以你有:
getSomeIsValidProperty(): Number {
return this.ruleService.runSomeRule();
}
get someIsValidProperty(): Number {
return this.getSomeIsValidProperty();
}
因此,您拥有简洁的模板和漂亮的测试。当然,缺点是您的代码有些冗余(即使不需要测试属性)。