Download - Enterprise js pratices
![Page 1: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/1.jpg)
Enterprise JS PracticesREFERENCE ARCHITECTURE
![Page 2: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/2.jpg)
Marjan Nikolovski
A professional senior software engineer and conference speaker who is mainly hooked on the .NET platform as development platform and its derivatives, but from time to time knows to kill some time with open source software.
Usually spends his time writing systems backend and testing cutting edge technologies.
In spare time actively participating in holding technical presentations on conferences and researching. Specially interested in Distributed programming, Software architecture, Middleware, SOA, Non-relational databases and Workflow driven systems.
![Page 3: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/3.jpg)
Agenda
Word-Two;
JavaScript mistakes from the C# programmer
Solution structure;
Solution architecture;
Dependency management;
Product modules;
UI Components;
Event Driven Messaging;
Application routing;
Localization;
Logging
![Page 4: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/4.jpg)
Word-Two
Enterprise JavaScript app - heavy data app that is hard to be maintained;
Development time increase as the complexity and the codebase grows up;
Frontend development usually not taken seriously;
Frontend development always underestimated and without certain development plan and architecture;
![Page 5: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/5.jpg)
JavaScript mistakes from the C# programmer
Writing jQuery still requires knowledge of JavaScript;
Using global variables and functions;
Object literal;
Self-Executing Anonymous Function;
Revealing Module Pattern;
Array and object declaration gone bad;
False value understanding;
Default value testing;
Using wrong comparison operators;
Misusing For..in statement on Arrays;
Misusing For..in statement on Objects;
Function and Object Scope in JavaScript;
Not aware of JSLint;
![Page 6: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/6.jpg)
Using global variables and functions
var invalid_username = "Username exists";
function log_in() {
//Placed in global scope when executed
invalid_username = "Really Bad";
}
//Bad way to prevent namespace clashing
function namespace_log_out() {
}
//Functions
window.log_in();
window.namespace_log_out();
//Global variables are available off window object
console.log(window.invalid_username);
console.log(window.log_in);
console.log(window.namespace_log_out);
![Page 7: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/7.jpg)
Object literal
Similar to JSON syntax;
Provide properties and function by choise;
Everything defined in the object literal is public;
Pros Cons
Remove global namespaces to properties, variables and methods
Difficult to maintain and understand
Functionality can be added at a later point
No way to have private properties and/or methods
All properties and methods are public
//Object Literal declaring properties and methodsvar user_model = { //public property username: "Some user", //public method login: function() {}};
![Page 8: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/8.jpg)
Self-Executing Anonymous Function
Non name function that executes after it is defined;
Isolate variables and functions from global namespace;
//Self-Executing Anonymous Function:(function() { //private variable var username = "Some username"; //private function function login() {} login();}());
Pros Cons
Hide implementation from external code
All information is hidden
The code runs only once
Complicated on first sight
Not using object literal notation
![Page 9: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/9.jpg)
Revealing Module Pattern
Uses the concept of the Self-Executing Anonymous Function;
Store the result into a variable;
//Revealing Module Pattern (Public & Private)var user_proxy = (function() { var me = {}, //Private property
username = "Some username"; //Public property me.message = "A message"; //Public method me.Login = function() { pvtLogin(); }; //Private method function pvtLogin() { //Do something... } //Return just the public parts return me;}());
Pros Cons
Allow private and public properties and methods
Easy to understand
![Page 10: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/10.jpg)
Array and object declaration gone bad
Many ways to create an object, but only one is the correct one;
Hesitate the temptation to use the new keyword;
// bad practicevar user = new Object();
// good practicevar user = {};
// bad practicefunction User(uname){ this.username = uname;}
var user = new User(‘test’);User.username == ‘test’
var user = User(‘test’);user.username != ‘test’user.username == window. username
![Page 11: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/11.jpg)
False value understanding
Same goes for arrays. Many ways to create an array, but only one is the correct one;
// bad practicevar userList = new Array(10);userList[0] === undefined;userList.length == 10;
// good practicevar userList = [];
![Page 12: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/12.jpg)
Default value testing
C#
If(user != null && user.Length > 0){ // do something}
JavaScript
If(user){ // do something}
OR
user = user || ‘default value’;
![Page 13: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/13.jpg)
Using wrong comparison operators
JavaScript ninja behavior can sometimes gives us unexpected results;
Sometime value comparison is not what it looks like;
Always use === or !== when doing comparison in JavaScript;
// Unexpected comparisons0 == '‘ //true0 == ‘0’ //truefalse == '0‘ //truenull == undefined //true' \t\r\n ' == 0 //true
0 === '' //false0 === '0' //falsefalse === '0' //falsenull === undefined //false' \t\r\n ' === 0 //false
![Page 14: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/14.jpg)
Misusing For..in statement on Arrays
Does not guarantee the order of the items that are going to be retrieved by the iterator;
The iterator can iterate both array and objects;
Bad declaration can result in incorrect iterator execution;
var user = { username: ‘Test’, name:’Some name’};
for(var data in user){ alert(data);}// outputs username, name
var userArray = [];userArray.push(‘data’)userArray.name = ‘Test’;
for(var data in user){ alert(data); alert(user[data]);}// outputs 0, name// outputs data, Test
![Page 15: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/15.jpg)
Misusing For..in statement on Objects
In most cases For..in is not harmful when iterating objects;
The problem arise when we inherit properties from the prototype;
Always check if the property exists in the instance before accessing it;
var User = function(uname){ this. Username = uname; return this;}User.prototype = { isDeleted:true}var usr = new User(‘Test’);for (var prop in User()) { // outputs Username // outputs isDeleted}
var User = function(uname){ this. Username = uname; return this;}User.prototype = { isDeleted:true}for (var name in username ) { if (username.hasOwnProperty(name) ) { // outputs Username }}
![Page 16: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/16.jpg)
Function and Object Scope in JavaScript
Variable scope visible in the function;
All internal closures or functions will see the defined variables in the parent function scope;
function login() { var user = "test", isWrongCaptcha = true; if (isWrongCaptcha) { var timeToWait = 10; console.log( "Waiting " + timeToWait + " minutes" ); internal_log_in(); } function internal_log_in() { //The chew function also has access to the //timeToWait variable because it is part of the //eat function's scope console.log("After waiting " + timeToWait + " minutes, " + "I am going to login to the system"); }} login();//Waiting 10 minutes//After waiting 10 minutes, I am going to login to the system
![Page 17: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/17.jpg)
Not aware of JSLint
JSLint is a static code analysis tool used in software development for checking if JavaScript source code complies with coding rules;
Provided primarily as an online tool, but there are also command-line adaptations;
![Page 18: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/18.jpg)
Solution structure
Large scale JavaScript development involves different source types and formats; Presentation code;
Proxy code;
Third party libs;
Solution structure is tightly coupled with the solution architecture approach;
Physical structure should match the solution architecture abstraction;
![Page 19: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/19.jpg)
Solution structure
/scripts /utils
/controllers
/models
/modules
/bootstrappers
/libs
/components
/external
/content /images
/css
/media
/scripts Development helpers
Proxy classes to the server methods
Models used for the client and server side
Modules per functionality
Application/module/plugin initializers
/libs Custom developed components
External libraries
/content /images
/css
/media
![Page 20: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/20.jpg)
Solution architecture
Plan before execute;
Questions to be answered before the design: What will be reused?
How many modules depend on other modules?
Are your module sandboxed?
![Page 21: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/21.jpg)
Solution architecture
Break your application into small single-purpose parts - modules;
Module pattern gives you implementation privacy, state and code organization;
Provide a way to handle private and public methods and variables;
Protects the code to leak into the global namespace;
![Page 22: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/22.jpg)
Solution architecture
namespace.modulename = function(module) {
var privateVar = 'some data';
module.init = function(){
};
module.doSomething = function(){
internalDoSomething();
};
function internalDoSomething(){
};
return module;
}(namespace.modulename || {});
![Page 23: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/23.jpg)
Solution architecture
In some point there will be a need to establish module communication;
In order to avoid tight coupling we can utilize the mediator pattern;
The mediator pattern encapsulates how a set of modules interact;
![Page 24: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/24.jpg)
Solution architecture
![Page 25: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/25.jpg)
Solution architecture
Utilized via Pub/Sub;
Modules communicates via message publishing;
;(function ($) { var o = $({}); $.subscribe = function () { o.on.apply(o, arguments); }; $.unsubscribe = function () { o.off.apply(o, arguments); }; $.publish = function () { o.trigger.apply(o, arguments); };} (jQuery));
$.subscribe('namespace/action', function (data) {
alert(data);});
$.publish('namespace/action', 'data')
![Page 26: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/26.jpg)
Solution architecture
Wrapping it all together;
The modules publish events which inform the application that something is happening;
The modules in the system are subscribed to certain events;
The mediator enables the modules to communicate via the PubSub mechanism;
![Page 27: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/27.jpg)
Solution architecture
![Page 28: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/28.jpg)
Product modules
Utilizing the module pattern;
JavaScript coding pattern;
Module pattern implementation with anonymous closures;
Should be considered: Every module should be part of a namespace;
Every module can contains sub modules;
What will be the global import of the module;
What will the module export;
![Page 29: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/29.jpg)
Product modules
var namespace.module = (function (import) {var me = {};// private propertyvar somePrivateVar = 'Test data';// public propertyme.publicProperty = 'Public data';// private methodfunction privateMethod() {
somePrivateVar = 'executed pvt method';}// publicmethodme.publicMethod = function () {
return me.publicProperty;};// the module exportreturn me;
}(GLOBAL_IMPORT));
![Page 30: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/30.jpg)
Product modules
Module inheritance can be done with module import;
namespace.module = (function (baseModule) {var me = {};// inherit the methods and propertiesfor (key in baseModule) {
if (baseModule.hasOwnProperty(key)) {me[key] = baseModule[key];
}}
var base_publicMethod = baseModule.publicMethod;
// public method overrideme.publicMethod = function () {
return base_publicMethod();};// the module exportreturn me;
}(module));
![Page 31: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/31.jpg)
Dependency management
Which scripts should be loaded before initializing the modules;
Dependency management can be solved by using script loaders: RequireJS;
LABjs;
Yepnope;
General idea is that your module will not be loaded/executed until the required dependencies are not loaded;
![Page 32: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/32.jpg)
Dependency management
$LAB .script("framework.js").wait() .script("plugin.framework.js") .script("myplugin.framework.js") .wait(function(){ myplugin.init(); framework.init(); framework.doSomething(); });
yepnope({ test : IsAdminUser, yep : 'normal.js', nope : ['polyfill.js', 'wrapper.js']});
define(["require", "./relative/name"], function(require) { var mod = require("./relative/name");});
![Page 33: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/33.jpg)
UI Components
Build your UI components in jQuery plugin fashion;
jQuery plugin pattern is well known and understood by most of the UI developers;
Offers simple implementation syntax and offers extensibility;
![Page 34: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/34.jpg)
UI Components
$.fn.pluginName = function(options){ // Create some defaults, extending them with any options that were provided var settings = $.extend( { 'location' : 'top', 'background-color' : 'blue' }, options);
// return the object back to the chained call flow return this.each(function() // This is the main processor // function that executes on // each selected element // (e.g: jQuery("div")) { var $this = $(this); alert($this); });};})(jQuery);
// usage$(document).ready(function() { // create a new instance of the plugin $(‘selector’).pluginName(options);});
![Page 35: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/35.jpg)
Event Driven Messaging
Allow communication between modules via event publishing managed by pub/sub component;
Each module can publish events, subscribe and unsubscribe to events;
![Page 36: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/36.jpg)
Event Driven Messaging
app.usermodule = (function () {var me = {};
me.onNewFriendNotificaion = function(notification){
alert(notification.from);};
me.init = function(){$.subscribe('on-new-friend-
notificaion', me.onNewFriendNotificaion);};
me.destroy = function(){$.unsubscribe('on-new-
friend-notificaion', me.onNewFriendNotificaion);
};
return me;}());
app.streammodule = (function () {var me = {};
me.post = function(){// do some client logic and
notify the other modules$.publish('on-new-friend-
notificaion', { from:'user' });};
return me;}());
![Page 37: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/37.jpg)
Application routing
Managing navigation between application parts and pages;
Useful for: Centralizing navigation;
Uri history;
Navigation logging;
![Page 38: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/38.jpg)
Application routing
<div id="container"> <div id="main"></div> <ul id="link"> <li> <a href="#/form">Form!</a> </li> <li> <a href="#/redirect">Redirect!</a> </li> <li> <a href="#/">Back</a> </li> </ul></div>
;(function ($) { var app = $.sammy('#main', function () { this.debug = true;
this.get('#/', function () { this.app.swap('Click form!'); }); this.get('#/redirect', function () { this.redirect('#/'); }); this.get('#/form', function () { this.partial('files/form.html'); }); }); $(function () { app.run('#/'); });})(jQuery);
![Page 39: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/39.jpg)
Localization
String localization;
Dates, times, numbers, and currencies;
Use jQuery Globalize plugin for Dates, times, numbers, and currencies;
![Page 40: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/40.jpg)
Localization
Store string resources in JSON format so they would be native to client;
Server string resources per culture;
Build language manager for the string resources;
Load the JSON resources into the language manager;
User the language manager to translate plugins, DOM elements and strings;
![Page 41: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/41.jpg)
Logging
Useful for tracking modules state, variables and processes while in development;
Natively supported in all of the new modern browsers;
Use an existing logging framework or wrap your logger around the existing browsers logger;
![Page 42: Enterprise js pratices](https://reader038.vdocuments.us/reader038/viewer/2022110306/554bbca1b4c90530298b4d2d/html5/thumbnails/42.jpg)
Logging
var logger = function(){var logger = {};window.onerror = function(message, file, line) {
logError(file + ':' + line + '\n\n' + message);};logger.log = function(message){
logError(message);};function logError(message){
if(console && console.log){console.log(message);
}};return logger;
}();