Я работаю над прототипом для использования базы данных документов (в настоящее время 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.
Так должен ли я попытаться справиться с побочным эффектом от добавления в базу данных при разработке типов? Как другие подойдут к этому, используете ли вы репозиторий или какой-либо интерфейсный класс, подобный этому, или у вас есть более функциональный подход?