`
oolala
  • 浏览: 103282 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
09c341db-7f05-3f2b-a572-9ee69a5d8a77
unix环境高级编程
浏览量:22702
社区版块
存档分类
最新评论

架构中的分层技术

阅读更多
何时使用分层技术?

分层技术实际上是把技术复杂化了。和以往简单的CS结构的系统不同,分层往往需要使用特定的技术平台来实现。当然,不使用这些技术平台也是可能的,但是效果可能就没有那么好了。支持分层技术的平台有很多,包括目前主流的J2EE和.NET。甚至在不同厂商的开发平台上,要求也不一样。使用分层技术实现的多层架构,成本要比普通的CS架构高得多。

这就产生了一个非常现实的问题-并不是所有的软件都适合采用分层技术的。一般来说,小型的软件使用分层并没有太大的意义,因为分层导致的成本超过它所能带来的好处。在一般的CS结构中,可以把界面控制、逻辑处理和数据库访问都放在一块儿。这种设计方式在纯粹的多层主义者看来简直就是十恶不赦。但是对于小型的软件而言,这并不是什么大不了的事情。因为从表示层到数据层的整套功能都被囊括在一个功能块中,同样能够实现较好的封装。而且,如果结构设计的足够好,也能够避免表示层、业务层和数据层之间出现过高的耦合度。因此,除非确实需要,不然没有必要使用分层技术。

尤其在处理一些特殊的项目时,严格的区分三层结构并不理想。比如在快速开发windows界面的应用时,往往会用到一些对数据库敏感的控件,这种处理方法跨越了三个层次,但是却很实用,成本也比较低。又比如一些框架,给出了从界面层到数据库的综合的解决方案,和windows的应用类似,严格的三层技术也不适用于这种情况。

如何使用分层技术?

从某种意义上来看,层其实是一个粗粒度的组件。就像我们使用组件技术是为了对系统进行一种划分一样,层的一个很大的作用也是如此。其目的是为了系统更容易被理解,不同的部分能够被较容易的替换。

使用分层技术的依据是软件开发人员的实际需要。如果你是在使用某些优秀的面向对象的软件开发平台的话,那它们一般都会建议(或是强制)你使用某一种分层机制。这是你采用分层技术的一大参考。

对于大多数有一定经验的软件团队而言,一般都会积累一些软件开发经验。其中包含了很多在某些特定的领域中使用的基础的类或组件。这些元素构成了一个系统的通用层次。这个层次也是分层时需要考虑的。例如一些应用软件中使用的一些通用的Currency对象或是Organization对象。分析模式一书对此类的对象进行了充分细致的阐述。这个层次一般被称为跨领域层(cross-domain layer),或称为工具层(utility layer)。

目前的很多软件都采用了数据库映射技术。数据库映射层对于企业应用系统非常的重要,因此也需要纳入考虑之列。数据库映射技术用起来简单,但是要实现可不容易。如果不是非常有必要,尽可能使用现成的框架,或是采用其中部分的设计思路。试图构建一个大而全的映射层次的代价是非常高昂的,认识不到这一点会带来很大的麻烦。数据库映射技术的知识,我们在下文中还有专门的篇幅来讨论。

如何存放数据(状态)?

在学习EJB的过程中,最先要理解的一定是有状态和无状态的概念。可以说,整个概念是多层体系的核心。为什么这么说呢?这里的状态指的是类的状态,例如类的属性、变量等。由于状态的不同,类也表现出差异来。而对于多层结构的软件,创建和销毁一个类的开销是很大的,如果该软件支持分布式的话尤为如此。所以如果系统的不同层次间进行频繁的调用-创建一个类,再销毁一个类。这种做法是非常消耗资源的。在应用系统的设计中,一般不单独使用COM,就是这个原因。所以我们很自然的想到了一种经典的设计-缓冲池。把对象存放在缓冲池中,当需要的时候从池中取出一个,当不需要的时候再把对象放入池中。这种设计思路能够大幅度的提高效率。但是这对能够放在池中的对象也提出了苛刻的要求-所有的对象必须是无差异的,也就是无状态的。只有这样才能够实现缓冲池。

一般来说,对象缓冲池的技术是用在中间的业务层上的。既然中间业务层上不能够保留有状态,那就出现了一个状态转移的问题。这里有两种的选择,一种是前移,把状态移到用户端,最典型的是使用cookie。这种选择一般是由于状态和用户端有关,不需要长时间保存。另一种选择是后移,把状态移到数据层,由数据库来实现持久性状态,当需要时才把状态提交给业务层。这种方式是企业应用软件中采用最多的,但是也增大了数据库的负担。

处理好接口

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

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

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

兼顾效率

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

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

以迭代的方式进行分层

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

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

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

层内的细分

分层的思路还可以适用于层的内部。层内的细分并没有固定的方式,其驱动因素往往是出于封装性和重用的考虑。例如,在EJB体系中的业务层中,实体Bean负责实现业务对象,因此一个应用往往拥有大量的实体Bean。而用户端并不需要了解每一个的实体Bean,对它们来说,只要能够完全一些业务逻辑就可以了,但完成这些业务逻辑则需要和多个实体Bean打交道。因此EJB提供了会话Bean,来负责把实体Bean封装起来,用户只知道会话Bean,不知道实体Bean的存在。这样既保证了实体Bean的重用性,又很好的实现了封装。

面向接口编程

在前面的章节中,我们提到一个接口设计的例子。为什么我们提倡接口的设计呢?Martin Fowler在他的分析模式一书中指出,分析问题应该站在概念的层次上,而不是站在实现的层次上。什么叫做概念的层次呢?简单的说就是分析对象该做什么,而不是分析对象怎么做。前者属于分析的阶段,后者属于设计甚至是实现的阶段。在需求工程中有一种称为CRC卡片的玩艺儿,是用来分析类的职责和关系的,其实那种方法就是从概念层次上进行面向对象设计。因此,如果要从概念层次上进行分析,这就要求你从领域专家的角度来看待程序是如何表示现实世界中的概念的。下面的这句话有些拗口,从实现的角度上来说,概念层次对应于合同,合同的实现形式包括接口和基类。简单的说吧,在概念层次上进行分析就是设计出接口(或是基类),而不用关心具体的接口实现(实现推迟到子类再实现)。结合上面的论述,我们也可以这样推断,接口应该是要符合现实世界的观念的。

在Martin Fowler的另一篇著作中提到了这样一个例子,非常好的解释了接口编程的思路:

interface Person {

public String name();

public void name(String newName);

public Money salary ();

public void salary (Money newSalary);

public Money payAmount ();

public void makeManager ();

}

interface Engineer extends Person{

public void numberOfPatents (int value);

public int numberOfPatents ();

}

interface Salesman extends Person{

public void numberOfSales (int numberOfSales);

public int numberOfSales ();

}

interface Manager extends Person{

public void budget (Money value);

public Money budget ();

}


可以看到,为了表示现实世界中人(这里其实指的是员工的概念)、工程师、销售员、经理的概念,代码根据人的自然观点设计了继承层次结构,并很好的实现了重用。而且,我们可以认定该接口是相对稳定的。我们再来看看实现部分:

public class PersonImpFlag implements Person, Salesman, Engineer,Manager{

// Implementing Salesman

public static Salesman newSalesman (String name){

PersonImpFlag result;

result = new PersonImpFlag (name);

result.makeSalesman();

return result;

};

public void makeSalesman () {

_jobTitle = 1;

};

public boolean isSalesman () {

return _jobTitle == 1;

};

public void numberOfSales (int value){

requireIsSalesman () ;

_numberOfSales = value;

};

public int numberOfSales () {

requireIsSalesman ();

return _numberOfSales;

};

private void requireIsSalesman () {

if (! isSalesman()) throw new PreconditionViolation ("Not a Salesman") ;

};

private int _numberOfSales;

private int _jobTitle;

}


这是其中一种被称为内部标示(Internal Flag)的实现方法。这里我们只是举出一个例子,实际上我们还有非常多的解决方法,但我们并不关心。因为只要接口足够稳定,内部实现发生再大的变化都是允许的。如果对实现的方式感兴趣,可以参考Matrin Fowler的角色建模的文章或是我在阅读这篇文章的一篇笔记。

通过上面的例子,我们可以了解到,接口和实现分离的最大好处就是能够在客户端未知的情况下修改实现代码。这个特性对于分层技术是非常适用的。一种是用在层和层之间的调用。层和层之间是最忌讳耦合度过高或是改变过于频繁的。设计优秀的接口能够解决这个问题。另一种是用在那些不稳定的部分上。如果某些需求的变化性很大,那么定义接口也是一种解决之道。举个不恰当的例子,设计良好的接口就像是我们日常使用的万用插座一样,不论插头如何变化,都可以使用。

最后强调一点,良好的接口定义一定是来自于需求的,它绝对不是程序员绞尽脑汁想出来的。

数据映射层

在各个层的设计中,可能比较令人困惑的就是数据映射层了。由于篇幅的关系,我们不可能在这个问题上讨论太多,只能是抛砖引玉。如果有机会,我们还可以来谈谈这方面的话题。

面向对象技术已经成为软件开发的一种趋势,越来越多的人开始了解、学习和使用面向对象技术。而大多数的面向对象技术都只是解决了内存中的面向对象的问题。但是鲜有提到持久性的面向对象问题。

面向对象设计的机制与关系模型有很大的不同,这造成了面向对象设计与关系数据库设计之间的不匹配。面向对象设计的基本理论包括耦合、聚合、封装、继承、多态,而关系数据模型的理论则完全不同,它的基本原理是数据库的三大范式。最明显的一个例子是,Order对象包括一组的OrderItem对象,因此我们需要在Order类中设计一个容器(各个编程语言都提供了一组的容器对象及相关操作以供使用)来存储OrderItem,也就是说Order类中的指针指向OrderItem。假设Order类和OrderItem分别对应于数据库的两张表(最简单的映射情况),那么,我们要实现二者之间的关系,是通过在OrderItem表(假设名称一样)增加指向Order表的外键。这是两种完全不同的设置。数据映射层的作用就是向用户端隐藏关系数据库的存在。

自己开发一个对象/关系映射工具是非常诱人的。但是应该考虑到,开发这样一个工具并不是一件容易的事,需要付出很大的成本。尤其是手工处理数据一致性和事务处理的问题上。它比你想象的要难的多。因此,获取一个对象/关系映射工具的最好途径是购买,而不是开发。

总结

分层对现代的软件开发而言是非常重要的概念。也是我们必须学习的知识。分层的总体思路并没有什么特别的地方,但是要和自己的开发环境、应用环境结合起来,你还需要付出很多的努力才行。

在完成了分层之后,软件架构其实已经清晰化了。
分享到:
评论

相关推荐

    软件架构设计分层模型和构图思考.docx

    在架构设计中,需要融合多种架构分层方法,例如云架构和 SOA 架构,云和 SOA 架构融合在一起,对于上图中的服务层实际可以理解为组件资源层和服务接口层的融合。更好的构图方式应该是拆分为标准的中台资源层-服务层-...

    系统架构与分层

    系统架构与分层设计在软件开发中扮演着至关重要的角色,尤其在Java开发环境中。一个良好的架构设计能够确保系统的稳定性、扩展性、柔韧性和有效性。本文主要探讨了系统架构的基本概念、分层设计以及面向服务的架构...

    基于的.net的分层架构

    在IT行业中,构建高效、可扩展且易于维护的软件系统是至关重要的。基于.NET的分层架构是一种常用的设计模式,...阅读“基于.NET平台的分层架构实战.pdf”这样的资料,可以帮助你更深入地理解如何在实践中应用这些概念。

    架构分层模型适配(39页).pdf

    架构分层模型适配是领域驱动设计(DDD)中的一个重要概念,旨在将系统分层,以便更好地管理复杂性和技术债务。该模型适配吴雪峰在2018年11月发布的PDF文件中详细介绍了架构分层模型的适配实践。 在架构分层模型中,...

    DDD分层架构的三种模式.

    在这篇文章中,我们讨论了 DDD 分层架构的三种模式:四层架构、五层架构和六层架构。每种模式都有其优点和缺点,但是它们都可以帮助我们设计高质量的软件模型。在实践中,我们可以根据实际情况选择合适的模式,并且...

    C#实现分层架构源程序

    在IT行业中,分层架构是一种常见的软件开发模式,它旨在提高代码的可读性、可维护性和可扩展性。C#作为.NET框架的主要编程语言,非常适合用于构建分层架构的应用程序。本文将深入探讨C#实现分层架构的源程序,并结合...

    华为企业数据架构、应用架构及技术架构设计方法.pptx

    华为企业数据架构、应用架构及技术架构设计方法 华为企业数据架构、应用架构及技术架构设计方法是企业架构设计的核心组件之一。企业数据架构旨在整合企业内的数据资源,提高数据的Accuracy、Completeness和...

    软件平台架构设计与技术管理之道.docx

    技术管理在软件平台架构设计过程中扮演着举足轻重的角色。技术管理涉及到需求分析、设计、编码、测试和维护等多个阶段。在每个阶段中,技术管理的作用都是至关重要的。技术管理人员需要具备深厚的技术知识、敏锐的...

    当前IT业界主流技术做个架构分层

    当前IT业界主流技术做个架构分层.jpg

    分层架构与业务逻辑实现方式

    在当今软件系统中,分层架构思想是现代软件架构的主要思想,无论是企业级应用系统、专用软件还是协议,都采用分层架构思想进行设计。分层架构是一种设计思想,也可以称之为一种软件架构模式(Pattern),其核心在于...

    VS2010架构分层应用系统

    小组成员经过详细的讨论和调研决定采取面向对象的分多层架构进行系统开发,采取SQl Server2008设计和管理数据库资源,采取VS实现分层架构和网络功能模块,开发小组面临的第一项任务就是要架构分层系统框架。...

    云计算基础架构-存储分层技术.pptx

    云计算基础架构中的存储分层技术是一种优化数据存储效率和成本的有效方法。这一技术将不同的存储设备根据其性能和成本划分为不同的层次,如高性能层、性能层和容量层,以满足不同类型数据的存取需求。 1. 分层存储...

    .Net分层架构设计

    .NET框架中的分层架构设计是一种常见的软件开发模式,它旨在提高代码的可读性、可维护性和可扩展性。在.NET开发中,分层架构通常包括数据访问层、业务逻辑层、表示层(或用户界面层)等部分,每个层次都有特定的责任...

    javaweb分层架构

    JavaWeb分层架构是开发大型、复杂Web应用的常用模式,它通过将应用程序的不同功能划分为各个独立的层,实现了代码的复用、模块化和易于维护。在JavaWeb开发中,通常会涉及到以下几层架构: 1. 表示层(Presentation...

    解析计算机软件开发中分层技术的实践运用.pdf

    在具体实践中,分层结构如网络架构的OSI模型,或者软件开发中的MVC架构,都展示了分层技术的应用。分层技术使得系统不同部分之间通过稳定的接口进行交互,从而提高了系统的可维护性和可扩展性。 接着,分层技术的...

    关于计算机软件技术中分层技术的应用思考.pdf

    本文主要探讨了计算机软件技术中分层技术的应用及其优势。 首先,分层技术的核心理念是将复杂的软件系统分解为多个独立的层次,每个层次专注于特定的功能,从而实现模块化设计。这种技术能够有效地减少不同功能模块...

    软件 架构 分层体系 结构

    ### 软件架构分层体系结构 #### 一、传统主机系统 (Traditional Host Systems) 在传统的主机系统中,所有处理工作均由一个中心处理器(通常是大型机)完成。本地终端负责用户输入显示功能,但不具备任何智能处理...

    C/S、B/S、分层、多层架构参考

    在IT行业中,架构设计是构建复杂系统的关键环节。本文将深入探讨C/S(客户端/服务器)、B/S(浏览器/服务器)以及分层和多层架构的相关知识点,旨在为你的理解和应用提供详尽的指导。 首先,让我们从C/S架构开始。C...

    智能网联汽车电子电气架构产业技术路线图.pdf

    4. 软件架构的服务化是智能网联汽车电子电气架构发展的重要方向,通过服务化可以实现软件架构的分层解耦和自动驾驶技术的发展。 5. 智能网联汽车电子电气架构的技术挑战包括汽车电子电气架构的演进趋势、软件架构的...

Global site tag (gtag.js) - Google Analytics