抽取出方法放于另一个类
请看下面这两个注释:
public class ParticipantInfoOnBadge {
...
void getParticipantFullNames() {
ParticipantsInDB partsInDB = ParticipantsInDB.getInstance();
Participant part = partsInDB.locateParticipant(participantId);
if (part != null) {
//取得参会者的英文全名.
engFullName = part.getELastName() + ", " + part.getEFirstName();
//取得参会者的中文全名
chiFullName = part.getCLastName()+part.getCFirstName();
}
}
}
因为程序员觉得这些代码片段还不够清楚,所以还是要用注释来解释它们。但这次移除注释时,我们会将抽取出来的方法放到Participant这个类里面,而不是ParticipantInfoOnBadge里了。
public class ParticipantInfoOnBadge {
...
void getParticipantFullNames() {
ParticipantsInDB partsInDB = ParticipantsInDB.getInstance();
Participant part = partsInDB.locateParticipant(participantId);
if (part != null) {
engFullName = part.getEFullName(); //将职责交给domain自己,也就是Participant
chiFullName = part.getCFullName();
}
}
}
public class Participant {
String getEFullName() {
return getELastName() + ", " + getEFirstName();
}
String getCFullName() {
return getCLastName() + getCFirstName();
}
}
用注释去命名一个已经存在的方法
请看下面的注释,这也是本例的最后一个注释了:
public class ParticipantInfoOnBadge {
...
void getOrgNameAndCountry() {
OrganizationsInDB orgsInDB = OrganizationsInDB.getInstance();
//取得参会者被雇佣部门的ID
String oid = orgsInDB.getOrganization(participantId);
if (oid != null) {
Organization org = orgsInDB.locateOrganization(oid);
engOrgName = org.getEName();
chiOrgName = org.getCName();
engOrgCountry = org.getEAddress().getCountry();
chiOrgCountry = org.getCAddress().getCountry();
}
}
}
之所以要用这个注释“取得参会者被雇佣部门的ID”是因为这个方法名“getOrganization”还不够清楚,所以,我们将注释表达的信息放在方法名里面,如下:
public class ParticipantInfoOnBadge {
...
void getOrgNameAndCountry() {
OrganizationsInDB orgsInDB = OrganizationsInDB.getInstance();
String oid = orgsInDB.findOrganizationEmploying(participantId);
if (oid != null) {
Organization org = orgsInDB.locateOrganization(oid);
engOrgName = org.getEName();
chiOrgName = org.getCName();
engOrgCountry = org.getEAddress().getCountry();
chiOrgCountry = org.getCAddress().getCountry();
}
}
}
public class OrganizationsInDB {
...
void findOrganizationEmploying(String participantId) {
...
}
}
改进完的代码
看看改进完的代码,如果让其他人读我们的代码,现在看懂需要多长时间?而重构之前,那个人又需要花多长时间?
public class ParticipantInfoOnBadge {
String participantId;
String participantEngFullName;
String participantChiFullName;
String engOrgName;
String chiOrgName;
String engOrgCountry;
String chiOrgCountry;
![]()
ParticipantInfoOnBadge(String participantId) {
loadInfoFromDB(participantId);
}
void loadInfoFromDB(String participantId) {
this.participantId = participantId;
getParticipantFullNames();
getOrgNameAndCountry();
}
void getParticipantFullNames() {
ParticipantsInDB partsInDB = ParticipantsInDB.getInstance();
Participant part = partsInDB.locateParticipant(participantId);
if (part != null) {
participantEngFullName = part.getEFullName();
participantChiFullName = part.getCFullName();
}
}
void getOrgNameAndCountry() {
OrganizationsInDB orgsInDB = OrganizationsInDB.getInstance();
String oid = orgsInDB.findOrganizationEmploying(participantId);
if (oid != null) {
Organization org = orgsInDB.locateOrganization(oid);
engOrgName = org.getEName();
chiOrgName = org.getCName();
engOrgCountry = org.getEAddress().getCountry();
chiOrgCountry = org.getCAddress().getCountry();
}
}
}
为什么要删除额外的注释?
为什么要删除额外的注释?其实,加注释本身是一件正确的事情,因为注释可以让人更容易地理解代码。但问题在于,因为常常没有把代码写清楚,所以我们就找了一个捷径,那就是写上注释。注释不够清楚,再写上文档。这样子,程序可以让人看懂了吧。这样造成的结果就是,没有人愿意去好好地组织代码,让代码清楚起来,因为他们觉得加上注释就好了。之后,代码更新,程序员却常常忘了去更新注释(我们不得不承认,这种情况经常发生)。过了一段时间,这些过时的注释不仅不能让代码更容易懂,反而会误导读代码的人。到了最后,我们剩下的东西就是:本身就不清晰的代码,加上一些不正确的注释。
因此,不论什么时候当我们要加注释时,我们应该再三想想:我的注释能否转化在代码里面,让代码跟注释一样的清晰呢?大多数情况下,我们得到的答案都是:能。每一个注释都是一个改进代码的好机会。我们不能说注释少的代码就是好代码,但我们绝对可以说,包含太多注释的代码绝对不是高质量的代码。
方法名太长
请看下面的例子:
class StockItemsInDB {
//找出所有数目少于10的海外存货
StockItem[] findStockItems() {
...
}
}
如果要将这段注释转为代码,原则上我们会改成这样:
class StockItemsInDB {
StockItem[] findStockItemsFromOverseasWithInventoryLessThan10() {
...
}
}
可惜的是,这个方法名实在太长了。别急,这并不表明我们不能去掉注释,相反这是在警告我们,代码有问题了。有什么问题呢?我们暂且不说,先看在这种情况下要怎么做呢?现在我们需要判断的是:这个系统的用户确实只对数目少于10的海外存货有兴趣吗?他有没有可能对那些数目少于20的海外存货有兴趣?他对本地存货就没兴趣了?或者超过25的存货有没有兴趣呢?基于以上考虑,我们可以把这里的注释转化到参数里面。具体如下:
class StockItemsInDB {
StockItem[] findStockItemsWithFeatures(
boolean isFromOverseas,
InventoryRange inventoryRange) {
...
}
}
class InventoryRange {
int minimumInventory;
int maximumInventory;
}
如果客户真是只对少于10的海外存货有兴趣呢?那他肯定有一些特殊的理由(为什么只是这些条件,而不是其他呢?)所以经过了解,我们发现因为海运所花时间很长,所以他需要补充这些存货。此时,我们发现客户真正感兴趣的是那些需要补充的存货,而不仅仅是那些海外数目少于10的存货。因此,我们可以将他真正的意思转化在方法名和方法的实现里。
class StockItemsInDB {
StockItem[] findStockItemsToReplenish() {
StockItem stockItems[];
stockItems = findStockItemsFromOverseas();
stockItems = findStockItemsInventoryLessThan10(stockItems);
return stockItems;
}
}
