Принятие решений по проектированию интерфейсов классов

Я хотел бы получить некоторые мысли от других о следующей проблеме. Давайте предположим, что у нас есть два класса продуктов и предметов. Объект Products позволяет нам получить доступ к любому объекту Item. Вот пример.

$products = new Products();

// get existing item from products
$item = $products->get(123);

// create item
$item = $products->create();
$item->setName("Some new product");
$item->setPrice(2.50);

Теперь, что было бы лучшим способом обновить / сохранить состояние элемента? Я вижу 2 варианта:

$item->save();

или же

$products->save($item);

Первый подход кажется очень прямым. Как только атрибуты объекта Item установлены, вызывая метод save, он сохранит изменения.

С другой стороны, я чувствую, что последний подход лучше. Мы разделяем роли двух объектов. Объект item содержит только состояние, а объект Products работает с этим состоянием. Это решение также может быть лучше для написания модульных тестов. Какие-нибудь мысли?

1 ответ

Решение

Таким образом, элементы эффективно буферизуют реальные изменения.

Очевидно, что оба подхода будут работать, однако все сводится к тому, насколько близко вы хотите придерживаться модели базовой базы данных или наложенной объектной модели.

Если смотреть снаружи, $item->save() имеет смысл с точки зрения модели - как вы указали, вы обновляете свойства элемента, а затем сохраняете их. Плюс это концептуально действие, которое выполняется над элементом.

Тем не мение, $products->save($item) предлагает два заметных преимущества и недостаток.

С другой стороны, перемещая сохранение в продукты, он (потенциально) может обрабатывать пакетирование / переупорядочение обновлений более интеллектуальным способом, поскольку он имеет видимость всех элементов. Это также позволяет использовать код сохранения как ->add() (более менее)

Недостатком является то, что он собирается (с точки зрения объектной модели) добавить следующее возможное использование, которое вы, вероятно, не хотите:

$p1 = new Products();
$p2 = new Products();
$item = $p1->create();
// set $item values
$p2->save($item);

Очевидно, вы могли бы просто добавить "это моя? нет? затем бросить тест на ошибку Products::save, но это дополнительный код для блокировки варианта использования, который подразумевает синтаксис, может / должен работать. Или, по крайней мере, вероятно, проскользнет через обзор кода.

Итак, я бы сказал, что придерживайтесь подхода, который кажется самым простым и крепче связывается с желаемой функциональностью ($item->save()), если вам не нужно делать кэширование / пакетирование / все, что заставляет вас идти с другим.

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