Skip to content

Instantly share code, notes, and snippets.

@kellabyte
Last active December 12, 2015 07:59
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kellabyte/4741078 to your computer and use it in GitHub Desktop.
Save kellabyte/4741078 to your computer and use it in GitHub Desktop.
// Struct Store
//
// Version 1: We may have written...
DocumentDatabase db = new DocumentDatabase();
User user = new User();
user.Id = 123;
user.FirstName = ....;
user.LastName = ....;
user.Bio = ....;
db.Put(user);
// Version 2: Two years forward... I want to add a Twitter handle.
DocumentDatabase db = new DocumentDatabase();
User user = db.Get(123);
user.TwitterHandle = ...;
db.Put(user);
// But because I have 100 servers, I can't afford to take all 100 down at once to make
// this change. So I'm going to do what any highly available service does,
// run parallel versions.
// Scenario: The cluster is going through a week long rolling upgrade that will eventually
// upgrade the entire cluster.
//
// 1. User adds their twitter handle to their profile.
// 2. Version 2 of the service stores new User struct/class to document DB with the twitter handle.
// 3. User 4 days later decides to update their bio.
// 4. Version 1 of the service handles the request, modifies the User document.
//
// Because version 1 and 2 use class/struct serialization, #4 above lost the twitter handle. Gone.
//
// We took flexible document databases using an extensible data formats (XML/JSON) & ejected flexibility.
//
// This is what happens when we treat databases as extensions of our programming language.
// We lose the benefits of the data model the database provides because we tried to
// type everything to death.
//
// This is just one example of Stuct Store, not Document Database.
@jbogard
Copy link

jbogard commented Feb 8, 2013

What's the alternative look like?

@zerodivide1
Copy link

I'm curious to see what an alternative would look like for this example as well.

@jbogard
Copy link

jbogard commented Feb 8, 2013

There's also an assumption of behavior here - that missing members are dropped.

@Buildstarted
Copy link

@jbogard the example usage is fairly spot on with most document dbs. you need to explicitly state you want to update only the fields you're changing. Since we are populating an object based on strict serialization it will automatically drop fields that don't exist when you reserialize the object back to json/whatever.

@kellabyte
Copy link
Author

Lotus Notes, the document database (yes!) only persisted and synchronized modified deltas of documents. Today's document databases don't really have a concept of a document.

Today's document databases typically store or retrieve entire values from a key/value store.

@peteraritchie
Copy link

Honestly, to push that level of knowledge into the code that calls Get/Put is a responsibility violation. The code that uses a User object shouldn't have to care about anything it doesn't need to know about. See (SRP and Interface Segregation). The "database" class (or a Repository wrapping it) should deal with that responsibility--it can be smart enough to know that despite having a UserV1 object that there's a bunch of other data that UserV1 doesn't contain but is in the database and assume a "Put" is an upsert.

@kellabyte
Copy link
Author

@peteraritchie that's going to introduce some pretty complicated code (change tracking) to figure that out. A lot of complexity I would argue isn't required if we weren't trying to be so addicted to strict typing. A domain can be loosely typed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment