Golang文档在how to name single-method interface上提供了清晰的指导(通过附加“ -er”)。但是,命名仅由一个结构实现的多方法接口的最佳实践是什么?
在C#中,该接口将具有“ I”前缀,在Java中,该类将具有“ Impl”后缀。 Golang是否有类似的指南?
这里有一个接口的目的是能够模拟它,以便对依赖于它的组件进行单元测试。
这是UserManager界面的特定示例。 Web api控制器将使用它,它将在此接口上将HTTP请求转换为方法调用。该Web API控制器将使用UserManager的大多数方法。
type UserManager interface { // Should it be UserManagerInterface ?
GetUser(id int) User
CreateUser(user User)
DeleteUser(id int)
ResetPassword(id int, newPassword string)
VerifyEmail(id int)
}
type UserManagerImpl struct { // -Impl, or -Struct, or something else?
}
答案 0 :(得分:1)
从Java / C#转到Go需要进行范式转换。
因为它们是隐式实现的,所以在使用的位置而不是在实现的位置定义接口。
因为它们是隐式实现的,所以较小的接口比较大的接口更受青睐,因此,重点放在单方法“ Verber”接口上。如果您有一个需要读取字节的函数,则可能需要一个io.Reader
,并且可以为该函数提供具有该方法的任何类型(无论它具有其他什么方法)。您可能没有一个函数可以调用界面中列出的所有5种方法(如果这样,则该函数可能做得太多)。
如果您想以相同的方式命名结构和接口,因此需要某种前缀/后缀,则可能是在考虑错误的方式,因此可能需要重新考虑设计。
DBAL是一个有时存在较大接口的真实情况的区域(尽管它可能仍应由较小接口组成)。但是在这种情况下,“ Impl”没有告诉您任何信息-Java和C#喜欢具有无意义的接口,而Go却没有。如果只有一种实现,则该接口可能无用。
如果您将有多个实现,则它们之间的差异将指导您的命名。例如,您可能有一个PostgresUserManager
,一个MongoUserManager
和一个MockUserManager
。
答案 1 :(得分:0)
您真的需要公开UserManagerImpl
结构吗?有一个公共接口和相应的私有实现是很常见的。选中this和this。
type Store interface {
RunRoot() string
GraphRoot() string
...
}
type store struct {
...
}
func New() Store {
return &store{}
}
func (s *store) RunRoot() string {
return s.runRoot
}
func (s *store) GraphRoot() string {
return s.graphRoot
}
我的意思是,如果您为接口想出了一个体面的名称,您仍然可以将其用于实现。但是总的来说,最好将其反映为真实的事物,而不管给定语言的最佳实践如何。项目是独一无二的,几乎不可能列出适合该语言所有用例的最佳实践。