技术开发 频道

敏捷开发的必要技巧(二)

【IT168 技术文章】    这是一个会议管理系统。在会议中,每个参会者都会戴一个牌子,牌子上面有该参会者的信息(比如姓名等)。在该系统中,Badge类用来存放参会者的信息。请看下面的代码跟注释:

//存放参会者所戴的牌子显示的信息 public class Badge { String pid; //参会者ID String engName; //英文全名 String chiName; //中文全名 String engOrgName; //所在部门英文名称 String chiOrgName; //所在部门中文名称 String engCountry; //部门所在国家的中文名称 String chiCountry; //部门所在国家的英文名称 //*********************** //构造函数 //根据参会者ID,从数据库取出该参会者信息 //*********************** Badge(String pid) { this.pid = pid; //*********************** //取出参会者 //*********************** ParticipantsInDB partsInDB = ParticipantsInDB.getInstance(); Participant part = partsInDB.locateParticipant(pid); if (part != null) { //取出参会者的英文全名 engName = part.getELastName() + ", " + part.getEFirstName(); //取出参会者的中文全名 chiName = part.getCLastName()+part.getCFirstName(); //*********************** //取出所在部门跟国家 //*********************** OrganizationsInDB orgsInDB = OrganizationsInDB.getInstance(); //取出所在部门的ID String oid = orgsInDB.getOrganization(pid); if (oid != null) { Organization org = orgsInDB.locateOrganization(oid); engOrgName = org.getEName(); chiOrgName = org.getCName(); engCountry = org.getEAddress().getCountry(); chiCountry = org.getCAddress().getCountry(); } } } ... }

    如何将注释转换为代码,让代码足够清楚到可以表示注释?我们先看一下第一个注释:

//存放参会者身上戴的牌子所显示的信息 public class Badge { ... }

    我们干吗需要这个注释呢?因为程序员认为“Badge”这个类名不足以让读代码的人清楚这个类的作用,所以写了这个注释。如果我们直接将注释所表达的一些信息放在类名里面的话,就没有单独写注释的必要。比如:

public class ParticipantInfoOnBadge { ... }

    其实很多人肯定会问难道写注释不是一个好的编程习惯吗?这问题很好,我也想知道。在解释之前,我们先把这个示例中所有的注释都转为代码看看。

将注释转换为变量名

    比如:

public class ParticipantInfoOnBadge { String pid; //参会者ID String engName; //英文全名 String chiName; //中文全名 String engOrgName; //所在部门英文名称 String chiOrgName; //所在部门中文名称 String engCountry; //部门所在国家的中文名称 String chiCountry; //部门所在国家的英文名称 ... }

    这里,我们将对属性的注释转化为属性名。比如:

public class ParticipantInfoOnBadge { String participantId; String participantEngFullName; String participantChiFullName; String engOrgName; String chiOrgName; String engOrgCountry; String chiOrgCountry; ... }

    又如,可将对参数的注释转化为参数名:

public class ParticipantInfoOnBadge { ... //*********************** //构造函数 //根据参会者ID,从数据库取出该参会者信息 //*********************** ParticipantInfoOnBadge(String pid) { this.pid = pid; ... } }

    可以转化为:

public class ParticipantInfoOnBadge { ... //*********************** //构造函数 //从数据库取出该参会者信息 //*********************** ParticipantInfoOnBadge(String participantId) { this.participantId = participantId; ... } }

将注释转换为方法的一部分

    上面的构造函数中有两句注释,第一句我们已经解决了,那么还有“从数据库取出该参会者信息”如何处理呢?这句注释描述了该构造函数如何实现,即从数据库取出信息。我们可以将这句话转化为:

public class ParticipantInfoOnBadge { ... //*********************** //构造函数 //*********************** ParticipantInfoOnBadge(String participantId) { loadInfoFromDB(participantId); //现在看一下这个构造函数内部,我们就能知道这个构造函数是做什么的了 } void loadInfoFromDB(String participantId) { this.participantId = participantId; ... } }

删掉没用的注释

    有时候,我们会碰到一些注释,很明显没什么用处的,比如:

public class ParticipantInfoOnBadge { ... //*********************** //构造函数 //*********************** ParticipantInfoOnBadge(String participantId) { ... } }

    就算去掉这些注释,我们也能看出来这是一个构造函数。这个注释并没什么用处。
    什么样的类是看代码的人最喜欢的?那就是简单易看的类。一个设计得好的类,能够让人一眼看出这个类都有些什么东西,明白这个类都做了什么事请。如果看这个类时,要不停地将屏幕滚来滚去,思维还要随屏幕的滚动跳转,无形中看懂这个类需要花的时间就多了。
    一个屏幕,差不多只能显示20行左右的代码,而这个没用的注释一下子就占用了3行代码,一些有用的信息反而被挤掉(比如代码),得不偿失。还是赶紧移除这个注释吧。

public class ParticipantInfoOnBadge { ... ParticipantInfoOnBadge(String participantId) { ... } }

用方法名来表达注释

    还可以将一部分代码重构成方法,用方法名来表达注释的意思。先看看下面这个注释:

void loadInfoFromDB(String participantId) { this.participantId = participantId; //*********************** //取得参会者的全名 //*********************** ParticipantsInDB partsInDB = ParticipantsInDB.getInstance(); Participant part = partsInDB.locateParticipant(participantId); if (part != null) { //取得参会者的英文全名 engFullName = part.getELastName() + ", " + part.getEFirstName(); //取得参会者的中文全名 chiFullName = part.getCLastName()+part.getCFirstName(); //*********************** //取得参会者所在部门和国家 //*********************** 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(); } } }

    现在我们已经看清这段注释要表达一些什么信息。要使代码跟注释一样清楚,我们可以将注释所解释的那一部分代码抽取出来做成一个方法,然后让方法名来表达注释的意思。如果可以的话,我们就不需要额外的注释了。

void loadInfoFromDB(String participantId) { this.participantId = participantId; getParticipantFullNames(); //取得参会者的全名,注意,我们已经将注释去掉了 //*********************** //取得参会者所在部门和国家 //*********************** //取得参会者被雇佣部门ID OrganizationsInDB orgsInDB = OrganizationsInDB.getInstance(); 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(); } } void getParticipantFullNames() { ParticipantsInDB partsInDB = ParticipantsInDB.getInstance(); Participant part = partsInDB.locateParticipant(participantId); if (part != null) { //取得参会者的英文全名 engFullName = part.getELastName() + ", " + part.getEFirstName(); //取得参会者的中文全名 chiFullName = part.getCLastName()+part.getCFirstName(); } }

    此外,还有一个注释“取得参会者所在部门和国家”也是可以重构在方法名里面的:

void loadInfoFromDB(String participantId) { this.participantId = participantId; getParticipantFullNames(); getOrgNameAndCountry(); //又抽取掉一个注释 } void getParticipantFullNames() { ParticipantsInDB partsInDB = ParticipantsInDB.getInstance(); Participant part = partsInDB.locateParticipant(participantId); if (part != null) { //取得参会者的英文全名 engFullName = part.getELastName() + ", " + part.getEFirstName(); //取得参会者的中文全名 chiFullName = part.getCLastName()+part.getCFirstName(); } } 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(); } }
0
相关文章