如何提高软件的可重用性_如何保证软件应用系统架构设计结果的可扩展性和可重用性(上篇)...

软件项目实训及课程设计指导——如何保证软件应用系统架构设计结果的可扩展性和可重用性(上篇)

1、良好的可重用性软件系统架构设计结果的主要体现

可重用性的软件应用系统的系统架构设计结果主要体现在如下两个方面——本项目的系统架构设计的结果是可重用的和在本项目的系统架构设计中重用成熟的系统架构设计方案。

当然,要能够达到这样的软件系统架构设计结果,需要设计人员充分地应用面向对象技术中的抽象机制,对软件应用系统中共性的部分进行充分的抽取。

而为了能够保证软件应用系统的系统架构设计结果是可扩展的,必须要应用"封装"和"隔离"的设计手段、并且遵守一些相关的设计原则和应用典型的设计模式。

作者在下文将为读者详细介绍如何保证软件应用系统的系统架构设计结果具有良好的可扩展性和可重用性。

2、软件应用系统在纵向结构方面需要进行分层和隔离

(1)纵向分层和隔离

"层(Layer)"在面向对象的系统设计中是指对软件应用系统中的功能模块和类、或子系统等粗粒度的分组机制,每一层具有相对独立和内聚的职责——各层之间的依赖关系应该是逐层向下而不能跨层产生依赖关系;而且只能是上层依赖于下层、而不能让下层反过来依赖于上层。

比如,本系列文章中所给出的示例项目——银行账户信息管理系统项目在纵向分层隔离方面采用四层次的系统架构设计,下图所示中的UML包图为体现本软件应用系统项目的系统架构设计结果的分层包图。

示例UML包图中所示的系统分层设计完全遵守依赖倒置原则——依赖倒置原则的本质就是要求将软件应用系统的架构设计中的各个层之间的关系要建立在依赖抽象接口的基础上,同时要求上层模块不应该直接依赖于下层的模块,它们两者都共同依赖于一个抽象;抽象元素不能依赖于具体元素,而具体元素则必须依赖于抽象元素。

d29cbd4bfdc2e2d8ada2abca66f6238e.png

(2)合理地对软件应用系统在纵向方向进行分层隔离设计

通过合理地对软件应用系统在纵向方向进行分层隔离设计——如目前的C/S和B/S等架构模式中的各个分层策略,将允许设计人员将复杂的软件应用系统中所涉及的各个方面的问题分解成多个不同层次的实现。每一层最多只影响其相关联的上、下两层,同时只要给相邻的上、下层提供接口或者实现接口,从而也就能够允许每层使用不同的方法包括不同的技术来实现,因此为软件应用系统的可重用提供了强大的结构支持。

经典的三层架构的系统设计——即自底向上依次是数据访问层、业务逻辑层和表示层,而MVC架构模式是对它的进一步完善;下图所示的J2EE Web系统平台中的四层架构设计(表示层、控制层、业务逻辑层和数据访问层)能够保证软件应用系统架构设计的结果是可重用的。

dbc708a8d771c9bbb8e32696d2d6b702.png

当然,为了进一步分离系统中的业务处理层和持久层之间的依赖耦合关系,也可以在系统的业务处理层和持久层之间插入一个数据服务层(一般应用于采用J2EE EJB分布式的数据访问和存储的应用系统的系统架构设计中)。如下示图为J2EE EJB系统平台中的五层架构设计示例图,同样也都能够保证软件应用系统架构设计的结果是可重用的。

6dec33b6eb35e624fb016a3c00c232f1.png

(3)层与层之间应该要相互分离

在软件应用系统的多层架构设计中,一般都倡导将软件应用系统中的界面显示功能、业务逻辑处理功能和数据访问功能完全分离(但按照MVC架构模式的划分规则,在软件应用系统的系统架构设计中的业务逻辑层以及数据访问层中的各个组件都属于MVC架构模式中的模型组件),而不要在软件应用系统的界面组件(一般处于系统的表示层)中加入应用逻辑功能实现,从而避免了在应用系统的需求发生变化时(功能方面或者非功能方面),而产生牵一发而动全身的连锁修改软件应用系统的设计方案和功能实现的代码,可以实现软件应用系统的松耦合和良好的系统可维护性。

如下示图为某个Web应用系统中的Web页面实现的代码局部截图--HTML标签和Java处理逻辑代码混杂在一起。这样的代码设计导致表示层和业务逻辑处理层相关的程序代码紧密耦合,其中的业务逻辑处理的程序代码也是不可重用的——因为其中的某些功能模块很难在别的软件应用系统中被重新使用,因为不能将它从现有的软件应用系统中独立地提取出来——在Java程序代码中混杂有HTML标签,产生类似"拔出萝卜带出泥"的状况!

96f9ea9627749bd5a65866a85ce67773.png

3、软件应用系统在横向结构方面也需要拆分为不同的功能模块

(1)横向拆分为不同的功能模块

软件应用系统的系统架构设计师为了能够分离各个模块之间的藕合度,应该要对软件应用系统的横向结构也进行拆分为不同的功能模块。但设计人员如何能够获得低藕合的模块设计结果?

常用的设计策略是遵守面向对象设计中所倡导的依赖倒置原则、并应用控制反转和依赖注入技术(IOC,Inversion of Control)。下图所示为某个字符转换小系统的横向分块设计结果的UML组件图的局部截图。

920313b43c6b95ca671caf566d8ce7db.png

(2)模块之间依赖关系应该要尽可能达到低藕合的模块设计目标

应用面向对象设计中所倡导的依赖倒置原则实现将依赖关系倒置为依赖接口,从而在很大程度上阻止了"由于需求发生变化而导致代码修改"的变化波及范围的扩大,有效地隔离了"变化"和有助于增强软件应用系统的可重用性和可扩展性。

利用控制反转技术能够消解框架系统和软件应用系统之间的依赖关系——因为利用"控制反转"技术能够减少对象的请求者对服务提供者的特定功能实现逻辑的依赖,此时系统中的各个组件类不再需要自己去查找或者实例化它们所依赖的其它目标组件类的对象实例。

如下示图所示,在Struts 2框架中由于应用了ActionProxy代理,从而隔离软件应用系统中的各种业务处理的Action组件对Servlet容器的依赖,并且Struts 2框架中的Action组件类无须继承Struts2框架中的任何基类或实现任何的接口,为纯的POJO。

而在早期的Struts框架中,由于承担系统业务处理功能的Action组件直接继承于Struts框架系统的ActionServlet组件(示例图中的上图),从而导致系统业务处理功能的Action组件紧密耦合Struts框架系统。

6902beb2f25c529af99a76c97b1a5088.png

利用依赖注入消除软件应用系统中的各个对象在创建时所产生的依赖藕合关系,在横向分块设计中尽管遵守了依赖倒置原则,也只能够隔离对象的使用者和对象功能的实现者之间的依赖关系。但在创建具体实现类的对象实例时,仍会造成对于具体功能实现类的直接依赖。而采用依赖注入技术则可以消除这种在对象创建方面所产生的依赖性,如下示图所示在Struts 2框架中应用struts.xml配置文件实现对软件应用系统中的各个Action类的对象实例进行定义,而不是直接在程序代码中创建出对象实例。

4831316a50370edbec9ebfd88b759b61.png

(3)通过不断地进行设计重构过程逐步完善系统架构设计的设计结果

当然,软件应用系统的设计人员在进行横向分块设计时,应该要尽可能减少各个模块之间的相互关系、特别是要避免出现"多对多"的依赖关系。从上图所示的组件图中,读者应该可以发现出该软件应用系统中的各个功能组件之间的关系是比较复杂的!

其中软件应用系统中的业务层(用户信息管理、各种形式的字符转换功能管理等)与软件应用系统中的持久层之间存在"多对多"的关系、并且软件应用系统中的业务层中的各个组件紧密依赖于持久层中的组件具体技术实现方式。

因此,对软件应用系统中横向分模块设计需要不断地进行系统重构,也就是在软件应用系统的"持久层"和"业务层"之间可以增加一个"数据服务层",从而隔离"业务层"对"持久层"的过分的依赖,并且可以在软件应用系统中的"持久层"的具体技术实现发生变化时,不会影响到软件应用系统中的"业务层"的功能实现。

该软件应用系统重构后的各个组件模块的UML组件图请见下图所示,最终解除了软件应用系统中的业务层与持久层之间的"多对多"的关系!软件应用系统中的各个组件模块之间的关系都简化为"单一关系"、而且高层组件只依赖于底层的组件——遵守了面向对象设计中的依赖倒置原则!

40baa3af3b42c6d2c3261d376e27d68f.png
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值