TODO
- Add full annotated example; manufacture sample data to use
- Add "Switch", "FirstOf", see TODOs
- Review the README, is it presented clearly and attractively, is the value clear?
- Make configurable: loggerWarn, the used subset of lodash, ... ?
Declarative Data Combiner
Add new properties to a tree data structure from a number of other data structures in a declarative manner.
The "business case" for the declarative data combiner
The combiner was created for a "frontend backend," a server-side application that fetches product, price, services, content, etc. JSON data from various sources and transforms them and combines them together to provide a single view of the data, optimized for the needs of the client-side frontend application.
Why?
It is easy - especially with functional programming - to massage and combine data into the form you want to have it. However, it is very difficult to know what data goes into and out of the transformation. The declarative data combiner makes at least part of it - the outgoing data, and where they come from - explicit, abstracting away the transformation process itself and focusing rather on the data and desired effect.
The idea is that you declare the shape of the input and output data and how the extra data are joined and added onto it.
Ideally, we would like to declare how the data we have should be joined and extended with the additional data:
// (Given a productCatalog, a map of products with color variants, add extra data to them:const productCatalogCombined = <JOIN: productWebshopOverrides = webshopOverridesproductId> <productId>: specifications: "productWebshopOverrides.specifications" colorVariants: <JOIN: variantWebshopOverrides = productWebshopOverridesvariantId> <variantId>: images: "variantWebshopOverrides.images" description: "variantWebshopOverrides.description" ;
JavaScript doesn't allow us to do exactly this, so we need to be somewhat more verbose:
const productCatalogDef = ;productCatalogCombined = combiner;
Introduction
Example
Assuming that you have this data:
const productCatalog = "ax-123-c": brand: "Apple" model: "iPhone 7 256 GB" specifications: colorVariants: "12345": color: "Metal Black" htmlColor: "black" images: price: 9599 description: "..." ;
and some other data that you want to combine with it:
const webshopOverrides = "ax-123-c": specifications: /* more reader-friendly specification descriptions for web shop ...*/ colorVariants: "12345": description: "A much better description for <blink>web</blink>" images: "superAwesomeBlackIphone.png" ;const pricePlans = "12345": "I_LOVE_DATA": data: "20 GB" voice: "unlimited" // ... ;
and you would like to end up with
const productCatalog = "ax-123-c": brand: "Apple" model: "iPhone 7 256 GB" specifications: /* more reader-friendly specification descriptions for web shop ...*/ colorVariants: "12345": color: "Metal Black" htmlColor: "black" images: "superAwesomeBlackIphone.png" price: 9599 description: "A much better description for <blink>web</blink>" pricePlans: "I_LOVE_DATA": data: "20 GB" voice: "unlimited" // ... ;
You could manually do that:
_;
but as the data becomes deeper and bigger and there are more and more complex other data sources, it quickly becomes difficult to follow. With the declarative data combiner, you can instead do the following, which is much easier to follow, once you learn the Domain Specific Language (DSL):
const productCatalogDef = ;productCatalog = combiner;
This is considerably longer than the manual transformation above. And I wouldn't use it for such a simple transformation. But as the data increases in complexity, the declarative approach starts to win in comprehensibility and in size (at least in our case it did). Imagine being inside 5th nested function call transforming a part of the data and trying to remember what the data looks like and where are you. Here you just look up the tree.
Pros & Cons
Cons:
- performance
- initial learning curve
Pros:
- clearly communicates the output data and where it comes from
- separates "what" data we want and "how" it is processed; we can improve the "how" independently - provide an audit trail of the processing, add optimizations, ...
History
The declarative data combiner has been used in Telia Norge since 2014.
Other concerns
Flexibility
TODO (declarative x functions)
Performance
TODO
User documentation and API reference
See
- API Guide
- TODO A complete, annotated example of a combination definition
- JSDoc of the DSL classes and
combine
- The unit tests
Also see CHANGELOG.md
API Introduction
- Dictionary, List, Template
- Joins, bindings
- extra: filter, ...
- flexibility: where can we use functions
- troubleshooting: audit, debug, functions calling console.log