Saturday, April 12, 2014

AngularJs: Splat Logging - A Simple $log Factory

Logging and debugging can be a pain

Background

Sometimes we must log/debug javascript. Kind of frequently, in fact, must the javascript things be logged/debugged. I work a lot in Chrome, which has this super neat object logger that folds objects and properties and collapses arrays and stuff.

In writing complex javascript, I find that I have to annotate what functions are running and under which conditions certain things are being called, which leads to a lot of code like:

console.log('I am about to log myObject: ');
console.log(myObject);
console.log('the myArray thingy: ');
console.log(myArray);
//or with AngularJs $log-->
$log.log('I am about to log myObject: ');
$log.log(myObject);
$log.log('the myArray thingy: ');
$log.log(myArray)

Splat Logging

Wouldn't it be super cool to be able to flip logging off and on easily?
Wouldn't it be super cool to just *splat* logging?

I thought so, so I wrote the following:

//the factory in this module allows you to splat angular's $log provider
//<jwLog>.log('so', { now : 'you' }, 'can' + 'log like', ['a','maniac']);
angular.module('jwLogModule',['ng'])
    .factory('jwLog', ['$log', function ($log) {
        var noOpLogger = function () {
            var n = angular.noop;
            this.info = n;
            this.debug = n;
            this.error = n;
            this.log = n;
            this.warn = n;
        };

        var debugLogger = function () {
            function logIt() {
                var args = [].slice.call(arguments);
                for (var i = 0; i < args[1].length; i++) {
                    $log[args[0]](args[1][i]);
                }
            }

            this.info = function () {
                logIt('info', arguments);
            };
            this.debug = function () {
                logIt('debug', arguments);
            };
            this.error = function () {
                logIt('error', arguments);
            };
            this.log = function () {
                logIt('log', arguments);
            };
            this.warn = function () {
                logIt('warn', arguments);
            };
        };

        var logger = function () {
            var args = [].slice.call(arguments)[0] || { debug: true };
            return (args.debug) ? new debugLogger() : new noOpLogger();            
        };

        return logger;
    }])

Here's a plunk: (view your browser console)

And this is what my browser console looks like:

Thursday, April 10, 2014

AngularJs + SignalR

Using SignalR in an AngularJs application...

Background

I recently had a situation at work where asynchronous functionality behind a web api necessitated bi-directional functionality between my angular client application and the web api. In a typical RESTful AngularJs application, I would create a service, using the $resource factory to set up some touch points. The problem with that approach in this scenario was - the server might respond n number of times, with n number of results.

***dilemma?***

Not exactly. I decided to use SignalR. It's there. It works. Decision indecision is time lost that could be spent working on something.

What is SignalR?

SignalR is an asp.net library that allows bi-directional operations between client applications and servers/hubs. (More info here)

SignalR is useful in situations like mine, when a server needs to send real time data to connected clients. Other examples of use cases, for instance, might include alerting connected client applications that someone has joined an IRC, or a stock price has changed, or perhaps a new message from a friend has been sent, etc. In addition to bi-directional communication in web applications, SignalR also has .net client libraries for windows and Xamarin.

This article, however, is about wiring up an AngularJs client application. So, on to angular...

What is AngularJs?

AngularJs is a superheroic js framework that truly makes developing web applications a very tenable process, if not a more manageable one. (More info here)

Angular's homepage sums it up best in their Why AngularJS? paragraph:

HTML is great for declaring static documents, but it falters when we try to use it for declaring dynamic views in web-applications. AngularJS lets you extend HTML vocabulary for your application. The resulting environment is extraordinarily expressive, readable, and quick to develop.

Enough of the formalities. On to the goodness...

Setting up the Hub

I am going to assume that you have read this article (or another like it) and have some familiarity setting up SignalR in your application.

Here is my hub to start:

public class GoodnessHub : Hub
{
    public void SayHello()
    {
        Clients.All.sayHello("Ooey, shuga!");
    }
}

Setting up the Html

Here is my html to start:

<!DOCTYPE html>
<html>
   <head>
       <meta charset="utf-8" />
       <meta name="viewport" content="width=device-width" />
       <title>SignalR Demo</title>

       <script src="~/Scripts/jquery-1.8.2.js"></script>
       <script src="~/Scripts/angular.js"></script>
    
       <script src="~/Scripts/jquery.signalR-2.0.3.js"></script>
       <script src="~/signalr/hubs"></script>
    
       <script src="~/app/signalrDemo.js"></script>
   </head>
   <body ng-app="signalrDemo">
       <div ng-controller="myClientGoodness as goody">
           <span ng-bind="goody.hello"></span>
       </div>
   </body>
</html>

Setting up the AngularJs App

Here is my js to start:

var app = angular.module('signalrDemo', []);
app.controller('myClientGoodness', ['$scope', function ($scope) {
        var goody = this;
        this.hello = 'hi world';
    }
]);

When we visit the page, we should see: hi world

Fantastic! Now that we know our angular app is working, let's wire up a call to the hub.
First, add a button to the html with an ng-click that calls goody.getHubHello(), like this:

<!DOCTYPE html>
<html>
   <head>
       <!--omitted for brevity-->
   </head>
   <body ng-app="signalrDemo">
       <div ng-controller="myClientGoodness as goody">
           <span ng-bind="goody.hello"></span>
           <button ng-click="goody.getHubHello()">Get Hub Hello</button>
       </div>
   </body>
</html>

Don't forget to add the getHubHello() function to your controller:

var app = angular.module('signalrDemo', []);

app.controller('myClientGoodness', ['$scope','$window', function ($scope, $window) {
        var goody = this;
        this.hello = 'hi world';

        this.getHubHello = function () {

           //instance a hub connection-->
           var hub = $window.jQuery.hubConnection();

           //instance a proxy from hub connection-->
           var proxy = hub.createHubProxy('GoodnessHub');

           //set callback on proxy-->
           //function invoked when server calls the client-->
           proxy.on('sayHello', function (hello) {
               goody.hello = hello;
           });

           //start hub with success/fail hooks-->
           hub.start(function () { /*hub started*/ })
            .done(function () {
                proxy
                  .invoke('sayHello')
                  .done(function () { /* proxy invoke done/successful */ })
                  .fail(function (failure) { /* proxy invoke failure */ });
            })
            .fail(function (failure) { /* hub start failure */ });
       };
    }
]);

There you go. That's it, right? Now when you click the AngularJs client starts the hub connection and calls the server method. The server method, in turn, then calls the AngularJs client via the proxy function we've configured, which will set goody.hello to whatever the server gives it.

At this point, if you've run the example, you may be wondering why the view didn't update with the server value. The answer is: because we subverted our angular application with our signalR $window.jQuery.hubConnection() stuff, our angular application doesn't know anything happened to goody.hello. AngularJs !== magic.

Angular applications work via watchers that keep track of things. When something happens that warrants a digest, angular queues up a digest, which will evaluate all watchers. Watchers are the things behind the scenes that angular is using to keep tabs on what it should update and how it should update it.

There are valid use cases when you must subvert your angular application to get things to work. If you're new to angular, you are likely seeing many more of these kinds of cases than you should. AngularJs has a mechanism built into it for these kinds of circumstances; the $apply() function. The $apply() function basically rolls behavior back into angular's digest. $digest() is also an AngularJs function, and it works very similarly to $apply(); however, $digest() is better avoided. In our case, $apply() is more appropriate anyhow. So let's add it to the getHubHello() function and get our view/model updating properly.

var app = angular.module('signalrDemo', []);
app.controller('myClientGoodness', ['$scope','$window', function ($scope, $window) {
        var goody = this;
        this.hello = 'hi world';
        this.getHubHello = function () {

           //instance a hub connection-->
           var hub = $window.jQuery.hubConnection();

           //instance a proxy from hub connection-->
           var proxy = hub.createHubProxy('GoodnessHub');

           //set callback on proxy-->
           //function invoked when server calls the client-->
           proxy.on('sayHello', function (hello) {
               $scope.$apply(function () { //<--APPLY!
                   goody.hello = hello;
               });
           });

           //start hub with success/fail hooks-->
           hub.start(function () { /*hub started*/ })
            .done(function () {
                proxy
                  .invoke('sayHello')
                  .done(function () { /* proxy invoke done/successful */ })
                  .fail(function (failure) { /* proxy invoke failure */ });
            })
            .fail(function (failure) { /* hub start failure */ });
       };
    }
]);

BOOM! Now we're cooking with fire! Now the model is updating when it hits the server... great... While our sayHello function seems pretty synchronous, it's not synchronous. If the server were to respond n more times with different things, our app would still work correctly to display that info. Check it out...

Hop back into your server hub and make it look like this:

   public class GoodnessHub : Hub
   {
        private static readonly string[] Goodnesses =
        {
            "buttery", "chocolatey", "salty", "sexy", "BIG sexy", 
            "cold steel", "cobalt blue", "rapid fire", 
            "random act of", "Gandalfian", "Millenium Falcon",
            "optional", "syntactic", "sugary sweet", "jolly grand",
            "hypertexty", "malnourished domain modely (aka anemic)"
        };

        public void SayHello()
        {
            Clients.All.sayHello("Ooey, shuga!");
        }

        //this is a crummy hack that fires a client proxy over and over-->
        public void GetGoodness(string goodnessKind = null)
        {
            const int upperbound = 100;
            var currentCount = 0;
            while (currentCount++ < upperbound)
            {
                var kindOfGoodness = string.IsNullOrEmpty(goodnessKind) 
                        ? GetRandomGoodness() 
                        : goodnessKind;
                Clients.All.getGoodness(kindOfGoodness + " goodness");
                Thread.Sleep(1500);
            }
        }

        private string GetRandomGoodness()
        {
            var r = new Random();
            var indx = r.Next(0, Goodnesses.Length);
            return Goodnesses[indx];
        }
   }

Then hop over to your html and add another input, button, and label, like this:

<!DOCTYPE html>
<html>
   <head>
       <!--omitted for brevity-->
   </head>
   <body ng-app="signalrDemo">
       <div ng-controller="myClientGoodness as goody">
           <span ng-bind="goody.hello"></span>
           <button ng-click="goody.getHubHello()">Get Hub Hello</button>
           <br /><br />
           <input ng-model="goody.overrideKind"/>
           <button ng-click="goody.getTrulyAsyncGoodness()">Get Goodness</button>
           <div ng-bind="'current goodness: ' + goody.kind"></div>
       </div>
   </body>
</html>

And then finally, rip the guts out of our getHubHello function (slightly modifying it, of course) and put into a new function called getTrulyAsyncGoodness. It should look like something like this:

var app = angular.module('signalrDemo', []);
app.controller('myClientGoodness', ['$scope','$window', function ($scope, $window) {
        var goody = this;
        this.hello = 'hi world';
        this.overrideKind = '';
        this.kind = '';

        this.getHubHello = function () {
           //omitted for brevity-->
        };

        this.getTrulyAsyncGoodness = function() {
           //instance a hub connection-->
           var hub = $window.jQuery.hubConnection();

           //instance a proxy from hub connection-->
           var proxy = hub.createHubProxy('GoodnessHub');

           //set callback on proxy-->
           //function invoked when server calls the client-->
           proxy.on('getGoodness', function (goodnessKind) {
               $scope.$apply(function () {
                   goody.kind = goodnessKind;
               });
           });

           //start hub with success/fail hooks-->
           hub.start(function () { /*hub started*/ })
            .done(function () {
                proxy
                  .invoke('getGoodness', goody.overrideKind)
                  .done(function () { /* proxy invoke done/successful */ })
                  .fail(function (failure) { /* proxy invoke failure */ });
            })
            .fail(function (failure) { /* hub start failure */ });
    };
}]);

After you rebuild, re-run it and click both buttons, it should resemble something like this:


Next article: AngularJs factory connections to SignalR hub resources.

Wednesday, March 12, 2014

Javascript OOP -- pgh dot net meetup follow up



It was nice being able to talk to you all last night. Thanks for coming. Feel free to ping me any time with any questions.


-click here to download the slideshow-

Jeremy Wells
http://jermywells.com
http://postcivilization.com
https://twitter.com/jermywells
https://plus.google.com/+JeremyWells
Jeremy.Wells@postcivilization.com

Sunday, September 22, 2013

Javascript : Web Storage - friend or foe?

Web Storage is super neat and fun to fly.


The advent of HTML5 (super hip, buzz word name drop) truly has brought about some neat stuff for us to use. One of these neat things is the concept of local storage in client browsers, or as it is also known - Web Storage. Web Storage, in spite of being a byproduct of HTML5, is a browser JavaScript feature.

In the early days of the web, there were all kinds of hacks that allowed the storing of user data and other small bits of data via the browser. The most widely used and adapted methods of which was probably the cookie. The cookie has limitations though, and is sent to and from the client to the server with every request made. This means that any hacks or workarounds still tend to result in an ultimately undesired scenario. More importantly, these methods (cookies and the like) are necessary because of the stateless nature of the web.

WHAT DO WE WANT? 
-LOCAL STORAGE!

WHEN DO WE WANT IT? 
-YESTERDAY.

WHY AREN'T WE USING IT?
-um, idk - listen, can we talk outside the protest song? Here's the thing...

What is Web Storage?


Web Storage is a term that encompasses the idea of persisting data in client browsers via two new HTML5 browser objects; localStorage and sessionStorage. I have had developers speak to me of using web storage as a replacement or successor to MSSQL, Oracle and/or MySql. I really balk at this idea -centralized data is defacto for very sound reasons in my opinion. That said - there are some GREAT reasons for using web storage. Let's get into it and you can see and decide for yourself.

How does it work?

localStorage.myVar = "something";
//or
sessionStorage.myVar = "something";
THAT'S IT!
You set any variable onto localStorage or sessionStorage and it's persisted. If your browser supports Web Storage, the features are already built into your browser, available on the window object, and anything stored will remain there until it is expressly cleared via JavaScript. No fuss. No muss. (For the record, I neither know nor care what "muss" is).

Here is an example of Web Storage persistence:
You can run it, refresh it, clear your browser cache, and/or do whatever else you like, - the variables set on localStorage remain in tact. sessionStorage works the same way - excepting that anything stored via sessionStorage will collapse with the browsing session.

How can I delete stuff from web storage?

 delete localStorage.myVar; //or
 delete localStorage['myVar']; //or
 localStorage.removeItem('myVar'); //or
 localStorage.clear(); //will delete all vars
 //--or from sessionStorage--
 delete sessionStorage.myVar; //or
 delete sessionStorage['myVar']; //or
 sessionStorage.removeItem('myVar'); //or
 sessionStorage.clear(); //will delete all vars

Do I need to worry about other sites deleting my site's data in a client browser's Web Storage?

Well - no. It follows the same Same Origin Policy as everything else in JavaScript, so you should not have to worry about other sites coming in and deleting your data.

How is browser compatibility/support with regard to Web Storage?

Browser compatibility/support for web storage is pretty awesome; with one well placed line, you can check if your browser supports it or not. (You actually saw it in the fiddle above).

How can I check if a browser supports Web Storage?

if (typeof localStorage === "undefined") throw 'localStorage not supported';
//or
if (typeof sessionStorage === "undefined") throw 'sessionStorage not supported';


Are there any gotchas/snafus/things I should be aware of before implementing?

As with anything else, there are a few caveats. Probably the most notable of which is the fact that localStorage and sessionStorage can only be used to store strings. They don't care about what you throw at them; they don't care what you try to put into them; they take what you give them, and store the JavaScript string primitive of that object or value.

Here is a fiddle:

Even though I set localStorage.mySuperObject equal to the instanced SuperObject ('o'), localStorage only stores strings, so it took my object and converted it to a JavaScript string primitive, then stored that. You may have encountered this behavior before. It's that ever-annoying and useless [object Object] string. More importantly, however, the data stored was useless. Also, stringifying any web storage variable for the sake of displaying it in html is kind of superfluous, but I did it anyway for posterity.

How can I use Web Storage to store meaningful information?


The solution should be somewhat clear at this point: JSON.stringify() and JSON.parse()

Here is the same fiddle from above - slightly modified:

In this fiddle, the object is stringified before it is set on localStorage. Then it is parsed back into JSON, making it as useful as it ever was. :D
JACKPOT!

What about namespacing in Web Storage, or perhaps some kind of data schema?

Here is what I came up with:

Web Storage can be dead-useful. It's definitely worth working with in situations where caching client side data or persisting client values is needed.

Are there major differences between localStorage and sessionStorage?

These two features work nearly identically. Anything pertinent to localStorage is also applicable to sessionStorage. The key difference is - sessionStorage does not persist beyond the current session.

Other key points:

  • Both localStorage and sessionStorage have built-in shortcut methods to some of the functionality you've already seen.
    Those methods are:
    • getItem(key) – returns the value for the given variable/member or null if the variable/member does not exist.
    • setItem(key, value) – sets the value for the given variable/member.
    • removeItem(key) – removes the variable/member from the storage object.
    • key(position) – returns the key for the variable/member in the given numeric position.
    • clear() - clears storage without prejudice
  • Saves (or setItem(key, value) calls) are best wrapped in try/catch because there are size constraints with Web Storage and the amount of data that can be stored in the localStorage and sessionStorage objects.
Any thoughts, tips, tricks, advice are all absolutely welcome!
-JW

Thursday, September 12, 2013

JavaScript : OOP part 3

if (!theFrontier.final()) {theFrontier.current(true, 'part 3');}


How does JavaScript work as an object oriented language?

Very practically, in fact. So - let's get into some code...


A Singleton Pattern in C#...

public class Singleton
{
   private static Singleton instance;

   private Singleton() {}

   public static Singleton Instance
   {
      get 
      {
         if (instance == null)
         {
            instance = new Singleton();
         }
         return instance;
      }
   }
}
Singletons are useful when you don't want multiple instances of an object. Definitively, a singleton should be used in situations when there must be only one instance of a class or object. In the example above, the constructor is private and the instance itself is private. This creates a scenario where the developer accesses and uses the Singleton object via the public Instance member, which actually returns the private static instance of the Singleton object. If the private static instance is null, the object is instantiated before it returns. Once instantiated, it will remain instantiated. In other words - when Singleton.Instance is called, if the private static instance has already been instantiated, return it for use and if not, instantiate it - then return it for use. Personally, I like to coalesce the private instance, but that isn't really important.


A Singleton Pattern in JavaScript...

  "use strict";
  var Singleton = function() {
    var instanceName = "";
    if (Singleton.prototype.instance) {
      return Singleton.prototype.instance;
    }
    Singleton.prototype.instance = this;

    this.setInstanceName = function(n){
       instanceName = n;
    };
    this.getInstanceName = function(){
       return instanceName;
    };
  };
Here's a fiddle demonstrating its use:
It's not very different from the C# example! When we instantiate the Singleton object in javascript, if the Singleton.prototype.instance is not undefined, return the Singleton.prototype.instance for use - and if it is undefined, instantiate Singleton.prototype.instance with the current object's scope/execution context (aka the this), then return the object for use. In other words - when new Singleton() is called, if the Singleton.prototype.instance has already been instantiated, return it for use and if not, instantiate it - then return it for use.

Here's the same example, with the singleton stuff commented out:

A Factory Pattern in C#...

public static class CheesecakeFactory
{
   public static ICheesecake GetNewYorkCheesecake()
   {
       return new NewYorkCheesecake();
   }
   public static ICheesecake GetStrawberryCheesecake()
   {
       return new StrawberryCheesecake();
   }
   public static ICheesecake GetToastedSmoresCheesecake()
   {
       return new ToastedSmoresCheesecake();
   }   
   public static ICheesecake Create(CheesecakeConfig config)
   {
       return new Cheesecake{
           Name = config.CheesecakeName;
           Flavor = config.CheesecakeFlavor;
           Size = config.CheesecakeSize;
       };
   }
}
Factories are useful when you want to organize the instantiation of objects into some logical division or encapsulation. Definitively, they are an abstraction of a constructor or constructors. They are used pretty frequently in software development because they are useful. Architecturally, they can really help organize an application.


A Factory Pattern in JavaScript...

var CheesecakeFactory = {
    GetNewYorkCheesecake: function () {
        return new NewYorkCheesecake();
    },
    GetStrawberryCheesecake: function () {
        return new StrawberryCheesecake();
    },
    GetToastedSmoresCheesecake: function () {
        return new ToastedSmoresCheesecake();
    },
    Create: function (config) {
        var ck = new Cheesecake();
        ck.Name = config.CheesecakeName;
        ck.Flavor = config.CheesecakeFlavor;
        ck.Size = config.CheesecakeSize;
        return ck;
    }
};
Here's a fiddle demonstrating a javascript factory pattern:
While very similar to the C# example, you can see javascript showing some of its dynamic colors. The javascript CheesecakeFactory is an object literal (or namespace - if you will). By calling the CheesecakeFactory factory's member functions, we're return new instances of objects. Easy peasy, right?

A Fluent Interface in C#...

public static class FluentCheesecaker
{
   public static ICheesecake SetName(this ICheesecake cake, string name)
   {
       cake.Name = name;
       return cake;
   }
   public static ICheesecake SetFlavor(this ICheesecake cake, string flavor)
   {
       cake.Flavor = flavor;
       return cake;
   }
   public static ICheesecake SetSize(this ICheesecake cake, string size)
   {
       cake.Size = size;
       return cake;
   }
}
Fluent interfaces are a nice way to set up and/or configure an object. They exist to provide a means of doing just that (configuring or setting up objects), leaving code more readable.


A Fluent Interface in JavaScript...

var Cheesecake = function () {
    this.Name = '';
    this.Flavor = '';
    this.Size = '';
    return this;
}
Cheesecake.prototype.setName = function (n) {
    this.Name = n;
    return this;
}
Cheesecake.prototype.setFlavor = function (f) {
    this.Flavor = f;
    return this;
}
Cheesecake.prototype.setSize = function (s) {
    this.Size = s;
    return this;
}
Here's a fiddle demonstrating a javascript fluent interface:


As you can see, by returning the scope/execution context (the this) of the instance, the object method is chainable, returning the instance with each subsequent function call. The example uses the object's prototype to extend the object by adding the functions to its prototype, but you could do the same thing without touching the prototype.


Here's a fiddle demonstrating a javascript fluent interface WITHOUT using the object's prototype:





Tuesday, September 10, 2013

JavaScript : OOP part 2

if (!theFrontier.final()) {theFrontier.current(true, 'part 2');}

Why don't we see object oriented javascript much as we should?

I don't know why we don't see it as much as we should. If I am speculating, (which I am), it's due in part to the way JavaScript was created, and also in part to Microsoft's refusal (until somewhat recently) to implement JavaScript spec in IE. Internet Explorer was the browser of choice in the early(ish) days of the web. More specifically, IE was the browser of choice when the web began to gain traction as a viable business tool. During that time, Microsoft created a scenario that allowed desktop developers to not have to know much about web development to do it. As such, many of the developers of web content and web applications did not actually have to care or worry about JavaScript development as web forms developers. And I think it's probably fair to say most of us were grateful to Microsoft for it at that time.

Now, however, we know better. Developers are rushing to catch up and keep up with the current incarnation of the www and current web application development practices. Sadly, despite the popularity of asp.net MVC (MVC in general actually), many developers are still averse to JavaScript, and are doing things like creating type-safe JavaScript abstractions that allow a developer to write type-safe code that produces JavaScript, or learning to use these types of tools so as to avoid learning JavaScript. This is silly.

So again, why don't we see object oriented javascript much as we should? I think the answer is twofold. On the one hand - we should begin to see it everywhere because we should strive to implement it in every situation where it will offer us benefit. On the other hand - we see it more than we realize; it's already out there, at large, doing our bidding. Did you recognize it?

jQuery is object oriented.


Take the following plugin:
If you were to debug the example and view the $ object, you might think you would find all the jQuery functions and properties that you know and love. This is not so. Accessing $ returns an initialized object. Accessing $ actually initializes and returns $.fn, and the $.fn object (the object that is created/accessed via $) is jQuery. To state it more simply, $.fn is the object that actually holds all the configuration, settings, functions, methods and other magic that comprise the most widely used javascript library on the net.

In the above fiddle, $.fn is the object being extended. Any time you add a plugin to jQuery, you are extending the $.fn by adding a member/property to it. So - a jQuery plugin simply allows a developer to use jQuery while extending jQuery. Pretty smart, right?

Prototype js is object oriented.


Prototype was built with object oriented programming in mind. Object oriented javascript is Prototype's WHOLE thing. It aims to make OOP in javascript simpler by allowing the developer to work with expressiveness that better mirrors the typesafe object oriented languages most developers are already familiar with.

It's silly to explain how Prototype is object oriented because it has to be. Prototype abstracts away all of the javascript mechanics of object oriented programming in a way intended to make things easier. If you are coming from something like Java or C# and don't have a lot of javascript knowledge/experience, Prototype js makes the task of writing object oriented javascript a little easier to tackle.
Here's an example:

Angular js is object oriented.


If you have worked with Angular js at all, you probably realize that controllers kinda feel like objects. They are, but not like you might think they are. From the developer's perspective, controllers are pretty much the thing through which we interact with scope. We're not setting or interacting properties of a controller as much as using a controller to interact with properties of scope.

Regardless - AngularJs is a dependency injected, fully object oriented client side javascript framework. Nuff said.

So on and so forth...


If you can name a popular javascript library, you can name an object oriented javascript library. The best javascript libraries are always going to be written in good javascript.





Sunday, September 1, 2013

JavaScript : OOP part 1

if (!theFrontier.final()) {theFrontier.current(true, 'part 1');}


This is part 1 of a series of javascript articles. Despite its origins as a prototype and function based language, JavaScript is an object based language and has ascended to a primary role in all modern web applications. It is capable of polymorphism, encapsulation, inheritance, abstraction, and anything else you can think of that makes a language object oriented.

Object oriented JavaScript is no less dynamic and no less functional than any other JavaScript. It's just better organized, more easily managed and more easily maintained; it's more easily unit tested, more modular, etc, etc, etc... [We all know why OOP is good, right?] As more web application functionality moves to the client, it makes sense to follow better design practices with client side code.

JavaScript Inheritance:


Inheritance is a mechanism for code reuse. Generally speaking, it is simply a way to establish a hierarchy or relationships between objects. While JavaScript inheritance is prototypal, it can still observe and/or implement a classical inheritance pattern. In the example below, the methods of the Person object are available on the derived objects (eg: BankTeller, StayAtHomeDad) via the derived object's prototype. That said, I doubt I can sum up the various incarnations of javascript inheritance better than Douglas Crockford does here.



JavaScript Encapsulation:


Encapsulation generally has 2 aspects to it: 1) it serves to restrict access to an object's properties or components, and 2) it serves to bundle logical units of data/code together with methods intended to operate on that data/code. While JavaScript does not have 'classes', it is perfectly capable of first class encapsulation. In the example below, a Person can be sent and used anywhere, and it will already have a number of properties available on an instance of it. Although, those empty property references are not needed at all in JavaScript. I could simply add them whenever I needed them to any instance of the object via that instance's execution context or it's prototype (I will cover this in more detail later). Also in the example, a Gender literal object encapsulates the concept of allowable genders (notwithstanding absent restriction of access to get/set a Person object's gender).


JavaScript Polymorphism:


Polymorphism is the concept by which an object is also another object. So - in terms of nouns and verbs, both a golfer and a 16 year old girl are people and both can drive, but the golfer could drive a golf ball while the 16 year old girl might drive a '94 VW Beetle. Conceptually, it may help to think of this in terms of overriding a default behavior in child or derived objects. Perhaps a better example of polymorphism might be something like this - an animal is an object, a dog is an animal, a dog is a mammal, a human is a mammal, a human may or may not be an animal. Anyhow - in the example below, I kept the same theme going (as above) with a Person, BankTeller and StayAtHomeDad. All 3 objects are people, but when instanced, different things happen when they open drawers.


JavaScript Abstraction:


Abstraction is a term used to describe a separation of concepts from instances of implementation. In the example below, there is a private array called 'collection', which is added to whenever the user clicks the add button. Everything that occurs to get the example to function the way it functions is abstracted away from by means of encapsulating everything in one single call to bindAdd(). The bindAdd() function sets up the variables and handling in perpetuity, thus there is abstraction. There are probably better ways to express abstraction, but this works for now.