очень простой момент:
class Point
{
private $x, $y;
public function __constructor($x, $y)
{
$this->x = $x;
$this->y = $y;
}
public function getX()
{
return $this->x;
}
public function getY()
{
return $this->y;
}
}
и круг
class Circle
{
private $r;
private $point;
public function __constructor (Point $point, $r)
{
$this->point = $point;
$this->r = $r;
}
public function getPoint() // here is the law breaking
{
return $this->point;
}
}
$circle = new Circle(new Point(1,2), 10);
$circle->getPoint()->getX(); // here is the law breaking
$circle->getPoint()->getY(); // here is the law breaking
конечно это нарушает закон Деметры. Итак, позвольте мне преломить это:
class Circle
{
private $r;
private $point;
public function __constructor (Point $point, $r)
{
$this->point = $point;
$this->r = $r;
}
public function getPointX()
{
return $this->point->getX();
}
public function getPointY()
{
return $this->point->getY();
}
}
$circle = new Circle(new Point(1,2), 10);
$circle->getPointX();
$circle->getPointY();
кроме того, что выглядит лучше, я не вижу никаких преимуществ — только две дополнительные функции обтекания. Технически у меня снова есть полный доступ к Point
и нет никакого способа, которым было бы добавлено больше методов Point
, Стоит ли еще использовать 2-й рефрактированный метод?
Помимо того, что это вопрос, основанный на мнении, я бы сделал это так:
class Circle extends Point
{
private $r;
public function __constructor (Point $point, $r)
{
$this->x = $point->getPointX();
$this->y = $point->getPointY();
$this->r = $r;
}
}
$circle = new Circle(new Point(1,2), 10);
$circle->getPointX();
$circle->getPointY();
Я согласен с @Webdesigner, что это скорее вопрос, основанный на мнении.
Однако, на мой взгляд, я не думаю, что нарушение закона деметры — это действительно проблема, если вы считаете, что Point объект стоимости.
Добытчик может быть
public function center() : Point { ... };
чтобы сделать это еще более ясным.
Хотя вторая версия технически не нарушает Закон Деметры, я бы сказал, что она все еще нарушает его «по духу». Причина, по которой вы не можете сказать, какая из них лучше, заключается в том, что вторая из них только незначительно лучше первой с точки зрения сокрытия и инкапсуляции информации (то, что Закон Деметры пытается кодифицировать).
Закон касается сокрытия внутренней структуры объекта, что позволяет инкапсулировать, скрывать информацию и предотвращать связывание. Геттеры (средства доступа) по своей природе являются противоположностью сокрытия информации, они обеспечивают доступ к внутренним структурам, а не предотвращают его.
Резюме: добытчики ваша проблема. Пока они у вас есть, вам всегда придется сражаться с Законом Деметры, и вы, вероятно, проиграете 🙂
Итак, как вы пишете код без геттеров, спросите вы? Ну, вы добавляете методы, которые делать что-то для вас с координатами. Вещи, которые вам нужны. Расстояние между точками, точки преобразования и т. Д. Все, что вам нужно в вашем текущем приложении. Подумайте о том, что означает точка в вашем текущем контексте.
Проверьте «Гений Закона Деметры».