Как я могу гарантировать, что объект принадлежит только одной коллекции, сохраняя принцип СУХОГО?

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

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

Итак, как я справлялся с этим в прошлом, так это чтобы дать объекту ссылку на коллекцию. Таким образом, мы пытаемся удостовериться, что Объект может принадлежать только одной Коллекции. Затем я бы добавил объект в коллекцию.

public function __construct(Collection $c)
{
    $this->setCollection($c);
}

public setCollection(Collection $c)
{
    $this->collection = $c;
    $c->addObject($this);
}

Это очевидное противоречие с "Не повторяй себя". И это происходит потому, что требования, которым нужен легкий доступ к коллекции объектов и что объекты принадлежат только одной коллекции, противоречат друг другу. Объект знает, что он находится в Коллекции, и Коллекция знает, что Объект находится в этой коллекции. Если какой-либо из них не синхронизирован, система сломана.

И проблемы становятся очевидными, когда вы начинаете пытаться создать код для перемещения объекта из одной коллекции в другую. Или при удалении объекта.

Итак, кто-нибудь нашел решение этой проблемы? Есть что-то, что я должен попробовать? В конце я могу заставить его работать с двойной проверкой, но кажется, что должен быть лучший способ.

1 ответ

Я не уверен, что следую вашей логике до конца игры "двойной проверки"... но что не так с таким кодом?

class Collection {

   public function AddMember(Member $m) {
       $m->SetCollection($this);
       // add to underlying data structure
   }

   public function RemoveMember(Member $m) {
       // remove from underlying data structure
   }
}

class Member {
    private $collection = null;

    public function SetCollection(Collection $c) {
        if($this->collection)
            $this->collection->RemoveMember($this);
        $this->collection = $c;
    }

    public __destruct() {
        if($this->collection)
            $this->collection->RemoveMember($this);
    }
}

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

Это отличный шаблон проектирования, где дружественные классы / методы были бы полезны для правильной инкапсуляции, чтобы не позволить никому, кроме объекта коллекции, установить или удалить элемент из своей коллекции. Вы также захотите долго и усердно подумать о том, какие методы вы хотите использовать в качестве точек входа, и в этих случаях поступайте правильно, не попадая в цикл рекурсии. Для такого класса фреймворка / библиотеки модульные тесты значительно облегчат вашу жизнь.

Да, я могу видеть, где вы можете беспокоиться о необходимости сделать if проверьте, прежде чем делать что-либо с добавлением, удалением или уничтожением. Но это природа умного и безопасного указателя / эталонного образца. Принцип СУХОЙ заключается не столько в том, чтобы избежать избыточности проверок безопасности, сколько в том, чтобы избежать нескольких копий данных или избыточных реализаций алгоритмов. Да, каждый из этих методов в моем псевдокоде технически является алгоритмом, но вот несколько вещей, которые нужно пережить (хорошо, это действительно одно и то же, заявленное с разных точек зрения):

  1. Они работают в постоянном времени (при условии, что вы избежите ловушек рекурсии, о которых я упоминал).
  2. Серьезно: самый короткий алгоритм.
  3. Если вы беспокоитесь об оптимизации половины вашего if операторы в библиотеке, вам не хватает леса для (одного) дерева. Время на оптимизацию тратится на то, чтобы сделать код более простым в использовании, обслуживании и снижении сложности алгоритмов. Он не становится менее сложным, чем алгоритм с постоянным временем.
  4. Вы не собираетесь привязывать свой процессор, делая дополнительные if заявление о каждом добавлении или удалении. Вы привязываете свой процессор, запустив O(n^2) алгоритм по большому n,

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

Другие вопросы по тегам