标题:
敏捷思维 架构设计中的方法学(14) 代码验证-1
[打印本页]
作者:
look_w
时间:
2018-4-16 22:18
标题:
敏捷思维 架构设计中的方法学(14) 代码验证-1
面向对象体系中的代码验证代码验证是保证优秀的架构设计的一种方法,同时也是避免出现象牙塔式架构设计的一种措施。我们在上一篇稳定化中提到说架构设计最终将会体现为代码的形式,因此使用形式化的代码来对架构进行验证是最有效的。
由于是代码验证,因此就离不开编写代码,而代码总是和具体的语言、编译环境息息相关的。在这里我们主要讨论面向对象语言,代码示例采用的Java语言。利用面向对象语言来进行架构设计有很多的好处:
首先,面向对象语言是一种更优秀的结构化语言,比起非面向对象语言,它能够更好的实现封装、降低耦合、并允许设计师在抽象层次上进行思考。这些因素为优秀的架构设计提供了条件。
其次,面向对象语言可以允许设计师只关注在框架代码上,而不用关心具体的实现代码。当然,这并不是说非面向对象的语言就做不到这一点,只是面向对象语言的表现更优秀一些。
最后,面向对象语言可以进行很好的重用。这就意味着,设计师可以利用原有的知识、原有的软件体系,来解决新的问题。
此外,利用Java语言,还可以获得更多的好处。Java语言是一种面向接口的语言。我们知道,Java语言本身不支持多重集成,所有的Java类都是从Object类继承下来的。这样,一个继承体系一旦确定就很难再更改。为了能够达到多重继承的灵活性,Java引入了接口机制,使用接口和使用抽象类并没有什么不同的地方,一个具体类可以实现多个接口,而客户端可以通过申明接口类型来使用,如下面这样:
1
List employees=new Vctor();
如果需要将Vctor换成LinkedList,那么除了上面的创建代码,其它的代码不需要再做更多的修改。而Vctor这个具体类除了实现List这个接口以外,还实现了Cloneable、Collection、RandomAccess、Serializable。这说明除了List接口之外,我们还可以通过以上所列的接口来访问Vector类。因此接口继承能够成为类继承的补充手段,发挥十分灵活的作用。同时又避免了多重继承的复杂性。但是接口中只能够定义空方法,这是接口的一个缺陷。因此在实际编程中,接口和抽象类通常是一起使用的。我们在Java的java.util包中看到Collection接口以及实现Collection接口的AbstractCollection抽象类就是这方面的例子。你可以从AbstractCollection抽象类(或其某个子类)中继承,这样你就可以使用到AbstractCollection中的缺省代码实现,由于AbstractCollection实现了Collection接口,你的类也实现Collection接口;如果你不需要利用AbstractCollection中的代码,你完全可以自己写一个类,来实现Collection接口(这个例子中不太可能发生这种情况,因为工具类的重用性已经实现设计的非常好了)。Java中有很多类似的例子。Java语言设计并不是我们讨论的重点,更加深入的讨论可以参看专门的书籍,这里我们就不作太多的介绍了。
以上花了一些篇幅来讨论面向对象设计和面向接口设计的一些简单的预备知识。这些知识将成为代码验证的基础。
接口和架构这里的接口指的并不是Java中的Interface的概念,它是广义的接口,在Java语言中具体表现为类的公有方法或接口的方法。在COM体系或J2EE体系中还有类似但不完全相同的表现。对于一个系统的架构来说,最主要的其实就是定义这些接口。通过这些接口来将系统的类联系在一起,通过接口来为用户提供服务,通过接口来连接外部系统(例如数据库、遗留系统等)。因此,我们为了对架构进行验证的要求,就转化为对接口的验证要求。
对接口进行验证的基本思路是保证接口的可测试性。要保证接口具有可测试性,首先要做的是对类和类的职责进行分析。这里有几条原则,可以提高接口的可测试性。
1、 封装原则
接口的实现细节应该封装在类的内部,对于类的用户来说,他只需要知道类发布出的公有方法,而不需要知道实现细节。这样,就可以根据类的共有方法编写相应的测试代码,只要满足这些测试代码,类的设计就是成功的。对于架构来说,类的可测试性是基础,但是光保证这一条还不够。
2、 最小职责原则
一个类(接口)要实现多少功能一直是一个不断争论的问题。但是一个类实现的功能应该尽可能的紧凑,一个类中只处理紧密相关的一些功能,一个方法更应该只做一件事情。这样的话,类的测试代码相应也会比较集中,保证了类的可测试性。回忆在分层模式中我们讨论的那个例子,实现类为不同的用户提供了不同的接口,这也是最小原则的一个体现。
3、 最小接口原则
对于发布给用户使用的方法,需要慎之再慎。一般来说,发布的方法应该尽可能的少。由于公布的方法可能被客户频繁的使用,如果设计上存在问题,或是需要对设计进行改进,都会对现有的方法造成影响。因此需要将这些影响减到最小。另一方面,一些比较轻型的共有方法应该组合为单个的方法。这样可以降低用户和系统的耦合程度,具体的做法可以通过外观模式,也可以使用业务委托模式。关于这方面的讨论,可以参考分层模式。较少的接口可以减轻了测试的工作量,让测试工作更加集中。
4、 最小耦合原则
最小耦合原则说的是你设计的类和其它类的交互应该尽可能的少。如果发现一个类和大量的类存在耦合关系,可以引入新的类来削弱这种耦合度。在设计模式中,中介模式和外观模式都是此类的应用。对于测试,尤其是单元测试来说,最理想的情况是测试的类是一个单纯的类,和其它的类没有任何的关系。但是现实中这种类是极少的,因此我们能够做的是尽可能的降低测试类和其它的类的耦合度。这样,测试代码相对比较简单,类在修改的时候,对测试代码的影响也比较小。
5、 分层原则
分层原则是封装原则的提升。一个系统,往往有各种各样的职责,例如有负责和数据库打交道的代码,也有和用户打交道的代码。把这些代码根据功能划分为不同的层次,就可以对软件架构的不同部分实现大的封装。而要将类的可测试性的保证发展为对架构的可测试性的保证。就需要对系统使用分层原则,并在层的级别上编写测试代码。关于分层的详细讨论,请参见分层模式。
如果你设计的架构无法满足上述的原则,那么可以通过重构来对架构加以改进。关于重构方面的话题,可以参考Martin Fowler的重构一书和Joshua Kerievsky的重构到模式一书。
如果我们深入追究的话,到底一个可验证的架构有什么样的意义呢?这就是下一节中提到的测试驱动和自动化测试的概念。
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/)
Powered by Discuz! 7.0.0