Фабричный метод может нарушать закон Деметры? - PullRequest
0 голосов
/ 29 ноября 2018

цитата отсюда: https://en.wikipedia.org/wiki/Law_of_Demeter

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

  • O *

  • параметры m

  • Любые объекты, созданные / созданные в пределах m

  • Объекты прямого компонента O

  • Глобальная переменная, доступная для O, в объеме m

В частности, объект должен избегать вызова методов объекта-члена, возвращаемого другим методом

, поэтому более подробно:

class O
{
    private $c;
    public function m($obj1)
    {
        $this->a(); // OK
        $obj1->a(); // OK
        (new C())->a(); // OK
        $c->a(); // OK
        $a = function() { };
        $a(); // OK
    }

    private function a() {}
}

теперь третий закон сомнителен.Итак, я недавно создал объект.Но если я вместо:

(new C())->a();

я сделаю:

$this->factory->createC()->a();

это все еще действует?Обычный класс был инстанцирован, просто не new, а фабрикой.Но эй!Закон гласил:

В частности, объект должен избегать вызова методов объекта-члена, возвращаемого другим методом

по этому правилу, метод фабрики завершается ошибкой!Что теперь?Это действительно терпит неудачу?

Ответы [ 2 ]

0 голосов
/ 04 декабря 2018

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

Каждая единица должна иметь только ограниченные знания о других единицах: только единицы, «тесно связанные» с текущей единицей

В вашем примере O-класс знает C-класс в любом случае.Использование фабрики не влияет на этот факт.Так или иначе класс O зависит от класса C, и эта зависимость неизбежна.Это означает, что зависимость не является избыточной.Фактически зависимость между классом C и классом O является зависимостью между «тесно связанными» единицами, поэтому при использовании фабрики не нарушается закон Деметры.

В качестве примера давайте представимследующий экземпляр кода:

class O
{

   public function m()
   {
      $c = new C();
      $c->a();
   }
}

Как вы можете видеть, O-класс знает класс C и зависит от него.Закон Деметры не нарушается в этом кодексе.Если вы измените этот пример следующим образом:

class O
{

   protected function build()
   {
      return new C();
   }

   public function m()
   {
      $c = $this->build();
      $c->a();
   }
}

класс O все равно будет знать класс C и зависеть от него, закон Деметры не будет нарушен в этом коде.Фактически мы делегировали ответственность за создание объекта на фабричный метод.Если вы измените этот пример следующим образом:

class Factory
{
   public function build()
   {
      return new C();
   }
}

class O
{

   /**
    * @var Factory
    */
   protected $factory;

   public function m()
   {
      $c = $this->factory->build();
      $c->a();
   }
}

Мы делегировали ответственность за создание объекта на объект фабрики, но этот факт нарушил закон Деметра, потому что ничего не изменится в зависимостях между классом O и Cучебный класс.Как и ранее, O-класс знает класс C и зависит от него.У нас одинаковые зависимости во всех трех случаях.

0 голосов
/ 29 ноября 2018

Я так не думаю.

Особенно это:

Любые объекты, созданные / созданные в m

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

Учитывая различные важные роли, которые фабрики играют в разработке программного обеспечения (инверсияконтроль является одним из них), я думаю, что они слишком ценны, чтобы отпустить.Лучше изменить ваше толкование этого закона или того, что такое конструктор, и использовать эти фабрики, когда захотите.

...