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

Getter composition #197

Open
apisurfer opened this issue Nov 30, 2015 · 4 comments
Open

Getter composition #197

apisurfer opened this issue Nov 30, 2015 · 4 comments

Comments

@apisurfer
Copy link

Hello all,

I'd like to ask if anyone has experimented with composing Getters and how it turned out? Also I would like to propose one possible approach that opened a bunch of new possibilities for me.

In my codebase I often have many entities that are related(up to 5 levels in depth) and to reduce everything to required values it usually takes few roundtrips through reactor.evaluate function using multiple KeyPaths or Getters. Even when using approach with functions that create Getters like it's described here. And this clutters the rest of the app logic with filtering functions etc.

Example problem: pull the currently selected organization from organizations list, use that organization's id to select all the websites under that organization and then use that website ids to filter just the administrator names under that websites. You can see that here you need to either make multiple evaluate calls or nest the Getters which can be really hard to comprehend.

For this I created a small lib that receives a list of KeyPath, Getters, functions and composes them in a way that every successive Getter and function receive result from previous computation and share the same context for more complex decision making. As a result you get one fat Getter that returns exactly the data you need.

Lib repo to check out: https://github.com/popc0rn/nuclear-transform, also available as "nuclear-transform" module through npm if you want to test it out.

Code example:

import { transform } from 'nuclear-transform';
const adminNamesGetter = transform([
    // 1st step
    [
      ['currentlySelectedOrganization'],
      ['organizations'],
      (selectedOrg, orgs) => {
        return orgs[selectedOrg];
      }
    ],
    // 2nd step
    [
      ['websites'],
      (organization, websites) => websites.filter(web => web.organizationId === organization.id)
    ],
    // 3rd step
    [
      ['users'],
      (websites, users) => users.filter(user => user.websiteId === websiteId && user.permission === 'administrator')
    ],
    // 4th step
    users => users.map(user => user.name)
]);
const administratorNames = reactor.evaluate(adminNamesGetter);

console.log(administratorNames);

What do you think about this approach? Anybody using something similar?

@jordangarcia
Copy link
Contributor

Ah that is really interesting!

We use a very similiar design philosophy of Getter composition but generally do it in a more manual way, where each of the above would be their own getters (either exposed or kept private to the getters.js file)

You're approach seems like nice sugar if you are composing a lot of getters that would end up as intermediate steps.

@apisurfer
Copy link
Author

Yeah my idea was to use this as intermediate step. There would be regular getters for different kinds of entities and this "transformation" would be used per view where I would need to combine that getters with custom filtering functions/Getters. It still needs some work on figuring out how to maximize the use of regular getters without changing them, if it's possible. Probably the approach might be to aggregate results from KeyPaths and Getters in the list and pass it as arguments only to the vanilla javascript functions that follow. Not to mess with passing arguments to Getter functions. I think that way much of the Getters could be reused.
Anyway, I just wanted to share this approach, as it might bring up some new and better ideas.
Feel free to close the issue when you want :)

@apisurfer
Copy link
Author

Just a quick update. Lib was changed in a way that you can use KeyPaths and Getters in a list with regular js functions in between them to reduce the values. This way normal Getters/KeyPaths can be reused and combined to form new values.

npm install nuclear-transform
https://github.com/popc0rn/nuclear-transform

If someone has more ideas on this feel free to reach me. I hope this will help someone else, also.
Cheers!

@mindjuice
Copy link

That's an interesting idea. So far I've just created multiple non-exported getters for the intermediate steps, then put the getter name in the dependencies list of the subsequent getter(s).

One benefit of your transform that I like is not having to create names for the intermediate steps. I've got getters named things like rawData, normalizedData, normalizedFilteredData, normalizedFilteredSortedData, etc. which is quite tedious.

The one benefit of doing it in separate steps is if the output of an intermediate step needs to be used by more than one subsequent getter, which in my project happens for a few of the higher level getters.

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

No branches or pull requests

3 participants