Подтвердить что ты не робот

Префиксные интерфейсы с I?

В настоящее время я читаю "Чистый код" Роберта Мартина (UncleBob) и вообще любит размышления о UncleBob. Тем не менее, я немного смутился, когда прочитал, что он избегает префикса таких интерфейсов, как "IPerson". Он утверждает: "Я не хочу, чтобы мои пользователи знали, что я передаю им интерфейс".

Думая о перспективах TDD/инъекции, я всегда буду очень заинтересован в том, чтобы рассказывать "пользователям" моих классов о том, что я передаю интерфейс. Основная причина заключается в том, что я рассматриваю Interfaces контракты между различными "агентами" системы. Агент, работающий с одним углом моей системы, не должен знать о конкретной реализации работы других агентов; они должны только обменивать контракты и ожидать, что контракты будут выполнены, не зная, как это сделать. Другая, но также очень важная причина заключается в том, что интерфейс можно полностью издеваться и, таким образом, сделать модульное тестирование намного проще. Есть ограничения на то, насколько вы можете издеваться над конкретным классом.

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

Неправильно ли мне настаивать на я в интерфейсах?

4b9b3361

Ответ 1

В Java и С# существует ряд соглашений, с которыми нам стало комфортно; но это наоборот. Например, соглашение о включении частных переменных в начало каждого класса довольно глупо с технической точки зрения. Самыми важными вещами в классе являются публичные методы. Наименее важные вещи, вещи, которые мы скрываем за защитой конфиденциальности, являются переменными экземпляра. Так зачем нам ставить их наверху?

"I" перед интерфейсами - это другое соглашение о возврате назад. Когда вам передается ссылка на объект, вы должны ожидать, что это будет интерфейс. Интерфейсы должны быть по умолчанию; поэтому нет смысла делать что-то лишнее, например, использовать префикс I, чтобы объявить, что вы делаете то, что все ожидают от вас. Было бы лучше (хотя и ошибочно), если бы мы зарезервировали специальный маркер для исключительного условия передачи конкретного класса.

Другая проблема с использованием я заключается в том, что (как это ни странно) мы используем его для связи с решением внедрения интерфейса. Обычно мы не хотим, чтобы решения по внедрению были выражены так громко, потому что это затрудняет их изменение. Рассмотрим, например, что может произойти, если вы решили, что IFoo действительно должен быть абстрактным классом вместо интерфейса. Если вы измените имя на Foo или CFoo или ACFoo?

Я слышу, как колеса поворачиваются в вашей голове. Вы думаете: "Да, но интерфейсы имеют особое место на этом языке, и поэтому разумно отметить их специальным соглашением об именах". Это правда. Но целые числа также имеют особое место на этом языке, и мы не отмечаем их (более того). Кроме того, спросите себя, почему интерфейсы имеют особое место на языке?

Вся идея интерфейсов в Java и С# была копией. Дизайнеры языка могли бы использовать абстрактные классы, но они были обеспокоены трудностями реализации множественного наследования. Поэтому они заключили сделку с самим собой. Они изобрели искусственную конструкцию (то есть интерфейсы), которая обеспечивала бы некоторую степень множественного наследования и ограничивала обычные классы на единичное наследование.

Это было одно из худших решений, сделанных разработчиками языка. Они изобрели новый и тяжеловесный синтаксический элемент, чтобы исключить полезную и мощную (хотя и противоречивую) особенность языка. Интерфейсы не были изобретены для включения, они были изобретены для отключения. Интерфейсы - это взлом, размещенный на языке дизайнерами, которые не хотели решать более сложную проблему МИ. Поэтому, когда вы используете префикс I, вы ставите большой центр внимания одного из крупнейших хаков в истории языков.

В следующий раз, когда вы напишете такую ​​подпись функции, как это:

public void myFunction(IFoo foo) {...}

Спросите себя: "Почему я хочу знать, что автор IFoo использовал слово" интерфейс "? Какая разница в том, использовал ли он" интерфейс "или" класс "или даже" структуру "? его дело, а не мое! Так почему он заставлял меня знать его дело, поставив этот большой большой я перед его именем типа? Почему он не застегивает свои заявления и не оставляет своих рядовых с лица?"

Ответ 2

Если вы говорите о .NET, то интерфейсы с я в начале настолько повсеместны, что их удаление путает ад всех.

Плюс я бы предпочел

public class Foo : IFoo {}

чем

public class FooImpl : Foo {}

Все сводится к личным предпочтениям, и я некоторое время играл с этой идеей, но я вернулся к префиксу I. YMMV

Ответ 3

Я рассматриваю контракты интерфейсов между различными "агентами" система. Агент, работающий с одним углу моей системы, не должен знать конкретная реализация другой агенты работают; они должны только обмениваться контрактов, и ожидаем, что контракты выполняться, не зная, как это сделать. другой, но и очень важный, разум заключается в том, что интерфейс можно издеваться полностью и, таким образом, модульное тестирование намного легче. Существуют ограничения на то, как вы можете издеваться над конкретным классом.

Все это верно, но как это требует соглашения об именах для интерфейсов?

В принципе, префиксные интерфейсы с "я" - не что иное, как еще один пример бесполезной венгерской нотации, потому что на статически типизированном языке (единственный вид, где интерфейсы как языковая конструкция имеют смысл), вы всегда можете легко и быстро найти что тип, как правило, наведите указатель мыши на него в среде IDE.