【问题标题】:How to avoid circular dependencies but keep a clean structure如何避免循环依赖但保持干净的结构
【发布时间】:2020-05-26 01:29:28
【问题描述】:

我有这个结构:

httpservice
L endpointHandler.go (it has as parameters databaseA and databaseB)
L types.gen.go (autogenerated from the api definition)

storage
L databaseA.go (each database has 'Store(Type)' and 'Get() -> Type' functions)
L databaseB.go

我的问题是我遇到了循环依赖错误。 endpointHandler 需要导入存储包才能访问数据库。数据库需要导入 httpservice,因为类型是在那里自动生成的(它需要类型来存储或读取结构)。

有没有办法用接口解决这个问题?我试过了,但它并没有摆脱循环问题。我能想到的一些解决方案:

  1. 复制粘贴存储包中的类型,忽略生成的类型

  2. 将数据库移到 httpservice 包中,忘记漂亮的文件夹结构

PD:有很多关于循环依赖的问题,但我无法解决我的特定问题。如有重复,请见谅。

【问题讨论】:

  • 您错过了一个简单的选项:在它们自己的包中定义通用类型(及其简单实用程序)。当在整个代码库中使用某些类型时,这是一种常用方法。
  • 存储包应该实现存储httpservice相关数据的接口,我的意思是为了更好的模块化代码,尝试六边形架构避免循环依赖-github.com/ganeshdipdumbare/hex-gopher
  • 问题是这些类型是在 httpservice 包中自动生成的,我没有能力移动它们 :( 所以也许我应该将类型复制粘贴到一个单独的包中,并使用自动生成的采场类型?

标签: go interface package circular-dependency


【解决方案1】:

如果应用程序增长 - 您可以考虑使用“端口和适配器”架构概念来反转依赖关系。

在这种情况下,您不希望“httpservice”依赖于低级“storage”包。 (httpservice 可能充当外部接口,不应该知道存储的技术细节。事实上,存储在未来可能会有所不同)。 所以你可以在“httpservice”层(包)中定义一个对该层有意义的接口(例如“mydataService interface {}”)——我称之为辅助端口。

“存储”层可以知道“httpservice”并实现一个适配器(实现定义的接口)

在初始化您的应用程序时,请确保您将正确的存储适配器注入到 httpservice..

一些更大的框架也使用这种方法 - 你可能想了解更多:https://docs.flamingo.me/2.%20Flamingo%20Core/1.%20Flamingo%20Basics/4.%20Ports%20and%20Adapters.html

【讨论】:

    猜你喜欢
    • 2013-02-06
    • 1970-01-01
    • 1970-01-01
    • 2012-02-15
    • 2013-04-02
    • 1970-01-01
    • 2012-08-10
    • 1970-01-01
    • 2016-08-09
    相关资源
    最近更新 更多