javascript abstraction
DESCRIPTION
These are the slides for this presentation http://www.meetup.com/HardCoreJS/events/133346272/ The goal is to influence the thought process of developers and make them into rockstar engineers by showing how to form the habit of abstraction into one's coding.TRANSCRIPT
JavaScriptAbstraction in Implementation
!by Milan Adamovsky
http://milan.adamovsky.com ◆ http://www.hardcorejs.com
Preface
• Based on personal observations
• Spanning over 15 companies
• Small companies to mostly enterprise
• Not based on comprehensive research
• Full life cycle of web development
Quick Exercise
Analyze<html> <head> <title> This is the title of the page </title> </head> <body> <p id="main_content"> This is my content </p> <ul> <li class="first"> One <li> Two <ol> <li class="first"> A </ol> <li> </ul> </body></html>
Analysis
• A document
• A tree of hierarchal nodes off of root node
• Two children nodes off of root node
• Second child node has two children nodes
• Two children nodes are siblings
Overview
• Ultimate goal is to write less code
• Increase reusability
• Change way of thinking
• Change way of coding
• Anticipate future code evolution
Quick Example
Beforefunction resolveFirstName(person) { if (person.firstName) return person.firstName; else return "First name could not be found!";}!function findAge(person) { return person.age;}!function printOutName(person) { if (cookie === "senior") { findAge() + 20; resolveAddress(); } return person.lastName || "No last name was found on record!";}
Afterfunction errorMessage(descriptor) { return ({ age : "Age could not be determined", firstName : "First name could not be found!", lastName : "No last name was found on record!" })[descriptor];}!function resolveDescriptor(descriptor) { return typeof this[descriptor] !== "undefined" ? this[descriptor] : errorMessage(descriptor);}!function resolveSeniority() { if (cookie === "senior") { findAge() + 20; resolveAddress(); }}
Paradigms
Overloading
• One function serves multiple purposes
• Argument signature determines function
• Must differ by arity or data types
• Same function name
• JavaScript can only simulate overloading
Examplefunction addMethod(object, name, fn){ // addMethod - By John Resig (MIT Licensed) var old = object[ name ]; object[ name ] = function(){ if ( fn.length == arguments.length ) return fn.apply( this, arguments ); else if ( typeof old == 'function' ) return old.apply( this, arguments ); };}function Users(){ addMethod(this, "find", function(){ // Find all users... }); addMethod(this, "find", function(name){ // Find a user by name }); addMethod(this, "find", function(first, last){ // Find a user by first and last name });}
Usagevar users = new Users();!users.find(); // Finds all!users.find("John"); // Finds users by name!users.find("John", "Resig"); // Finds users by first and last name!users.find("John", "E", "Resig"); // Does nothing
Events
• Usually we couple an event to a function
• Sometimes many functions to one event
• We know what happens on an event
• We should not care what happens
• Decouple handlers from events
Click
function () { alert(‘hello world!’); }
Coupled Binding
Decoupled Binding
Click
function () { alert(‘hello world!’); }
Greet
Load
Decoupled Binding
function () { alert(‘hello world!’); }
Greet
function
function
OOP
• Object oriented programming
• Base classes are usually most abstract
• Polymorphism
• Duck typing
• Composition
function sayHello() { alert(‘hello world!’); }
Procedural
function joe() { sayHello(); }
joe(); jane();function jane() { sayHello(); }
function sayHello() { alert(‘hello world!’); }
Object Oriented
joe.hi(); jane.hi();
joe = new Person();
jane = new Person();
function Person() { this.hi = sayHello; }
Examplefunction Person(name) { this.hi = sayHello; this.name = name; function sayHello() { console.log('hello world from ' + this.name); }}!function init(names) { var people = []; for (var i = 0, count = names.length; i < count; i++) { people.push(new Person(names[i])); } return people;}function greet(people) { for (var i = 0, count = people.length; i < count; i++) { people[i].hi(); }}greet(init(["Joe", "Jane"]));
Examplevar Rifle = function () { this.reload = function () {}; this.fire = function () { /* ... */ };},!Cannon = function () { this.reload = function () {}; this.fire = function () {};};!var Soldier = function (gun) { this.currentGun = gun; this.inventory = { guns : [ gun ] }; this.attack = function () { this.currentGun.fire(); };};!var Tank = function (gun) { this.currentGun = gun; this.inventory = { guns : [ gun ] }; this.attack = function () { this.currentGun.fire(); };};!var soldier = new Soldier( new Rifle() ), tank = new Tank( new Cannon() );
Examplevar Rifle = function () { this.reload = function () {}; this.fire = function () { /* ... */ };},!Cannon = function () { this.reload = function () {}; this.fire = function () {};};!var Combatant = function (gun) { this.currentGun = gun; this.inventory = { guns : [ gun ] }; this.attack = function () { this.currentGun.fire(); };};!var soldier = new Combatant( new Rifle() ), tank = new Combatant( new Cannon() );
MVC
• Abstraction engrained in architecture
• Separation of concerns (SoC)
• Decouple model, view, controller
• Each component replaceable
• Any of these can be further abstracted
Traditional
HTML
CSS
JS
MVC
HTML
JS
CSS
Data
Examplefunction controller(model, view) { var items = “";! for (var i = 0, count = model.items.length; i < count; i++) { items += view.item.replace("{{item}}", model.items[i]); }! return view.list.replace("{{items}}", items);}!var view = { item : "<li>{{item}}</li>", list : "<ul>{{items}}</ul>"};!var model = { items : [1, 2, 3]};!console.log(controller(model, view));
RWD / AWD
• Responsive responds to screen widths
• Adaptive adapts to devices
• Use mobile-first approach in all code
• Segment code to accommodate growth
• Use lazy loaders and module patterns
Coding
Thought Process
• Do not care for specifics
• Do not care who calls what
• Assume anyone can call anything
• Assume anything can contain anything
• Think interfaces not internals
APIs
• Make them intuitive
• Do not rely on documentation
• Provide switches for easy customization
• Prioritize flexibility and agility of code
• Design functions to handle one thing
Nomenclature
• Generalize identifiers
• Don’t over-generalize, stay within context
• Reverse name groupings
• Group related variables in objects
Beforefunction buildPage() { var facebookIcon = "http://www.facebook.com/icon.png"; while (someConditionIsTrue()){ doSomeWork(); } var i = resolveTwitterIcon(); }!var PinterestSmallLogo = pinterest();!buildPage();
Improvingfunction buildPage() { var iconFacebook = "http://www.facebook.com/icon.png"; while (someConditionIsTrue()){ doSomeWork(); } var iconTwitter = resolveTwitterIcon(); }!var iconPinterest = pinterest();!buildPage();
Afterfunction buildPage(icons) { icons.facebook = "http://www.facebook.com/icon.png"; while (someConditionIsTrue()){ doSomeWork(); } icons.twitter = resolveTwitterIcon(); }!var icons = { facebook : "", pinterest : pinterest(), twitter : ""};!buildPage(icons);
Habit Forming
• Adhere to strict coding style
• Remove comments
• Progressively generalize identifiers
• Identify similar patterns to normalize
• Code in anticipation for change
Generalize
• This will do something
• When something happens
• It will take some parameters
• Parameters will map to some object
• The outcome will be specific to context
Examplefunction initModules() { for (module in app.modules) { if (app.modules[module].init && app.modules[module].checked()) { if (app.modules[module].init.call(this, arguments)) { initialized++; } } } }function initModules() { var module; for (moduleName in app.modules) { module = app.modules[moduleName]; if (module.init && module.checked()) { if (module.init.call(this, arguments)) { initialized++; } } } }
Considerations
• Balance performance
• Balance maintainability
• Strive for quality
• Balance code base size
• Balance complexity
Exercise
0
1 2 3
4 5 6
7 8 9
+ 0 *
Update on button click
White border on click
Gray background
Connect
• Thank you for your time
• Connect with me on LinkedIn
• Join the Hardcore JavaScript community
• Read my blog
• Contact me via e-mail