.NET Core开发实战(第26课:工程结构概览:定义应用分层及依赖关系)--学习笔记...
26 | 工程結(jié)構(gòu)概覽:定義應(yīng)用分層及依賴關(guān)系
從這一節(jié)開始進(jìn)入微服務(wù)實(shí)戰(zhàn)部分
這一節(jié)主要講解工程的結(jié)構(gòu)和應(yīng)用的分層
在應(yīng)用的分層這里定義了四個(gè)層次:
1、領(lǐng)域模型層
2、基礎(chǔ)設(shè)施層
3、應(yīng)用層
4、共享層
可以通過代碼來看一下
源碼鏈接:
https://github.com/witskeeper/geektime/tree/master/microservices
共享層一共建立三個(gè)工程:
1、GeekTime.Core:主要承載基礎(chǔ)的簡單的類型,比如說異常或者一些幫助類
2、GeekTime.Domain.Abstractions:抽象層,領(lǐng)域的抽象是指在領(lǐng)域模型可以定義一些基類或者接口,領(lǐng)域事件接口,領(lǐng)域事件處理接口,還有 Entity 的接口和 Entity 的基類
3、GeekTime.Infrastructure.Core:基礎(chǔ)設(shè)施的核心層,是指對倉儲(chǔ),還有 EFContext 定義一些共享代碼
這些包實(shí)際上在不同的項(xiàng)目里面都可以共享,所以建議的做法是把這些代碼都通過私有的 NuGet 的倉庫來存儲(chǔ),然后其他的工程可以使用 NuGet 包來直接引用即可
領(lǐng)域模型層就是定義領(lǐng)域模型的地方,這里面會(huì)有不同的聚合,還有領(lǐng)域事件,不同的聚合下面就是領(lǐng)域模型
基礎(chǔ)設(shè)施層是倉儲(chǔ)層和一些共享代碼的實(shí)現(xiàn),這里只定義了倉儲(chǔ)層的實(shí)現(xiàn),包括 EF 的 DomainContext,還有 Order 的倉儲(chǔ)層,User 的倉儲(chǔ)層,還定義了領(lǐng)域模型與數(shù)據(jù)庫之間的映射關(guān)系,就是在 EntityConfigurations 這目錄下面去定義
應(yīng)用層分兩個(gè),一個(gè)工程是 API 層,是用來承載 Web API 或者 Web 應(yīng)用的,另外一個(gè)是后臺任務(wù),這個(gè)就是用來執(zhí)行一些特殊的 Job,作為 Job 的宿主運(yùn)行的,它可以是一個(gè)控制臺的應(yīng)用程序
在 Web 層,Web API 層,也分了幾個(gè)關(guān)鍵目錄 Application,Controllers,Extensions,Infrastructure
基礎(chǔ)設(shè)施層會(huì)放一些身份認(rèn)證緩存之類的與基礎(chǔ)設(shè)施交互相關(guān)的一些代碼
擴(kuò)展層主要是將服務(wù)注冊進(jìn)容器的代碼和中間件配置的代碼,也就是兩擴(kuò)展方法,一個(gè)是對 ServiceCollection 的擴(kuò)展,一個(gè)是對 ApplicationBuilder 的擴(kuò)展
控制器層主要用來定義 Web API,這一層就是定義前后端交互的接口
應(yīng)用層使用了 CQRS 的設(shè)計(jì)模式,就是命令與查詢職責(zé)分離,把命令放在一個(gè)目錄,把查詢放在一個(gè)目錄,同樣的這里還有兩個(gè)事件處理的目錄,一個(gè)是領(lǐng)域模型,領(lǐng)域事件的處理,一個(gè)是集成事件的處理
再看一下各層之間的依賴關(guān)系
Shared 層實(shí)際上是不依賴任何層次的,它存儲(chǔ)了共享的代碼,被各個(gè)工程共享
GeekTime.Core,GeekTime.Domain.Abstractions 是不依賴任何工程的,而 GeekTime.Infrastructure.Core 依賴了 GeekTime.Domain.Abstractions,實(shí)現(xiàn)了倉儲(chǔ),比如說倉儲(chǔ)會(huì)依賴 IAggregateRoot 接口
public interface IRepository<TEntity> where TEntity : Entity, IAggregateRoot領(lǐng)域模型需要繼承模型的基類,并且實(shí)現(xiàn)一個(gè)聚合根的接口,表示它是一個(gè)聚合根
public class Order : Entity<long>, IAggregateRoot領(lǐng)域事件需要實(shí)現(xiàn)一個(gè)領(lǐng)域事件的接口
public class OrderCreatedDomainEvent : IDomainEvent基礎(chǔ)設(shè)施層是一個(gè)獨(dú)立的程序集,實(shí)現(xiàn)了倉儲(chǔ)的部分,定義了一個(gè) Order 的倉儲(chǔ)
public interface IOrderRepository : IRepository<Order, long>還定義了 Order 倉儲(chǔ)的實(shí)現(xiàn)
public class OrderRepository : Repository<Order, long, DomainContext>, IOrderRepository {public OrderRepository(DomainContext context) : base(context){} }這里可以看到倉儲(chǔ)實(shí)際上依賴了基礎(chǔ)設(shè)施層共享代碼里面的倉儲(chǔ)的定義 IRepository,這樣就可以復(fù)用倉儲(chǔ)層的代碼,這樣定義 OrderRepository 就會(huì)比較簡單,可以復(fù)用 Repository 的一些實(shí)現(xiàn)
public abstract class Repository<TEntity, TKey, TDbContext> : Repository<TEntity, TDbContext>, IRepository<TEntity, TKey> where TEntity : Entity<TKey>, IAggregateRoot where TDbContext : EFContext {public Repository(TDbContext context) : base(context){}public virtual bool Delete(TKey id){var entity = DbContext.Find<TEntity>(id);if (entity == null){return false;}DbContext.Remove(entity);return true;}public virtual async Task<bool> DeleteAsync(TKey id, CancellationToken cancellationToken = default){var entity = await DbContext.FindAsync<TEntity>(id, cancellationToken);if (entity == null){return false;}DbContext.Remove(entity);return true;}public virtual TEntity Get(TKey id){return DbContext.Find<TEntity>(id);}public virtual async Task<TEntity> GetAsync(TKey id, CancellationToken cancellationToken = default){return await DbContext.FindAsync<TEntity>(id, cancellationToken);} }已經(jīng)實(shí)現(xiàn)了一些基本的方法,增刪改查的方法
數(shù)據(jù)庫訪問的實(shí)現(xiàn),繼承了自己定義的 EFContext,EFContext 作為共享代碼在各個(gè)工程里面復(fù)用
public class DomainContext : EFContext另外一個(gè)比較特殊的是事務(wù)處理的對象,這個(gè)對象是用來管理整個(gè)應(yīng)用程序的請求上下文中的事務(wù),這樣就可以避免手動(dòng)地去處理事務(wù),簡化代碼
public class DomainContextTransactionBehavior<TRequest, TResponse> : TransactionBehavior<DomainContext, TRequest, TResponse> {public DomainContextTransactionBehavior(DomainContext dbContext, ICapPublisher capBus, ILogger<DomainContextTransactionBehavior<TRequest, TResponse>> logger) : base(dbContext, capBus, logger){} }應(yīng)用層依賴了基礎(chǔ)設(shè)施層,基礎(chǔ)設(shè)施層又依賴了領(lǐng)域?qū)?/p>
應(yīng)用層實(shí)際上是把各層組裝在一起的這一層,它是應(yīng)用程序的一個(gè)宿主,協(xié)調(diào)各層之間的關(guān)系,以及組裝代碼都是在這里實(shí)現(xiàn)的
總結(jié)一下
領(lǐng)域模型層專注于業(yè)務(wù)的設(shè)計(jì),它不依賴于其他各層,它是相對獨(dú)立的
基礎(chǔ)設(shè)施的倉儲(chǔ)層僅僅負(fù)責(zé)領(lǐng)域模型的存取,它不負(fù)責(zé)任何的業(yè)務(wù)邏輯代碼的承載
推薦使用 CQRS 的模式來設(shè)計(jì)應(yīng)用程序,使應(yīng)用程序的代碼結(jié)構(gòu)更加的合理,在團(tuán)隊(duì)和項(xiàng)目膨脹的情況下,工程的可維護(hù)性不至于急劇的下降
Web API 是面向前端交互的接口,避免依賴領(lǐng)域模型
共享代碼建議設(shè)計(jì)為共享包,使用私有的 NuGet 倉庫來分發(fā)和管理
總結(jié)
以上是生活随笔為你收集整理的.NET Core开发实战(第26课:工程结构概览:定义应用分层及依赖关系)--学习笔记...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 玩转控件:重写/重绘Dev中Messag
- 下一篇: .NET Core开发实战(第27课:定