zoukankan      html  css  js  c++  java
  • 系统内部模块(子系统)之间的耦合以及模块(子系统)划分 Virus

      题外话

      最近已经在努力学习了,学习基本功,学习设计模式,学习成熟框架,学习软件架构。发现越是学习的多,越是发现自己知道的少。

      

      引言

      本篇中的系统使用的技术背景是:.NET平台,C#语言,数据库是SQL Server,其他平台没有参与过,所以没有验证过。

      简写解释

      BA,Business Access,业务访问

      DA,Data Access,数据访问

      Entity,实体

      Service Layer,服务层

      Order,订单

      Product,商品

      正文

      做系统大多时候会用到分层,不管是跟随流行趋势还是自己已经搞明白了分层的好处。大多时候就分割为:Entity, DAL(Data Access Layer), BAL(Business Access Layer)。

      在VS中就产生了下面的项目结构。

      

      有的时候如果需要的话,可能还会有个Service Layer,提供更加粗粒度的服务访问,有时候也是为了方便其他系统调用,也为了隔离,提高安全性,屏蔽实现的细节。一个服务调用下去,可能会有多个BA在后面协调运作。

      对了还要加上一个Common类库,肯定会有一些基类、自定义异常、Cross-Cutting跨层的关注点、公用的方法、自定义常量,反正公用的都可以放在里面。

      

      

      然后大家就开始分工了,可以按照模块,也就是功能,有人写Order相关的,有人写Product相关的。但是我认为这么划分不太好,有以下几点为证,以订单模块为例:

      1、一个人需要写订单操作的存储过程,然后写实体,然后写DA、BA,从底层写到UI,需要熟悉多方面的知识,每个层面的知识都要学习,但是时间紧、精力不足,造成每个层面都学的不是很精,写出来的代码也就不是太好,反正倒是能跑。有两个缺点:对个人来说,不利于发展,没有特长,哪里都不精通;对公司来说,个人没有特长,其实就意味着公司没有特点,前途的话,可想而知。

      2、就算完成了,拿DA来说,每个模块都需要DA,但是每个人写的习惯不一样,你用ADO.NET,我用Entlib,我用NH。。。。,而且就算用ADO.NET也不一样,造成后面的维护的升级有很大的困难,维护周期会加长。而且不利于优化,因为写法不统一,就算优化,也需要更多的时间来统一;而且由于上面的一点,没有人对数据访问精通,所以也没有办法优化了。

      那就按层来划分吧,你写DA,我写BA,还有人写Service。写之前,先定义层之间的接口,接口定义好了,自动化测试工程师,还可以写自动化测试脚本,然后每个人写自己一层的具体实现。针对接口编程,不针对实现编程。哈哈,用在这里了。

      项目组终于有了较为正确的开发方式。过了一段时间,V1.0出来了,大家都很高兴。但是后期肯定会有变化吗,软件吗,不变化也就代表没有生命力,没有生命力,肯定会完蛋,完蛋了,我们也就失业了,需要换个地方从头来过了。

      好的,变化来了,比如说订单部分有逻辑需要修改,甚至改动较大,工期大概2个星期。商品部分也有bug,但是2天就可以了。假设改动都在BA。

      过了两天,商品的bug修改完毕,想要测试一下。但是由于order的还没有修改完毕,所以BA整个编译通不过,所以UI没有办法测试,自动化也没有办法测试,因为需要引用BA程序集,但是BA编译不过。只好等了,一等就是7-8天啊,有几个人就可能闲了下来,做别的事情吧,product的相关bug不能关闭,没有结果。好像是出了点问题。

      当然了,也有解决的办法,就是被order在BA中需要修改的逻辑代码都注释掉,然后编译就通过了,就可以发布测试了。但是本来能用的order部分,虽然逻辑有问题,但是原来还是可以跑的,由于注释了代码,所以不能运行了。应该还有更好的解决办法。

      简单的模块划分有问题,分层开发了,后面还是有不太好的地方,而且越做越大,问题会更加明显,矛盾也会更加明显,有没有解决办法呢?

      这两种是不是可以结合起来呢?答案是:可以。

      项目整体上按照模块来划分,划分为几个小的子系统,然后再每个模块中应用分层开发的方式。刚开始我也有疑惑,比如说分为两个模块,order和product。但是订单模块里面,有时候会要求显示商品信息,订单模块就需要商品实体吧,但是这个实体在商品模块已经定义过了,是再次定义一遍呢?还是引用product模块的实体呢?定义吧,有点多余了。引用吧,耦合了。

      后来我想通了,应该是在order模块定义一个商品类。虽然表面看起来是多余了,其实订单中要看的商品和商品模块中显示的商品是不一样的,也就是显示的内容不一样。比如说在订单中可能只需要用到商品名称,编号就可以了,但是在商品模块可能需要用到更多的属性,例如:特性、标签、使用方法等。

      所以说还是应该定义两个的,如果说只是定义一个大而全的商品实体,就会发生在某些时候,可能用一两个字段,有时候用4、5个,调用的人不知道里面有没有值,可能会处理报错。最好是用几个属性,就有几个属性,这几个属性都有值。既减少错误,也减少耦合。

      下面借用一下Artech 的WCF.PetShop项目的结构图,如有不妥,请来电说明,我会及时替换。感谢Artech 给大家带来的精彩分析,以及他无私的奉献。

      

      采用了上面的结构之后,如果是前面的情况,product的bug修改完毕之后,发布product相关的dll就可以了,可以进行测试,不影响order部分的使用。也算是项目的OCP(Open-Closed Protocal)原则吧。(请各位原谅我的冒用)
     
      结论
     

     

    1、实体的专用性

    1)        尽量的保持实体的专用性,也就是一个功能的方法,虽然和两外一个方法的返回结果类似,可能只需要添加一两个属性,这样的情况,重新建立实体,方便后面可能对这两个方法返回内容的修改不至于相互影响。

    2)        尽量保持一个实体中的每一个属性,每一个被赋值的属性,将来都会用到,否则减少实体的属性,或者新建一个实体,使用正好合适的属性个数。

     

    3)        分离添加和显示用的实体,因为添加可能不是每个字段都需要赋值,或者一些值是默认值。

     

    4)        分离不同类型的用户使用的实体,尽管是相同的功能。可以在类名添加ForPlanter之类的后缀来解决。因为不同用户关注的点不同,关注的属性肯定不相同。而且修改也不影响其他类型用户的使用。

     

    2、方法的专用性

     

    保持方法的专用性,分离不同用户的业务方法和数据访问方法。也是为了后面的修改,不至于影响其他用户功能的使用。

     

    3、系统划分

    先按照功能模块或者是服务的对象主体来划分系统,划分为子系统。然后再每个子系统中分层,子系统之间的交互使用接口。子系统相关的后台代码独立,方便日后维护升级。

     

     

      具体分析可以参看园子中的Artech 写的一个小系列:

      WCF版的PetShop之一:PetShop简介

      WCF版的PetShop之二:模块中的层次划分

      WCF版的PetShop之三:实现分布式的Membership和上下文传递

      大家有什么想法,欢迎留言或者来电交流。

    【Blog】http://virusswb.cnblogs.com/

    【MSN】jorden008@hotmail.com

    【说明】转载请标明出处,谢谢

    反馈文章质量,你可以通过快速通道评论:

  • 相关阅读:
    Linux文件属性
    [Oracle] Listener的动态注册
    jQuery easyUI Pagination控件自定义div分页(不用datagrid)
    桂林电子科技大学出校流量控制器Android版1.0.0
    php使用check box
    Python windows ping
    Python selenium chrome 环境配置
    Linux wget auto login and backup database
    PyQt4 ShowHMDB show sqlite3 with QTableWidget summary
    PyQt4 py2exe 打包 HardwareManager
  • 原文地址:https://www.cnblogs.com/virusswb/p/1777163.html
Copyright © 2011-2022 走看看