Я только что провел внутреннюю дискуссию по этому поводу и закончил тем, что написал эту статью, которую я считаю слишком хорошей, чтобы ею не поделиться.Я копирую его здесь (почти) неотредактировано, но, хотя это и является частью более масштабного внутреннего обсуждения, я думаю, что большинство из них могут остаться в одиночестве.
Обсуждение касается введения пользовательского интерфейса под названием IPurchaseReceiptService
и должен ли он быть заменен на использование IObserver<T>
.
Ну, я не могу сказать, что у меня есть сильные данные по любому из этих вопросов - это всего лишь некоторые теории, которые я 'Я продолжаю ... Однако моя теория о когнитивных издержках на данный момент выглядит примерно так: рассмотрите ваше специальное IPurchaseReceiptService
:
public interface IPurchaseReceiptService
{
void SendReceipt(string transactionId, string userGuid);
}
Если мы оставим его как Интерфейс заголовка в настоящее время он имеет только один SendReceipt
метод.Это круто.
Что не так круто, так это то, что вам пришлось придумать имя для интерфейса и другое имя для метода.Между ними есть некоторое совпадение: слово Квитанция появляется дважды.IME, иногда такое перекрытие может быть даже более выраженным.
Кроме того, имя интерфейса - IPurchaseReceiptService
, что также не особенно полезно.Суффикс Service - это, по сути, новый Manager , который, по мнению IMO, является запахом дизайна.
Кроме того, не только нужно было назвать интерфейс и метод, но вы также должны назвать переменную, когда вы ее используете:
public EvoNotifyController(
ICreditCardService creditCardService,
IPurchaseReceiptService purchaseReceiptService,
EvoCipher cipher
)
В этот момент вы, по сути, сказали то же самое трижды.Это, согласно моей теории, когнитивные накладные расходы и запах того, что дизайн может и должен быть проще.
Теперь, сопоставьте это с использованием известного интерфейса, такого как IObserver<T>
:
public EvoNotifyController(
ICreditCardService creditCardService,
IObserver<TransactionInfo> purchaseReceiptService,
EvoCipher cipher
)
Это позволяет вам избавиться от бюрократии и уменьшить замысел в самом деле.У вас по-прежнему есть намеренное раскрывающее наименование - вы только смещаете дизайн с подсказки роли имени типа на подсказку имени роли аргумента .
Когда это происходитк дискуссии о «отключении», я не питаю иллюзий, что использование IObserver<T>
волшебным образом устранит эту проблему, но у меня есть другая теория об этом.
Моя теория заключается в том, что причина в том, что многие программистынаходить программирование для интерфейсов настолько трудным именно потому, что они используются для функции Перейти к определению в Visual Studio (кстати, это еще один пример того, как инструменты отвлекают внимание ).Эти программисты постоянно находятся в состоянии ума, когда им нужно знать, что находится «на другой стороне интерфейса».Почему это?Может ли это быть из-за плохой абстракции?
Это связано с RAP , потому что если вы подтверждаете убеждение программистов, что за каждым интерфейсом стоит отдельная, конкретная реализация, неудивительно, что онидумаю, что интерфейсы только в пути.
Однако, если вы примените RAP, я надеюсь, что программисты постепенно поймут, что за конкретным интерфейсом может быть любая реализация этогоинтерфейс, и их клиентский код должен быть в состоянии обрабатывать любую реализацию этого интерфейса без изменения правильности системы.Если эта теория верна, мы только что ввели принцип подстановки Лискова в кодовую базу, не пугая никого концепциями высокого броуна, которые они не понимают:)