技术开发 频道

敏捷思维:分层 (下)

    处理好接口

    由于使用了分层技术,因此原先那种在CS结构中类之间存在复杂关系就有必要重新评估了。一般层间的耦合度不宜过大。因此需要慎重的设计层之间的类调用方式。一些分布式软件体系(例如J2EE)对层之间的调用方式以接口的形式给出了要求。同时,不同层之间仅仅知道目标层的接口,而不知道目标层的具体实现。EJB的home接口和remote接口就是这样。在COM+体系中,也需要在设计类的同时,把接口公布出来,以供客户方使用。

    在设计层间的接口时,除了考虑开发平台的约束之外,还有一点是开发人员必须考虑的。那就是业务需要。业务层中往往有非常多的对象和方法,它们之间的关系也非常的负责,但对于其它的层次来说,它并不关心这些细节。因此业务层公布的接口必须要简单,而且和实现无关。因此,可以使用设计模式的Facade模式来简化层间的接口。这种做法非常有效,EJB中的SessionBean和EntityBean区分就含有这种设计思路。

    同样的,不同层之间的数据传递也存在问题。如果不同层的物理节点在一起还好办,如果不在一起,那就需要使用到分布式技术了。因为不同机器的内存地址编码是不同的,如果接口之间采用对象引用的方式,那一定会出现问题。因此会将对象打包成字符串,发送到目标机器后再还原为对象。所有的分布式平台都提供了对这种技术的支持,这里就不多说了。但是这种实现技术会对我们的设计思路产生影响,少量的数据直接使用字符串来传递,数据量大的话,就需要使用封装了数据的对象。这类对象的设计需要非常的小心。在设计过程中可以参照开发平台提供的一些标准做法。同样的,数据的请求的频率也是难点之一。过于频繁的操作来自后端的数据会加大系统的开销。因此,在设计调用方法时同样需要结合实际应用来考虑。

    兼顾效率

    一般来说,纯粹的面向对象设计者设计出的软件都会比较完美。但是需要付出一定的代价。在一些大的软件平台上编程的时候,往往需要利用到平台的一些机制。最典型的就是平台的事务机制(最典型的包括J2EE平台的JTS,以及COM+平台的MTS),但是事务机制的实现往往需要平台大量对象的支撑。这种情况下,创建一个支持事务的对象的开销是很大的。处理这种问题有一种变通的办法,就是仅仅对需要事务支撑的对象提供事务支持。这就意味着,一个单独的业务实体类,可能需要根据是否支持事务分为两种类:对该业务实体的select方法不需要事务的支持,只有update和delete方法才需要有事务的支持。这是不符合纯面向对象设计者的观点的。但是这种做法却可以获得比较优秀的效率。

图1 将单个的业务实体分为不同的实现

    应该承认,这种提高效率的做法加大了复杂度。因为对于客户端来说,它们并不关心具体的实现技术。要求客户端在某一种情况下调用这个类,在其它情况下又调用另一个类,这种做法既不符合面向对象的设计思路,也增大了层间耦合度及复杂性。因此,我们可以考虑使用接口或是外观类(参见设计模式一书中的facade模式),把具体的实现封装起来,而只把用户关心的部分提供给用户。这方面的技巧我们在下面的章节中还会提到。

    以迭代的方式进行分层

    软件设计中的迭代做法同样可以适用于分层。根据自己的经验,在一开始就定义好所有的层次是很难的。除非有着非常丰富的经验,都则实现和原先的设计总有或大或小的差距。因此调整势在必行。每一次的迭代都能够对分层技术进行改进,并为后一个项目积累了经验。

    这里的分层迭代不可以过于频繁,每一次的迭代都是对架构的重大修改,都是需要投入人力的,而且会影响到软件开发的进度。但是成功的迭代的效果是非常明显的,能够在接下来的开发周期中起到稳定架构,减少代码量,提升软件质量的功效。注意,不要让新潮技术成为分层迭代的推动力。这是开发人员都常犯的毛病,这并不是什么缺点,只能称为一种职业病吧。分层迭代的推动力应该源自于需求的演进以及现有架构的不稳定已经妨碍了软件进一步的开发。因此这需要团队中的技术主管对技术有着非常好的把握。

    重构能够对迭代有所帮助。嗅出代码中隐藏的坏味道并加以改进。应该说,迭代是一种比较激烈的做法,更好的做法是在开发中不断的对架构、层次进行调整。但这对团队、技术、方法、过程都有着很高的要求。因此迭代仍然是一种主要的改进手段。

0
相关文章