Смутно о принципах кодирования интерфейса и класса для TypeScript

Я прочитал TypeScript рекомендации по кодированию

И я нашел это утверждение довольно озадачивающим:

Не используйте "I" в качестве префикса для имен интерфейсов

Я имею в виду что-то вроде этого не будет иметь большого смысла без префикса "I"

class Engine implements IEngine

Я пропустил что-то очевидное?

Еще одна вещь, которую я не совсем понял, это:

Классы

Для согласованности не используйте классы в конвейере основного компилятора. использование вместо этого закрываются функции.

Означает ли это, что я не должен использовать классы вообще?

Надеюсь, кто-то может очистить его для меня:)

Ответ 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. Дублирование интерфейсной части класса в отдельном типе интерфейса магическим образом не превращает его в абстракцию. Вы все равно получите конкретную реализацию, но с дублированной интерфейсной частью. Если ваша абстракция не так хороша, дублирующая часть интерфейса не улучшит ее в любом случае. Извлечение абстракции - тяжелая работа.

Ответ 2

Разъяснение ссылки, которую вы ссылаетесь:

Это документация о стиле кода для TypeScript, а не руководство по стилю для реализации вашего проекта.

Если использование префикса I имеет смысл для вас и вашей команды, используйте его (я).

Если нет, возможно, стиль Java SomeThing (interface) с SomeThingImpl (реализация), тогда, во всяком случае, используйте это.

Ответ 3

Тип, являющийся интерфейсом, является деталью реализации. Детали реализации должны быть скрыты в API: s. Вот почему вы должны избегать I.

Вам следует избегать ботов prefix и suffix. Они оба не правы:

  • ICar
  • CarInterface

Что вы должны сделать, это сделать красивое имя видимым в API и скрыть детали реализации в реализации. Вот почему я предлагаю:

  • Car - интерфейс, предоставляемый в API.
  • CarImpl - реализация этого API, скрытого от потребителя.

Ответ 4

Руководство TypeScript говорит обо всем. Просто обратите внимание на примеры и будьте счастливы. <3