示例VS解决方案的创建(一)

 

  进行项目开发的第一步,是创建出适合自己团队习惯的VS解决方案,虽然我已经提供了项目示例,但毕竟是我创建的,你直接使用可能并不合适,另外你如果尝试模仿重新创建该示例,中间可能碰到各种障碍,特别是项目间的依赖关系。

  本文的目的是帮助.Net架构初学者能顺利搭建起适合自己的VS解决方案,我会在本文演示曾经用过的几种不同风格的目录结构,你可以根据自己的习惯选择一种并自行修改。

  本系列假定你已经熟悉如何创建.NET类库等基础知识,并具有.Net开发经验,我不会详细到每一个细节。如果你是.Net初学者,尚未开发过任何实际项目,对你的建议就是关闭本页面,去买本书打好基础,需要提升时再来。

影响VS解决方案结构的因素

分层

  VS解决方案的创建,与你采用的分层方式密切相关,我在之前的文章已经简单介绍过单层架构和三层架构,本文采用DDD分层架构进行演示,说明项目示例Applications.Managements是怎样创建出来的,并且可以怎样简化。

  我们平时所说的分层,属于逻辑分层,它按照一定的逻辑层次分离关注点,以便更好的组织代码结构,方便维护。

  物理分层,是将不同的代码部署到不同的服务器,以提供更高性能和安全性,如果对逻辑分层和物理分层的关系感兴趣,请参考《C#企业应用开发艺术-CSLA.NET框架开发实战》一书。

  对于逻辑分层,只要将代码分离到不同区域即可,可以按照不同的抽象粒度来组织代码,比如类级别、目录级别、程序集级别。

  目前普遍采用的是程序集级别进行分层,即不同层的代码放到不同的程序集中。

  如果期望减少程序集,可以仅创建一个类库,采用目录级别的划分方式,在一个类库中创建不同层的文件夹,各目录放置各层的代码。

  类级别粒度将不同层的对象合并,通过方法的形式分离各层代码。

  通过程序集方式分层有诸多好处,比如清晰度、复用性等,我将采用程序集方式进行演示,建议你在项目上也尽量采用这种方式。

功能模块

  另一个影响VS解决方案创建的因素是功能模块的划分。

  对于一个业务系统,我们不仅要分层,而且还要划分功能模块,以便对较大的业务问题进行分解,从而降低复杂度,同时在解决某个特定模块的问题时,减少其它模块的干扰。

  对于领域层,我目前的方式是为每一个功能模块创建一个类库项目,这样做的好处是更方便复用,另外当我需要将这个功能模块分离出去也会更容易。

  当然,采用文件夹来分隔也同样可行,这是两种不同的风格,我会向你演示如何设计可以更方便的切换。

可复用能力

  对于一个稍大的项目,把特定业务模块、通用业务模块、通用技术类库放在同一个VS解决方案中,VS解决方案上的项目可能会达到上百个,编译速度将非常缓慢,导致很多不必要的麻烦。

  我之前已经多次提到,你可以把通用技术类和通用业务类从具体项目中分离出来,这样可以供多个项目使用,每个项目拥有自己的VS解决方案,共享相同的应用框架,这样维护会更容易,编译速度也更快。

  对于Applications.Managements项目示例,通用技术类库已经抽取到Util解决方案中,Applications.Managements不包含通用性的纯技术代码。

  我不会为你演示通用业务类的分离,因为代码示例太简单。

其它因素

  不同的应用程序类型也会影响VS解决方案的创建,比如创建WPF智能客户端应用程序,需要将应用层创建为WCF类库,这样可以将应用服务直接开放出来供WPF调用。对于WPF+WCF的架构,我后续也会进行介绍,如何通过IOC切换本地调用和远程调用,通过这个架构可以在开发时期采用本地方式调用,提高开发效率,部署时切换到WCF远程代理。

  如果你采用了诸如SOA架构,需要切割子系统部署成服务,可能需要创建更多类型的项目和多个VS解决方案,这些架构也对VS解决方案的创建具有相当影响。由于本人在SOA方面经验尚浅,待后续有更多经验再进行分享。

VS解决方案创建实战

  下面的步骤演示了我创建VS解决方案的习惯,你不一定要按我的步骤,只要最终达到你的要求即可。

创建表现层MVC项目

  打开VS解决方案,我使用的是VS 2013,自带了MVC4。

  创建MVC4项目,项目名称为Applications.Presentation.Managements,解决方案名称为Applications.Managements,MVC项目模板选择“基本”。

  先来讨论顶级空间的命名,即这里的Applications,要点是尽量抽象。顶级空间名称尽量不使用特定于项目或客户的名称,因为你做下一个项目时,需要大量更改命名空间。我采用Applications,代表抽象的应用程序,任何项目都是应用程序。你也可以采用公司的名称,比如你们公司简称为abc,那么可以这样Abc.Managements。

  Managements代表这是一个管理系统。Applications.Presentation.Managements说明它是管理系统的表现层,但为什么不用Applications.Managements.Presentation,后面介绍到领域层时我会说明这样做的原因。

  对于表现层来讲,没有其它层会调用它的API,所以我想保持表现层命名空间的简短,我耍了一个小技巧,将表现层的命名空间改成了Presentation。

  右键单击Applications.Presentation.Managements项目,选择“属性”,修改“默认命名空间”为Presetation,如下图所示。

  MVC创建完成后,会在根目录留下一个packages文件夹,MVC项目也会添加packages.config配置,这玩意很有用,Nuget会帮你管理依赖的程序集及版本,当别人运行你的解决方案时缺少程序集,会自动下载还原。但我更喜欢自己手工管理,在Applications.Managements根目录创建Libraries文件夹,我会把packages中必须的几个dll复制进去,其它全部删掉。

  当然,修改表现层默认命名空间和删除packages属于我的个人习惯,介绍这个是方便你看我的代码,对于你自己的项目,完全没必要这么麻烦。

  编译通过,继续下面的步骤,后面再返回到表现层。

创建表现层扩展项目

  在Applications.Managements解决方案上右键,“添加”->“新建项目”,创建一个类库项目,名称为Applications.Presentation.Managements.Extensions。

  这个项目用来为表现层提供一些支持,比如业务组件的封装。

  将它的默认命名空间改成Presentation,方便表现层的调用。

  下面来考虑类库输出的DLL目标位置,默认是在bin\Debug\,表示DLL将输出到类库项目的bin目录下Debug文件夹中。由于我们后续会创建更多的程序集,如果对输出位置不进行统一,将导致每个输出目录都产生大量重复的DLL。

  右键单击扩展类库,选择属性,找到“生成”选项卡的“输出路径“,修改为..\Release\,如下图所示。

  下面为Applications.Presentation.Managements项目添加Applications.Presentation.Managements.Extensions扩展项目的引用。

编译通过,继续下面的步骤。

创建应用层项目

  在Applications.Managements解决方案上创建类库项目,名称为Applications.Services,修改类库输出路径为..\Release\。

  应用层是为表现层提供服务的,所以表现层Applications.Presentation.Managements需要添加应用层Applications.Services的引用。

  编译通过,继续下面的步骤。

创建基础设施层项目

  DDD分层架构中没有了数据访问层的概念,被包含到基础设施层中。

  基础设施层是为其它各层服务的,按道理说,其它各层应该包含对基础设施层的引用。

  但是,为了让领域层变得更纯净,一般会应用依赖倒置原则,让基础设施层反过来依赖领域层。

  一些初学者会产生疑惑,这样不是造成循环引用的死循环了吗?下面谈下我的看法,不一定正确,仅供参考。

  在《领域驱动设计》一书中,对基础设施层的描述为:基础设施层为各层提供通用的技术能力

  可见基础设施层是一个抽象概念,诸如层超类型、公共操作类的封装、数据库的持久化,发邮件,发短信等操作,都是基础设施层的范畴。

  在我的代码中,大量通用技术,都被封装到Util相关的程序集中,如果需要合并VS解决方案,那么所有的Util项目都是基础设施层的一个组成部分。

  对于领域层与基础设施层的引用关系,与基础设施层中项目耦合性强弱有关,一般规律是:

  1. 领域层只引用基础设施层中低耦合的项目,比如领域层可以引用Util.Core、Util.Domains,这些项目只包含对.NET本身类库的引用,没有外部依赖,也不需要任何配置,领域层依赖这些项目不会降低可复用性和可测试性等指标。
  2. 与领域层密切相关的高耦合基础设施层项目,应用依赖倒置原则,先在领域层定义操作接口,由基础设施层项目引用相关领域层项目,并实现该接口。比如仓储代表聚合的集合,仓储的实现依赖于特定数据访问技术,甚至包含SQL语句,所以具有很高的耦合,且与领域层特定模块密切相关。如果领域层直接引用数据访问实现的程序集,将严重降低领域层的可复用性,且更难测试。
  3. 与领域层关系不大的高耦合基础设施层项目,应用分离接口模式,将操作接口与具体实现分离到基础设施层的不同项目中。比如工作单元的接口IApplicationUnitOfWork,它与领域层基本没啥关系,如果你的领域层只包含一个类库项目,把IApplicationUnitOfWork放到领域层项目中也没什么问题,我之前一直是这样干的,但如果你的领域层包含多个项目,你应该放到哪一个项目中?单独创建一个基础设施层项目来放置这些接口会好一些。

(未完待续…

代码更新

  1. 更新了js中的一些Bug
  2. 由于项目上需要使用MYSQL,最近几天摸索了EF操作MYSQL,遇到的一些障碍已解决,特将解决方案放出,供使用MYSQL的同学参考。

    a) MYSQL的乐观离线锁与SQL SERVER显著不同,主要参考王刚的这篇:EF6 Code First 系列 (三):在MySql中使用和SqlServer一致的RowVersion并发控制。不过对于Sql Server,我还是使用IsRowVersion,毕竟这是大部分项目的主打。

    b) 通过一个简单的Ioc配置,即可将Sql Server切换到MySql。

  c) MySql不支持Sql Server的schema,我使用.分隔MySql表名模拟schema,以保持与Sql Server的一致性风格,这需要一点EF映射技巧。

  3. codesmith代码生成模板已更新,调整了命名空间,并增加了对mysql特定配置的生成。

  4. 数据库备份中提供了一个MYSQL建库脚本。

QQ群

  应用程序框架交流QQ群1:386092459(已满)

  应用程序框架交流QQ群2:376124781

  EasyUi交流QQ群:157809322

源码下载:(下载时顺手推荐)

框架源码

项目示例源码

数据库备份

Codesmith生成器模板

备注

  本来准备只用一篇来完成本文,不过太忙了,只有分几次来写,希望各位见谅,下次更新的时间会比较长。

版权所有,转载请注明出处 何镇汐的技术博客

最新文章

  1. python基础之常用模块以及格式化输出
  2. [转] - Ubuntu 安装Eclipse
  3. Android Monkey
  4. Label 表达式绑定
  5. Oracle dual表的用途
  6. OpenLayers学习笔记(十一)— 飞机速度矢量线预测
  7. MySQL中dblink的实现(通过federated引擎实现)
  8. MSIL 教程
  9. spring 装配
  10. git 使用ssh密钥
  11. Centos7使用pxe安装KVM虚拟机
  12. Jquery 给Js动态新添加的元素 绑定的点击事件
  13. ASP.NET中关于XML的AJAX的读取与删除
  14. 禁止同一条ajax请求重复发出的方法
  15. swagger简单配置
  16. APIGateway网关安全设计
  17. easyui 列表 条件检索
  18. CAD 卸载工具,完美彻底清除干净cad各种残留注册表和文件
  19. Error: could not find java.dll 解决办法
  20. POJ-1564 dfs

热门文章

  1. python遗产
  2. (转)maven设置内存
  3. RH033读书笔记(6)-Lab 7 Standard I/O and Pipes
  4. [ACM] poj 3468 A Simple Problem with Integers(段树,为段更新,懒惰的标志)
  5. cocos2dx环境配置和打包
  6. Android 它们的定义ContentProvider和ContentObserver充分利用
  7. hdu 5074 相邻的和最大dp
  8. 【Android进阶】快捷图标的创建与移除
  9. HDU 2454 Degree Sequence of Graph G(Havel定理 推断一个简单图的存在)
  10. Java绘制艺术图形