Шаблон репозитория в F #

Я работаю над прототипом для использования базы данных документов (в настоящее время MongoDB, может измениться) и обнаружил, что драйверы .NET немного затрудняют работу, поэтому я подумал, что абстрагирую доступ к данным с помощью шаблона репозитория. Это должно упростить замену любого драйвера, который я использую сейчас (NoRM, mongodb-csharp, simple-mongob), на ваш убийственный драйвер f # mongodb, который не отстой , когда он будет готов.

Мой вопрос касается операции Добавить . Это будет иметь некоторые побочные эффекты для базы данных, и поэтому последующие вызовы All будут другими. Должен ли я заботиться? В C # традиционно я бы этого не сделал, но я чувствую, что в F # должен.

Вот общий интерфейс репозитория:

type IRepository<'a> =
    interface
        abstract member All : unit -> seq<'a>

        // Add has a side-effect of modifying the database
        abstract member Add : 'a -> unit
    end

А вот как выглядит реализация MongoDB:

type Repository<'b when 'b : not struct>(server:MongoDB.IMongo,database) =
    interface IRepository<'b> with

        member x.All() =
            // connect and return all

        member x.Add(document:'b) =
            // add and return unit

Во всем приложении я буду использовать IRepository, упрощая изменение драйверов и потенциально баз данных.

Calling All - это нормально, но с помощью Add, на которое я надеялся, вместо того, чтобы возвращать unit, вернуть новый экземпляр репозитория. Что-то вроде:

        // Add has a side-effect of modifying the database
        // but who cares as we now return a new repository
        abstract member Add : 'a -> IRepository<'a>

Проблема в том, что если я вызываю Get, а затем Add, исходный репозиторий по-прежнему возвращает все документы. Пример:

let repo1 = new Repository<Question>(server,"killerapp") :> IRepository<Question>
let a1 = repo1.All() 
let repo2 = repo1.Add(new Question("Repository pattern in F#"))
let a2 = repo2.All()

В идеале я хочу, чтобы длина a1 и a2 была разной, но они одинаковы, поскольку оба попадают в базу данных. Приложение работает, пользователи могут задать свой вопрос, но программисту остается недоумевать, почему он возвращает новый IRepository.

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

12
задан bcosca 29 November 2010 в 16:46
поделиться