技术开发 频道

软件质量之路(4):建立核心框架

    框架对软件开发的意义  

    知识积累

    框架的核心价值是对知识的积累。软件开发是一项知识性的活动。但是知识存在于人的大脑中,是最难进行积累的。而在软件开发中,代码是最确定的知识,人和机器通过浏览代码都能够了解代码的目的,而且不会出现不同的理解。所以,从代码出发进行知识的积累是非常好的的办法。框架就是这种思路的产出物。框架包含了大量的代码,这些代码是对某个特定问题领域中抽象概念及这些抽象概念之间关系的描述。所以,框架能够胜任知识积累的工作。

    虽然代码是框架的核心,但是光有代码的框架是很难为人所理解的。代码的层次太低,开发人员从代码的角度来完全的理解框架是很困难的。所以,必须要有层次高于代码的工件。这些工件可以是设计文档、领域模型、UML图、JavaDoc。他们的目的都是为了帮助框架的开发人员和使用人员顺利的理解框架。

    就像我们上面的实例中,通过一个JdbcTemplate对象,就将一个JDBC的非常好的实践给积累起来了。当然,你也可以使用文档要求开发人员按照某种方式来使用JDBC,但在实践中会遇到不少的问题,例如,JDBC的异常处理可能过于繁琐而被忽略。虽然大多数时候都不会有问题,但是当问题发生时往往会很麻烦。采用框架的方式则不会有类似的问题。

    资产的保护

    知识积累本身就是一项对资产的保护工作。而另一项很重要的保护工作就是软件组织(尤其是企业)需要保证对知识的学习和改进是经过合法授权的。例如,知识的非法外流是任何组织都不希望看到的。将知识积累为框架的形式有助于缓解这种情况。框架可以是以源码形式发布的,也可以是以库形式发布的,为不同的框架用户选择不同的发布形式,可以起到权限控制的作用。

    鼓励重用

    框架之所以称为框架,是因为它可以重用。在软件组织中形成以框架为核心的开发方式,在开发中使用框架,并在开发完成后改进框架。在这个反覆的过程中,重用的工作就已经开展起来了。

    重用其实并没有那么困难。就像上面的例子中,其实代码并不难,思路也很清晰,其实就是将通用的行为抽取出来。

    优化架构

    框架代表了一种优秀的软件架构。框架定义了扩展方式,从而规范了框架的使用行为。这使得软件能够保持整体架构的稳定性和一致性。

    在上面的例子中,使用框架之后,客户端可以节省大量的代码,代码结构会更加清晰。

    大规模软件设计

    大规模的软件设计的关键在于对应用进行合理的划分,并提供一种一致的方式建立架构。大规模的软件设计要求核心的设计人员工作在一个抽象的层次上。虽然他们属于设计人员,但是同样需要编写代码,而这些代码则是框架代码。

    在敏捷方法中,设计师的职业决不意味着你仅仅只需要编写设计文档,如果你常常阅读一些规范的话,你会发现,很多的规范是采用代码编写而成的。只不过这些代码并不提供实现,只提供了抽象接口。

    如何进行有效的框架设计

    一个好的框架设计是有一定的准则可供遵循的。以下给出的一些概念奠定了框架开发的理论基础。

    设计抽象层次。

    在框架的定义中,抽象体是至关重要的。抽象体的定义取决于框架的目标。没有目标的框架决不是一个框架,要么是一个类库,要么是一种编程语言。在上面的例子中,首先是有了一个简化JDBC操作的目标,然后从这个目标出发定义抽象体。于是我们得到了Connection 、ResultSet、Statement等抽象体。

    在抽象层次中规范行为。光有抽象体还是没有办法工作。还需要定义出抽象体的行为。在上例中,我们定义了获取数据集的行为。但是在JDBC中,除了获取数据集,可能还需要将数据填充到值对象中,还需要能够支持CRUD的所有操作。这些都是抽象的行为。有了这些行为之后,我们就需要规范、穷尽这些行为。

    分析抽象行为的通用部分和非通用部分。在抽象体的行为中,有些动作是通用的,有些是特殊的。前者就是框架要实现的部分。而后者则作为扩展留给用户。

    将抽象层次提取为框架,并设计扩展点。有了抽象体、抽象体的通用行为之后,就可以设计扩展点了。最简单的扩展点是采用方法调用的方式,复杂的可能通过设计模式或是配置文件等方式。扩展点设计优劣的评价标准是使用起来是否方便,这里的使用包括应用、调试、测试等。
   
    适当的使用设计模式。设计模式代表了先进的软件设计思路。在框架中适当的使用设计模式有助于改进框架的结构。例如在上例中,扩展点的设计就采用了回调的设计模式。在框架设计中不宜采用过多的设计模式,这会使得框架理解起来困难。当然也有反例。

    反例-Junit Framework。作为自动化单元测试框架,Junit在简小的设计中采用了大量的设计模式,包括Command模式、Template Method模式、Collecting Parameter模式、Pluggable Selector模式、Adapter模式、Composite模式等。

    简化框架的使用。在上例中,框架的扩展点设计完毕后,使用框架的代码仍然比较复杂,回调接口和匿名类仍然会把人弄的有些莫名其妙。所以,为了使框架使用方便,一定程度的简化还是需要的。

    在Junit框架中,我们只需要让测试方法以test开头就能够自动进行测试,而这种功能是Command模式无法提供的。按照Command模式的要求,一个测试类只能包括一个测试方法。原因就在于Junit中利用了Pluggable Selector模式、Adapter模式、以及反射技术对Command模式作了新的封装:

protected void runTest() throws Throwable {
    Method runMethod= null;
    try {
        runMethod= getClass().getMethod(fName, new Class[0]);
    } catch (NoSuchMethodException e) {
        assert("Method \""+fName+"\" not found", false);
    }
    try {
        runMethod.invoke(this, new Class[0]);
    }
    // catch InvocationTargetException and IllegalAccessException
}

0
相关文章