之间的耦合以及模块(子系统)划分)
题外话最近已经在努力学习了学习基本功学习设计模式学习成熟框架学习软件架构。发现越是学习的多越是发现自己知道的少。引言本篇中的系统使用的技术背景是.NET平台C#语言数据库是SQL Server其他平台没有参与过所以没有验证过。简写解释BABusiness Access业务访问DAData 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部分的使用。也算是项目的OCPOpen-Closed Protocal原则吧。请各位原谅我的冒用结论1、实体的专用性1) 尽量的保持实体的专用性也就是一个功能的方法虽然和两外一个方法的返回结果类似可能只需要添加一两个属性这样的情况重新建立实体方便后面可能对这两个方法返回内容的修改不至于相互影响。2) 尽量保持一个实体中的每一个属性每一个被赋值的属性将来都会用到否则减少实体的属性或者新建一个实体使用正好合适的属性个数。3) 分离添加和显示用的实体因为添加可能不是每个字段都需要赋值或者一些值是默认值。4) 分离不同类型的用户使用的实体尽管是相同的功能。可以在类名添加ForPlanter之类的后缀来解决。因为不同用户关注的点不同关注的属性肯定不相同。而且修改也不影响其他类型用户的使用。2、方法的专用性保持方法的专用性分离不同用户的业务方法和数据访问方法。也是为了后面的修改不至于影响其他用户功能的使用。3、系统划分先按照功能模块或者是服务的对象主体来划分系统划分为子系统。然后再每个子系统中分层子系统之间的交互使用接口。子系统相关的后台代码独立方便日后维护升级。