英文:
Go Interfaces with more than one method - Acceptable or unacceptable?
问题
一个接口中分配多个函数是否有问题?
在我阅读的所有地方,一个接口理想情况下应该只有一个方法(接口的命名应该与该方法相对应)。但是,一个接口有多个方法是否会有任何问题?
例如:
type FooMgrInterface interface {
CreateFoo(hostname string, fooConfig interface{}) (uuid string, err error)
DeleteFoo(hostname string, fooID string) (err error)
CreateBar(hostname string, barID string, barConfig interface{}) (uuid string, err error)
DeleteBar(hostname string, barID string) (err error)
AttachBar(hostname string, fooID string, bars []string) (err error)
DetachBar(hostname string, barID string) (err error)
GetBars(hostname string) (bars []Bar, err error)
GetBar(hostname string, barID string) (bar Bar, err error)
GetFoo(hostname string, fooID string) (foo Foo, err error)
GetFoos(hostname string) (foos []Foo, err error)
}
如果有问题,如何简化上述接口或者(也许)将其拆分为多个接口?
英文:
Is there anything wrong with an interface with more that one function assigned to it ?
Everywhere I read, an interface should ideally have only one method (which is what the interface should be named after). But are there any pit falls to having more than one method for an interface ?
Ex.
type FooMgrInterface interface {
CreateFoo(hostname string, fooConfig interface{}) (uuid string, err error)
DeleteFoo(hostname string, fooID string) (err error)
CreateBar(hostname string, barID string, barConfig interface{}) (uuid string, err error)
DeleteBar(hostname string, barID string) (err error)
AttachBar(hostname string, fooID string, bars []string) (err error)
DetachBar(hostname string, barID string) (err error)
GetBars(hostname string) (bars []Bar, err error)
GetBar(hostname string, barID string) (bar Bar, err error)
GetFoo(hostname string, fooID string) (foo Foo, err error)
GetFoos(hostname string) (foos []Foo, err error)
}
If so how could the above interface be simplified or (maybe) split into multiple interfaces ?
答案1
得分: 6
这是要翻译的内容:
这没有问题,因为语言完全支持它。
我认为作者是基于经验提供架构建议。具体来说,如果你的接口有很多方法,很可能在某个地方抽象得不对。
你可以问自己一些澄清的问题:
- 这个接口会有多少个不同的实现?
- 它们中有多少个方法实现是相同的?
- Foo/Bar 是如何与实现者关联的?是否可以简化一些?例如像
NewFoo(owner FooMgrInterface) *Foo
这样的方式。
英文:
There's nothing wrong with it, in that the language supports it just fine.
I believe the authors are offering architectural advice based on experience. Specifically, if your interface has many methods, you likely have the wrong abstraction somewhere.
You can ask yourself some clarifying questions:
- How many different implementations of this interface will there be?
- How many of them will have identical method implementations?
- How are the Foos/Bars attached to the implementor? Would it be simpler to reverse it somehow? eg something like
NewFoo(owner FooMgrInterface) *Foo
答案2
得分: 3
在https://golang.org/src/io/io.go中寻找灵感。
你会看到:
a. "原子"接口:Reader
、Writer
、Closer
、Seeker
b. 组合接口:ReaderWriter
、ReaderWriterSeeker
、ReaderSeekerCloser
等等。
Golang不会对庞大的接口提出抱怨,而是你和你的同事会对庞大的单体接口提出抱怨。
我建议将你的接口分成4个(也许是2个)接口:FooOps
、FoosOps
、BarOps
、BarsOps
,然后从它们定义组合接口。
英文:
Look for inspiration in https://golang.org/src/io/io.go
You will see:
a. "Atomic" interfaces: Reader
, Writer
, Closer
, Seeker
b. Composed interfaces: ReaderWriter
, ReaderWriterSeeker
, ReaderSeekerCloser
etc.
Golang will not complaint about gigantic interfaces, it's you and your collegues will have complaints about big monolithic interfaces.
I recomend divide your interface to 4 (maybe 2) interfaces: FooOps
, FoosOps
, BarOps
, BarsOps
and then define composed interfaces from them.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论