自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

從業(yè)務域驅(qū)動開發(fā)看三層架構(gòu)夠不夠?

開發(fā) 架構(gòu)
表現(xiàn)層、業(yè)務層和數(shù)據(jù)層的三層架構(gòu)體系大家都不會陌生。但今天我們要談的是從業(yè)務域驅(qū)動開發(fā)看三層架構(gòu)夠不夠。

三層架構(gòu)

相對于目前日新月異的新概念,新名詞,三層架構(gòu)已經(jīng)算得上元老了。雖仍有爭議,但業(yè)界更多的是共識。

圖1 常用三層的描述圖

 

足夠簡單、清晰,我仍要提醒的是,注意層之間連線的箭頭,非常之重要,借用UML的定義,箭頭表示依賴關(guān)系。也就是說,必須先有數(shù)據(jù)層,才有業(yè)務層,然后才有表現(xiàn)層。這又怎么樣,小問題。不,這是一個大麻煩!

從DDD看三層

我們暫時靶這個話題放一放,挑個比較新一點的東西。業(yè)務域驅(qū)動開發(fā)(DDD) 近年也是風生水起,紅紅火火,但它是什么,是怎么回事,似乎就不如三層架構(gòu)那么婦孺皆知了。

圖2 從DDD的角度看三層架構(gòu)

以業(yè)務域為系統(tǒng)的核心,所有其它與業(yè)務無關(guān)的內(nèi)容對這個核心來談,都是外部服務/功能。這里,出于本文說明的需要,獨立出了兩個較為特別的外部功能,持久層和用戶接口。

兩個看上去完全不同的架構(gòu)設計,哪個更對哪個更好?每一個都有大量的擁護者,大量的討論,互相三間似乎又涇渭分明,至少我們經(jīng)常看到的文章給我們?nèi)绱说挠∠?。自然,我們的思考,為什么不能融合在一起呢?其實,它們并不像看起來區(qū)別那么大。從名詞上,雖然我有意把名稱錯開,我們也仍能看到之間的對應關(guān)系、業(yè)務層=業(yè)務域,數(shù)據(jù)層=持久層,表現(xiàn)層=用戶接口。當然,這些細節(jié)用詞的不同仍有必要的,畢竟,它們不完全是一回事。

DDD的三層實現(xiàn)詳細架構(gòu)

好了,抽象的討論已經(jīng)足夠了,我們也足夠糊涂了。細節(jié)為王,我們?nèi)绾螌崿F(xiàn)?來看看這個實際系統(tǒng)的簡化架構(gòu)圖。.

圖3 實際架構(gòu)設計

可以看到,在保留了清晰的三層外,重要的是把依賴關(guān)系改變了。而所謂依賴注入(DI),只是一種實際的技術(shù)實現(xiàn),完成和實現(xiàn)這種架構(gòu)設計需求。也可以清晰的看到,圖中是以Domain為核心的。 當然,這是一個簡化又簡化的示意圖,不想一開始就把事情弄的復雜.

看代碼

最后,來看看具體的代碼,才有更好的體驗。

業(yè)務域 (Domain)

考試類:

  1. namespace Skight.Demo.Domain.Examination{  
  2. public class Exam{public virtual int Id { getset; }  
  3. public virtual string Code { getset; }  
  4. public virtual string Name { getset; }}} 

view raw gistfile1.cs This Gist brought to you by GitHub.

很簡單的一個考試類,可以看到,域中的類定義幾乎不受持久層(數(shù)據(jù)庫)影響,除了兩點:

1.屬性ID是從數(shù)據(jù)表的主鍵而來;

2. 如果要用nHibernate的Lazy Load每個屬性都必須是Virtual。

即使如此,這個類已經(jīng)足夠干凈了。我也看到,一些系統(tǒng)實現(xiàn),專門定義了一個基礎(chǔ)類Entity,然后,把ID的定義放在這個類中. 我覺得很沒必要, 畫蛇添足。

作為示例,這個域類很簡單, 但卻是核心的核心。項目越往后,這一層膨脹的越厲害。后面幾部分,現(xiàn)在看起來比較多,復雜。之后,不會有大的變化,反而顯得會越來越簡單。

倉儲接口:

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq.Expressions;   
  4. namespace Skight.Demo.Domain{  
  5. public interface Repository{Item get_by_id<Item>(int id);   
  6. void save<Item>(Item item);   
  7. Item get_single_item_matching<Item>(Query<Item> query);  
  8. void delete<Item>(Item item);   
  9. IEnumerable<Item> get_all_items_matching<Item>(Query<Item> query);  
  10. IEnumerable<Item> get_all_items<Item>();}} 

view raw gistfile1.cs This Gist brought to you by GitHub.

注意到:

1. 接口命名,我沒有加I,這是特意的。

2. 用到了Query<>接口, 這個是對查詢的一個抽象。好處是,不需要像大多數(shù)的倉儲實現(xiàn),要為每個類建立一個倉儲接口,膨脹的很厲害。

Quer接口很簡單,沒有任何方法和屬性,只是為了使用強類型。它的實現(xiàn)類會根據(jù)需要, 越來越多。 因為,查詢幾乎就是數(shù)據(jù)層的主要功能。

查詢接口的定義:

  1. namespace Skight.Demo.Domain  
  2. {  
  3. public interface Query<Item>{}  

view raw gistfile1.txt This Gist brought to you by GitHub.

持久層 (數(shù)據(jù)層)

考試映射類:

  1. using FluentNHibernate.Mapping;  
  2. using Skight.Demo.Domain.Examination;   
  3. namespace Skight.Demo.NHRepository{  
  4. public class ExamMap:ClassMap<Exam>{  
  5. public ExamMap(){Id(x => x.Id);Map(x => x.Code);  
  6. Map(x => x.Name);}}} 

view raw gistfile1.cs This Gist brought to you by GitHub.

Fluent nHibernate對倉儲接口的實現(xiàn):

  1. using System;using System.IO;  
  2. using System.Reflection;  
  3. using FluentNHibernate.Cfg;  
  4. using FluentNHibernate.Cfg.Db;  
  5. using NHibernate;using NHibernate.Cfg;  
  6. using NHibernate.Tool.hbm2ddl;  
  7. namespace Skight.Demo.NHRepository{      
  8. public class SessionProvider      
  9. {         
  10.  #region Instance for use outside          
  11. private static SessionProvider instance;          
  12. public static SessionProvider Instance {             
  13.  get            {                 
  14.  if (instance == null)                  
  15. {                     
  16.  instance = new SessionProvider();          
  17.         }                  
  18. return instance;            
  19.   }        }       
  20.    #endregion        
  21.   #region Set up database       
  22.    private const string DBFile = "SkightDemo.db";     
  23.      public bool IsBuildScheme { getset; }     
  24.      public void initilize()      
  25.     {                       session_factory = Fluently.Configure()            
  26.       .Database(SQLiteConfiguration.Standard.UsingFile(DBFile).ShowSql())           
  27.        .Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.GetExecutingAssembly()))          
  28.       .ExposeConfiguration(c => c.SetProperty("current_session_context_class""thread_static"))         
  29.        .ExposeConfiguration(build_schema)              
  30.     .BuildSessionFactory();        }      
  31.     private void build_schema(Configuration configuration)      
  32.     {            if (IsBuildScheme)        
  33.       {                new SchemaExport(configuration)           
  34.            .Execute(truetruefalse);            
  35.   }        }        #endregion       
  36.    private readonly object lock_flag = new object();     
  37.      private ISessionFactory session_factory;       
  38.    public ISessionFactory SessionFactory {           
  39.    get {                 
  40.  if (session_factory == null) {       
  41.                lock (lock_flag) {                        
  42.  
  43.   if (session_factory == null) {                         
  44.      initilize();                       
  45.    }                    }               
  46.    }                
  47.   return session_factory;         
  48.      }        }          
  49. public ISession CreateSession() {         
  50.      ISession session = SessionFactory.OpenSession();           
  51.    return session;        
  52.   }          
  53. public ISession CurrentSession      
  54.     {          
  55.     get { return SessionFactory.GetCurrentSession(); }      
  56.     }     
  57.  }} 

view raw gistfile1.cs This Gist brought to you by GitHub.

Fluent nHibernate的配置:

view raw gistfile1.cs This Gist brought to you by GitHub.

使用的SQLite文本數(shù)據(jù)庫,作為示例。

測試和使用的例子

自動創(chuàng)建數(shù)據(jù)庫:

  1. using NUnit.Framework;   
  2. namespace Skight.Demo.NHRepository.Tests{[TestFixture]  
  3. public class CreateDatabase{[Test]public void Run(){
  4. var provider = SessionProvider.Instance;provider.IsBuildScheme = true;provider.initilize();}
  5.  }} 

view raw gistfile1.cs This Gist brought to you by GitHub.

這里,只是用測試的形式,實現(xiàn)功能。如果運行這個測試,將自動生成數(shù)據(jù)庫。并且,可以輸顯示數(shù)據(jù)庫生成腳本。在產(chǎn)品環(huán)境下,我就是用這個腳本來做數(shù)據(jù)庫安裝的。

操作數(shù)據(jù)(模擬UI):

  1. using NHibernate;  
  2. using NHibernate.Context;  
  3. using NUnit.Framework;  
  4. using Skight.Demo.Domain;  
  5. using Skight.Demo.Domain.Examination;   
  6. namespace Skight.Demo.NHRepository.Tests{[TestFixture]  
  7. public class DataOperation{  
  8. private Repository repository;  
  9. private ISession session;private ITransaction transaction;  
  10. [SetUp]public void SetUp(){  
  11. //Dependecy Injectrepository=new RepositoryImpl();  
  12. session = SessionProvider.Instance.CreateSession();  
  13. transaction = session.BeginTransaction();  
  14. CurrentSessionContext.Bind(session);  
  15. }[TearDown]public void TearDown(){   
  16. transaction.Commit();  
  17. transaction.Dispose();  
  18. transaction = null;   
  19. session.Close();  
  20. session.Dispose();  
  21. }[Test]public void create_a_exam(){var exam = new Exam();  
  22. exam.Code = "001";exam.Name = "計算機考試";  
  23. repository.save(exam);  
  24. }   
  25. [Test]public void get_the_exam_by_id(){
  26. var exam = repository.get_by_id<Exam>(1);  
  27. Assert.IsNotNull(exam);  
  28. }   
  29. [Test]public void delete_the_exam()   
  30. {var exam = repository.get_by_id<Exam>(1);repository.delete(exam);  
  31. }   
  32. }} 

view raw gistfile1.cs This Gist brought to you by GitHub.

同樣,用測試的形式,模擬UI的數(shù)據(jù)的操作。
首先,運行Create_a_exam()插入一個考試對象。
然后,運行g(shù)et_the_exam_by_id()獲取剛插入的考試。
運行 delete_the_exam()刪除考試。

完全代碼下載  下載頁面     直接下載

原文鏈接:http://www.cnblogs.com/Wonner/archive/2012/04/16/From_DDD_To_3Tier.html

【編輯推薦】

  1. 架構(gòu)師向左,項目經(jīng)理向右??
  2. 淺談Web自動化測試原理
  3. 百度首席架構(gòu)師眼中的架構(gòu)
  4. 給用戶和開發(fā)者最佳的.Net框架部署方案
  5. XQuery 開發(fā):一種更好的數(shù)據(jù)庫編程語言
責任編輯:彭凡 來源: 博客園
相關(guān)推薦

2013-01-09 11:00:20

架構(gòu)開發(fā)三層架構(gòu).NET架構(gòu)

2011-04-19 13:53:41

三層架構(gòu)

2015-07-02 10:57:11

General框架架構(gòu)開發(fā)

2009-05-06 09:40:04

LINQWEB開發(fā)構(gòu)架

2009-08-26 18:20:42

三層架構(gòu)

2015-05-25 15:15:53

浪潮

2011-08-08 14:14:03

架構(gòu)

2009-07-28 17:25:14

ASP.NET三層結(jié)構(gòu)

2010-01-04 17:36:40

2010-02-22 13:41:49

三層交換機

2022-07-22 10:09:28

架構(gòu)設計

2012-02-03 09:44:33

.NET

2022-07-26 12:33:38

架構(gòu)設計場景

2018-10-31 14:32:53

數(shù)據(jù)中心網(wǎng)絡架構(gòu)

2009-04-30 15:56:50

三層架構(gòu)MVCMVP

2009-07-28 15:08:50

MVC三層架構(gòu)實例

2018-03-08 15:30:31

超融合架構(gòu)傳統(tǒng)三層架構(gòu)

2010-01-15 10:33:28

三層交換技術(shù)演變

2010-02-22 14:05:33

三層交換機

2012-02-07 10:40:13

MVCJava
點贊
收藏

51CTO技術(shù)棧公眾號