f# - How to set up non-trivial data persistence? -


most generally, question is: how set non-trivial data persistence in nice functional way?
prefer answers people real experience, people have done it. happy hear other thoughts on subject.

and now, let me clarify mean examples.

let's have data program handles , needs keep. say, our old friend employee:

module employees =   type employee = { name: string; age: int; /* etc. */ }  module employeespersistence =   type employeeid = ...    let getemployee: (id:employeeid -> employee) = ...   let updateemployee: (id:employeeid -> c:employee -> unit) = ...   let newemployee: (c:employee -> employeeid) = ... 

doesn't matter how persistence functions implemented, let's go relational database, or document-based database, or file on disk. don't care right now.

and have program them:

module somelogic =    let printemployees emps =       let print { name = name, age = age } = printfn "%s %d" name age      seq.iter print emps 

so far straightforward.

now, let's have kind of data, department, related employee, yet needs stored independently (in separate table, separate collection, separate file).
why independently? honest, don't know. do know needs have own identity, can display/update without relation particular employee. this, infer storage must separate, i'm open alternative approaches.

so pretty same thing did employees:

module departments =   type department = { name: string; /* etc. */ }  module departmentspersistence =   type departmentid = ...   let getdepartment, updatedepartment, newdepartment = ... 

but now, how express relationship?

attempt #1: ignore persistence.

in great time-honored tradition of "abstract things", let design our data model while pretending there no persistence. we'll add later. day. it's "orthogonal". it's "auxillary". or such.

module employees =   type employee = { name: string; age: int; department: department }  module somelogic =    let printemployees emps =       let print { name = name, age = age, department = { name = dept } } = printfn "%s %d (%s)" name age dept      seq.iter print emps 

this approach means every time load employee persistent storage, must load department well. wasteful. , then, employee-department 1 relationship, in real application i'd have lot more that. what, load whole graph every time? prohibitively expensive.

attempt #2: embrace persistence.

ok, since can't directly include department in employee, include department's artificial identity, can load when needed.

module employees =   type employee = { name: string; age: int; department: departmentid } 

now model doesn't make sense on own: modeling storage, not domain.
then, turns out "logic" functions need department must parametrized on "loaddepartment" function:

module somelogic =    let printemployees loaddept emps =       let print { name = name, age = age, department = deptid } =         let { name = deptname } = loaddept deptid        printfn "%s %d (%s)" name age deptname      seq.iter print emps 

so functions also don't make sense on own. persistence has become intimately integral part of program, far being "orthogonal concept".

attempt #3: hide persistence.

ok, can't include department directly, , don't including id, do?
here's idea: can include promise of department.

module employees =   type employee = { name: string; age: int; department: () -> department }  module somelogic =    let printemployees emps =       let print { name = name, age = age, department = dept } = printfn "%s %d (%s)" name age (dept()).name      seq.iter print emps 

so far looks cleanest way (incidentally, orms do), still not without problems.
one, model doesn't exacly make sense on own: components included directly, others via "promise", without evident reason (in other words, persistence leaks through).
another, having department promise fine reading, how update? guess use lens instead of promise, gets more complicated.

so.

how people this? should compromise, works, doesn't? , have compromise, isn't there "pure" way?
since there real data-driven applications out there, there must way these things done, right? right?..


Comments

Popular posts from this blog

PHP DOM loadHTML() method unusual warning -

python - How to create jsonb index using GIN on SQLAlchemy? -

c# - TransactionScope not rolling back although no complete() is called -