Я нарушаю «Закон Деметры»? - PullRequest
       4

Я нарушаю «Закон Деметры»?

11 голосов
/ 14 сентября 2010

Я только недавно узнал о Законе Деметры .

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

Например ...

У меня может быть объект Address:

public class Address : IAddress
{
   public string StreetAddress { get; set; }
   public string City { get; set; }
   public int Zip { get; set; }
}

и объект Customer:

public class Customer : ICustomer
{
   private IAddress address;

   Customer()
   {
      Address = null;
   }
   public string Name { get; set; }
   public IAddress
   {
      get
      {
         if (address == null)
         {
            address = new Address();
         }
         return address;
      }
      set
      {
         address = value;
      }
   }
}

Хорошо, это фальшивый код, так что вам, вероятно, не придется прыгать на меня, чтобы использовать IoC для устранения new Address() или чего-либо еще, но это в значительной степени пример того, что я делаю. Я не включил интерфейсы, так как надеюсь, что они очевидны.

Я бы тогда использовал его в своем коде для таких вещей, как int zip = customer.Address.Zip; и customer.Address.City = "Vancouver";

Насколько я понимаю, я нарушаю Закон Деметры, манипулируя деталями Обращения от Клиента.

Опять же, похоже, что и фреймворк тоже. В конце концов, не будет адреса. Город. Длина будет нарушением? Должен ли я добавлять методы в адрес для обработки доступа к свойствам строки? Возможно нет. Итак, зачем засорять адрес?

Я не могу просто добавить методы к Address, которые относятся только к клиенту. У меня есть объекты Member, Employee, Dependent, Vendor, Employer и т. Д., Которые тоже имеют адреса.

Есть ли лучший способ справиться с этим? Какими проблемами я рискую, если использую Адрес таким, какой я есть сейчас?

Для Java-пользователей класс Address может выглядеть примерно так, если это поможет:

public class Address extends AddressInterface
{
   private String m_city;

   public String getCity() { return m_city; }
   public void setCity(String city) { m_city = city; }
}

Я должен признать, что customer.getAddress().setCity("Vancouver"); издает больше сигналов, чем customer.Address.City = "Vancouver"; сделал для меня. Может быть, мне стоит ненадолго переключиться на Java.

Ответы [ 3 ]

11 голосов
/ 14 сентября 2010

Эта статья: http://haacked.com/archive/2009/07/14/law-of-demeter-dot-counting.aspx содержит отличное объяснение проблем, которые вы обсуждаете.

Поскольку он отмечает, что это не упражнение по подсчету точек, это проблема сопряжения.В настоящее время ваши классы Customer и Address слишком тесно связаны.Для начала, Customer не должен создавать новые адреса, возможно, передайте Address при использовании конструктора.Относительно того, должны ли вы использовать несколько точек для доступа к частям адреса, прочитайте статью ...

Мартин Фаулер: «Я бы предпочел, чтобы это называлось иногда полезное предложение Деметры.«

2 голосов
/ 14 сентября 2010

Нарушения закона Деметры являются примерами запаха кода, названного Неуместная близость . Чтобы устранить этот запах, вы можете реорганизовать свой код, скрыв внутренние адреса и внедрив в Customer методы, делегирующие адрес. Таким образом, вы уважаете инкапсуляцию в адресе внутри Клиента.

Пример:

public class Customer extends ICustomer{
    private Address address;
    ....

    public void setCity(String city){
        address.setCity(city);
    }

    public String getCity(){
        return address.getCity();
    }
}

Надеюсь, это поможет.

1 голос
/ 19 ноября 2010

Проблема в том, что Address является ValueObject. Вы никогда не измените город, не изменив почтовый индекс.

public class Customer extends ICustomer{
    private Address address;
    ....

    public void setAddress(String street, String city, int zip){
        address = Address.new(street, city, zip);
    }
    // or even better but i'm not sure if it's valid C#
    public void setAddress(int zip){
        address = Address.lookup(zip);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...