Чи застосовується "Закон про деметер" для підписів методів public / API?


10

Враховуючи, що зміни в підписі API / public методу повинні бути мінімальними, щоб запобігти порушенню тих клієнтських кодів, які використовують ці методи, мені було цікаво, чи Закон Деметер менш застосовний до них.

Простий приклад:

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

Зауважте, що дебетовий метод передає об'єкт транзакції, а не просто подвійну суму («Закон Деметера», наскільки я розумію, сказав би просто передати необхідну інформацію, в даному випадку - лише суму, а не об’єкт транзакції ... ). Причина цього полягає в тому, що метод в майбутньому може зажадати від суми інших властивостей транзакцій. Як я розумію, це не дозволить порушити підпис методу, додавши новий параметр у майбутньому.

Чи робить це тоді розумним вибором? Або я щось пропускаю?

Відповіді:


3

Але це не порушує Закон Деметера.

Більш формально Закон Деметера для функцій вимагає, щоб метод M об'єкта O міг посилатися лише на методи таких типів об'єктів:

  • O себе
  • Параметри М
  • будь-які об’єкти, створені / створені в М
  • О прямі компоненти об'єктів
  • глобальна змінна, доступна O, в області M

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

Трансакція є аргументом дебетового методу, тому виклик t.getAmount () чудово.

Редагувати: неправильно, що ви говорите, що LoD мав би передати суму транзакції, а не об'єкт транзакції. Якщо це так, то так, я думаю, що це гарне місце, щоб його зламати, знаючи, що вам потрібно буде більше від об’єкта транзакції в майбутньому. Крім того, інкапсуляція примітивів у об'єктах доменного рівня - ще одна добра практика програмування.

Редагування 2: Прочитавши, можливо, в майбутньому може знадобитися більше, можна також побачити це як непотрібне позолочення. Забезпечити метод, який зараз займає подвійний (а краще грошовий клас), є достатнім. Якщо вам потрібен аргумент Transaction пізніше, не катастрофічно надавати другий підпис, приймаючи транзакцію, але продовжуйте підтримувати оригінальний підпис. Це не так, як ви впроваджували б два методи, один називав би інший.


Дякуємо за ваш внесок. Я згоден щодо інкапсуляції примітивів у доменних об'єктах. Тим не менш, тільки ваш пункт редагування 2, ви говорите, що не катастрофічно додати новий 2-й підпис, але це означатиме зміну коду на код клієнта, який тепер повинен передавати 2 параметри замість одного. Цей другий пункт, я не вагаючись погодився ...
Карлос Хайме К. Де Леон

Правка 2 суб'єктивна, я згоден.
Шон

0

Якщо ви плануєте розширювати Accountклас у майбутньому, я б сказав, що це ситуація, коли зробити Transactionоб'єкт більш загальним призначенням було б вдалим вигином норм Закону.

Наприклад:

public class Amount {

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

public abstract class Transaction {

    public String getType();

}

Я думаю, що я якось відхиляюся від початкового запитання, але мій погляд на те, що, хоча ви можете переживати, що ви відхиляєтесь від Закону Деметера, переваги цього переважають над негативом.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.