Это анти-паттерн? - PullRequest
       42

Это анти-паттерн?

8 голосов
/ 21 января 2010

Ситуация такова: у вас есть два класса, которые реализуют один и тот же интерфейс, и оба класса работают вместе, чтобы завершить некоторый бизнес-процесс.

Например, networkUserManager и localUserManager реализуют IUserManager, который имеет метод getUser(). networkUserManager.getUser() помещает запрос на получение User в очередь и возвращает ответ. localUserManager.getUser() получает запрос из очереди, находит информацию о пользователе в некоторой базе данных и затем отвечает данными пользователя.

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

Ответы [ 6 ]

10 голосов
/ 21 января 2010

Это пахнет довольно плохо для меня. Конечно, разные классы могут иметь методы с одним и тем же именем, но если они оба реализуют один и тот же интерфейс, то существует предположение, что они будут делать одно и то же. Здесь они делают противоположные вещи!

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

2 голосов
/ 21 января 2010

Вы, похоже, описываете шаблон Decorator . В этом случае NetworkUserManager предоставляет дополнительные функциональные возможности по сравнению с LocalUserManager. Вы не говорите, какой язык используете, но этот шаблон встречается в пакете java.io.

С другой стороны, ваше описание LocalUserManager.getUser() извлечения сообщения из очереди кажется неправильным - оно отстает от способа работы NetWorkUserManager. Я бы воспринимал это как правильный декоратор, если бы LocalUserManager получил доступ к базе данных, в ответ на что-то еще (возможно, NetworkUserManagerService), вызвав getUser().

1 голос
/ 21 января 2010

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

Вопрос здесь в том, является ли getUser значимой абстракцией и инкапсулирует ли она вашу логику, которая для меня выглядит как многоуровневый доступ.Я бы сказал, что он скрывает больше, чем освещает.Например, декораторы java.io могут (в основном) быть привязаны друг к другу в любом порядке;Учитывая многоуровневый доступ, который вы описываете, LocalManager.getUser (NetworkManager.getUser ()) имеет смысл, а NetworkManager.getUser (LocalManager.getUser ()) - нет.

1 голос
/ 21 января 2010

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

Если я вас правильно понимаю, у вас есть очередь. Процесс A, независимо от имени, помещает вещи в очередь. Процесс B, независимо от имени, забирает вещи из очереди и обрабатывает их.

Затем вы добавляете дополнительный незначительный усложняющий фактор в этот процесс. A хочет получать уведомления о результатах обработки очереди. Ничего страшного.

Если есть плохая практика, я бы сказал, что это именование классов и использование общего интерфейса. Похоже, они не выполняют аналогичные задачи. Похоже, что они оба работают с одним и тем же классом / объектом (эта очередь).

1 голос
/ 21 января 2010

Предположим, networkUserManager необходимо получить данные через сеть. Таким образом, он помещает запрос в очередь запросов к сетевому серверу, который имеет эту информацию, и localUserManager, находящийся на сервере, фактически обслуживает этот запрос. Когда вы пишете версию программного обеспечения для одной машины, вероятно, лучше оставить ее почти такой же, чем тратить время разработчика на переписывание этой области без причины.

0 голосов
/ 21 января 2010

Я бы не стал называть это антипаттерном, но определенно очень плохой реализацией интерфейса. («Дурной запах», как упомянуто в этой теме?)

Я бы даже сказал, что эти два метода getUser () должны иметь разные имена, поскольку, хотя они имеют одинаковые возвращаемые значения и не имеют аргументов, их «семантические» интерфейсы явно различаются:

  • localUserManager.getUser () ожидает, что что-то уже находится в очереди
  • networkUserManager.getUser () - нет.
...