Ответ 1
Когда команда/компания поставляет фреймворк/компилятор/набор инструментов, у них уже есть некоторый опыт, набор лучших практик. Они делятся этим в качестве руководства. Руководящие принципы являются рекомендациями. Если вам не нравится, вы можете игнорировать их. Компилятор все равно скомпилирует ваш код. Хотя, когда в Риме...
Это мое видение, почему машинопись команда не рекомендует I
-prefixing интерфейсы.
Причина № 1 Времена венгерской нотации прошли
Основной аргумент сторонников I
-prefix -for-interface заключается в том, что префикс полезен для немедленной проверки того, является ли тип интерфейсом. Утверждение, что префикс полезен для немедленного ворчания, - это обращение к венгерской нотации. I
префикс для имени интерфейса, C
для класса, A
для абстрактного класса, s
для строковой переменной, c
для константной переменной, i
для целочисленной переменной. Я согласен, что такое оформление имени может предоставить вам информацию о типе без наведения мыши на идентификатор или перехода к определению типа с помощью горячей клавиши. Эта крошечная выгода перевешивается недостатками венгерской нотации и другими причинами, упомянутыми ниже. Венгерская нотация не используется в современных рамках. С# имеет префикс I
(и это единственный префикс в С#) для интерфейсов по историческим причинам (COM). Оглядываясь назад, один из архитекторов.NET (Брэд Абрамс) считает, что было бы лучше не использовать префикс I
TypeScript не поддерживает COM-наследство, поэтому у него нет правила I
-prefix -for-interface.
Причина № 2 I
-prefix нарушает принцип инкапсуляции
Предположим, у вас есть черный ящик. Вы получаете ссылку на тип, которая позволяет вам взаимодействовать с этим полем. Вам не должно быть дела, если это интерфейс или класс. Вы просто используете его интерфейсную часть. Требование знать, что это (интерфейс, конкретная реализация или абстрактный класс) является нарушением инкапсуляции.
Пример: предположим, что вам нужно исправить в своем коде миф о дизайне API: интерфейс как контракт, например, удалите интерфейс ICar
и используйте взамен базовый класс Car
. Тогда вам нужно выполнить такую замену у всех потребителей. I
-prefix приводит к неявной зависимости потребителей от деталей реализации черного ящика.
Причина № 3 Защита от неправильного именования
Разработчикам лень правильно думать об именах. Именование - одна из двух трудностей в информатике. Когда разработчику нужно извлечь интерфейс, легко добавить букву I
к имени класса, и вы получите имя интерфейса. Запрещение префикса I
для интерфейсов вынуждает разработчиков напрягать мозг, чтобы выбирать подходящие имена для интерфейсов. Выбранные имена должны отличаться не только в префиксе, но и подчеркивать разницу в намерениях.
Случай абстракции: вы не должны определять интерфейс ICar
и связанный с ним класс Car
. Car
- это абстракция, и он должен быть тем, который используется для контракта. Реализации должны иметь описательные, отличительные названия, например SportsCar, SuvCar, HollowCar
.
Хороший пример: WpfeServerAutosuggestManager implements AutosuggestManager
, FileBasedAutosuggestManager implements AutosuggestManager
.
Плохой пример: AutosuggestManager implements IAutosuggestManager
.
Причина № 4 Правильно выбранные имена прививают вас против мифа о дизайне API: интерфейс как контракт.
В своей практике я встречал много людей, которые бездумно дублировали интерфейсную часть класса в отдельном интерфейсе, в котором в Car implements ICar
именования Car implements ICar
. Дублирование интерфейсной части класса в отдельном типе интерфейса магическим образом не превращает его в абстракцию. Вы все равно получите конкретную реализацию, но с дублированной интерфейсной частью. Если ваша абстракция не так хороша, дублирующая часть интерфейса не улучшит ее в любом случае. Извлечение абстракции - тяжелая работа.