Использование интерфейса для слабой связи провайдера NoSQL - PullRequest
1 голос
/ 25 января 2012

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

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

Набросать это вЯ подумал, что лучший способ сделать это - создать интерфейс, подобный следующему:

public interface INoSql
{
    string ServerLocation
    {
        get; set;
    }

    string DatabaseName
    {
        get; set;
    }

    string CollectionName
    {
        get; set;
    }

    void SaveChanges(List<NoSqlItem> nsCollection);
}

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

* 1009.*

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

 INoSql noSQLConnection = new INoSql;

Поскольку вы не можете создать экземпляр интерфейса.

Так, каково решение, чтобы мой код был красивым и свободным?Чтение вокруг выглядит так, как будто один ответ состоит в том, чтобы вставить его в конструктор:

public class MyClass
{
    private INoSql NoSql;

     public myClass(INoSql NoSql)
     {
         this.NoSql = NoSql;
     }
 }

Что выглядит аккуратно, но разве это не устраняет проблему?Потому что тогда вам придётся создавать конкретную версию чего-то, что реализует INoSql, когда вы создаете MyClass, да, и это должно быть MongoDBConnection - или что угодно - вместо слабо связанного класса?

Очевидно, я что-то пропустил, но что?И есть ли другие решения этой распространенной проблемы?

Cheers, Matt

Ответы [ 4 ]

5 голосов
/ 25 января 2012

Вам не нужно заново изобретать колесо.

По моему скромному мнению, Шаблон проектирования репозитория сделает работу:

UPDATE

Я забыл часть "как получить реализации интерфейса".

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

Чтобы получить правильную реализацию, как указывали другие, вы можете использовать некоторые фреймворки, такие как:

И, наконец, я хотел бы предложить вам, что Common Service Locator является хорошим другом, чтобы не иметь прямой зависимости от конкретной платформы IoC / DI:

2 голосов
/ 25 января 2012

Я согласен с Матиасом в отношении шаблона Репозиторий.Другой проблемой, которую вы пытаетесь решить, является жесткая зависимость от провайдера БД (MongoDB в вашем примере).Несмотря на то, что действительно возможность поменять ваш доступ к данным редко бывает так просто, как скрыть его за интерфейсом, метод, который это делает, называется внедрением зависимости, и вы используете его форму (внедрение конструктора) в своем коде MyClass.

Вот краткий обзор внедрения зависимостей: http://jamesshore.com/Blog/Dependency-Injection-Demystified.html

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

https://stackoverflow.com/questions/2515124/whats-the-simplest-ioc-container-for-c

Autofac, StructureMap и Unity - вот те, которые я использовал с успехом.

Надеюсь, это поможет!

2 голосов
/ 25 января 2012

Посмотрите на контейнеры IoC, например Castle Windsor , SpringFramework.net и StructureMap . Это та проблема, для решения которой они предназначены.

1 голос
/ 25 января 2012

Вы можете использовать Unity или другой контейнер IoC для регистрации и создания объектов, реализующих интерфейсы. Ваш код будет выглядеть примерно так:

INoSql noSQLConnection = UnityContainer.Resolve<INoSql>();

Microsoft Unity Framework

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...