我试图在使用 Bob Martin 叔叔的“清洁架构”设计的 Go 程序中为我的 ID 找到合适的类型。
type UserID ...
type User struct {
ID UserID
Username string
...
}
type UserRepository interface {
FindByID(id UserID) (*User, error)
...
}
我正在关注 Bob Martin 叔叔的“清洁架构”,其中代码被组织为一组层(从外到内:基础设施、接口、用例和域)。原则之一是依赖规则:源代码依赖只能指向内部。
我的User
类型是域层的一部分,因此ID
类型不能依赖于为UserRepository
;选择的数据库。如果我使用 MongoDB,ID 可能是ObjectId
( string
),而在 PostgreSQL 中,我可能使用整数。领域层中的User
类型无法知道实现类型将是什么。
通过依赖注入,一个真正的类型(例如MongoUserRepository
)将实现UserRepository
接口并提供FindByID
方法。由于这MongoUserRepository
将在接口或基础设施层中定义,因此它可以取决于UserRepository
(更向内的)领域层中的定义。
我考虑过使用
type UserID interface{}
但是,如果外层之一中的代码尝试分配不正确的实现类型,则编译器将不会很有帮助。
我想让指定数据库的接口层或基础设施层确定并要求特定类型UserID
,但我不能让域层代码导入该信息,因为这将违反依赖规则。
我也考虑过(目前正在使用)
type UserID interface {
String() string
}
但这假设知道数据库将使用字符串作为其 ID(我正在使用 MongoDB 及其ObjectId
-- 的类型同义词string
)。
如何以惯用的方式处理此问题,同时允许编译器提供最大的类型安全性并且不违反依赖规则?