面向对象的应用服务层设计2020-11-25 08:41
面向对象的应用服务层设计前言N层的应用软件系统,由于其众多的优点,早已沦为典型的软件系统架构,也早已为广大开发人员所熟悉。在一个典型的三层应用软件系统中,应用于系统一般来说被区分成以下三个层次:数据库层、应用服务层和用户界面层。其中,应用服务层集中于了系统的业务逻辑的处置,因此,可以说道是应用软件系统中的核心部分。软件系统的健壮性、灵活性、可器重性、可升级性和可维护性,在相当大程度上各不相同应用服务层的设计。因此,如何建构一个较好架构的应用服务层,是应用软件开发者必须侧重解决问题的问题。1/39为了使应用服务层的设计超过最差的效果,我们一般来说还必须对应用服务层作更进一步的职能分析和层次细分。很多开发者在建构应用服务层的时候,把数据库操控、业务逻辑处置甚至界面显示夹杂着在一起,或者,把业务逻辑处置等同于数据库操控,等等,这些,都是有缺陷的作法。本文,就在这个方面展开设计时可使用的方案展开一些探究。为了使辩论更加具备针对性,本文不会辩论一些较为风行的系统架构,例如J2EE架构,以及JDO。在微软公司的.Net平台上,将以Websharp中间件为事例。Websharp中间件是笔者研发的一个建构在微软公司.Net平台之上的一个中间件系统,也是构建文章所述的系统架构的承托系统。搭配这些架构做到例子,也是因为.Net经常出现的时间较为较短,目前在这个平台上没成熟期统一的架构,而J2EE是目前最成熟期的建构企业应用的平台。自本人的《利用.Net框架研发应用于系统》和《空战揭露:研发.Net平台应用于系统框架》两篇文章公开发表以来,接到很多对系统和写信,明确提出了很多问题。因为时间的关系,无法一一恢复,因此,也借本文给大家一些答案。必须解释的是,原本的Jobsinfo现在早已做到了升级,名称更改为Websharp。2/39设计的原则和评判标准同软件工程的原则一样,应用服务层的设计,必需遵循的最重要的原则就是低内聚和较低耦合。软件分层的本来目的,就是提升软件的可维护性和可器重性,而低内聚和较低耦合正是达成协议这一目标必需遵循的原则。尽可能减少系统各个部分之间的耦合度,是应用服务层设计中必须重点考虑到的问题。内聚和耦合,包括了纵向和横向的关系。功能内聚和数据耦合,是我们必须达成协议的目标。纵向的内聚和耦合,一般来说反映在系统的各个模块、类之间的关系,而横向的耦合,反映在系统的各个层次之间的关系。系统的框架,一般来说包括了一系列规范、誓约和承托类库、服务。3/39对于如何辨别一个软件的系统框架的好坏,笔者指出,可以从以下几个方面来评判: ◆系统的内聚和耦合度这是确保一个系统的架构否合乎软件工程原则的首要标准。◆层次的明晰和简洁性系统每个部分已完成功能和目标必需是具体的,某种程度的功能,应当只在一个地方构建。如果某个功能可以在系统有所不同的地方构建,那么,将不会给后来的研发和确保带给问题。系统应当简单明了,过分简单的系统架构,不会带给不必要的成本和确保可玩性。在尽量的情况下,一个部分应当已完成一个分开并且原始的功能。4/39◆更容易构建性如果系统架构的构建十分艰难,甚至远超过团队现有的技术能力,那么,团队被迫花上很多的精力用作架构的研发,这对于整个项目来说,可能会得不偿失。非常简单就是美。◆可升级和可扩充性一个系统框架,不受设计时技术条件的容许,或者设计者本人对系统了解的局限,有可能会考虑到今后所有的变化。但是,系统必需为将来有可能的变化作好打算,需要在今后,在目前有数的基础上展开演变,但会影响原先的应用于。接口技术,是在这个方面广泛应用于的技巧。5/39◆否不利于团队合作开发一个好的系统架构,某种程度只是从技术的角度来看,而且,它还应当限于于团队研发模型,可以便利一个研发团队中各个有所不同角色的相互协作。例如,将Web页面和业务逻辑组件分离,可是使页面设计人员和程序员的工作分离来同步进行而会相互影响。◆性能性能对于软件系统来说是很最重要的,但是,有的时候,为了能让系统获得更大的灵活性,有可能被迫在性能和其他方面获得均衡。另外一个方面,由于硬件技术的飞速发展和价格的上升,性能的问题往往可以通过用于用于更佳的硬件来取得提高。6/39应用服务层的内容应用服务层,一般来说也被称作业务逻辑层,因为这一层,是应用软件系统业务逻辑处置集中于的部分。然而,我将这一层称作应用服务层,而不称之为业务逻辑层,因为,这一层必须处置的某种程度是业务逻辑,还包括了其他方面的内容。7/39从原始的角度来说,应用服务层必须处置以下内容:◆数据的回应方式数据,是软件处置的对象。从或许上来说,软件,就是数据结构特算法的众说纷纭,是有一定意义的。在面向对象的系统中,数据是用类来回应的,代表了现实世界实体对象在软件系统中的抽象化。考虑到所谓的MVC模式,这个部分的类归属于M--实体类的范畴。由于应用软件一般来说不会用于数据库,数据库中的数据,可以看作是对象的长久化留存。由于数据库一般是关系型的,因此,这个部分,还必须考虑到类(对象)同关系型数据的同构,即一般来说所说的O-RMAP问题。8/39◆数据的读取方式如同上述所说,软件系统处置的实体对象数据必须长久化留存数据库中,因此,我们必需处置系统同数据库的交互,以及数据的读取和切换方式的问题。◆业务逻辑的的组织方式在面向对象的系统中,业务逻辑展现出为对象之间的交互。有了上述的实体对象,以及对象的留存策略,就可以将这些对象人组一起,撰写我们的业务逻辑处理程序。在业务逻辑的处置中,必需确保处置的正确性和完整性,这将不会牵涉到到事务处理。一般来说,我们也不会把业务逻辑PCB成组件的形式,以获得仅次于的可器重性。9/39◆业务服务的获取方式在我们已完成系统的功能后,如何向客户获取服务,是我们必须考虑到的问题。这里的客户,某种程度是指软件的使用者,也还包括调用的界面、其他程序等。例如,在一个基于Web的ASP.Net或JSP系统中,业务逻辑功能的客户乃是这些ASP.Net页面或JSP页面。业务逻辑组件应当通过什么方式,必要的,或间接的,向这些客户获取服务,是这一层必须已完成的任务。◆层的部署和层间交互对于一个多层的应用软件系统来说,特别是在是大型的应用软件系统,一般来说必须把有所不同的部分部署在有所不同的逻辑或物理设备上。尤其是一些基于Web的应用软件系统,其部署工作将牵涉到到Web服务器、组件服务器、数据库服务器等有所不同的服务设备。在展开应用软件架构的设计的时候,必需考虑到各种有所不同的部署方案。10/39综上所述,一个原始的基于Web的应用软件系统,其架构可以用右图来回应(Websharp引荐的应用软件系统架构):对于以上各个方面来说,每个问题都可以有很多种策略和方案,但是,在一个系统中,应当尽量的统一这些策略和方案。也就是说,在一个系统,或者一个项目中,应当统一每个解决问题每个问题所使用的方法。软件的开发方法是灵活性的,可以用有所不同的方法解决问题完全相同的问题,这不会引诱开发人员使用他们指出需要展现出自己的方法,但是,从整个系统来看,这将不会是灾难性的。我们应当尽量统一,就是,使用统一的数据表示方式、统一的数据读取方式、统一的业务逻辑处理方式等。下面,将就这些部分的设计策略和能用方案展开一些较为详尽的阐述。11/39数据实体的回应应用软件系统,从本质上来说,是计算机对现实世界的仿真。现实世界中的实体对象,在软件系统中,展现出为必须处置的数据。在面向对象的系统中,这是通过类和对象来回应的。参照知名的MVC模式,类可以分为实体类(M)、掌控类(C)、和边界类(V),分别代表了实体对象、掌控和界面显示。系统中必须处置的数据,在面向对象的系统中,归属于实体类部分。12/39在考虑到数据实体层的设计策略的时候,必须做到以下要点:◆完全一致的数据表示方式。在一个系统中,数据的回应方式必需尽量统一,同时,在处置单个数据和多个数据的时候,处理方式尽量完全一致。◆因为数据一般来说是必须存储到数据库中,因此,较好的同构方法是必须的。◆处置好对象的粒度,即所谓的粗粒度对象、细粒度对象。13/39一般例子考虑到一个现实的例子,一个仓库中的产品(Product),在系统中可以用于如下定义:publicclassProduct{publicstringName;//名称publicdecimalPrice;//价格publicintCount;//数量}可以按照如下方法用于Product类:Productp=newProduct();//……处置Product14/39这是一个包括了三个属性的Product类的定义。为了便于解释,在这里,我们尽可能将问题修改了。又例如,一张入库单可以用于如下定义:publicclassForm{publicstringID;//入库单编号publicDateTimeAddTime;//入库时间publicFormDetail[]FormDetails;//入库单明细}publicclassFormDetail{publicProductInProduct;//入库产品publicintCount;//入库数量}15/39对于处置单个对象,一般来说使用上述的方法,但是,当我们必须处置完全相同类的一组对象,也就是处置一个对象子集的时候,就不会有一些小小的困难。如前所述,我们期望在处置单个对象和对象子集的时候,处置的方式尽可能统一,这对于软件开发的意义是相当大的。常用的处置对象子集的方法有:◆数组回应的方法例如,上面的例子中当一张入库单包括多条入库单明细的时候使用的方法。为了灵活性,也可以用于容器来,如Java中的Vector或C#的ArrayList(C#)。只是,在处置对象的时候,必须一个构造函数的操作者。这个问题,在反对泛型的语言中会不存在,如用于C++的标准库的容器类。16/39◆ObjectCollection方法。这个方法同上面的方法类似于,不同之处在于,为每个实体类设计一个Collection类。例如,可以为FormDetail设计一个FormDetailsCollection类(C#):publicclassFormDetailsCollection:ArrayList{publicvoidAdd(FormDetaildetail){base.Add(detail);}publicnewFormDetailthis[intnIndex]{get{return(FormDetail)base[nIndex];}}}这么做到的益处在于,在操作者子集中的对象时,不用展开构造函数的操作者。17/39◆数据集的回应方法。使用这种方法,一般来说是必要把从数据库查找中提供的数据集(Recordset)作为数据处理对象。这种方法在ASP应用程序中是十分少见的作法。这种作法非常简单,初学者很更容易掌控,但是弊病也很多。EJB的方法在J2EE体系中,对实体对象的处置的典型方法是EntityBean。J2EE中用于EntityBean来回应数据,以及封装数据的长久化储存(同数据库的交互)。由于EntityBean较为消耗资源,而且使用的是远程调用的方式来采访,因此,在必须传送大量数据,或者在有所不同的层次之间传递数据的时候,往往还不会使用一些诸如值对象(ValueObject)的设计模式来提高性能。关于J2EE中的设计模式的更好内容,读者可以参照《J2EE核心模式》一书。18/39JDO的方法相对于J2EE这个便宜的方法来说,JDO获取了一个比较轻量级的方案。在JDO中,你可以使用一般的作法,撰写实体类,然后,通过一些增强器对这些类展开增强,以使其合乎JDO的规范,最后,你可以通过PersistenceManager来构建对象的长久化储存。无论是EJB还是JDO,在同数据库展开同构的时候,都搭配了XML配置文件的方式。这是一种灵活性的方式。由于XML强劲的表达能力,我们可以很好的用它来叙述代码中的实体类和数据库之间的同构关系,并且,不必在代码中展开软编码,这样,在情况发生变化的时候,有可能只必须改动配置文件,而不必去改动程序的源代码。关于EJB和JDO的配置文件的更好的信息,各位可以参照涉及的文档,这里仍然赘述了。然而,用于XML配置文件的方式并不是唯一的方法,在微软公司获取的一些案例中,如Duwamish示例,就没使用这种方式。至于开发人员在研发过程中明确使用哪种方式,是必须根据具体情况展开权衡和权衡的。19/39Websharp的方法Websharp在数据的展现出上,充分利用了.NetFramework类库中DataSet的功能,设计了一个EntityData类。