个人财务系统——Petshop实战
一、关于Petshop
PetShop是微软用来展示.Net进行系统开发能力的一个范例,目前版本为4.0。PetShop采用三层架构思想,综合运用面向接口的编程、依赖倒置原则(DIP Dependency Inversion Principle)、工厂模式、单一职责原则、反射等理论和技术,是开发人员学习架构的好范例。
PetShop4.0下载地址为: http://download.microsoft.com/download/8/0/1/801ff297-aea6-46b9-8e11-810df5df1032/Microsoft%20.NET%20Pet%20Shop%204.0.msi
网上已有很多关于PetShop的讲解和剖析,不乏精辟之论,如下地址的一篇文章讲解简练、到位,推荐给大家。http://blog.youkuaiyun.com/zhanghefu/archive/2007/03/06/1522244.aspx
二、我对三层架构的应用和学习历程
早在05年的时候,公司一个项目采用三层架构,我是做开发,项目做下来我并没有感觉到分层开发带来的便利,相反我感觉很累,整个开发小组也有很多抱怨,感觉多了几个层次写起来工作量很大。之后了解到PetShop,PetShop也是采用分层开发的思想,想自己也曾经进行过分层开发,但看了PetShop却怎么也找不到头绪,只好放弃。
时隔半年有余,在一次公司内部培训上, 听了技术经理对三层中各层内容、书写、职责等的阐述,有种醍醐灌顶的感觉,再去看PetShop,居然很快就看懂了,也一下找到了我原来做那个分层开发的项目很累的原因,当时未能真正领会分层开发的思想,分层开发已经被我们仅仅体现在了visual studio的项目层次上,并没有真正体现在各层职责和书写规范上(对于初学分层架构者来说是个误区),比如我们在界面层和数据访问层写了很多逻辑处理,而在业务逻辑层却仅仅实现了对接口的调用,这犯了层次理解上的错误,同时也没有做到层次的单一职责。单一职责原则对类和方法也同样适用,我们的很多不同类型的处理写在同一个类和方法中,像个大杂烩一样,这样的代码没有良好的可读性和可维护性。
三、PetShop实战——个人财务系统
看懂了PetShop,也理解了我们原来项目的失败之处,出于学习的目的,赶紧将自己开发给自己用的个人财务系统重构一番,第一次领略到了分层开发的爽快。
个人财务系统是采用Visual Studio 2005开发的WinForm程序,数据库采用Access 2003,业务较为简单,在架构上相对PetShop的架构而言少了异步处理、缓存管理等辅助层次,对于初学三层架构的朋友来说,避繁就简,或许更容易入门。源代码可以到http://softwaret.cn上获取。
如下是个人财务系统的系统架构图,图中三个层次的划分很清晰,界面层、业务逻辑层、 数据访问层,其中数据访问层包含了数据访问工厂、数据访问接口、数据访问层。公共服务组件中的数据访问组件采用微软企业库(Enterprise Library)。
源代码中共有7个项目,风别是界面、业务逻辑、数据访问工厂、数据访问接口、数据访问、数据实体(注意:并不是7个层次,数据访问工厂、数据访问接口、数据访问层合在一起归为数据访问层,初学者不要将Visual Studio中的一个项目即理解为一个层次),它们之间的引用关系如下图:
四、若干原则
1、依赖倒置原则(DIP Dependency Inversion Principle),其定义为“高层模块不应该依赖于低层模块,二者都应该依赖于抽象;抽象不应该依赖于细节,细节应该依赖于抽象”。上面层次依赖关系图中,我们可以看到数据访问工厂(高层)和数据访问层Access(低层)共同依赖于数据访问接口(抽象);个人财务系统使用的是Access数据库,如果你想改为SQL Server,那么你只需要新增一个数据访问层SQL Server的项目,实现数据访问接口即可。
2、接口隔离原则(ISP Interface Separation Principle),就是不应该强迫客户依赖于它们不用的方法。比如最初的时候我们让雇员信息维护和产品维护实现同一个接口,因为它们都是单记录的增、删、改、查,但后来我们发现要为产品增加一个实现分页查询功能的方法,而这个方法在雇员信息维护功能中并不使用,这样接口变得越来越“胖”,所有依赖于此接口的功能不得不实现它们并不需要的功能。这时候我们就应该使用多个接口。这就是接口隔离原则。
3、单一职责原则(SRP Single Ralationship Principle)。相对于层次来说,对业务规则的处理都应当放在业务逻辑层,而不应该分散到界面层或数据访问层去实现,尽管有时候感觉不在业务逻辑层实现反而更直观和方便,前面我讲的我们在做某个项目时将业务逻辑写在了界面层,就破坏了界面层仅负责用户界面这一单一职责。对于一个类来说,不要让一个类实现两个以上不同类型的功能,方法也如此,大概我们都听过类似这样的话,一个方法不要写得超过100行或200行,应该就有这一层含义,如果一个方法写出来太多行,团队其他成员阅读起来也肯定困难重重。
五、结语
以上这些原则在清华大学出版社出版的《敏捷软件开发——原则、模式与实践》中均有详细阐释和示例,当然还有更对原则没有在本文提到。以前看这本书,自认为对每个原则都很理解,现在真正将这些原则在实际的项目中运用了,再回过头来看,才明白理解并不代表会用,会用也不代表能够灵活运用,从理解到会用,再到灵活运用,这之间一定会有摸索、走弯路的过程,作为程序员,多接触、多动手、多实践是进步的最重要途径。
好了,本人不善行文,至此已是勉强,如有语言不通或者理解错误的地方,恳请批评指正,对我的源代码的理解有问题,或有改善意见的,也欢迎与我交流。谢谢。