Применим ли «Закон Деметры» к публичным сигнатурам / методам API?

10

Учитывая, что изменения в сигнатуре API / публичного метода должны быть минимальными, чтобы не допустить взлома тех клиентских кодов, которые используют эти методы, мне было интересно, не применим ли закон Деметры к ним.

Простой пример:

class Account() {
   double balance;
   public void debit(Transaction t) {
      balance -= t.getAmount();
   }
}

Обратите внимание, что метод дебетования передает объект транзакции, а не просто двойную сумму («Закон Деметры», как я понимаю, сказал бы просто передать необходимую информацию, в данном случае только сумму, а не объект транзакции ...) ). Причина этого заключается в том, что метод в будущем может потребовать некоторые другие свойства транзакции помимо суммы. Насколько я понимаю, это предотвратит нарушение сигнатуры метода, добавив новый параметр в будущем.

Делает ли это разумный выбор? Или я что-то упустил?

Карлос Хайме К. Де Леон
источник

Ответы:

3

Но это не нарушает Закон Деметры.

Более формально, закон Деметры для функций требует, чтобы метод M объекта O мог вызывать только методы следующих типов объектов:

  • О себе
  • Параметры М
  • любые объекты, созданные / созданные в M
  • Прямые составляющие объекты О
  • глобальная переменная, доступная O, в области M

Википедия: Закон Деметры

Транзакция является аргументом метода дебетования, поэтому вызов t.getAmount () - это нормально.

Редактировать: неправильно, вы говорите, что LoD заставит вас передать сумму транзакции, а не объект транзакции. Если это так, то да, я думаю, что это хорошее место, чтобы сломать его, зная, что вам понадобится больше от объекта Transaction в будущем. Кроме того, инкапсуляция примитивов в объектах уровня домена является еще одной хорошей практикой программирования.

Редактировать 2: прочитав, возможно, потребуется больше в будущем, можно также увидеть это как ненужное золотое покрытие. Достаточно предоставить метод, который теперь принимает удвоение (или лучше класс Money). Если вам позже понадобится аргумент транзакции, не беда предоставить вторую подпись, принимающую транзакцию, но продолжайте поддерживать оригинальную подпись. Не то, чтобы вы реализовывали два метода, один вызвал бы другой.

Шон
источник
Спасибо за ваш вклад. Я согласен с инкапсулирующими примитивами в доменных объектах. Тем не менее, вы просто говорите, что в Edit 2 вы добавили новую 2-ю сигнатуру, что это не пагубно, но это означало бы изменение кода в клиентском коде, который теперь должен передавать 2 параметра вместо одного. По этому второму пункту я не решаюсь договориться ...
Карлос Хайме К. Де Леон
Редактировать 2 субъективно, я согласен.
Шон
0

Если вы планируете расширять Accountкласс в будущем, я бы сказал, что это ситуация, когда создание Transactionобъекта более общего назначения будет хорошим отклонением от норм Закона.

Например:

public class Amount {

    public void process( Transaction t ) {
        ....
    }
}

public abstract class Transaction {

    public String getType();

}

Я думаю, что я немного отклонился от первоначального вопроса, но я хочу сказать, что, хотя вы можете быть обеспокоены тем, что отклоняетесь от закона Деметры, преимущества этого перевешивают негативы.

chooban
источник