JavaScript design patterns

Here are the most common JavaScript solutions that should be used in production code, everybody calls this list as JavaScript Design Patterns, but I think that it’s just good code’s rules. By the way, here they are:

immediate function pattern
purpose: to wrap some code in the context. Let us reduce polluting of the global context

(function () {
    alert('Hello');
} ());

purpose: the same solution, but with saving of results

var someVar = (function () {
    return 'result';
} ());

purpose: here is the real world example, it allows to use $ symbol as a jQuery in one context and as a Prototype library in another context without polluting of the global context. This solution must be used with any external library.

(function ($) {
    $(".menuOverlay").show();
} (jQuery || $));

note: Immediate function wrapped in parens, because:

  • Without parens it would be interpreted as function declaration (not expression) which is syntax error
  • Function expression can not start with word “function”

What is a Function Declaration?

function foo() {
    return 'result';
}

What is a Function Expression?

var bar = function () {
    return 'result';
}

immediate object initialization pattern
purpose: This pattern is mainly suitable for one-off tasks, and there’s no access to the object after the init() has completed. If you want to keep a reference to the object after it is done, you can easily achieve this by adding return this; at the end of init().

({
    width: 100,
    height: 200,
 
    getArea: function () {
        return this.width * this.height;
    },
    init: function () {
        console.log(this.getArea());
        //other init code
    }
}).init();

memoization pattern
purpose: the main goal is performance optimization. It’s real deal to save pre-calculated results. E.g. for Fibonacci numbers, juat implement solution with and without this pattern and you will see the difference.

function average(x, y) {
    var key = x + '_' + y;
    if (!average.cache.hasOwnProperty(key)) {
        average.cache[key] = (x + y) / 2;
    }
    return average.cache[key];
}
average.cache = {};
 
average(10, 20); //calculate
average(10, 20); //take from cache
average(20, 10); //calculate

Loop closure pattern
purpose: to eliminate “cycle f**k ups”, I mean the situation when you use cycle iterator variable in closure and you expect 1, 2, 3 .. values in different functions, but you have always last value in all.

var arr = ['one', 'two', 'three'];
 
for (var i = 0, len = arr.length; i < len; i++) {
    (function (i, d) {
        //access index and data
        console.log(i + ') ' + d);
    } (i, arr[i]));
}

The same code with jQuery

var arr = ['one', 'two', 'three'];
 
$.each(arr, function (i, d) {
    console.log(i + ') ' + d);
});

implementation is similar to

var forEach = function (d, f) {
    for (var i = 0, l = d.length; i < l; i++) {
        f(i, d[i]);
    }
};

Private member
purpose: restrict access to private members

function Semaphore(start) {
    var value = start; //private variable
 
    //private method
    function resetValue(){
        value = 0;
    }
 
    return {
        enter: function () {
            value++;
        },
        leave: function () {
            value--;
        },
        getValue: function(){
            return value;
        }
    };
}
 
var sem = new Semaphore(0);
sem.enter();
sem.enter();
Assert(sem.getValue()==2);
sem.leave()
Assert(sem.getValue()==1);
Assert(!sem.hasOwnProperty('resetValue'));//could not access private method
Assert(!sem.hasOwnProperty('value')); //could not access private variable

Optional parameter pattern

purpose: add ability to specify optional parameters
When function has a lot of parameters

function Car(name, model, color, number, wheelsRadius, year, autoTransmission) {
    //do something with all parameters
    return 'result';
}

This is bad code, because all parameters must be set when instantiating (even optional parameters)
e.g.

var myCar = new Car('Honda', 'civic', 'red', null, null, 2004, false);

also the order of the parameters is fixed and it’s hella hard to add one more parameter, when this is boilerplate code

So, the decision is to convert list of parameters to one object…

function Car(settings) {
    var defaultSettings = {
        name: 'Unknown',
        model: null,
        autoTransmission: false,
        wheelsRadius: 16
    };
 
    this.settings = $.extend({}, defaultSettings, settings);
 
    return this.settings;
}
 
var myCar = new Car({ name: 'Honda', model: 'civic', color: 'red', year: '2004', autoTransmission: true });

Note: if function has more then 3 parameters it must be converted to the function with one object-parameter.

Namespace pattern
purpose: reduce pollution of global context and simplify code organisation.
Here is Bad practice (pollute global scope):

function Init() { };
function Run() { };
var state = 1;
var module1 = {};
module1.data = [1, 2, 3];
var module2 = {};

Here is Better practice, but not good enough:

var MYAPP = {};//only one global object;
MYAPP.Init = function () { };
MYAPP.Run = function () { };
MYAPP.state = 1;
MYAPP.module1 = {};
MYAPP.module1.data = [1, 2, 3];
MYAPP.module2 = {};

Why not good enough? Because if you have a lot of modules, you will do something like:

if (typeof MYAPP === "undefined") {var MYAPP = {};}
if (typeof MYAPP.modules === "undefined") {var MYAPP.modules = {};}

Here is the Namespace pattern (read it carefully, it’s pretty interesting):

var MYAPP = MYAPP || {};
MYAPP.namespace = function (nameSpace) {
    var parts = nameSpace.split("."),
        parent = MYAPP,
        i;
 
    if (parts[0] === "MYAPP") { // strip redundant leading global
        parts = parts.slice(1);
    }
    for (i = 0; i < parts.length; i++) {
        // create a property if it doesn't exist
        if (typeof parent[parts[i]] === "undefined") {
            parent[parts[i]] = {};
        }
        parent = parent[parts[i]];
    }
    return parent;
};

To create new (or get already existing) namespace you need to write:

var moduleCar = MYAPP.namespace("MYAPP.modules.moduleCar");

Module pattern
purpose: Javascript doesn’t have special syntax for packages, but with help of “namespace” and “immediate function” patterns we can achieve this:

MYAPP.namespace("MYAPP.utilities.stack");
MYAPP.utilities.stack = (function () {
    var stack = [];
 
    function push(value) {
        stack.push(value);
    }
 
    function pop() {
        return stack.pop();
    }
 
    function somePrivateMethod() {
        stack = [];
    }
 
    return { // public API
        push: push,
        pop: pop
    };
} ());

Chaining pattern
purpose: add ability to use similar cool stuff as it possible with jQuery (I mean this chaining – $(‘.container’).html(markup).show() …)

var calculator = (function () {
    var value;
    return {
        init: function (startValue) {
            value = startValue;
            return this;
        },
        add: function (val) {
            value += val;
            return this;
        },
        mul: function (val) {
            value *= val;
            return this;
        },
        result: function () {
            return value;
        }
    };
} ());
 
console.log(calculator.init(2).add(2).mul(2).result());//8

P.S. It’s pretty obvious, but you can use different combination of these patterns to achieve your goal.

Social Share Toolbar

slides from frontendConf

My slides from frontendconf.by – https://speakerdeck.com/mikitamanko/high-load-javascript-framework-without-inheritance-1

video with presentation:
part 1 – http://video.yandex.by/users/fdconf/view/22/ (Russian)
part 2 – http://video.yandex.by/users/fdconf/view/21/ (Russian)

Social Share Toolbar

Link folder into Visual Studio Project

As far as we all might know, Visual Studio allows to add existing file as a link.

file as a link

But sometimes it could be pretty useful to add whole folder as a link. As a result I want to change\add\remove files in one directory and to observe the same changes in the other project. The first thing that came up to my mind was hard link (yeah it’s strange).
But I was sure enough that I can make it by adding several lines to .csproj file. Here they are:

<Compile Include="..\..\..\OtherProject\CommonFolder\*.cs">
     <Link>CommonFolder\%(FileName)</Link>
</Compile>

and here is the example ho to add files as a content (one file)

    <Content Include="..\WebClient\index.html">
      <Link>www\index.html</Link>
    </Content>

and the whole directory

    <Content Include="..\WebClient\Pages\*.html">
      <Link>www\Pages\%(FileName)</Link>
    </Content>

Just to clarify – all these changes I’ve added to e.g. MyProject.csproj file.

Social Share Toolbar

HOW TO run Window Phone 8 emulator on parallels on mac

That awkward moment, when you want to use you windows on parallels for Windows Phone 8 development (and don’t want to install windows via bootcamp).

Shortly some helpful point:

  • first of all ensure that you have Parallels desktop 8 for mac (it’s really important to have 8 version, if not – just update it by the install 8 version)
  • go to parallels settings – “Optimisation” and check “Nested virtualisation enabled”
  • go to parallels hardware settings and ensure that you have configured ONE cpu and at least 4GB of ram (may be it will work with 2 GB I don’t know). It is really important to set only 1 CPU
  • make sure that you have installed parallels tools on your windows 8 (yep windows 8 on your parallels)
  • ensure that you have windows 8 pro edition (I had windows 8 N, then updated to windows 8 Pro N), if not – update it. Open My Computer, right click – Properties. Check your windows version, if it’s not pro, click “get more features” or something like this. You should enter serial key and wait until windows will install all cool features. (Serial keys could be taken from your msdn premium subscribtion account, if you have one, just click “get key” near the windows 8 pro, on pro N edition, copy-paste it to the windows updating window and follow the white rabbit)
  • Now you have windows 8 pro edition, cool! Find on start screen “Hyper-v manager”, configure your device emulator, and set ONE cpu, only ONE, seriously 1.
  • Now you could try to run you project in VS 2012 on device. In case if you will have an error with CPU counts, something like “…this can happen when the virtual processor or socket count…” open parallels settings and ensure that you configured one cpu, and open hyper-v manager and look at settings for device emulator you trying to run – open it’s settings and set cpu count to one
  • That was the small manual how to run windows 8 emulator on parallels for mac, or how to start hyper-v on parallels for mac.

    Social Share Toolbar

    My thoughts about future of pointing devices

    It’s cool to be on the cutting edge of new technologies, and it is cool to invent or even just try something new.
    All we have been inspired by sci-fi films with “future-rised” interfaces.
    And all we have been inspired by google glasses, it’s hella cool device

    But STOP, what’s going on with PC/Laptop’s pointing devices?
    You know, I mean “leap motion”, “mycestro” and other similar devices that reinvented kinect for PC/Laptop.
    For example here is one more DIY motion device – http://www.youtube.com/watch?feature=player_embedded&v=U180f3XG20o. It is great presentation, it is interesting device, but thats it. I don’t believe that lazy people will waving their hand the whole day. It’s too hard, believe me. May be in the near future laptops and other devices will have second web-camera and somebody gonna use “leap motion\kinect like” gestures to list presentation’s slides. But I’m sure that nobody will use it in daily work, just because it’s too hard.
    I believe that mouse/trackpad device will be replaced by eye-tracking mechanism, or by the mind-PC interface, but not with the kinect like toys. It is really funny, but I think that this is totally useless

    Social Share Toolbar

    Some thoughts about html5 by Christian Heilmann

    http://www.youtube.com/watch?v=r7xnKSPWTjo – it is really cool presentation for anyone who cares about the web (by Christian Heilmann http://christianheilmann.com/)

    P.S. just put here some interesting tools:

    Social Share Toolbar

    You can’t create a button

    Here is very interesting article http://www.nczonline.net/blog/2013/01/29/you-cant-create-a-button/ by Nicholas C. Zakas. Most excited point is about replacing default browser’s elements (such as checkbox, button, etc) with simple div and span elements. This patters is actively used by google, and as it was described in article it’s a mistake. Details are in the article

    Social Share Toolbar

    Hackathon – first experience, helpful tips

    I have heard about hackathon events in Facebook and Google and about all this hackers culture, that could pass for something for nerds only. I have even experience as an organiser of company’s internal hackathon event. And finally I took part in hackathon
    in person with excellent team, and this is beyond words how cool it was. It is the great challenge to create something new, something completely ready for demo, only for 24 hours.
    In hackathon you can participate in all phases of the software’s lifecycle only for 24 hours.

    Some tips that I discovered for myself:

  • find your team
  • find something like whiteboard and marker
  • come up with some ideas
  • finally choose idea that your team will implement
  • work out the details of minimum working version – all features and improvements MUST be hold over till minimum version will be ready
  • DON’T try to do everything right, I’m about good architecture design and universalism. This is very important point that may save your time. If you can not do something fast enough – hack it. If you have a problem – hack it. This is HACKathon. The result you will show on the demo, so you should hack enough to prepare application for the demo
  • Think about what will take place at the demo
  • It’s obviously, but divide functionality into tasks.
  • It is necessary to monitor progress of each team member. For example we have been working by agile methodology. We used 45 minutes sprints. And after each sprint we got stand up meeting. Then we must rest – 10-20 minutes we had been playing in kicker/kinect/eat something/etc
  • rest is very important point – don’t forget about it
  • Here is our result – https://github.com/DjComandos/MobileRockBand

    Looking forward to the next Hackathon.

    Social Share Toolbar

    Some helpful videos for front-end developers

    Here is the collection of some helpful videos for front-end developers (by Paul Irish) http://delicious.com/paul.irish/frontend+video

    Social Share Toolbar

    asp.net MVC3 Versioning of Views and Controllers

    Sometimes it could be necessary to have ability to add “Versioning” to Pages on your site. For example we have URL like this – http://localhost:4444/Authentication/ShowLogin and this “ShowLogin” page used on many sites (e.g. integrated via iframes) and suddenly it is necessary to change something on this page, but not for all users of this page (required back compatibility).

    First step is to use custom CSS. But when it is needed to make functional changes – completely change View, Model or Controller, in this case CSS won’t be enough. For this purpose we can request new Page via this URL – http://localhost:4444/Authentication/1001/ShowLogin where “1001” is version of the page. It is obviously that in case of “1001” version MVC Engine should find appropriate controller and views, and if no controllers or views were found – should be used default version (it sounds like View’s inheritance or overriding – this mechanism will allow to override only several views, not all).

    How to implement this approach? – for this we need the following:

    • override default MVC controller’s factory – here we will define custom logic for searching and creation of controller
    • replace Views engine. Also it is needed to add new route.
    • define custom route to MVC routes
    • add ability to configure versions and other settings via web config

    You can find complete example here – https://github.com/DjComandos/MvcVersioning/

    Some clarifications how to do this. First of all it is needed to add new rule to Routes – it should be done in Global.asax

    routes.MapRoute(
        "ControllerWithVersion",
        "{controller}/{version}/{action}/{id}",
        new {controller = string.Format(@"\{0}\", config.ControllerNameRegexForEnablingCustomControllerFactory), 
            action = "ShowLogin", id = UrlParameter.Optional},
        new {version = @"\d{4}"});

    Here “config.ControllerNameRegexForEnablingCustomControllerFactory” is just a regex, something like “^Authentication|ForgotPassword$” (where Authentication or ForgotPassword are controllers names). This setting is stored in web.config.

    Then it is needed to override default RouteControllerFactory – for this purpose we will create next class:

        public class RouteControllerFactory : IControllerFactory
        {
            private readonly IControllerFactory _defaultFactory = new DefaultControllerFactory();
            private readonly IAppConfiguration _configuration = new AppConfiguration();
     
            public IController CreateController(RequestContext requestContext, string controllerName)
            {
                IController controller = NeedToUseCustomFactory(controllerName, requestContext)
                                             ? CreateControllerInstance(requestContext)
                                             : _defaultFactory.CreateController(requestContext, controllerName);
     
                return controller;
            }
     
            public SessionStateBehavior GetControllerSessionBehavior(
                RequestContext requestContext, string controllerName)
            {
                return _defaultFactory.GetControllerSessionBehavior(requestContext, controllerName);
            }
     
            public void ReleaseController(IController controller)
            {
                _defaultFactory.ReleaseController(controller);
            }
     
            private IController CreateControllerInstance(RequestContext requestContext)
            {
                var currentVersion = requestContext.RouteData.Values.ContainsKey(_configuration.ApiVersionKey)
                                         ? requestContext.RouteData.Values[_configuration.ApiVersionKey].ToString()
                                         : _configuration.DefaultControllerVersion;
     
                var controllerVersionedTypeName = string.Format(
                    "{0}{1}Controller",
                    ControllerName(requestContext),
                    _configuration.TryGetControllerPostfix(currentVersion));
                var controllerDefaultTypeName = string.Format(
                    "{0}{1}Controller",
                    ControllerName(requestContext),
                    _configuration.TryGetControllerPostfix(_configuration.DefaultControllerVersion));
     
                var typeType = TypesFinder.FindTypeInExecutingAssembly(controllerVersionedTypeName) ??
                               TypesFinder.FindTypeInExecutingAssembly(controllerDefaultTypeName);
     
                var controller = Activator.CreateInstance(typeType) as IController;
     
                return controller;
            }
     
            protected string ControllerName(RequestContext requestContext)
            {
                return requestContext.RouteData.Values[_configuration.ControllerKey].ToString();
            }
     
            private bool NeedToUseCustomFactory(string controllerName, RequestContext requestContext)
            {
                return Regex.IsMatch(controllerName, _configuration.ControllerNameRegexForEnablingCustomControllerFactory)
                    && requestContext.RouteData.Values.ContainsKey(_configuration.ApiVersionKey);
            }
        }

    The main idea is that we use Custom Controller factory only in case is varsion is defined, for usual cases will be used default controllers factory. Let’s add some code to Global.asax after routing:

    // register custom controller factory
    ControllerBuilder.Current.SetControllerFactory(typeof(RouteControllerFactory));

    Let’s override Views Rendering Engine

        public class VersionedRazorViewEngine : RazorViewEngine
        {
            private readonly IAppConfiguration _configuration = new AppConfiguration();
     
            public VersionedRazorViewEngine()
            {
                AreaViewLocationFormats = new[]
                {
                    "~/Areas/{2}/Views/{1}%1%/{0}.cshtml", 
                    "~/Areas/{2}/Views/{1}%1%/{0}.vbhtml", 
                    "~/Areas/{2}/Views/Shared%1%/{0}.cshtml", 
                    "~/Areas/{2}/Views/Shared%1%/{0}.vbhtml"
                };
     
                AreaMasterLocationFormats = new[]
                {
                    "~/Areas/{2}/Views/{1}%1%/{0}.cshtml", 
                    "~/Areas/{2}/Views/{1}%1%/{0}.vbhtml", 
                    "~/Areas/{2}/Views/Shared%1%/{0}.cshtml", 
                    "~/Areas/{2}/Views/Shared%1%/{0}.vbhtml"
                };
     
                AreaPartialViewLocationFormats = new[]
                {
                    "~/Areas/{2}/Views/{1}%1%/{0}.cshtml", 
                    "~/Areas/{2}/Views/{1}%1%/{0}.vbhtml", 
                    "~/Areas/{2}/Views/Shared%1%/{0}.cshtml", 
                    "~/Areas/{2}/Views/Shared%1%/{0}.vbhtml"
                };
     
                ViewLocationFormats = new[]
                {
                    "~/Views/{1}%1%/{0}.cshtml", 
                    "~/Views/{1}%1%/{0}.vbhtml", 
                    "~/Views/Shared%1%/{0}.cshtml", 
                    "~/Views/Shared%1%/{0}.vbhtml"
                };
     
                MasterLocationFormats = new[]
                {
                    "~/Views/{1}%1%/{0}.cshtml", 
                    "~/Views/{1}%1%/{0}.vbhtml", 
                    "~/Views/Shared%1%/{0}.cshtml", 
                    "~/Views/Shared%1%/{0}.vbhtml"
                };
     
                PartialViewLocationFormats = new[]
                {
                    "~/Views/{1}%1%/{0}.cshtml", 
                    "~/Views/{1}%1%/{0}.vbhtml", 
                    "~/Views/Shared%1%/{0}.cshtml", 
                    "~/Views/Shared%1%/{0}.vbhtml"
                };
            }
     
            protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
            {
                return base.CreatePartialView(controllerContext, GetViewPath(controllerContext, partialPath));
            }
     
            protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
            {
                return base.CreateView(
                    controllerContext, GetViewPath(controllerContext, viewPath), GetViewPath(controllerContext, masterPath));
            }
     
            protected override bool FileExists(ControllerContext controllerContext, string virtualPath)
            {
                return base.FileExists(controllerContext, GetViewPath(controllerContext, virtualPath))
                       ||
                       (IsVersioningEnabled(controllerContext) &&
                        base.FileExists(controllerContext, GetViewPath(controllerContext, virtualPath, _configuration.DefaultViewsVersion)));
            }
     
            private bool IsVersioningEnabled(ControllerContext controllerContext)
            {
                return controllerContext.RouteData.Values.ContainsKey(_configuration.ControllerKey)
                       &&
                       Regex.IsMatch(
                           controllerContext.RouteData.Values[_configuration.ControllerKey].ToString(), _configuration.ControllerNameRegexForEnablingCustomControllerFactory)
                       && controllerContext.RouteData.Values.ContainsKey(_configuration.ApiVersionKey);
            }
     
            private string GetVersion(ControllerContext controllerContext)
            {
                if (IsVersioningEnabled(controllerContext))
                {
                    return controllerContext.RouteData.Values.ContainsKey(_configuration.ApiVersionKey)
                               ? controllerContext.RouteData.Values[_configuration.ApiVersionKey].ToString()
                               : _configuration.DefaultViewsVersion;
                }
     
                return string.Empty;
            }
     
            private string GetViewPath(ControllerContext controllerContext, string virtualPath, string version = null)
            {
                if (string.IsNullOrEmpty(virtualPath))
                {
                    return string.Empty;
                }
     
                version = version ?? GetVersion(controllerContext);
                return base.FileExists(controllerContext, virtualPath.Replace("%1%", _configuration.TryGetViewFolderPostfix(version)))
                           ? virtualPath.Replace("%1%", _configuration.TryGetViewFolderPostfix(version))
                           : virtualPath.Replace(
                               "%1%", _configuration.TryGetViewFolderPostfix(_configuration.DefaultViewsVersion));
            }
        }

    Main idea – replace mechanism that will find necessary views (just add version number to path). As a result views for default version will be in “Views/Authentication” folder, and views for “1001” version will be in “Views/Authentication1001” folder (this suffix is configurable in web.config). It’s also needed to register new view’s engine in global.asax:

    // register custom razor view engine
    ViewEngines.Engines.Clear();
    ViewEngines.Engines.Add(new VersionedRazorViewEngine());
    // note: that there is no custom ViewEngine for webforms (it is need to implement it in case it will needed for API versioning)
    ViewEngines.Engines.Add(new WebFormViewEngine());

    Finally thats it, it is needed just to implement custom RouteControllerFactory that implements IControllerFactory and register it in Global.asax, And implement custom VersionedRazorViewEngine inherited from RazorViewEngine and also register it in global.asax. And views\controllers versioning for MVC3 is ready. It is not only versioning but also Views’ inheritance, because this approach allows us to override only views that should be changed (with reusage of old views).

    Sources could be found here – https://github.com/DjComandos/MvcVersioning/

    Social Share Toolbar