Aspect Oriented Programming with using WinJS

JavaScript metadata descriptors

Metadata programming is very handful in many scenarios, e.g. in Aspect Oriented Programming (AOP). Typical scenarios are

  • tracing
  • value change notifications
  • security checks
  • etc.

Basically all scenarios where it’s necessary to write boilerplate code over methods or properties. The problem is that this boilerplate code is mixed with the business logic and it decreases the readability of the code. It can be solved by applying AOP. AOP leverages can leverage the metadata defined around method and properties. Let’s look how it could be applied in context of Javascrip and WinJS library.

ECMA script 5 support metadata in form of descriptors. Basically, method Object.getOwnPropertyDescriptor(object, property_name) returns the descriptor object, aka metadata of the property or method. It’s very similar to System.Reflection known form .NET.

 

Object.defineProperty(instance, "foo", {
    firstName: {
        value: "bar",
        configurable: true,
        enumerable: true,
    }
});

Object.defineProperty(instance, "foo", {
    firstName: {
        get: function () { return this._foo; }, set: function (value) { this._foo = value; },
        configurable: true,
        enumerable: true,
    }
});

As you can see, there are 2 possible descriptor definitions:

  1. value descriptors
  2. get/set descriptors

The difference is that the first has property “value” which refers to the function (in case of method) or value (in case of property). The latter has “get” and/or “set” properties referring to the property get/set methods. The rest are same:

  • enumerable
  • writable

That’s all what can be defined on JavaScript descriptors and that’s the standard property definition via Object.defineProperty mechanism.

It would be nice to use property descriptors for AOP or other advanced scenarios, as shown in the following code: 

            var instance = function() { };

            Object.defineProperty(instance, "name", {
                firstName: {
                    value: "frantisek",
                    configurable: true,
                    enumerable: true,
                    observable: true // custom metadata
                }
            });

            var descriptor = Object.getOwnPropertyDescriptor(instance, "name");
            WinJS.log("Metadata for name: n" + JSON.stringify(descriptor));

 

Unfortunately, JavaScript implementation of descriptors is not extensible.  So that Object.getOwnPropertyDescriptor() drops all non-ECMA5 descriptor properties. 

 

The above code returns ECMA5 property descriptor, skipping our custom observable metadata information.

"Metadata for name: n{"writable":false,"enumerable":false,"configurable":false}"

 

WinJS and metadata

But we can overcome this issue with WinJS. Anyway, on WWA platform, we use WinJS to define classes which under the hood calls Object.defineProperty(). We could replace-via-extend WinJS.Class.define or just define new helper method for defining the class with the possibilities to use pre/post processing.

The whole idea is that we can do any pre/post processing when defining the class via WinJS, we could hook into the process of class definition and do the custom steps. I already used it in my previous post, but lets see it on the sample example.

Let’s say we want to define a class and we want to add tracing over the selected properties.

            var Klass = defineClass(function() {
            }, {
                firstName: {
                    value: "frantisek",
                    trace: true,
                    writable: true,
                    enumerable: true
                }
            });

            instance = new Klass();
            instance.firstName = "fero";

 

The goal is to get the tracing automatically available over firstName property. 

 

Step #1: custom class define function

            var aopFilters = [];
            function defineClass(ctor, instanceMembers, staticMembers) {
                var base;
                aopFilters.forEach(function (aopFilter) {
                    base = aopFilter(instanceMembers, base); // apply filter
                });

                return WinJS.Class.derive(base, function () {
                    base.call(this);
                    ctor.apply(this, arguments);
                }, instanceMembers, staticMembers);
            }

The above code defines a list of AOP filters so that we can add there our AOP filters, in this example it’ll be the tracing filter. When defining the class, all AOP filters will be applied and then the final class will be defined. 

Step #2: tracing filter

            function traceFilter(instanceMembers, baseClass) {
                expandTraceProperties(instanceMembers);
                return baseClass;
            }

            function expandTraceProperties(shape) {
                var props = {};
                Object.getOwnPropertyNames(shape).forEach(function (name) {
                    var descr = shape[name];
                if (descr.trace) {
                        var defaultValue = shape[name].value;
                        var field = "_" + name;
                        shape[name] = {
                            get: function() {
                               WinJS.log("getting " + name);

                                if (Object.hasOwnProperty(this, field)) {
                                    return this[field];
                                } else {
                                    return defaultValue;
                                }
                            },
                            set: function(value) {
                                this[field] = value;
                                WinJS.log("setting " + name + " to " + value);
                            }
                        };
                    }
                });
                return props;
            };

 

The code above defines the tracing filter which uses WinJS.logging capabilities. The above code is just a demo code. It’s not production ready code. Generally, AOP filter is a function which gets instance members and a reference to the base class. In general, it could be used in the scenarios where AOP filter requires a specific base class. In our case we don’t need it, so we return what we get passed. 

The main logic is in the expandTraceProperties method. This metod filters only trace-able properties and replaces their value with custom get/set method. 

 

Step #3: final example

 Let’s use it and run the example again:  

var Klass = defineClass(function() {
            }, {
                firstName: {
                    value: "frantisek",
                    trace: true,
                    writable: true,
                    enumerable: true
                }
            });

            instance = new Klass();
            instance.firstName = "fero"; // outputs setting firstName to fero

 

The above described approach gives the developer possibility to mark-up (attribute) the properties with the metadata and let AOP filter to be applied. 

 

What do you think about this approach? Any other ideas how to overcome that metadata constraint?

Metadata.zip

WinJS observables (Part IV) – final solution

In my previous blog posts I showed possible solutions to WinJS observables pitfalls. Let’s combine both into the one, final solution.

 

Goal

Just repeat again what’s our goal in BDD style:

AS a developer

I WANT to be able to define observable properties on the class as well as other class parts: get/set properties and methods and I don’t want to pay any unnecessary performance penalties

SO THAT the observable object will be able to notify listeners that the property has changed

 

Solution

The previous both solutions were not perfect solution. Manual approach was flexible very much but manual, latter solution doesn’t handle methods nor get/set properties correctly. Let’s combine them to solve both issues:

  1. it will use WinJS as much as possible
  2. handle class methods correctly
The idea is that:
  1. we mark the properties which we need to be observable and 
  2. mix observable capabilities into class
The desired result is:
 
var Person = observableClass(function () {
}, {
    name: observableProperty("Frantisek Kaduk"),
    _year: 1234,
    year: { get: function () { return this._year; } },
    getName: function () { return this.name; }
});
 
 
 
Let’s start with marking the property as observable:

function observableProperty(defaultValue) {
    return {
        value: defaultValue,
       observable: true,
        writable: true,
        enumerable: true
    };
}
 
 
 
The solution uses Javascript posibilities to define the property metadata. It’s similar to .NET attributes. The method creates the property definition with the custom attribute ‘observable’  which will be used later.
 
 
 Let’s look at the class definition helper method:

function observableClass(ctor, instanceMembers, staticMembers) {
    var properties = extractObservableProperties(instanceMembers);

    var baseClass = WinJS.Binding.define(properties);
    return WinJS.Class.derive(baseClass, function () {
        baseClass.call(this);
        ctor.apply(this, arguments);
    }, instanceMembers, staticMembers);
}

The method uses WinJs.Binding on the filtered “observable”-only properties. 

 
function extractObservableProperties(shape) {
    var props = {};
    Object.getOwnPropertyNames(shape).forEach(function (k) {
        var descr = shape[k];
      if (descr.observable) {
            delete shape[k];
            props[k] = descr.value;
        }
    });
    return props;
};

After running the sample (attached to the blog) the output is as expected:

 
person: name has changed to Frantisek Kaduk
name is: Fero Kaduk
year is: 1234
person: name has changed to Fero Kaduk
 
That’s all.
 
The next step is to add support for deriving the classes. 

Observables.zip

WinJS observables (Part III) – using WinJS.Binding.define

In my previous blog post I showed first possible solution to WinJS observables pitfalls. Let’s see another.

 

Goal

Just repeat again what’s our goal in BDD style:

AS a developer

I WANT to be able to define observable properties on the class as well as other class parts: get/set properties and methods and I don’t want to pay any unnecessary performance penalties

SO THAT the observable object will be able to notify listeners that the property has changed

 

Solution

The previous solution has the problem that we had raise property change manually. In this blog post we try to use more WinJS.

In order to make the class observable we mix into class all required mixins (already done in previous post) but now, let’s do it in the different way. Let’s define a helper method:

function observableClass(ctor, instanceMembers, staticMembers) {
    var baseClass = WinJS.Binding.define(instanceMembers);

    return WinJS.Class.derive(baseClass, function () {
        baseClass.call(this);
        ctor.apply(this, arguments);
    }, null, staticMembers);
}

This will define observable class and wraps all instance properties to be observable.

 

The class definition looks like:

var Person = observableClass(function () {
}, {
    name: "Frantisek Kaduk",
    _year: 1234,
    year: {
        get: function () {
            return this._year;
        }
    },
    getName: function () {
        return this.name;
    }
});

 

 And its usage would be:

var person = new Person();
person.bind("name", function (v) {
    WinJS.log("name has changed to " + v, "person");
});
person.name = "Fero Kaduk";

WinJS.log("name is: " + person.getName());
WinJS.log("year is: " + person.year);

 

The above class definition uses more WinJS funcitonality but has again following issues:

  • all instance members are wrapped with observable functionality (including methods)
  • get/set methods doesn’t work!
Running the above code generates the following output:
 
person: name has changed to Frantisek Kaduk
name is: Fero Kaduk
year is: [object Object]
person: name has changed to Fero Kaduk

 

Summary

As we can see, getting the year doesn’t work at all!

 

So let’s see the final solution in the next post. 

 

Observables.zip

WinJS observables (Part II) – manual approach

In my previous blog post I mentioned WinJS observables and their usage and pitfalls. There are several alternative implementations which could help us to overcome that issues. Let’s see first of them.

 

Goal 

Just repeat what’s our goal in BDD style:

AS a developer

I WANT to be able to define observable properties on the class as well as other class parts: get/set properties and methods and I don’t want to pay any unnecessary performance penalties

SO THAT the observable object will be able to notify listeners that the property has changed

 

Solution 

In this blog post we’ll look at the manual approach. We need to do two things:

  1. ensure that the class has all required methods and fields needed for being observable
  2. wrapping the property with the observable functionality There are mixins which define the required methods and fields.

 

 So the first requirement can be solved by defining a base class with all mixins 

var ObservableBase = WinJS.Class.mix(function () { 
}, WinJS.Utilities.eventMixin, WinJS.Binding.mixin);

 

 The second requirement can be solved by defining the helper method:

function observableProperty(name, defValue) {
    var backingName = "_" + name;
    return {
        get: function getter() {
            if (!(backingName in this)) {
                return defValue;
            }

            var currentValue = this[backingName];
            return currentValue;
        },
        set: function setter(newValue) {
            var oldValue = this[backingName];
            if (oldValue !== newValue) {
                this[backingName] = newValue;
                this.notify(name, newValue, oldValue);
            }
        }
    };
}

 

So let’s put the things together:

            var Person = WinJS.Class.derive(ObservableBase, function () {
            }, {
                name: observableProperty("name", "Frantisek Kaduk"),
                _year: 1234
            });

 

Deriving from ObservableBase class ensures that new class has all mixins imported and observableProperty helper function creates property definition with get/set wrapper methods. The most important is the “set” method. This method makes sure that when the value has changed all listeners are notified (calling method notify).

 

Let’s use it:

            var person = new Person();
            person.bind("name", function (v) {
                WinJS.log("name has changed to " + v, "person");
            });
            person.name = "Fero Kaduk";

 

Running the above code generates the following output:

person: name has changed to Frantisek Kaduk            <= initial value
person: name has changed to Fero Kaduk

 

The complete sample is attached to the blog post.

 

Summary

The manual solution has the following disadvantages.

  • It forces the developer to derive from ObservableBase class. 
  • observable property is handled manually

 

So let’s see another solution in the next post.

Observables.zip

WinJS observables (Part I)

Introduction

First, lets make sure we understand what are observables.

The object is observable when it’s able to notify all listeners when its property has changed.

 In addition, this capabilities are applied only to the set of the properties and all that notifications are done automatically.

 

Implementation

Automatic property change notifications are crucial part in MVVM architecture (MVVM stands for Model View ViewModel) . WinJS team (author of WinJS library) prepared a built-in support for it. I think, they should be called notifications (in .NET it’s based on interface INotifyPropertyChange) rather than observables (as WinJS proposes) because the story is about notifying the listeners that the property has changed. But let’s stay with the original name “observables”.

 

WinJS observable related methods are defined on WinJS.Binding namespace. There are two levels of defining observables:

  • object level: it’s done by calling the method WinJS.Binding.as(object_to_be_made_observable). It takes any object and returns new instance with same set of the properties as the original object but making all properties auto-observable.
  • prototype level: it’s done by calling a method WinJS.Binding.define(class_to_be_observable). It takes a class definition and turns its properties into the observable properties

 

Pitfalls

WinJS.Binding was implemented ONLY for plain data JS objects and classes. It has the following limitations/disadvantages when it’s used in the traditional JS Prototype Oriented Programming:

  1. only value properties are supported (no get/set properties) 
  2. observable notifications are applied over ALL class members including methods! which is performance bottleneck and useless. This unfortunately causes another issue: calling the private field (its name starts with ‘_’) from the observable method throws exception that the private field is not found. Only private fields defined via WinJS.Class.define() are omitted from making observable.
  3. there is no way how to specify that only an explicit set of members (fields, properties) should be observable

 

The developers has to be very careful with using observable objects.

 

Recapitulation

  • WinJS.Binding.as() works on object level and only for plain JavaScript Data Transfer Object (DTO)
  • WinJS.Binding.define() works on class level but works only for DTO classes

 

 

 Observables in the action

There are 3 samples showing observables.

 

Let’s see the video showing their capabilities and later more details.

[View:http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-59-20/3603.oservables.wmv%5D

The demonstrated project is attached to this article.

Samples

Sample #1 – direct usage of plain DTO objects

When pure DTO object is bound directly to the view and DTO object changes its state, there are no updates propagated to the view. So there is no observation at all. 

Sample #2 – using observable DTO objects

Pure DTO objects transformed by calling WinJS.Binding.as(dto) are called observable DTO objects. When a property changes its value, all listeners (objects subscribed to this ‘event’) are notified. It’s basic publish/subscribe scenario.

Sample #3 – using observable DTO objects

Same as previous sample but defined on the prototype level. That’s the best option of all three samples in this article. The difference is that a reader of the code immediately can see that the class exposes observable functionality and all references to the created objects are observable. 

Usage

The most common usage of observable DTO objects is binding them to View. When observable DTO object is bound to the view and the observable DTO object changes its state (properties), all its property changes are propagated to the view. This enables great separation of concerns and fits well in MVVM architectural style. But more on this in other posts.

 

How does this observable magic work in detail

Binding the object to the view or calling WinJS.Binding.as(dto) extends DTO with the following observable capabilities:

  • _getObservable() – returns the observable proxy instance, one instance per DTO object.
  • _backingData – refers the original DTO object
  • _listeners – comes from dynamic observable mixin , maps property names to the listeners
  • notify(property, newValue, oldValue) – comes from dynamic observable mixin , calls all listeners when the property has changed

 

The trick behind the scene is that binding related WinJS functioanlity calls _getObservable which returns new instance of ObservableProxy. This proxy object copies all properties (including methods) from original DTO object on proxy object and defines them with setter and getters. The setter method contains a check of difference between old and new values. If the new value differs from the old value, all listeners are notified. I explicitly write, all listeners are notified as it doesn’t use events at all.

When a property changes its value, the logic in the notify method iterates over all listeners subscribed to that property and calls them with 2 arguments: new and old value. The notifications are done asynchronously, via setImmediate() call!

 

 Unfortunately, that’s not enough for real M-V-VM scenarios.

 

Limitations:

  • Only value properties are supported, unfortunately, no support for get/set properties is available
  • It’s not possible to define only subset of the properties to be observable
  • PropertyChange notifications are raised via “setImmediate”, not directly synchronously and sometimes it’s helpful

 

 All these limitations can be solved but more on this in the next part.

Observables.zip