或者一个开发人员重用了这个构造器来校验一个潜在的用户所希望的用户名和密码,那么他被迫作出了一个不需要的远程调用,因为这些方法(isRequestedUsernameValid(), isRequestedPasswordValid())不需要账户状态。

String username = "robertmiller";

String password = "java.net";

try {

 //makes unnecessary remote call

 ICustomerAccount ca = new CustomerAccount(username, password);

 if(ca.isRequestedUsernameValid() && ca.isRequestedPasswordValid()) {

    ...

    ca.createNewActiveAccount();

    ...

 }

} catch (CustomerAccountsSystemOutageException e){

 ...

}

 
  习惯2:方法名清晰的表达方法的意图

  第二个习惯是,通过它们的方法名,所有的方法必须清晰的传递它们的意图。例如,isRequestedUsernameValid()让开发人员知道这个方法确定请求的用户名是否是合法的。与之相对照的是,isGoodUser()可能有好几种用途:它能决定一个用户的账户是否是活跃的,决定是否请求的用户名或密码是正确的,或者决定用户是否是一个好人。既然这个方法名的描述性不强,那么它对于其他开发人员来说很难确定它的意图是什么。简短地说,一个方法名使用长的和描述性的比使用短的和毫无意义的好。
长的、描述性的方法名帮助开发团队迅速的理解他们的软件的意图和功能。此外,应用这种技术到测试方法的名称,使得测试表达了软件现有的需求。例如,软件要求检验请求的用户名和密码是不同的。使用方法名称:testRequestedPasswordIsNotValidBecauseItMustBeDifferentThanTheUsername()能传递测试的这个意图,因此为表达了软件需求的意图。

import junit.framework.TestCase;

 

public class CustomerAccountTest extends TestCase{

 public void testRequestedPasswordIsNotValid

        BecauseItMustBeDifferentThanTheUsername(){

    String username = "robertmiller";

    String password = "robertmiller";

    ICustomerAccount ca = new CustomerAccount(username, password);

    assertFalse(ca.isRequestedPasswordValid());

 }

}

  这个测试方法可以很简单的被命名为testRequestedPasswordIsNotValid(),或者更差的testBadPassword(),这两个名称都使得它很难确定测试的意图。不清楚地或者说含糊不清的名称将导致效率的损失。效率的损失导致需要增加额外的时间来理解测试、创建不需要的方法或属性、重复的或者冲突的测试、或者销毁了对象已经测试过的已经存在的功能。

  后,描述性的方法名减少了对于常规文档或者Javadoc注释的需要。
 
  习惯3:一个对象执行功能集中的服务集

  第三个习惯是,软件的每一个对象都集中的执行一个小的、的服务集。执行小基数工作的对象容易阅读,容易正确使用,因为只有少量的代码需要理解。此外,软件的每一个对象都必须执行的服务集,因为重复的逻辑浪费开发人员的时间,增加维护的成本。设想,未来,业务团队要求升级isRequestedPasswordValid()的逻辑,如果两个不同的对象都有执行相同动作的类似方法,在这种情况下,软件开发人员将要比升级仅仅一个对象花费更多的时间来升级两个对象。
作为案例学习的示例,CustomerAccount对象的目的是管理一个独立的客户的账户。它首先是创建一个账户,然后是验证账户对于购买商品来说仍然是活跃的。假设在未来,软件需要给那些购买了十件以上商品的客户折扣。创建一个新的接口,ICustomerTransactions,而且对象,CustomerTransactions,来实现这些新的特性。这些都是开发“易于理解”软件需要有目的进行的工作。