Java 关于罗伯特·C·马丁的例子的问题';s_清洁代码_
这是一个关于函数只做一件事的概念的问题。如果没有一些上下文相关的段落,这是没有意义的,所以我将在这里引用它们。它们出现在pgs 37-38上: 换言之,我们希望能够像读取一个集合一样读取程序 of TO段落,每个段落都描述了当前的抽象级别,并引用了下一级别的后续段落 为了包括设置和拆卸,我们先包括设置,然后包括测试页面内容,然后包括拆卸。为了包括设置,我们包括套件设置如果这是套件,那么我们包括常规设置 事实证明,程序员很难学会遵守这一规则并编写代码 停留在单一抽象级别的函数。但是学习这个技巧也是非常重要的 重要的。这是保持函数简短并确保它们执行“一件事”的关键 让代码像一组自上而下的TO段落一样阅读是一种有效的方法 保持抽象级别的一致性 然后,他给出了以下糟糕代码的示例:Java 关于罗伯特·C·马丁的例子的问题';s_清洁代码_,java,design-patterns,Java,Design Patterns,这是一个关于函数只做一件事的概念的问题。如果没有一些上下文相关的段落,这是没有意义的,所以我将在这里引用它们。它们出现在pgs 37-38上: 换言之,我们希望能够像读取一个集合一样读取程序 of TO段落,每个段落都描述了当前的抽象级别,并引用了下一级别的后续段落 为了包括设置和拆卸,我们先包括设置,然后包括测试页面内容,然后包括拆卸。为了包括设置,我们包括套件设置如果这是套件,那么我们包括常规设置 事实证明,程序员很难学会遵守这一规则并编写代码 停留在单一抽象级别的函数。但是学习这个技巧也是
public Money calculatePay(Employee e)
throws InvalidEmployeeType {
switch (e.type) {
case COMMISSIONED:
return calculateCommissionedPay(e);
case HOURLY:
return calculateHourlyPay(e);
case SALARIED:
return calculateSalariedPay(e);
default:
throw new InvalidEmployeeType(e.type);
}
}
并将其问题解释如下:
这个函数有几个问题。首先,它很大,而且是新的
员工类型增加后,它将增长。其次,它显然不止一件事。
第三,它违反了单一责任原则7
(SRP)因为有不止一个
改变的理由。第四,它违反了开放-封闭原则8
(OCP)因为它
必须在添加新类型时进行更改
现在我的问题
首先,我很清楚它是如何违反OCP的,我也很清楚,仅此一点就使得它的设计很糟糕。然而,我试图理解每一个原则,我不清楚SRP是如何应用的。具体来说,我能想象的改变这种方法的唯一原因是增加了新的员工类型。只有一个“变化轴”。如果需要更改计算的详细信息,这只会影响“calculateHourlyPay()”等子方法
此外,虽然从某种意义上讲,它显然在做3件事,但这三件事都处于相同的抽象层次,并且都可以放在一个与示例一相同的段落中:为了计算员工的薪酬,如果员工是受委托的,我们计算委托的薪酬,如果他是每小时的,我们计算每小时的薪酬,因此,除了违反OCP之外,该准则似乎符合Martin的清洁准则的其他要求,尽管他认为不符合
有人能解释一下我遗漏了什么吗
谢谢 由于我没有足够的背景,我在这里做了一个很长的尝试。由于两个原因,此方法可能会更改(顺便说一句,代码也违反了基本的封装原则)
interface SalariedEmployee
{
BigDecimal calculatePay();
}
class HourlyEmployee implements SalariedEmployee
{
}
class CommissionedEmployee implements SalariedEmployee
{
}
Calculate可能会发生更改,原因似乎有两个:
在新的解决方案中,您要求员工计算他/她的工资,我不喜欢,因为这不能反映实际情况。实际上,你可以说这也违反了SRP。该计算由工资部门负责。我喜欢软件中的模型尽可能地代表现实世界的领域,但我们通常不得不做出妥协。在这种情况下,我认为员工类型的变化不会定期发生。事实上,它们很可能很少发生。所以,我会把事情放在业务领域有意义的地方,比如让payroll对象计算员工工资。同时,我将拥有并保留一套广泛的单元测试,因为我们应该确保当员工类型发生变化时,一切都能按预期进行。我也在努力解决这个问题,我想如果你不这样做,我可能会找到一些东西来说服你 改变这种方法实际上有两个原因:
这篇文章似乎有点陈旧,但我希望这能帮助其他人理解 嗯。。。。在这两种情况下,它仍然需要将新员工类型添加到