背景
Byteart Retail是一个面向领域驱动的.NET企业级应用架构设计案例,到目前为止已经发布了三个版本。有关这三个版本的详细介绍,请参考以下几个链接:
- V1:《EntityFramework之领域驱动设计实践【后续篇】:基于EF 4.3.1 Code First的领域驱动设计实践案例》
- V2:《Byteart Retail V2 - 基于Entity Framework Code First的领域驱动设计实践案例》
- V3:《Byteart Retail V3 - 全新的面向.NET与领域驱动设计的企业应用实践案例》
为了向读者朋友详细介绍Byteart Retail项目,我打算写一个系列专题文章,对案例的各个方面进行详细介绍。随着Byteart Retail的版本更新,发表在本博客的文章不一定会保证100%同步更新,但在系列文章结束的时候,我会给出一个PDF格式的电子版,这个电子版文档是会与最新版的案例保持同步的,有兴趣的读者敬请关注。
前言
从2007年至今,我一直关注着与领域驱动设计相关的软件开发过程与技术,在这几年中,我坚持不懈地学习、实践,在总结自己实践经验的基础上,设计并开发了一套基于.NET的面向领域驱动的企业应用程序开发框架,沿用我以前开发的一个松耦合架构实验原型,为之取名为Apworks。为了向社区展示Apworks在企业级应用开发上给开发人员带来的便捷,我也针对Apworks框架开发了一套面向CQRS架构的案例程序:Tiny Library CQRS。随着Apworks的不断发展,Tiny Library CQRS也先后更新了两个版本,毋庸置疑,第二版更为成熟,更贴近于实际项目应用。
然而,社区对Tiny Library CQRS的反馈却不是那么积极,分析原因,我觉得有三个方面:首先,基于事件溯源(Event Sourcing)机制的CQRS架构本身就非常复杂,套用世界级软件架构大师Udi Dahan对CQRS架构的总结,就是:“简单,但不容易(Simple, but not easy)”,要让一个对企业级软件架构设计不太熟悉的开发人员掌握好CQRS相关的知识,是一件困难的事情,即使有现成的案例,也会让人感觉无从下手;其次,目前大多数应用程序还远没达到需要使用CQRS架构的规模,在项目中应用CQRS,只能把简单问题复杂化;再次,由于个人时间能力有限,Tiny Library CQRS案例本身也没有提供太多的文档与说明,加上该案例直接使用了Apworks框架,所以很多后台运行机制就变得不那么明朗,这对希望研究CQRS架构的开发人员造成了一定的困难。因此,Tiny Library CQRS感觉就与真实项目的实践脱节,自然关注的人就不多了。所以我打算暂时搁置Tiny Library CQRS的更新,让其也成为一个CQRS架构设计的参考原型,供有兴趣的朋友参观学习。
于是,从今年4月开始,我就着手开发并发展了另一个面向领域驱动的.NET企业级应用架构设计案例:Byteart Retail。与Tiny Library CQRS不同的是,Byteart Retail采用了面向领域驱动的经典分层架构,并且为了展示微软.NET技术在企业级应用开发中的应用,它所使用的第三方组件也几乎都是微软提供的:Entity Framework、ASP.NET MVC、Unity IoC、Unity AOP、Enterprise Library Caching等(用于记录日志的log4net除外,但log4net本身也是众所周知的框架),所以,开发人员只需要打开Byteart Retail的源程序,就能够很清楚地看到系统的各个组件是如何组织在一起并协同工作的。经典分层架构的采用,也为实际项目带来了参考和指导的价值。
图一 Byteart Retail V1&V2 界面,略显简单
Byteart Retail以一个在线零售系统为业务背景,目前经过了三个版本的演进,无论在业务方面还是在技术方面,都在逐渐完善。在第一版(V1)中,案例着重于框架的搭建,并偏重于后台技术的演示,因此用户界面仍然还是一个经典的ASP.NET MVC3界面,而且实现的业务功能也显得过于简单;第二版(V2)在第一版的基础上,完善了技术架构,引入了WCF Per-Request生命周期管理器(Lifetime Manager)、基于Unity的AOP拦截、异常处理和日志管理等企业级应用程序架构元素,相信它能够成为软件开发人员很好的学习材料。然而第二版在业务功能和用户体验方面,与第一版完全相同,作为企业级架构的演示案例,又显得不够完善。之后,我利用业余时间,历经3个多月打造了Byteart Retail的第三个版本(V3),这个版本进一步完善了业务功能,同时使用ASP.NET MVC 4的新技术,让用户界面焕然一新:基于jQuery的图片上传、级联菜单、数据分页等,让人感觉耳目一新,使Byteart Retail更接近于一个实际项目。虽然从业务上看,V3与实际应用之间还是有段距离,在今后我仍然会安排一定的时间来改进它的业务模型,但它毕竟是一个演示案例,所以核心业务部分不打算做得过于复杂,以方便开发人员对领域建模和技术架构的研讨。
图二 Byteart Retail V3 界面,比前两版丰富不少
为了能让感兴趣的读者朋友更好地了解到Byteart Retail的架构设计思路与方法,我在发布案例源代码的同时,编写了本文档。虽然从V2开始,我在源代码中,加入了不少中文注释,但毕竟注释的描述能力有限,对于一些设计上的动态特性,或许使用图表的表示方式会更加直观,因此,我觉得除了向大家展示出源代码之外,能让大家拥有这样一份文档是很有必要的。
图三 Byteart Retail案例整体架构概览,与微软NLayerApp的架构类似
本文会跟随“领域驱动设计”的经典分层方式,从基础结构层、领域层、应用层和展示层四大部分对案例进行介绍。展示层的介绍会相对简单一些,因为展示层更偏向于已有框架的技术应用,而且前台技术也不是我的技术强项,因此这方面的细节内容就只能靠读者们自己研究发挥了。在基础结构层部分,我将详细介绍Byteart Retail所使用的与技术相关的内容,比如Service Locator与AOP拦截、配置文件和配置信息读取、异常处理、缓存服务,以及基于Entity Framework的仓储实现;在领域层部分,我将针对Byteart Retail的业务功能对领域建模进行讨论,比如领域对象设计和聚合划分等;在应用层部分,我会讨论对象模型的失衡问题,同时还会向读者介绍一些应用层相关的框架和技术。在学习和讨论的过程中,我们会涉及到很多企业级应用架构模式,比如Service Locator模式(Core J2EE Patterns)、Unit Of Work模式(PoEAA)、Separated Interface模式(PoEAA)等;也会涉及到一些.NET/C#惯用法,比如Dispose模式、不变对象(Immutable Object)、基于C#的Singleton等,在文章中我也会以注解的方式向读者阐述模式与惯用法在实际项目中的应用。希望能对学习企业应用架构模式的读者有一定的帮助。
最后,说说本案例名称的由来吧。Retail很简单,“零售”的英文单词,表示本案例的业务背景;而Byteart(字节艺术),则是我刚开始学习编程的时候,跟我一个同学组成的软件工作室名称。年轻人,对未来总会有很多梦想和期望,虽然除了一个简单的DirectX RPG游戏引擎和小霸王学习机上用BASIC语言开发的扫雷游戏(支持游戏手柄的喔)以外,我们并没有做成过什么,但当年那种为梦想而奋斗的激情却总是无法忘记。将Byteart用在本案例的名称中,以纪念那段美好的时光。