Чтобы упростить интерфейс, лучше просто не иметь getBalance()
метод? Переход 0
к charge(float c);
тому же результату даст:
public class Client {
private float bal;
float getBalance() { return bal; }
float charge(float c) {
bal -= c;
return bal;
}
}
Может быть, сделать заметку в javadoc
? Или просто оставьте это пользователю класса, чтобы выяснить, как получить баланс?
interfaces
cqrs
Дэвид
источник
источник
Ответы:
Вы, кажется, предполагаете, что сложность интерфейса измеряется количеством элементов, которые он имеет (методы, в данном случае). Многие утверждают, что необходимость помнить, что
charge
метод может использоваться для возврата баланса,Client
добавляет гораздо больше сложности, чем наличие дополнительного элементаgetBalance
метода. Делать вещи более явными гораздо проще, особенно до такой степени, что это не оставляет двусмысленности, независимо от большего количества элементов в интерфейсе.Кроме того, вызов
charge(0)
нарушает принцип наименьшего удивления , также известный как показатель WTFs в минуту (из «Чистого кода», изображение ниже), что затрудняет работу новых членов команды (или текущих, через некоторое время вдали от кода) до они понимают, что звонок фактически используется для получения баланса. Подумайте, как отреагируют другие читатели:Кроме того, сигнатура
charge
метода идет вразрез с рекомендациями делать одно и только одно и разделение команд и запросов , потому что это заставляет объект изменять свое состояние, а также возвращать новое значение.В общем, я считаю, что самым простым интерфейсом в этом случае будет:
источник
getBalance()
возвращает какое-то значение и ничего не меняет. С другой стороны,charge(0)
похоже, что он что-то изменяет ... может быть, он отправляет событие PropertyChanged? И что это возвращает, предыдущее значение или новое значение? Теперь вы должны искать это в документации и тратить мозги, которых можно было бы избежать, используя более четкий метод.charge(0)
в качестве способа получения баланса, потому что это, оказывается, не имеет никакого эффекта, теперь приводит вас к этой детали реализации; Я легко могу представить себе будущее требование, когда отслеживание количества сборов становится актуальным, и в этот момент ваша кодовая база изобилует платежами, которые на самом деле не являются сборами, становится проблемой. Вы должны предоставить элементы интерфейса, которые означают, что ваши клиенты должны делать, а не те, которые просто делают то, что нужно вашим клиентам.charge()
метода, если этот метод является атомарным в параллельной системе, может быть целесообразно вернуть новое или старое значение.ИМО, заменив
getBalance()
сcharge(0)
через приложение не является упрощение. Да, в нем меньше строк, но он запутывает смыслcharge()
метода, который потенциально может вызвать головную боль, когда вам или кому-то еще понадобится вернуться к этому коду.Хотя они могут дать один и тот же результат, получение остатка на счете не равно нулю, поэтому, вероятно, было бы лучше разделить ваши проблемы. Например, если вам когда-либо нужно было вносить изменения
charge()
в журнал при каждой транзакции учетной записи, у вас сейчас есть проблема, и вам все равно придется разделить функциональность.источник
Важно помнить, что ваш код должен самодокументироваться. Когда я звоню
charge(x)
, я ожидаюx
оплаты. Информация о балансе является вторичной. Более того, я не знаю, какcharge()
это реализовано, когда я это называю, и я точно не буду знать, как это будет реализовано завтра. Например, рассмотрим это потенциальное будущее обновление дляcharge()
:Внезапно использование
charge()
баланса не выглядит так хорошо.источник
charge
намного тяжелее.Использование
charge(0);
для получения баланса - плохая идея: однажды кто-то может добавить туда некоторый код, чтобы регистрировать произведенные платежи, не осознавая другое использование функции, и затем каждый раз, когда кто-то получает баланс, он будет регистрироваться как сбор. (Есть способы обойти это, например, условное утверждение, которое говорит что-то вроде:но они полагаются на то, что программист знает, как их реализовать, чего он не сделает, если не сразу станет очевидно, что они необходимы.
Короче говоря: не полагайтесь ни на своих пользователей, ни на ваших последователей-программистов, понимающих, что
charge(0);
это правильный способ получить баланс, потому что если нет документации, которую они гарантированно не пропустят, то, откровенно говоря, это выглядит как самый пугающий способ получения баланса возможный.источник
Я знаю, что существует множество ответов, но другая причина в
charge(0)
том, что простая опечаткаcharge(9)
приведет к тому, что баланс вашего клиента будет уменьшаться каждый раз, когда вы хотите получить его баланс. Если у вас есть хорошее модульное тестирование, вы можете уменьшить этот риск, но если вы не будете прилежны при каждом обращении кcharge
вам, это может привести к неудаче.источник
Я хотел бы упомянуть конкретный случай, когда было бы целесообразно иметь меньше многоцелевых методов: если много полиморфизма, то есть много реализаций этого интерфейса ; особенно если эти реализации находятся в отдельно разработанном коде, который не может быть обновлен синхронно (интерфейс определяется библиотекой).
В этом случае упрощение работы по написанию каждой реализации гораздо более ценно, чем ясность ее использования, поскольку первая позволяет избежать ошибок, связанных с нарушением контракта (эти два метода несовместимы друг с другом), тогда как последняя только ухудшает читабельность, что может быть восстановлены вспомогательной функцией или методом суперкласса, определяющим
getBalance
в терминахcharge
.(Это шаблон проектирования, для которого я не помню конкретного имени: определение сложного дружественного к абонентам интерфейса в терминах минимального дружественного к исполнителю. В Classic Mac OS минимальный интерфейс для операций рисования назывался «узким местом». но это не похоже на популярный термин.)
Если это не тот случай (существует несколько реализаций или ровно одна), тогда
charge()
имеет смысл разделить методы для ясности и для простого добавления поведения, относящегося к ненулевым зарядам .источник
realloc
иногда в некоторых системах.