Как придумать более понятные имена интерфейсов? - PullRequest
15 голосов
/ 11 марта 2011

Я видел в приложении, где у него были интерфейсы, такие как:

IHasContent
IHasValue
IHasMesh
IHasGeometry
IHasTransformation

Разве их не должно быть?:

IHaveContent
IHaveValue
...

Или:

IIncludeContent
IIncludeValue
...

Лично я склоняюсь к тому, чтобы просто сделать их:

IContent
IValue
IMesh
IGeometry
ITransform

Потому что не ISomething уже подразумевает, что у него есть something?

Что касается последнего, я должен вместо этого сделать ITransformable?

Я думаю, что использование I + (Has/Have/Include/Exist, etc) + Name делает имена интерфейсов более запутанными.

Есть какие-нибудь идеи о том, как придумать лучшие имена интерфейсов, которые не кажутся неловкими, актуальны и дают смысл?

Ответы [ 7 ]

30 голосов
/ 11 марта 2011

Некоторые из этих названий («Содержимое», «Значение» и т. Д.) Являются расплывчатыми и мало описывают содержание / поведение элемента. В общем, имена должны быть как можно более конкретными и отличными - IScriptParameter может быть более информативным, чем IValue. По мере роста вашего проекта наличие более описательных имен значительно облегчит распознавание типов (если вы не будете осторожны, вы можете использовать IValue, INumber и IAmount для обработки вариантов «значений»!)

Если ваш интерфейс (например, IMesh) означает «обеспечивает свойства меша», то IMesh - отличное имя - он описывает тот факт, что вы можете обращаться с объектом, как если бы он был сеткой.

Если ваш интерфейс используется для применения действия (например, для визуализации объекта в виде сетки или применения преобразования к объекту), тогда рассмотрите возможность использования глагола / прилагательного, а не именования существительного (например, IRenderable, ITransformable) - это общий шаблон в .net (например, IEnumerable (глагол / прилагательное), а не ICollection (существительное))

Для меня «IHasMesh» больше похоже на IMeshContainer - то есть это объект, который содержит сетку, а интерфейс позволяет мне «получить сетку». Так что это не позволило бы мне действовать или запрашивать данные в сетке, а просто извлекать весь объект Mesh через интерфейс.

Так что я бы использовал:

  • ITransformable , если объект может быть преобразован через интерфейс
  • ITransform , если объект можно использовать напрямую, как если бы это было преобразованием
  • IHasTransform / ITransformContainer / ITransformProvider , если объект является контейнером , который можно запросить для извлечения объекта Transform
15 голосов
/ 11 марта 2011

Лично мне нравится IHas + Word, потому что имя интерфейса описывает свойство классов, которые их реализуют.Например:

public class Lolcat : IHasCheezburger

Когда я читаю, я легко понимаю, что у лолкатов есть чизбургеры.

С другой стороны,

public class Lolcat : ICheezburger

Заставляет меня задуматься,lolcats ЕСТЬ чизбургеры или ARE чизбургеры (это традиционный глагол, используемый при интерпретации наследования).

8 голосов
/ 11 марта 2011

Первое, что вы должны понять, это то, что «I» в именах не относится к местоимению «I», а скорее соответствует стандарту именования, согласно которому интерфейсы начинаются с заглавной буквы «I».

В этом смысле интерфейсы на самом деле называются «HasContent», «HasValue» и т. Д., Поэтому не изменяйте их на «HaveContent» и «HaveValue», поскольку это было бы так же неудобно.

С учетом сказанного я не могу точно понять, для чего используются эти интерфейсы.Интерфейс (по определению) предназначен для навязывания условия всем классам, которые его реализуют, и я не уверен, что эти интерфейсы обеспечивают - все классы имеют функцию с именем HasContent()?

Iподумайте, что вместо этого вам следует сосредоточиться на интерфейсах, имеющих отношение is a.Когда вы объявляете класс, который реализует интерфейс IList, вы не подразумеваете, что ваш класс имеет список, а скорее, что ваш класс является списком .

Так, например, один из них IHasGeometry ... ну, это дает мне возможность проверить, имеет ли он геометрию, но я бы реально хотел иметь дело только с фигурами, которые являются геометрическими фигурами,поэтому я бы вместо этого создал интерфейс с именем IGeometricFigure, ограничив его использование всем, что работает с геометрическими фигурами.

Я согласен, что названия звучат неловко, но я думаю, что это больше, потому что эти интерфейсы используютсяв неловких целях, а не потому, что они неправильно названы.

4 голосов
/ 11 марта 2011

Мне нравится думать, что ISomething означает, что оно является Нечто, как в роли чего-то, а не в том, что оно «имеет» или «включает» Нечто.Итак, IFather означает «я играю роль отца», или я отец ».IDispatcher означает «я играю роль диспетчера» или «я являюсь диспетчером» и т. Д.

Некоторые люди любят называть интерфейсы, чтобы ответить на вопрос «что мне делать?»: IListenForEvents, ILogExceptions. Как в этом посте

4 голосов
/ 11 марта 2011

Ваш первоначальный список имен интерфейсов звучит абсолютно правильно.Имя интерфейса должно описывать контракт.Например, это один интерфейс, с которым я недавно столкнулся, который мне очень понравился:

public interface IDeterminesEmptyValue
{
    bool IsEmpty { get; }
}

Отлично!Имя говорит само за себя.«I» относится к тому факту, что это интерфейс, а остальное описывает то, что будет выполнять контракт.

Если бы интерфейс назывался IEmptyValue, это означало бы, что интерфейс гарантирует, что разработчик ISпустое значение.Это не так - он обладает способностью определять , является ли значение пустым.

(Вероятно), ни один класс не будет назван DeterminesEmptyValue.Но может существовать тысяча классов, каждый из которых может определить, являются ли различные типы значений пустыми, и этот интерфейс позволяет вызывать их все обычным способом.

Интерфейс должен четко описывать определенную характеристику классов, которые его реализуют.В случае IContent - у разработчиков HAVE контент или у разработчиков ARE content?

3 голосов
/ 16 марта 2011

Интерфейсы используются для многих целей, с различными соглашениями по присвоению имен.Прежде чем беспокоиться об именах, лучше сначала решить, как разделить функциональность.К сожалению, в коллекциях Microsoft слишком мало различных интерфейсов, самыми большими из которых являются IReadableList и IAppendable, оба из которых могут быть унаследованы IList, но поддерживают контравариантность и ковариационную поддержку [поэтому можно передать IList (из Cat) в код, ожидающий IReadableList (из Animalили IAppendable (от SiameseCat)].С другой стороны, также возможно слишком тонкое разделение, поэтому любой полезный класс должен реализовывать десятки интерфейсов.

Не зная, какие типы функциональности использовались в приложении и интерфейсах, трудно сказать, являются ли онибыли разработаны с хорошим уровнем детализации.Похоже, они слишком тонко разделены, но я не могу сказать точно.Как только функциональность сгруппирована соответствующим образом, имеет смысл беспокоиться об имени.

1 голос
/ 11 марта 2011

«Я» не означает «я».Это просто расшифровывается как Interface.

Но у Microsoft есть свои собственные рекомендации для именования интерфейсов.

Имена должны отличаться только префиксом I на интерфейсе.имя.

...