Skip to main content

基础设施层

过往,在描述领域驱动的一些架构图或分层图中,一个常见的做法是将基础设施层放在最下面,让其它层都依赖它。

这是非常明显的错误。

真正正确做法是:没有任何一个层是依赖基础设施层的,基础设施层的真正作用是提供对接口的实现。

是实现而非依赖#

我们反过来说,如果领域层依赖基础设施层,而基础设施层又依赖了hibernate或其它具体框架。那就变成这样的场景了。

这是错误的

错误

如上图所示,如果我们是这么个依赖法,受传递依赖的影响,等同于我们的领域层就依赖了具体的技术,比如Hibernate或Redis了。

这肯定是错误的。

如上图所示,基础设施层是提供实现,而非依赖。而领域层或其它层依赖的是接口或抽象,而不是基础设施层


interface ISVClientRepository : EntityRepository {
    suspend fun querySuiteTicket(suiteId:String,clientType:ISVClientType):Future<ISVSuiteTicket?>
    suspend fun queryAuthCode(suiteId: String, domainId:String, orgCode:String, clientType: ISVClientType):Future<ISVAuthCode?>
    suspend fun queryTemporaryAuthCode(suiteId: String, domainId:String,orgCode:String, clientType: ISVClientType):Future<ISVAuthCode?>
    suspend fun queryPermanentAuthCode(suiteId: String, domainId:String, orgCode:String, clientType: ISVClientType):Future<ISVAuthCode?>}

如上代码所示,在领域层中,需要的行为,你可以抽象为仓储或其它接口。这样依赖的就是接口,而非实现了。

而基础设施层则是提供此接口的实现的地方


class ISVClientRepositoryHibernate : EntityRepositoryHibernate(),ISVClientRepository {
    override suspend fun querySuiteTicket(suiteId: String, clientType: ISVClientType): Future<ISVSuiteTicket?> {        return singleQuery(            clazz = ISVSuiteTicket::class.java,            sql = "from ISVSuiteTicket where suiteId = :suiteId and clientType = :clientType",            params = mapOf("suiteId" to suiteId,"clientType" to clientType)        )    }
    //...省略其它实现}

这就是著名的依赖倒转

所以,记住,基础设施层是对接口的实现,是提供实现的地方。不是被依赖的一方。