`

编写好的面向对象代码

    博客分类:
  • j2se
阅读更多

 本文是java.net上的一篇博客,作者Curtis Cooley对编写好的面向对象代码有些建议,希望对大家都有所帮助。(2008.10.08最后更新)

获取经验没有捷径。编写好的面向对象代码需要经验,但这儿有三种做法能帮你在一开始就很顺利,即便你是老顽固:
    1. 使用测试驱动开发(TDD)编写你所有的代码
    2. 遵循简单法则
    3. 告之而非问之

使用TDD编写所有代码
    按测试先行编写的代码与按测试后行编写的代码是极为不同的代码。按测试先行编写的代码是松耦合与高聚合的。当某个属性或私有方法需要暴露给测试程序时,按测试后行编写的代码常会打破封装,因为该类并不是为了测试而设计的。如果你首先编写测试代码,你的依赖将会更好,你的代码将是松耦合与高聚合的。后面会有更多关于测试能帮助你设计更佳代码的内容。

遵循简单法则
    代码是简单的,只要当它:
    1. 执行了所有的测试
    2. 不包含重复
    3. 表达了所有的意图
    4. 使用最少的类和方法
注意到我用的是个被排序了的列表是很重要的。顺序是重要的。只有一个main()方法的的GodClass[1]不会是简单的。这个类可能执行了所有的测试,但在任何比"Hello, world!"更复杂的程序中,它肯定包含了重复,并且也没有表达出全部的意图。
我努力使用简单法则去关注If问题。我不知道如何使用简单法则去阻止某人编写重量级的If代码。有人可能会提出不同意见,我也尝试过,但这样的重量级If代码确实无法表达意图。但当你阅读如下代码时

<!---->if (mobile.getType() == MobileTypes.STANDARD) {
  alert();
}

确实难以看出其中的意图。这些代码无论处于哪个方法的上下文环境中,我们都能知道,如果mobile是STANDARD类型的话,那么就报警。而你所需要的更多意图呢?
我还有一点儿灵感显现。如果有那样的代码,那么在其它地方肯定还会有更多那样的代码。这些代码可能就像:

<!---->if (mobile.getType() == MobileTypes.GAS) {
  registerGasReading();
}

<!---->if (mobile.getType() == MobileTypes.TEXT) {
  sendTextMessage();
}

<!---->if (mobile.getType() == MobileTypes.LOCATION) {
  notifyLocation();
}

你看出来了吗?我是看出来了。它违反了规则2,有很多地方都违反了规则2,并且是一种最坏的情形。这段代码有多处重复。重复将极难发现。所以,请帮助防止这种情形的发生,我已包含其中了。

告之而非问之
简言之,告之而非问之意指不要先问一个对象的状态,然后才让它去工作。而应该告之对象如何去工作。这就意味着之前所有的那些If例子应该变为:

<!---->mobile.alert();

<!---->mobile.registerGasReading();

<!---->mobile.sendTextMessage();

<!---->mobile.notifyLocation();

现假设遍布该程序中的一些If语句块有重复的实现。在"重量级If"版本的程序中,可能很难发现它们;但在"告之而非问之"版本的程序中,所有的实现都在Mobile中。所有的实现都在一处,这就便于察觉并根除问题。
    倾听你的测试程序也能帮助你保持代码的简洁。

<!---->public interface Alarm {
  
void alert(Mobile mobile);
}

public class Siren implements Alarm {
  
public void alert(Mobile mobile) {
    
if (mobile.getType == MobileTypes.STANDARD) {
      soundSiren();
    }
  }
}

public class TestSiren extends TestCase {
  
public void test_alert() {
    LocationMobile mobile 
= new LocationMobile();
    Siren siren 
= new Siren();
    siren.alert(mobile);
    
assert(sirenSounded());
  }
}

如果你密切地倾听测试程序,它可能会问你,"为什么你需要一个LocationMobile去测试Siren呢?"的确,为什么呢?看起来,Siren应该还不知道LocationMobile吧。

<!---->public class LocationMobile {
  
private Alarm alarm;
  
public LocationMobile(Alarm alarm) {
    
this.alarm = alarm;
  }
  
public void alert() {
    alarm.alert(); 
// alert on Alarm no longer needs a mobile
  }
}

public class TestLocationMobile() extends TestCase {
  
public void test_alert() {
    Alarm alarm 
= EasyMock.createMock(Alarm.class);
    alarm.alert();
    EasyMock.replay(alarm);
    Mobile mobile 
= new LocationMobile(alarm);
    mobile.alert();
    EasyMock.verify(alarm);
}

好像我只是交换了依赖关系。Alarm不再依赖Mobile,现在是Mobile依赖Alarm。但如果你仔细地观察这个测试程序,你会发现真正的依赖关系是,Siren知晓了LocationMobile。一个具体类依赖另一个具体类,这违反了依赖反转原则(DIP)。第二个例子就让LocationMobile依赖Alarm接口。具体类依赖抽象,这就满足DIP了。
    如果你使用TDD,并遵循简单法则和告之而非问之原则去编写所有的代码,你就处于成为一个更好的面向对象程序员的道路上了。好的面向对象代码易于阅读和维护,但难以编写,至少,在开始时是这样的。你写的越多,你就会变得越好,也会获得更多的经验。同时,这些实践经验也会使你在自己的道路上受益匪浅。

译注
[1]GodClass(上帝类)指包含了太多内容的类。

分享到:
评论

相关推荐

    西工大面向对象实验答案代码

    【标题】"西工大面向对象实验答案代码"是一个针对西安工业大学面向对象编程课程的实验解答,主要涉及Java语言。这个资源包含了解决unit2的coffee作业问题和测试2的完整代码,据描述所述,这些代码是经过验证的,确保...

    java面向对象代码实例

    每个"lesson"可能包括具体的Java代码示例,解释如何运用这些面向对象的特性。例如,"lesson02"可能讲解类和对象的基础,"lesson18"可能涉及继承的实现,"lesson26"可能是关于多态的案例,而"lesson27"可能探讨封装的...

    Java面向对象程序设计(源代码)

    最后,附带的源代码可以帮助读者更好地理解书中的实例,通过实际运行和调试代码,加深对面向对象编程的理解。在学习过程中,读者可以对照源代码逐步分析,从而提高编程技能。 总的来说,《Java面向对象程序设计(源...

    Java面向对象程序设计 例子源代码

    Java面向对象程序设计是计算机科学中的一个重要领域,它基于面向对象编程(OOP)的理念,强调将现实世界的问题抽象为类和对象,...通过实践这些例子,你将能够更好地掌握Java面向对象编程的精髓,提升自己的编程技能。

    如何用面向对象思想来编写程序

    在.NET框架下,C#、VB.NET等语言都支持面向对象特性,使开发者能够构建模块化、可重用的代码。 首先,我们来理解面向对象的基本概念: 1. **类(Class)**:是创建对象的模板,定义了一组属性(数据成员)和方法...

    面向对象 面向对象 面向对象

    因此,遵循SOLID原则(单一职责、开闭、里氏替换、接口隔离、依赖倒置),以及使用合适的设计模式,是实现高质量面向对象代码的关键。 总之,面向对象编程提供了一种强大的工具,帮助开发者更好地组织和管理代码,...

    《c++面向对象程序设计》例题代码(第二版)

    在这个压缩包中,“教材例程”可能包含了每个章节相关的示例代码,这些代码通常会覆盖类的定义、对象的创建、继承、多态、封装等面向对象的关键概念。虽然不是每个章节的例题都齐全,但现有代码足以让学习者深入理解...

    编写可维护面向对象的JavaScript代码[翻译]

    面向对象编程(Object-Oriented Programming,简称OO)是计算机编程范式之一...通过以上要点,可以编写出既可维护又面向对象的JavaScript代码,不仅让他人容易理解和使用,还能在长时间内节省维护成本,提高开发效率。

    delphixe6 编写的dll面向对象的例子 源代码

    总之,这个"delphixe6 编写的dll面向对象的例子"是一个宝贵的教育资源,它可以帮助开发者更好地理解和运用Delphi中的DLL编程和面向对象设计原则。通过深入研究源代码,开发者可以增强自己的编程技巧,提高代码质量和...

    面向对象程序设计代码

    面向对象程序设计(Object-Oriented Programming,OOP)是一种编程...以上就是关于“面向对象程序设计代码”以及C#中的相关知识点。在实际编程中,理解并熟练运用这些概念能够帮助我们编写出更加高效、可维护的代码。

    NET 4.0面向对象编程漫谈 代码

    .NET 4.0框架是微软推出的.NET Framework的重要版本,它为开发者提供了许多增强的功能和优化,尤其是在面向对象编程(OOP)...通过学习和实践这些代码,开发者可以深入了解.NET 4.0面向对象编程的精髓,提升编程技能。

    面向对象的银行管理系统课程设计完整代码Python版本

    通过阅读和分析这些代码,可以深入理解面向对象编程在实际项目中的应用,以及Python如何处理文件I/O和数据管理。 总之,这个面向对象的银行管理系统课程设计是一个综合性的项目,涵盖了Python编程基础、面向对象...

    【面向对象程序课程设计】学生考勤系统(含源代码)

    面向对象程序设计是一种重要的编程范式,它将复杂的软件系统分解为一系列相互协作的对象,使得代码更易于理解和维护。在本课程设计中,我们关注的是一个具体的应用——学生考勤系统。这个系统采用面向对象的方法进行...

    东北大学软件学院面向对象程序实验设计实验代码(全)

    在东北大学软件学院的实验中,学生们会通过编写和调试代码,理解并掌握这些面向对象编程的核心概念。这些实践经验对于成为一名优秀的软件开发者至关重要,因为面向对象编程是现代软件工程的基础,广泛应用于各种软件...

    写给大家看的面向对象编程书(第3版)代码

    - Java是跨平台的面向对象语言,强调“一次编写,到处运行”。 - **抽象类与接口**:Java中既支持抽象类也支持接口,它们都可以作为多态的基础。 - **异常处理**:Java有完善的异常处理机制,提高了程序的健壮性...

    基于JavaScript的面向对象可维护代码编写.pdf

    "基于JavaScript的面向对象可维护代码编写" 本文主要探讨如何编写可维护的面向对象JavaScript代码。面向对象编程是一种编程范式,它通过定义类和对象来描述现实世界中的实体。在JavaScript中,类是通过函数来定义的...

    测试驱动的面向对象软件开发

    这种方法结合了测试驱动开发(TDD)和面向对象编程(OOP)的优势,旨在提高代码质量、增强可维护性和降低后期修复错误的成本。 ### 测试驱动开发(TDD) 测试驱动开发是一种软件开发流程,它要求在编写任何生产代码...

    VC++面向对象编程教程代码3

    通过实践这些代码,读者可以更好地理解如何在VC++环境中应用面向对象编程思想。 在面向对象编程中,主要的概念包括类(Class)、对象(Object)、封装(Encapsulation)、继承(Inheritance)和多态(Polymorphism...

    面向对象JavaScript精要(英文原版pdf)

    通过本书的学习,读者可以深入了解面向对象编程的原理,并掌握如何在JavaScript中有效地运用这些原理来编写高质量的代码。此外,书中还包含了大量的示例代码和实践案例,帮助读者更好地理解和掌握所学知识。 #### ...

Global site tag (gtag.js) - Google Analytics