Blog Archive

Home
Application Development

“This. Is Not. For. Practice!” – a phrase used to emphasize that you must get things right.  Mentors have used it to mean “Get serious, now!”.

For years jQuery has been a tremendous productivity boost for client-side development; so successful, that it gave rise the Single Page Application (SPA) where a good portion of your application logic was now written with Javascript. Soon, so soon, we all learned that the increased complexity of our client side solutions required good organization, a better architecture.  Time to get serious about clean code.

If you are .Net developer, then many times you can fall into the ECMAScript trap: all ECMAScript must be the same.  What I know from C# must be applicable to Javascript, ’cause it looks the same. Sad news, it’s not. Javascript executes in a much different environment. And to make things more confusing, close cognates such as this are not close enough. “this” in C# is a reference to the current object. “this” is Javascript is , well, it all depends. “this” in Javascript changes context dependent on many factors.  A good reference is here at Mozilla.  Let’s create a quick summary, and where relevant we’ll talk relevant areas that impact programming practice:

Global Context

When you are outside any function, this is referred to as the global context.  ”this” will refer to document.  So if you fire up the console and perform this test:


console.log(this == document); // true.

And in web browsers this also equals the window.  So:


console.log(this == window); // true.

Yikes!  Wait there’s more.  Try this little piece:


var yikes = "ouch";

console.log(window.yikes); // ouch

window is our global memory space.  So think back to any client side code you have written, and this should be very familiar to you:


<script type="text/javascript" src="scripts/jquery.min.js"></script>

This loads jQuery into the global memory space.   Go look at window and you will see “window.$” and “window.jQuery”.  You guessed it, jQuery is now loaded into the global namespace.

This may seem like a digression, but we need to pause at this very important point.  You must be really careful what you put into this global space.  As you grow in Javascript capability you will eventually develop your own utils or libraries.  So consider this very innocent utility file:

  function objectToArray(sourceObj) {
    var results = [];

    for (var key in sourceObj) {
      if (sourceObj.hasOwnProperty(key)) {
        var newObj = sourceObj[key];
        newObj.objectKey = key;
        results.push(newObj);
      }
    }

    return results;
  };

function localize(t) {
  var d = new Date(t + " UTC");
  return d;
}

function parseDecimal(d, zeros, trunc) {
  if (d == null)
    return 0;

  if (typeof d == "number") {
    return parseFloat(d);
  }

  d = d.replace(/[a-zA-Z\!\@\#\$\%\^\&\*\(\)\_\+\-\=\{\}\|\[\]\\\:\"\;'\<\>\?\,\/\~\`]/g, "");
  while (d.indexOf(".") != d.lastIndexOf("."))
  d = d.replace(/\./, "");

  if (typeof zeros == 'undefined' || zeros == "") {
    return parseFloat(d);
  }
  else {
    var mult = Math.pow(10, zeros);
    if (typeof trunc == 'undefined' || (trunc) == false)
      return parseFloat(Math.round(d * mult) / mult);
    else
      return parseFloat(Math.floor(d * mult) / mult);
    }
};

All of these functions are now attached to the global namespace, our what is called “polluting the global namespace”.  Most likely a utility class will have 20 – 30 functions, not the mere three listed above.  These functions will remain in memory until the user refreshes or navigates away from the page.  With a small app, this will be no problem, but anything with a moderate degree of code will soon balloon and consume memory.  And in some cases, such as a mobile friendly websites, you want to conserve as much memory as you can, only loading the objects that you need then allowing them to be garbage collected.

Wow – we’ve only covered “this” in a global context, and if your head isn’t a little numb, don’t worry, do another shot and see if it gets worse!

Function Context – Simple Call

Here we get a strange, as this is the rule:  ”this” will depend on how the function is called.  Consider this code:


var myFunc = function(){
   return this;
 };

myFunc() == window;

Since we are not using strict mode “this” must refer to something so it will default to the global object.  Changing the code to:


var myFunc = function(){
  "use strict";
  return this;
 };

myFunc() == "undefined";

Function Context – As An Object Method

The rule here is “this” refers to the object that the method is called on.  For example:


var mathDoer = {
  someNumber: 13,

  addSomeNumber: function(addMe){
    return this.someNumber + addMe;
  };
 };

mathDoer.addSomeNumber(7); // returns 20

You’ll note that both mathDoer.someNumber and mathDoer.addSomeNumber() are public in scope.  When first developing in Javascript it may be tempting to create your objects as depicted below, and while it is legitimate, it will lead to clutter very quickly:


var mathDoer = {};

mathDoer.someNumber = 13;

mathDoer.someArray = [];

mathDoer.addSomeNumber = function(){ ...};

Imagine this is a none trivial object, and you will have a cluttered mess.  Also, all your methods and properties are public, which you may not want to expose.

Function Context – As A Constructor

When used in a constructor “this” will refer to the object that is being instantiated.  This is best illustrated with the following:


var mathDoer = function(){
this.someNumber = 13;

this.addSomeNumber = function(addMe){
    return this.someNumber + addMe;
  };
 };

var mathIsFunObj = new mathDoer();

mathIsFunObj.addSomeNumber(7); // returns 13

Many of you may be coming to Javascript via KnockoutJS, a data binding library that provides two way binding between the DOM and Javascript objects.  Many of the KnockoutJS samples use this “style” for creating ViewModels:


var mathDoerViewModel = function(){
  this.justAnInt = 5;
  this.someNumber = ko.observable();

  this.addSomeNumber = function(addMe){
    return addMe + this.someNumber();
  };
};

var vm = new mathDoerViewModel();
ko.applyBindings(vm);

Again, our observables and functions are public in scope.  If you have a separate file for this ViewModel and simply include it with the HTML your “vm” variable is now added to the window object and part of the global memory space.  This can be considered good or bad.  From a diagnostics perspective, you can sit at the console and see what our ViewModel is doing by simply issuing commands like “vm.someNumber(45);”  Good for debugging.  This is also considered bad by others for two reasons: everything is public, and this can lead to bloated objects that are hard to use; and, you have added yet another item to the global memory space.  Imagine you have several ViewModels for a single page.  Things can get confusing very quickly.

So how can you make items private?  Remember that the scope of “this” when used in a constructor is a reference to that object – in our case that object is mathDoerViewModel.  If you were merely to declare a variable in the constructor, the scope of that variable would be local to the constructor.  This “hides” the variable from contexts that are outside the scope of the constructor.  That would look like this:


var mathDoerViewModel = function(){
  var _justAnInt = 5; //this makes the variable private

  //  function is local in scope
  var privateFunction = function(){

    //  our locals are available as well a methods and properties from the object ("this")
    return _justAnInt + this.someNumber();
  };

  this.someNumber = ko.observable();

  this.addSomeNumber = function(addMe){
    return addMe + this.someNumber();
  };
};

From the console still can interact with mathDoerViewModel.someNumber() and mathDoerViewModel.addSomeNumber(). We also have private functions and variables now: _justAnInt and privateFunction. For the .Net developer these conventions should have more familiar feel.

When you scour the web for Javascript code, you’ll find that many of the Javascript heavies will use a different standard for variable / scope hiding. We touch on that briefly here before we move on.  In Javascript, your constructor returns a reference to the object you are creating.  In other words, your constructor will return a version of “this” that refers to the objects properties and functions.  However, your constructor can also return an object.  This gives you great flexibility, and makes the  “Module Reveal Pattern” possible.  First here is what our ViewModel would look like using the Module Reveal Pattern:


var mathDoerViewModel = function(ko){

  var _justAnInt = 0;
  var _someNumber = ko.observable();

  var privateFunction = function(){
    return _justAnInt + _someNumber();
  };

  var addSomeNumber = function(addMe){
    return addMe + _someNumber();
  };

  var setJustAnInt = function(value){
    _justAnInt = value;
  };

  var showMeTheInt = function(){
    return justAnInt;
  };

  //  We return an object that refers to items we want to be public
  return {
    someNumber: _someNumber,
    addSomeNumber: addSomeNumber,
    showMeTheInt: showMeTheInt
  };
};

Looks a little different. In our constructor we are creating local variables and local functions, and in fact our observable – _someNumber – is now a local variable. But we “reveal” the items that we want to be public with the “return” statement. So in this case, we return an object with someNumber that references _someNumber, and references addSomeNumber. As a result, we can create:

  var vm = new mathDoerViewModel(ko);

  // Set value of someNumber
  vm.someNumber(35);
  vm.addSomeNumber(5); // returns 40

  //  Let's use our setter
  vm.setJustAnInt(12);
  vm.showMeTheInt(); // returns 12

Notice that we are passing in a “ko” variable in the constructor call. This serves many purposes: firstly, it makes the ViewModel modular, and allows us to load the module asynchronously with AMD tools like requirejs or curljs; secondly, the constructor signature lets us know that we are depending “ko” to make our ViewModel work; finally, it gives us a tiny speed boost as now that “ko” is local, since Javascript does not have to search up the stack to find it.

You should avail yourself of the fantastic book “Learning Javascript Design Practises” by Addy Osmani.  He’s been kind enough to place a copy online.  This will help you understand some of the code that is that would otherwise seem very strange compared to what you are used to in C#.

Function Context – As A DOM Handler

Moving on the DOM, “this” takes on a different context.  You’ll most likely be familiar with this common jquery statement:


$(".apparea").on("mouseover", ".milestone-border", function (event) {
//   here this means the DOM element with a class of "milestone-border"

$(this).addClass("selected-children");
 });

The rule here is that “this” means the DOM object that fires the handler.  So in this case “this” is equal to event.currentTarget.

Go Forth And Create

ImageBy now your head should hurt a little, with all these nuances it’s wonder that you don’t feel more beaten up.  That’s where the complexity of web development is under appreciated.  Hopefully we have covered enough here for you to save some time debugging, designing, or trying to understand some the vast Javascript frameworks, utils and libraries that are out there.  If you are coming from .Net and are new to Javascript, you avoid the trap that many have fallen into of creating monstrous Javascript objects of pure public functions and properties jammed into a single file.  This will lead to a deep valley of frustration when it comes time to refactor your code after you realize you have a hard time maintaining things.  If you can keep your code modular and have things reside in separate files, you’ll be better off.

We covered “this” in order to reveal some deeper yet vital nuances to Javascript.  Mastering “this” and the related topics above are going to help.  A lot.  This brings Javascript from being a “toy” to  really productive platform because you can avoid some pitfalls that slow you down.  In future posts we continue to build on this foundation where we focus on modular design and asynchronous loading.

ski_and_snowboard_snowsport1Enterprise level software can provide marvelous benefits with process automation; yet, how many tales can you recount of the company that has implemented Enterprise level procurement / ERP / BPM, etc and it was a death march. Pure and simple it was a nightmare, accounting couldn’t close the books for over 5 weeks, and this continued for almost a year. True story.

This post is not to be seen as refutation of automation, business process management, statistics, and economics. People, organizations, and companies need direction, require a director to set the tone, the pace and cadence for reaching goals. But there is a danger that we treat processes like science with the belief that when business behaves in a more rational fashion, things will operate like physics or mathematics. While it is true that applying scientific approach and principals to business can help, at its essence, business is not science. Here’s another analogy – while you should apply science to the field of medicine, in the end, the body and mind heal in manners that are not scientific. Ask any doctor about misdiagnosis and miracles. If he or she hasn’t been humbled by their lack of understanding of healing, change doctors!

We have to careful with model-abstraction worship. Let me tell you, the model is not the process – it’s a representation. Look at the two intrepid skiing figures above. Do you think they are thinking of the mechanics or the physics of what they are experiencing? Torque on the knees? Now put yourself in their instructors or trainers shoes and ask “how would I really go about communicating what needs to be learned to survive this type of run?”

General_Consultation_Workflow_diagram_v68An organization is comprised of the interactions of people, and these series of steps, while seeming out of control, create the cadence of your business. At the level where the work is completed, if you were to ask someone to describe what they do, it will start with a list items, not a diagram like the one above. At the level where the work is done,the people pushing the buttons, experience a different reality than what management experiences. If your goal is to assist those people, then your first step is not to alienate them by diagramming their busy day with pseudo scientific terms and weird charts. Remember, the director who can’t get her actors to relate to the story makes an awful film. You have to relate to others on a fundamental level, and for the most part in business, people don’t relate to this diagram. A picture is worth a thousand words, but for those whose inbox is flooded with requests, a diagram is not a picture, it a a thousand confusing questions. “Why is the box blue? Can I have a diamond instead?”

“Ok”, you ask, “what do we do instead?” Well, as luck would have, there is a good way to implement process, get approvals, and have consistency without over orchestrating business process and creating confusion. The approach is to view the decisions that people make as gateways between important steps. This is best illustrated with an example, so let’s model a bonus approval process for a sales organization.

We have a sales team who is closing deals weekly, and for each deal a manager and vice president will need to weigh in on the merits of the award. Fairly standard in most businesses, and in many cases this is managed with email. The bonus manager is the fulcrum of this process, as it he who currently reminds the sales agents that they have not supplied the correct supporting materials, as well as gently nudging the vice president of sales that she needs to get into the system and complete approvals so that the request can be released to payroll before the Wednesday paycheck run. Your role, dear reader, is to get the steps of this process that are inside the bonus managers head and create something that they will engage in. To create a fan of the new process, it’s better that the process come from the bonus manager – they have to do it, so if they create it, they own it!

Remember the diatribe against diagrams? You can’t ask the bonus manager to diagram their process, as they’re too busy. But have them list the steps – yes a simple list. It may be a very limited set of items. You get this:

  • Fill Out Bonus Request
  • Bonus Manager Reviews
  • Vice President Reviews
  • Payroll Issues payment

You can prod the bonus manager further, and get them to categorize the end states of this process. We’ll add Bonus Denied and Bonus Paid, as this will represent all the stops in the process. Now the list looks like this:

  • Fill Out Bonus Request
  • Bonus Manager Reviews
  • Vice President Reviews
  • Payroll Issues payment
  • Bonus Denied
  • Bonus Paid

The next thing to do is ask “What decisions get you from step to step? For example, what do you do when work is incomplete from the Sales Agent?” The answer – “Today? I email them and request more info”. Lets model this action as a phrase starting with a verb:

Request More Info

Now you start a helpful chart that looks like this:

Step Decision Next Step
Bonus Manager Review Request More Info Fill Out Bonus Request

 

Simple. It’s in English, and there is direct understanding of what happens. What’s more, these are the phrases, thoughts, and language used by the key person of the process. Their “vocab” is the context of how they think, and it’s not a stretch for understand what is occurring, no threat from the oppressive science of process modeling. You could even do this at lunch! Here is what the end product will look like:

Step Decision Next Step
Fill Out Bonus Request Complete Bonus Manager Review
Bonus Manager Review Request More Info Fill Out Bonus Request
Bonus Manager Review Approve VP Review
VP Review Deny Bonus Denied
VP Review Approve Payroll Issues Payment
Payroll Issues Payment Complete Bonus Paid



There’s more good news. ActiveEngine Software has a product that will take this list and create a workflow. Here is a demo video. Thanks for reading.


ActiveEngine Software by ActiveEngine, LLC.