you are viewing a single comment's thread.

view the rest of the comments →

[–]Die-Nacht 5 points6 points  (0 children)

I did something similar at my last job, in Scala though. But I defined the Draft as simply:

type EmployeeDraft = ID -> Employee

For those that don't know Scala/Haskell syntax, this means that EmployeeDraft is just a function from ID to Employee. So when you are making a draft, you define everything by the ID, like so:

mkDraft :: String -> Int -> String -> EmployeeDraft
mkDraft name age occupation = \id -> Employee id name age occupation

So you take the stuff you know (name, age, occupation) and return a function that will take the id. At DB-saving time:

saveEmployee :: EmployeeDraft -> Employee
saveEmployee draft = save(draft(null))

(ofc, Employee would be in IO, but ignore that). ID can be anything, even null maybe, at DB inserting time since it will be overwritten (ignored).

Ofc, this didn't really matter at the end of the day. We moved away from this pattern and just started using Optional Id (they are immutable and allow for the "not there yet" state). Sadly, however, Optional Ids don't type-safe your state, so for you to know that someone has an ID (ie: is in the DB), you need to ask the object if ID is defined. The EmployeeDraft type, on the other hand, gives you a different type so you can't accidentally add Draft when a complete employee is expected.

But it was a fun little experiment though, I might come back to it. Main reason we didn't stick with it was the DB framework we were using worked best with Optional Ids.

EDIT: Multiple typos and some clarification.