foxdonut/meiosis

Alternative method for nesting approach

sassanh opened this issue ยท 8 comments

Lets assume we have an encapsulated part of software that we're willing to store all if its storage in one central place, lets call it a module. Consider that this module is made of instances of some components. Each component in meiosis is a function that returns a model and a view. In meiosis you're suggesting storing these models in a hierarchical dict. It's good approach and Redux has something similar too: https://redux.js.org/api/combinereducers.

But in my experience with Redux in a super huge web-application with more than 200 view components, more than 40 tables in server's db some having more than 200k rows served by a rest api I found that it'd be much easier if instead of this hierarchical dict my store was just a single level dicts with unique ids as keys and instance storage data as values. These keys can be uuids or in "model:id" format or even in "model:view:id" format, values can be js objects (or immutable objects), single level here doesn't mean values should be flat numbers or strings, it just means each component is in first level of hierarchy in the store dict. For example in my web-application a view component in this path in the store dict: x->y->z->a->b->c would want to have access to this path and use some data from there X->Y->Z->A->B->C. After the app grew I found it much easier if my store was stored the way I described. If c in example above needs data from C then it should have its whole path in hierarchical dict in hierarchical model but in single level dict model it only needs to know the uuid or if it's stored in "model:id" format it only needs to know the id of the instance.

There are some challenges in this storage model such as what if user is modifying an instance stored in "model:1" but when the edit shouldn't apply to whole web app nor it should be synced with server until he presses some "save" button. (not syncing with server is not the challenge but not syncing with whole web app is a challenge.) It can be solved by following a pattern to store editions in a temporary store and sync it with global storage only when user saves the editions, views should read data from the temporary store dedicated for their edits unless it's not present. I can't remember any other challenges write now but I'm sure there were more and I'm sure the solution to these challenges were straight forward.

This model is similar to how you would store your data in your server using a db server. Most of the reasons that database servers don't save data in a big dict and rather store it in tables and give you an api to access your data in "model:id" format (SELECT * FROM "model"_talbe WHERE id="id") and it's obvious to us that this model of saving data is best approach applies here too.

What do you think about it?

Hi @sassanh

I demonstrated how you could nest using multiple levels, but there is nothing stopping you from deciding to nest at a single level only (or even not nesting at all). Would nesting at a single level correspond to the approach that you are suggesting?

Thank you for sharing your experience!

I know there is nothing stopping me from implementing it another way in my project, thanks for confirming it ๐Ÿ˜„ I wrote it here to suggest changing the nesting approach in Meiosis pattern. I think storing data in a nested dict will make things hard when the app grows and components need to share data and it can get improved by keeping all data in first level of the dict. For example if component A needs to read some data from Component B, in nested dict the address it requires to read the data is something like ['X','Y','Z',..., 'A'] and it should iterate over this array and lookup the key in each level to reach the data. but if the address is simply 'Model:5' or some uuid, it's simpler and it can fetch the data it requires in a single dict lookup. I think it reduces complexity.

@sassanh I like your idea of flattening the model to a single level. I will work on refactoring the random-gif example to use this approach -- I will let you know when it is ready and will look forward to your thoughts. Thank you for the feedback!

Cool, if you don't have the time I can prepare a draft and we can discuss it together. I mean I didn't mean to bother you, just wanted discuss the idea here and know your opinion about applying it in meiosis. But if you're willing to do it yourself I guess it's best because you know the details of your pattern much better than me. Thank you for your great welcoming repository :-)

@sassanh I refactored the random-gif example to use a single-level model. I also incorporated a couple of other concepts I've been working on -- onUpdate and state -- and I also switched to tachyons for now, reducing the memory usage.

View functions are now (model, id) => view, so every view gets the whole model, but also the id so that it can look up its own model.

So far I like the result, it is simpler without nesting and also has other benefits that come simply: having access to the whole model means it's easy to read other parts of the data, as needed. Updates can also affect other parts of the model if so desired.

The code is in the improve-random-gif branch, if you have a chance to have a look, I'd love to hear what you think. EDIT: the code is now merged to master.

Thanks!

Thanks man, I loved it, long ago I tried to convince Redux guys to have the instantiation as a first class citizen in their pattern: reduxjs/redux#1850 but I failed to convince them.

Now I love it how Meiosis implements the concept of instantiating a component. by providing an id to create... functions. So far everything looks perfect to me. I have a new project that's going to need some store soon, I didn't want to use Redux or MobX and googled alternatives and found Meiosis, I'll use it in my project and if I found any issues or anything that can get improved I'll discuss it here with you.

Maybe over time we can add a section to tutorial for using Meiosis with flat dicts or maybe we can update the existing parts with this idea if you think the same.

@sassanh Thank you! I am liking this approach as well. I definitely want to add a section to the docs about this. I hope your project works out well, let me know how it goes!

Using an id is now in the tutorial.