题外话
最近已经在努力学习了,学习基本功,学习设计模式,学习成熟框架,学习软件架构。发现越是学习的多,越是发现自己知道的少。
引言
本篇中的系统使用的技术背景是:.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和上下文传递
大家有什么想法,欢迎留言或者来电交流。
分享到:
相关推荐
在本文中,我们将深入探讨系统功能模块设计的基本概念、设计原则、常见方法以及如何进行有效的模块划分。 首先,系统功能模块设计是软件工程中的一个关键步骤,它将整体系统的需求分解为可管理的小部分,每个部分...
在进行服务子系统划分时,有几点需要注意: 1. 避免跨服务的数据依赖:每个服务应尽可能保持数据的独立性,不要出现A服务的SQL需要查询B服务中的表的情况。这样的设计会使得服务间的边界模糊,当需要进行数据库的...
模块独立性是指在软件系统中,每个模块都应尽可能地只完成独立的子功能,并且与其他模块之间的依赖关系最小化。为了实现这一点,引入了两个关键指标:耦合性和内聚性。 #### 耦合性 耦合性(Coupling)是用来衡量...
首先,子系统设计的目标是明确在软件生命周期中何时进行子系统划分以及如何设计。它通常在早期精化阶段进行,可能在先启迭代(可选)之后,伴随着架构定义和数据库设计(如果需要)。设计子系统是为了实现更好的模块...
这个方法首先定义了不同层级的实体模型,包括业务层、操作系统分区层、模块层、子系统层和系统层,以反映陆战平台信息控制系统的复杂结构。每个层级都具有特定的属性和约束,这些属性和约束有助于理解和评估系统的...
子系统软件结构设计则关注软件的组织架构和模块划分。文档中提到了以下方面: 1. **软件结构图**:这是一种图表,用于可视化软件的组成部分,如模块、子系统和它们之间的关系。它帮助开发者理解代码的层次结构,...
件开发与项目管理中,模块设计...通过合理划分模块,降低耦合度,提高内聚度,以及遵循信息隐蔽原则,可以创建出结构清晰、易于扩展的软件系统。在实际开发过程中,需要结合具体项目需求,灵活应用这些设计原则和方法。
首先,模块化设计的基本原则是单一职责原则(Single Responsibility Principle, SRP),即每个模块应只负责一项功能,确保模块间的边界清晰,降低模块之间的耦合度。例如,我们可以将用户管理功能划分为用户注册、...
模块化的核心理念是减少循环依赖和耦合,通过合理划分模块,使得每个模块专注于自己的功能,从而提高设计效率。 模块化设计的主要目标包括: 1. 减少循环依赖:循环依赖可能导致组件之间的相互影响,模块化通过明确...
该文档覆盖了整个项目的所有主要模块,包括但不限于子系统A和B的模块,以及其他相关的辅助模块。它详细描述了模块的命名规则,模块之间的关系,以及各个模块的功能和实现细节。 0.3 读者对象 此报告主要面向项目...
- **优化子系统**:确保每个子系统具有良好的内聚性,并且与其他子系统之间的耦合尽可能少。 #### 四、系统分解的步骤详解 1. **明确对象**:确定分解的具体对象,例如在汽车电子电气系统中,组件可以是硬件设备...
在这个过程中,主要活动包括子系统的划分、控制关系的一般模型构建,以及子系统进一步划分为模块。值得注意的是,子系统和模块之间的界限可能并不清晰。 体系结构设计有多种模型,如仓库模型和客户机/服务器模型。...
- **高内聚**指的是单个模块内部元素之间的紧密联系。良好的内聚意味着模块内部的功能紧密相关且自包含,这有助于提高代码的可读性和可维护性。 - **低耦合**是指不同模块之间的依赖程度较低。这样做的目的是为了...
在物流成本管理子系统中,通过MVC模式,可以清晰地划分职责,降低组件间的耦合度,便于后期的维护和升级。 该系统作为一个毕业设计项目,不仅展示了开发者对Java、jsp、Struts等技术的熟练掌握,还体现了他们对于...
在【描述】中提到,外观模式的主要作用是松散客户端与子系统的耦合,使得子系统的内部模块可以独立地进行扩展和维护,而不影响到客户端的使用。这种模式通过引入一个高层次的接口,简化了客户端对子系统功能的调用,...
在本文中,我们将深入探讨如何基于SpringBoot构建一个多模块化的开发平台,其中包括系统基础设置、账号权限管理、日志记录、监控以及代码生成等关键模块。 首先,让我们了解**多模块开发**的概念。在大型项目中,...
3. **电磁兼容模块**:在EMC(Electromagnetic Compatibility)分析中,该模块可以帮助工程师预测和减少设备间的电磁干扰,确保系统之间的互不干扰。 4. **粒子物理模块**:对于高能粒子加速器和粒子束传播的研究,...
这种模式降低了客户端与子系统之间的耦合度,提高了系统的可维护性和可扩展性。 在软件开发中,随着系统的复杂性增加,往往会出现多个模块或子系统相互协作的情况。每个子系统都可能有复杂的内部结构和交互,这对...
高内聚意味着模块内部的元素紧密相关,执行单一功能,而低耦合则意味着模块之间相互依赖的程度较低,这样改动一个模块不会过多地影响其他模块。这样的设计模式有助于减少代码重复,降低错误传播,同时使代码更易于...