Я работаю над прототипом для использования базы данных документов (в настоящее время MongoDB, может измениться) и обнаружил, что драйверы .NET немного больно, поэтому я подумал, что я бы абстрактным образом предоставлял доступ к данным с помощью шаблона репозитория. Это должно облегчить замену любого драйвера, который я использую сейчас (NoRM, mongodb-csharp, simple-mongob) с вашим драйвером killer f # mongodb, который не сосать, когда он готов.
Мой вопрос связан с операцией Add. Это будет иметь некоторое влияние на базу данных, и поэтому последующие вызовы для всех будут разными. Мне все равно? В С# традиционно я не хотел бы, но я чувствую, что в 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, упрощая изменение драйверов и потенциально баз данных.
Вызов Все в порядке, но с добавлением того, что я надеялся, вместо возврата единицы, верните новый экземпляр репозитория. Что-то вроде:
// 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.
Так должен ли я пытаться обработать побочный эффект от Add в базе данных в дизайне типов? Как другие подумают об этом, используете ли вы репозиторий или какой-либо интерфейс, например, или используете более функциональный подход?