软件系统架构心得

      毕业这几年来,不敢说设计过多少大项目,小项目也有若干个了。再加上平时设计和开发控件(其实一个控件就是一个小型的系统,它也有自己的架构)也有相关设计,我对软件系统架构也有了一定的心得,现分享一下。

      其实我在系统架构方面的真正提升,还是在设计DIM平台时。当时考虑的因素很多,包括接口和实现的低耦合,业务细分(分离),平台管理方式,权限及日志设计等。当时考虑到用户可能会用多种数据库,多种搭建方式(最简单的就是单机版使用,最复杂的就是自己架构一台服务器),及完全的动态数据表的建立及维护。那时对控件也进行了升级,功能块完全抽象出来,使后台调用更为简洁(用过我那个动态列表和动态表单控件的比较清楚,在1.0版本中业务处理起来还是比较复杂和混乱的,功能扩展比较繁琐)。这样在2.0版本里,动态列表和表单内部职责进行了细分,并把常用功能块抽象,使控件内部逻辑更加清晰,方便维护及扩展。目前比较可惜的就是这个平台最终还是因时间和精力问题被放弃了,不过当作系统架构来练笔的话,还算一个比较不错的例子吧。

      后来在就在DIM平台架构的基础上,架构了现在的终端管理平台。同时加了版本机制,设计了界面引擎(毕竟它跟DIM是两个方向的平台)。在平台维护中我也逐渐意识到,架构复杂并不是一件好事,怎么说呢。当时考虑到架构要复杂是因为我们得考虑客户会使用不同的数据库,而业务逻辑可能会发生变化,使用低耦合能比较方便的在线切换业务实现模块,而把功能细分,建立不同的项目,则是为了在程序更新时只需要更新需要更新的部分,节约更新成本。但实际上造成的影响是,我们不得不为了考虑多数据库而设置一些屏障(比如将数据库的一些连接符、分页取数抽象出来),发布版本时一定要将更新过的模块一起发布(否则就会导致依赖的模块版本较低而出错)。后来我就更改了方案,把一些目前不需要考虑的因数给修正了一下。比如说终端的数据库基本上是固定的(因为决定权在我们手里),客户也不用操心用的是啥数据库,而且数据库最好不用安装这样对系统影响最小。这样终端的业务也基本固定下来了,就不用再提取接口搞什么低耦合了。后台呢,因为目前平台后台不支持客户自己部署,所以一些参数我们还是能把它固定下来的,比如说数据库统一使用MSSql,业务层也固定下来了。当平台发展到3.0时就允许客户自己搭建服务器,这时也将终端部署的思想加进来,直接不用客户操心需要安装额外的软件(比如数据库,IIS等),一切都是傻瓜式操作。

      说了这么多,架构一个系统,我认为应该注意以下几点:

      1、尽量去固定化一些因素,使系统尽量精简。比如说客户端使用的数据库,客户端程序模块需不需要经常切换和变动。不可否认的是考虑多的因素,会是系统的适应性更强。但根据实际情况来看,我们也整天说平台移植,数据库更换。但你见过哪几个项目三天两头地换平台和换数据库的?一个平台建立起来后,尤其是正常运行后,如果没遇到严重的瓶颈或者无法解决的问题,是不会轻易动根基的。因为现在大家使用的技术或者语言,都是在不断跟进和发展的。从而向过程编程到面向对象,再到函数式,一门语言也在不断进化着。而数据库也一样,不好说一种数据库完全比不上另外一种(当然是同级别的),良好的数据库设计比数据库本身更有影响力(不合理的设计,Oracle都有可能跑不过Access的)。当然我这里主要指中小平台,如果你设计的平台过于庞大了,我这个说法可能就不大适合您了。

      2、内部功能模块尽量分工明确。这也是我在跟同事培训时经常说的,你在做一个功能的时候,要参考现实中的做法来做。比如用户登录模块,如果允许多种登录方式,怎样设计比较好呢?换成现实中的想法,就是我只管记录登录进来的用户,至于它是怎么登录进来的,不关我事,这你得去问某某。这样这个业务实现可以分两个模块,模块A来负责记录登录进来的用户,时间超时让用户自动退出。模块B来负责检查用户是否可以登录,即实现登录过程。并且将模块B抽象出来,这样就可以实现一系列的登录方式。这样下来,模块A只负责记录登录进来的用户(至于用户是怎么登录进来的,不关他的事),模块B只负责检查用户是否能登录(至于登录后需要做什么,不关他的事)。再一个,如果用户登录后要实现一系列的操作,也可以建立一个模块C来实现。即模块A把用户登记后,通知模块C有用户登录了,该你来处理了。如果不同用户有不同处理方式,就可以将模块C抽象。这样整个业务设计比较清晰,各部分职责明确,容易维护和扩展。

      3、注意属性,方法,事件的设计。这是从具体实现来讲述的,比如我要实现一个界面里的数据展示,可能不止一条,是列表形式的。然后数据的绑定操作就可以由属性来解决。我可以将当前的一些状态信息(如当前第几页,共几页,共多少条记录)等以属性方式展示出来,在属性赋值时由内部自动去绑定一些数据,这样会使业务逻辑更简明,更贴切实际。举个例子,比如要做一个商家分类列表展示界面,那么我需要传递的参数就是商家分类标识,这个标识在赋值时,它先记录下当时的分类标识,然后转到第一页(即将当前页赋值为1)。当前页也是一个属性,它在被赋值时就会触发数据查询操作,将查询出来的数据绑定到相应的界面元素上,然后更新一下总页数和总记录数。这样的一个功能模块就比较清晰,翻页的时候也只需要将当前页累加即可,设计简单,维护也方便。

      4、静态元素的处理。这个就是小细节了,就是利用DotNet框架的好处,将一个类分成若干文件。将对象级别的元素放一起,然后再将静态元素放一个文件(比如以ClassA.static.cs命名),或者根据不同的功能分成不同的文件,这样的好处就是功能比较分明。

      目前总结的也就这么多吧,实际项目中会有更多需要注意的地方,一时半会也没想到那么多,等我想到了再一并总结。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注