Должны ли реализации интерфейса быть независимыми

Я натолкнулся на какой-то унаследованный код, который поднял все мои шкуры как объектно-ориентированный программист.

Вот часто используемый шаблон:Интерфейс имеет две реализации, и одна реализация вызывает метод другой.

Теперь я думаю, что это следует изменить, чтобы реализации не знали друг о друге. Это достаточно просто, КАК это сделать. То, что я не могу понять ясно - и надеюсь, что хорошие люди из СО помогут мне - это ПОЧЕМУ.

Я вижу теоретическую причину - это ужасный объектно-ориентированный дизайн. Но я играю здесь адвоката дьявола и спрашиваю - каков практический недостаток двух реализаций, имеющих знание друг о друге. Почему нужно тратить время и деньги, чтобы избавиться от этого (на мой взгляд) анти-паттерна?

Любая информация или ссылки на это будут оценены.

4 ответа

Решение

Нет ничего плохого в том, что реализация1 интерфейса1 осознает или взаимодействует с реализацией2 интерфейса1.

Я думаю, что вы только что обнаружили предполагаемую или непреднамеренную реализацию шаблона прокси http://en.wikipedia.org/wiki/Proxy_pattern

Надеюсь это поможет:)

Я вижу теоретическую причину - это ужасный объектно-ориентированный дизайн.

Зачем? Это звучит вполне разумно для меня.

Например, предположим, что я хочу украсить каждый вызов - например, добавить статистику о частоте выполнения вызова, добавить проверку авторизации и т. Д. Имеет смысл отделить это оформление от реальной реализации и просто делегировать:

public class DecoratedFoo : IFoo
{
    private readonly IFoo original;

    public DecoratedFoo(IFoo original)
    {
        this.original = original;
    } 

    public string Bar() // Defined in IFoo
    {
        // Update statistics here, or whatever
        return original.Bar();
    }
}

Почему вы считаете такое разделение интересов "ужасно объектно-ориентированным дизайном"? Даже если оформленный класс знает о конкретной реализации IFoo и называет членов, которые не являются частью IFoo Само по себе, чтобы сделать вещи более эффективными, мне это не кажется особенно ужасным. Это просто один класс, который знает о другом, и они реализуют один и тот же интерфейс. Они более тесно связаны, чем в примере выше, который знает только о IFoo, но это все же не "ужасно".

Этот метод "другой реализации", который вызывает первая реализация, я бы назвал библиотечной функцией. Поместите его в отдельный модуль / файл / проект / что угодно (зависит от вашего языка /dev env) и включите его в обе реализации и используйте его оттуда.

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

Мои мысли по этому поводу

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

  2. Всегда чище иметь единственную ответственность.

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