我正在学习如何用Java编写整洁有序的代码。 set()方法可以返回一个值,还是有更有效/可读的方法?
public class Car {
private boolean mHasAxles;
private boolean mHasTires;
private Tires mTires;
public setAxels(boolean hasAxles) {
mHasAxels = hasAxles;
}
public boolean hasAxles() {
return mHasAxles;
}
public boolean setTires(Tires tires) {
if(hasAxles()){
mTires = tires;
mHasTires = true;
return true; // Returns true if it was able to set tires
}
return false; // Returns false because car did not have axels
// Therefore, tires could not be set
}
}
在这个例子中,我的问题是关于setTires()方法。 如果班级在设置轮胎时检查汽车是否有车轴,或者应该将逻辑留给使用Car的班级? 是否应该调用setTires()方法,因为它返回一个值?
"常规",没有。
这与你的主要问题无关,但与编写有组织的代码有关:mHasAxels字段对于Car类没有多大意义,因为几乎所有汽车都有轴...我想。如果你想使用没有轴的汽车,我会将Car子类化为AxellessCar。
另一种方法是抛出异常,就像IllegalStateException一样
它可能不常见,但这个例子确实没有错。我认为更常规的方法是在调用set方法之前检查它是否有轴,或者知道如果你调用setTires方法然后汽车有车轴,也就是说汽车没有办法让车轴没有车轴。
这是一个很好的编码实践?没有!曾经听说过"关注点分离"吗?如果您需要这种类型的代码,那么您的基本设计是错误的。你需要阅读鲍勃叔叔的"清洁代码"
可能是以下内容的副本:stackoverflow.com/questions/1345001/…
addTires听起来像是一种更好的方法,这种方法更有意义返回true/false来指示结果。否则,setter有时返回this以便链接setter。
@Hector谢谢!这就是我想要的。我肯定会读那本书。因此,为了遵循这个例子中的"关注点分离"设计原则,使用Car的班级是否必须在设置轮胎之前检查汽车是否有车轴,因为汽车无法独立思考?这是最好的做法吗?
你还需要考虑封装。当然程序化的汽车可以自己思考:)。根据您在问题中提供的信息,您无法说明如何完成应用程序的整体设计。如果我是你,我会后退一步,想一想大图。您是否尝试代表所有类型的"Known To Man"?或只是汽车的类型?
传统上严格 - 不,设定者通常会返回空白。
话虽如此,如果你愿意,你可以自由地返回boolean - 约定经常被破坏(即使在内部java api中),方法签名(包括它的返回类型)应该激发感兴趣的开发人员导航到代码中看到究竟为什么返回boolean。
为了更清楚,您可能希望使用不同的方法名称,例如setTiresIfAble(Tires tires),或者您也可以返回void并按以下方式抛出异常:
public void setTires(Tires tires){
if(!hasAxels()) {
throw new IllegalStateException("no axels!");
}
mTires = tires;
mHasTires = true;
}
顺便提一下,mHasTires是还原剂,您可以随时检查是否tires == null。
最后,您可以避免使用java中的m或匈牙利符号(按照惯例),如下所示:
public setAxels(boolean hasAxels){
this.hasAxels = hasAxels;
}
setSomething方法不应返回任何内容
trySetSomething必须返回一个布尔值,表示该集合是否成功。
为什么?当您使用Java,C ++,任何语言编写代码时,您希望代码的任何读者(可能是人类)可以访问方法所做的大部分知识,只需读取他的名字。
为了完成这个断言,我们可以研究set可能失败的情况。处理故障有两种可能性,具体取决于方法的范围:
如果setSomething的范围是受保护的,私有的或包的,则意味着您可以作为API开发者控制它的调用方式。可以使用断言或RuntimeException来管理可能的失败(因为在方法签名中声明throws子句不是必需的)。
如果setSomething的范围是公共的,则意味着您无法控制它作为API开发者的控制方式。您必须警告API的用户setSomething不是错误安全的。您必须使用必须在throw子句中声明的异常来管理可能的失败。
您"可以"返回一个值,但按照惯例,setter不返回值。由于setter通常以一种甚至不引用返回值的方式使用,因此类的任何调用者都很容易忽略您返回的值。什么都没有阻止被叫做:
myCar.setTires(aTire);
...并忽略你甚至返回一个布尔值,因为这是调用和使用setter的正常方式。如果调用者可以忽略它并且代码看起来正确,则这会使您返回值的目的失败。
我的第一个倾向是抛出java.lang.IllegalArgumentException而不是返回false。