public class FooList {
public boolean add(Foo item) {
int index = indexOf(item.getKey());
if (index == -1) {
list.add(item);
}
return index == -1;
}
}
由于这会添加一个项目并返回一个成功值,它是否违反了单一责任原则? 如果是这样,有关系吗?
另一种方法是抛出异常:
public class FooList {
public boolean add(Foo item) throws FooAlreadyExistsException {
int index = indexOf(item.getKey());
if (index == -1) {
list.add(item);
} else {
throw new FooAlreadyExistsException();
}
}
}
但这是否也违反了单一责任原则? 该方法似乎有两个任务:如果该项不存在,则添加它;否则,抛出异常。
奖励问题:可以返回 null 的方法是否违反了单一责任原则? 下面是一个示例:
public class FooList {
public Foo getFoo(String key) {
int index = indexOf(key);
return (index == -1) ? null : list.get(index);
}
}
根据情况,返回 Foo 或 null 是"做两件事"吗?
这个怎么样:
public class MyVector{
private int[] data;
private int count;
public void add(int value){
data[count]=value;
++count;
}
}
add
做两件事 - 它更新data
并递增count
。根据单一责任规则,我应该将其分为两个功能:
public void MyVector{
private int[] data;
private int count;
public void add(int value){
data[count]=value;
}
public void inc(){
++count;
}
}
这 - 显然 - 打破了 OOP 的基础。我希望data
和count
一起改变 - 这就是将它们捆绑在一个班级中的全部意义!
如果你应用这样的单一责任规则,你不会走得太远。如果每个方法只能做一件事,那么整个程序只能做一件事,当一件事的定义像上面的例子中使用的那样时,你的程序就不能做任何有趣的事情。
问题是 - 这不是单一责任规则的工作方式:
您不应该努力编写无法以指定多个事物的方式定义的方法。相反,您应该编写可以有意义且充分定义的方法,以指定他们唯一做的事情。
您不应该基于实现定义一件事 - 您应该根据承载该方法的类的抽象来定义它。
这将有点争议:您应该对副作用更加严格,而对返回值则不那么严格。原因是方法的用户忽略返回值比忽略副作用更容易。
例外不应计为"该方法正在做另一件事"。它们不是方法功能描述的一部分 - 它们是例外,只有在出现问题时才会发生。这就是例外的重点。
现在,让我们看一下您的方法。实现包括三件事:检查是否存在、添加项和返回成功结果。但是,如果您查看抽象,则可以将其定义为添加不存在的项目 - 这是一回事!
是的,它也返回了一些东西,但返回值很容易被忽略,所以我不会把它算作"另一件事"。该方法的用户将使用它来添加项,因此如果他们不需要返回值,他们可以忽略返回值。如果情况正好相反,并且他们使用您的方法来检查项目是否存在,他们将无法忽略添加项目的副作用,那将是糟糕的。很差。但是由于"附加内容"是返回值(或异常)而不是副作用 - 您的方法没有问题。
最重要的设计规则是不要盲目遵循设计规则。