Абстрактный класс или интерфейс для сервиса IoC?

В настоящее время я использую IoC для предоставления конкретных реализаций репозиториев в проекте. Все примеры, которые я прочитал, используют интерфейс в качестве определения сервиса. Однако, прочитав рекомендации от Microsoft, рекомендуется отдавать предпочтение абстрактным классам над интерфейсами.

Я нашел это полезным в сочетании с шаблоном шаблона, чтобы уменьшить количество повторений. Например дать Product класс со свойством IsActive Я мог бы использовать интерфейс для хранилища, такой как:

interface IProductRepository
{
    IEnumerable<Product> Load();
}

Если общей задачей является загрузка активных продуктов, то мне нужно сделать:

IEnumerable<Product> activeProducts = repository.Load().Where(x => x.IsActive);

куда repository это конкретная реализация. Если бы я использовал абстрактный класс, такой как:

abstract class ProductRepository
{
    protected abstract IEnumerable<Product> LoadCore();

    public IEnumerable<Product> Load()
    {
        return LoadCore().Where(x => x.IsActive);
    }
}

Тогда я мог бы загружать активные продукты, используя

IEnumerable<Product> activeProducts = repository.Load();

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

Есть ли польза от использования интерфейса вместо абстрактного класса? С какими потенциальными недостатками использования абстрактных классов я могу столкнуться?

Я использую Castle Windsor в качестве контроллера IoC и.Net Framework 3.5.

2 ответа

Решение

Я не думаю, что этот вопрос зависит от IoC; большинству этих фреймворков все равно, какие вы используете.

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

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

Рекомендация исходит из Руководства по разработке структуры. Эта рекомендация Microsoft существует специально для многократно используемых библиотек классов. Другими словами: фреймворки, подобные самой платформе.NET. Если вы создаете бизнес-приложение, это руководство не применяется. Это не применимо, потому что маловероятно, что у вас будут проблемы с версиями в бизнес-приложениях, потому что у вас есть контроль над всем клиентским кодом, который взаимодействует с вашими классами / интерфейсами. Это, конечно, не относится к повторно используемым библиотекам.

Даже статья Фила Хаака, где Уилл ссылается на это, описывает это:

Опять же, эти рекомендации относятся к разработке Framework (для статически типизированных языков), а не к другим типам разработки программного обеспечения.

Поэтому удаление проблем управления версиями, вероятно, не является хорошим аргументом для использования базовых классов. Сохранение кода СУХОЙ, однако, может быть. Однако использование базовых классов и интерфейсов не является взаимоисключающим; ты можешь позволить своему abstract class ProductRepository воплощать в жизнь IProductRepository, Однако, если вы сделаете это, разоблачение чего-либо еще, кроме IProductRepository было бы плохой идеей.

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