Virtual Instances in JavaScript with Proxy API – JSDataViews

Today I discovered an interesting new way of declaring variables. I used a technique to mimic a principle which is called “Views” and which is well known in the database world.

DB Views !== UI Views

On the PostgreSQL website Views are described as follows:

The view is not physically materialized. Instead, the query is run every time the view is referenced in a query.

The principle can be simply visualized using a set of data entries where each “View” builds a subset of these entries (colored boxes) when executed:

db views

Enter JS

Instead of declaring the final variable/dataset for the View we will create a function that behaves like a View object. I’ll call this a Virtual Instance since the data for this View is not existent before it is accessed. Instead, the function is evaluated and brings data into the  variable at runtime.

virtual instance

In JavaScript this principle can be emulated using the Proxy API introduced in ECMAScript 6 as follows:

Now it is time for the important piece of code that drives the Virtual Instance:

What’s interesting?

In my opinion there are at least 3 interesting things about this technique:

1. Pseudo Declarative Programming

Instead of defining what the data is (at the moment of initialization) we  only specify which tests the data has to pass.
Thereby we explicitly determine that the value of employeesOver30s is not fixed but driven by our root dataset.

2. Inversion of (Inversion of control)

In order to achieve the same behavior one would normally register such Data Views on the root dataset.
Whenever this dataset changes it would update all its Views in a Hollywood fashioned manner „don’t call us, we’ll call you“.

By inversing this communication, the instance is only updated when it is used. In terms of Hollywood this would correspond to a Stubborn Starlet calling her agents whenever she needs a job 😉

3. Syntax

The way one can operate on these Virtual Instances is really straightforward. Most of the code can be reused so that for every additional VI one only has to write the declaration function.

Pros and Cons

The above code may be a pattern, anti-pattern or like new wine in an old bottle, either way there are some serious downsides but also good benefits.

Why should I NOT USE this technique?

  • The Proxy handler or (in other terms) the Virtual Logic is fragile:

    Programmers have to deal with exceptions such as the “don’t override length” rule.

  • The code is hard to debug:

    console.log(employeesOver30) in the code causes ~7 get/function calls and may lead to strange results
    console.log(target) causes endless recursion

  • Virtual Instances are lazy

    Instead of being proactive and publishing change events to the outside world, virtual instances have only a defined state at the moment we access them. For this reason they can hardly be observed.

  • Syntax

    The syntax of JavaScript is modified in a not-standard-conform way

Why should I USE this technique?

  • Reduce complexity of data structures

    I think this technique can be especially powerful when used in rich clients which handle a lot of complex data. Some days ago I ran into a problem where I had to implement a complex data structure and had to implement a lot of conditions like isDescendant, isParent, isSibbling, hasSibblings etc. With views this work would have been a lot easier.

  • Performance

    At the same time the performance was really tricky since all operations on the main datastructure triggered changes in subsets of the data which trigered changes on other subsets and so on. With this technique I think there is a chance that the performance can be highly optimized for large datasets.

  • Reduce complexity of code

    Last but not least the code complexity literally exploded at some point. With this kind of views a lot of reoccuring tasks can be encapsulated. Virtual Instances are more than “DB Views” – they are bidirectional. This means they reflect data in the root dataset but can also affect and change this data which might be a realy nice feature.

Is there a Lib?

Yes, I packed the code into a small “lib” which can be found on GitHub
With this lib the above code can be expressed with these 3 LoC:

That’s it!

Please let me know if you know other projects using similar techniques, or if you know scenarios in which this approach would be dangerous or handy.

Have Fun!

Optimizations:
Use flags on original dataset to see if it changed and only execute view if it has changed.

Notes:
The API is not available in all browsers at the moment so there is a need for polyfills.

Leave a Reply

Your email address will not be published.

Time limit is exhausted. Please reload the CAPTCHA.