Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How about "versioned tree" option? #97

Open
nikolakanacki opened this issue Feb 8, 2016 · 5 comments
Open

How about "versioned tree" option? #97

nikolakanacki opened this issue Feb 8, 2016 · 5 comments
Labels

Comments

@nikolakanacki
Copy link

We basically have two options in the pool: "mutable" and "persistent", and there are tradeoffs in both of them. Since baobab already has a good grasp of the paths involved in any kind of "mutations" produced by invoking its public methods, I'm thinking this third option could cover the vast numbers of use cases for immutability while still keeping the CPU and memory consumption low.

For an example, a baobab tree with a structure like this:

state: {
  todos: {
    id_1: {...}
  },
  ui: {
    sort: "name"
  }
}

would become something like this:

state: { __v: 0,
  todos: { __v: 0,
    id_1: {...}
  },
  ui: { __v: 0,
    sort: "name"
  }
})

and executing the following operation:

state.set(["ui","sort"],"date")

would cause the tree to look like this:

state: { __v: 1,
  todos: { __v: 0,
    id_1: {...}
  },
  ui: { __v: 1,
    sort: "name"
  }
})

Affected paths would have their versions updated (incremented). This would keep the cpu and memory usage down for even the deepest structure updates, but would still make the pureRenderMixin-alike performance optimisation possible by doing currState.__v === nextState.__v.

Further more, __v property can be incremented every time it is touched, so you could reason about how many operations have acted on the path (e.g. in one operation cycle). A new version of the pureRenderMixin would not care about how much the version has incremented, only that is "different".

Version (__v) properties would (optionally) be stripped off when consuming data trough the serialize method.

I'm posting this here as a discussion point. I may be very wrong, but I have been looking trough the code, and I think this is actually doable.

@Yomguithereal
Copy link
Owner

Hello @nikolakanacki. This is probably more an issue for Baobab than for baobab-react itself. Let me check your idea. The first thing I notice is that it would be easy to implement through the update or write event with a mutable tree without needing to touch the core of the lib itself. Your use case is very specific and bring some problems with it that would wreck generic use cases because you are going to mutate objects given by the user and set some weirdly-named keys (you should probably make them non-enumerable for instance).

TL;DR: your idea can work and I can help you implement it if you want but I don't think it should get into the core of the library since it can be very easily implemented on top of it.

@nikolakanacki
Copy link
Author

Thank you for the fast response!

I was so busy writing the damn thing that I didn't even realise I was "barking up the wrong tree" apparently. Yes, this is definitely an issue/proposal for the baobab core. Should I move it (copy/paste) it there, or can you do something like a reference or smtn?

Quick response:

I think I didn't present my case precisely enough. The example I described is not meant to be specific to any project, but a general immutability alternative that is (much) more cpu and memory efficient, no matter the use case and the amount of data involved. Think of the "weirdly-named" keys (the same ones mongodb is using for document versioning) in the way baobab monkeys are implemented. They do sit in a tree, but are not serialised when the data is accessed trough .serialize() method. Of course, there can be other implementations, like a cursors/tree method. I do not see the way it can be implemented on top of it (without monkey-patching or some other weird stuff) but I am open to suggestions.

@Yomguithereal
Copy link
Owner

immutability alternative

It is an alternative, yes, but not an immutable nor persistent one. The only benefit you keep is the one from emulating referential equality.

Here is how you could implement your idea on top of it without monkeys or cursors:

tree.on('write', function(e) {
  var writtenPath = e.data.path;

  // Now you just retrieve the value at that path
  var target = tree.get(writtenPath);

  // And if it's an object, you edit/add your property
  // You should use defineProperty to make it non-enumerable
  if (typeof target !== 'object')
    return;

  Object.defineProperty(target, '__v', {
    configurable: false,
    enumerable: false,
    writable: true,
    value: target.__v ? target.__v + 1 : 0
  });
});

@dyatlov
Copy link

dyatlov commented Feb 16, 2016

@nikolakanacki see this: Yomguithereal/baobab#268
and this: https://github.com/Yomguithereal/baobab/blob/master/src/baobab.js#L396-L421

basically, what @Yomguithereal means is that checking if node is changed happens using references ( a === b ).
After every update reference is changed because a new object is being generated, see: https://github.com/Yomguithereal/baobab/blob/master/src/update.js#L299-L300
Version number would be just another way to compare them, so not worth it.

Version numbers could help with dirty checkings if objects were staying as is, i.e. baobab wouldn't make a new node after every update but instead would write changes to the original node, but in this case (in order to save some compatibility) there would be needed copying of current node data to _previousData object.. so it's anyway new object creation..

Hope I understood and described it all right.

@nikolakanacki
Copy link
Author

@dyatlov Yes you did, definitely.

Since writing this I read the source again, and yes, there are things already implemented that would make this difficult to implement in an "immutable" mode, while keeping the benefit.

Now, correct me if I'm wrong here, but since this isn't really an immutable mode (we're still mutating nodes, we just keep the books about it), a third option (1:immutable,2:mutable,3:version) could be implemented, right? I'll look into forking this and trying something out I get some free time. I really do think it would make a great addition > many people are using baobab for react.js and a "pure render mixin" style checking would be a breeze.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants