Правило для имени интерфейса GoLang и его количества методов
У меня была дискуссия о работе между именем интерфейса и числом его методов. В частности, существует неписанное правило об интерфейсе с постфиксной нотацией, оканчивающейся на er
в его названии. Правило гласит, что такой интерфейс должен содержать один метод.
Давайте посмотрим на пример. В стандартной библиотеке Go lang есть Pusher
Интерфейс, который выполняет одно действие: "Push инициирует HTTP/2-серверный push". Вот его определение:
type Pusher interface {
Push(target string, opts *PushOptions) error
}
https://golang.org/pkg/net/http/
Хороший пример. Тем не менее, некоторые коллеги защитили его реализацию, которая содержала более двух методов с er
в постфиксе имени. Основным аргументом было то, что есть интерфейсы stdlib, которые нарушают такое правило. Он сослался на интерфейс ReadCloser
,
Глядя на его определение:
type ReadCloser interface {
Reader
Closer
}
Я могу сказать, что это неверное предположение. Интерфейс встраивает в себя два других интерфейса. Как я это понимаю? Правило не нарушено.
Как вы будете интерпретировать такой случай?
1 ответ
Этот вопрос, возможно, будет закрыт, потому что он считается основанным на мнении, или не связан с кодом, или как там...
Тем не менее, Голанг считается весьма самоуверенным, и, поскольку я считаю стандарты очень важными, я буду придерживаться своего взгляда на неписаное правило и на то, как я примирю, по сути, почему ReadCloser
хорошо, но некоторые другие er
интерфейсов может не быть.
Я бы истолковал ReadCloser
не нарушать "правило" (я бы назвал это соглашением больше похожим). У меня есть ряд аргументов, почему я бы сказал, что это не нарушает соглашение:
1. Это не автономный интерфейс
ReadCloser
Интерфейс не является автономным интерфейсом. Это сложный интерфейс. Это имя отражает это. Объединяет Read
а также Close
(2 функции в интерфейсе, который вы ищете), и добавляет er
суффикс. То, как реализованы обе функции и откуда они берутся, не имеет отношения к интерфейсу. Если вы что-то прочитали, скорее всего, вам тоже придется закрыть ресурс. Имеет смысл только объединить два интерфейса, так что вы можете использовать тип, который гарантирует оба Reader
а также Closer
функциональность будет доступна.
2. Имена не должны заикаться
Как и в случае с заиканиями в названиях пакетов WRT, их следует избегать. Особенно, если это не добавляет никакой ценности. Технически можно утверждать, что интерфейс должен называться ReaderCloser
, но означает ли это имя что-либо, что не передается именем ReadCloser
? Конечно нет. Последний не повторяет суффикс и читается легче.
3. er
интерфейсы и CamelCasing
Примеры однофункциональных er
интерфейсы как Stringer
, или же Publisher
действительно порезанный и сухой. Stringer
содержит String
функция. Конец истории. Такой же как Publisher
интерфейс.
Вы заметите, что ReadCloser
интерфейс CamelCased, предполагая, что это композитный тип. Просто разделите имя на символы UpperCase и добавьте суффикс к каждой части. Если части добросовестны er
интерфейсы, и составной интерфейс имеет смысл (см. пункт 1: если вы читаете, скорее всего, вам придется закрыть), то это допустимый составной интерфейс.
Примеры недействительных er
Интерфейс будет:
type FileReader interface {
ReadCloserer
ScanDir(string) ([]string, error)
IsFile(string) bool
Open(string, string) error
// and so on
}
Этот интерфейс содержит слишком много функций BS для упаковки в FileReader
интерфейс.