SlideShare uma empresa Scribd logo
1 de 40
Baixar para ler offline
Why the



SOLID
principles matter - even for JavaScript




               Martin Lippert,VMware
       mlippert@vmware.com, @martinlippert
Why should I care?
Its easy and
smooth at the
   beginning...
Sooner or later...
But why?
Change happens

„Nothing endures but change“
                        Heraclitus
Dependencies matter
„Taking care of dependencies is one of the most
  critical success factors of healthy software.“
Utilities
        structured                                               object-oriented
       programming                                                programming
(„Go To Statement Considered Harmful“, 1968)
                                                                     (Simula 1967)


                                       functional
                                     programming                       modular
                                     (Lambda calculus 1930ies)
                                                                     programming
                                                                           (Modula-2 1978)
                 APIs
                                               component-oriented
                   plugins                         software
                    (Eclipse 2001)
Back to Reality
„structured“
programming
then we got
object-orientation
now everybody is
 programming in
    JavaScript
Design Principles matter
Information Hiding      Don‘t Repeat Yourself

Interface Segregation   Separation Of Concerns

 Liskov Substitution        Simple Design

Single Responsibility      Avoid Inheritance

   Speaking Code             Open Close

Dependency Inversion        Tell, Don‘t Ask

             Acyclic Dependencies
Single Responsibility
Open Close
Liskov Substitution
Interface Segregation
Dependency Inversion
Single Responsibility
             Principle




   „A class should have one,
and only one, reason to change.“
function Product(id, description) {
    this.getId = function() {
        return id;
    };
    this.getDescription = function() {
        return description;
    };
}                                                    (function() {
                                                         function addToCart() {
function Cart(eventAggregator) {                             var productId = $(this).attr('id');
    var items = [];                                          var product = $.grep(products, function(x) {
                                                                 return x.getId() == productId;
    this.addItem = function(item) {                          })[0];
        items.push(item);                                    cart.addItem(product);
    };
}                                                                 var newItem = $('<li></li>')
                                                                      .html(product.getDescription())
var products = [                                                      .attr('id-cart', product.getId())
    new Product(1, "Star Wars Lego Ship"),                            .appendTo("#cart");
    new Product(2, "Barbie Doll"),                          }
    new Product(3, "Remote Control Airplane")],
    cart = new Cart();                                   products.forEach(function(product) {
                                                             var newItem = $('<li></li>')
                                                                 .html(product.getDescription())
                                                                 .attr('id', product.getId())
                                                                 .dblclick(addToCart)
                                                                 .appendTo("#products");
                                                         });
                                                     })();



                                         http://freshbrewedcode.com/derekgreer/2011/12/08/solid-javascript-single-responsibility-principle/
function Product(id, description) {
                    add the item to the cart
    this.getId = function() {

    };
        return id;
                    when an item is clicked
    this.getDescription = function() {
        return description;
    };
}                                                    (function() {
                                                         function addToCart() {
function Cart(eventAggregator) {                             var productId = $(this).attr('id');
    updating the DOM to display
    var items = [];                                          var product = $.grep(products, function(x) {
                                                                 return x.getId() == productId;
          the newly added item
     this.addItem = function(item) {
         items.push(item);
                                                             })[0];
                                                             cart.addItem(product);
    };
}                                                                 var newItem = $('<li></li>')
                                                                      .html(product.getDescription())
var products = [                                                      .attr('id-cart', product.getId())
    new Product(1, "Star Wars Lego Ship"),                            .appendTo("#cart");
    new Product(2, "Barbie Doll"),                          }
    new Product(3, "Remote Control Airplane")],
    cart = new Cart();                                   products.forEach(function(product) {
         populate the initial list of                        var newItem = $('<li></li>')

          products on the page                                   .html(product.getDescription())
                                                                 .attr('id', product.getId())
                                                                 .dblclick(addToCart)
                                                                 .appendTo("#products");
                                                         });
                                                     })();



                                         http://freshbrewedcode.com/derekgreer/2011/12/08/solid-javascript-single-responsibility-principle/
MVC pattern instead
function Cart() {
    var items = [];

    this.addItem = function(item) {
        items.push(item);
        eventAggregator.publish("itemAdded", item);
    };
}

var cartView = (function() {
    eventAggregator.subscribe("itemAdded", function(eventArgs) {
        var newItem = $('<li></li>')
            .html(eventArgs.getDescription())
            .attr('id-cart', eventArgs.getId())
            .appendTo("#cart");
    });
})();

var cartController = (function(cart) {
    eventAggregator.subscribe("productSelected", function(eventArgs) {
        cart.addItem(eventArgs.product);
    });
})(new Cart());




                         http://freshbrewedcode.com/derekgreer/2011/12/08/solid-javascript-single-responsibility-principle/
function Product(id, description) {
    this.getId = function() {
        return id;
    };
    this.getDescription = function() {
        return description;
    };
}

var productView = (function() {
    function onProductSelected() {
        var productId = $(this).attr('id');
        var product = $.grep(products, function(x) {
            return x.getId() == productId;
        })[0];
        eventAggregator.publish("productSelected", {
            product: product
        });
    }

    products.forEach(function(product) {
        var newItem = $('<li></li>')
            .html(product.getDescription())
            .attr('id', product.getId())
            .dblclick(onProductSelected)
            .appendTo("#products");
    });
})();




                  http://freshbrewedcode.com/derekgreer/2011/12/08/solid-javascript-single-responsibility-principle/
Open Close
                  Principle




     „You should be able to extend
a classes behavior, without modifying it.“
var AnswerType = {                 var view = (function() {
    Choice: 0,                         function renderQuestion(target, question) {
    Input: 1                               ... // create DOM nodes
};
                                           if (question.answerType === AnswerType.Choice) {
function question(label,                       var input = document.createElement('select');
       answerType,                             var len = question.choices.length;
       choices) {                              for (var i = 0; i < len; i++) {
    return {                                       var option = document.createElement('option');
         label: label,                             option.text = question.choices[i];
         answerType: answerType,                   option.value = question.choices[i];
         choices: choices                          input.appendChild(option);
    };                                         }
}                                          }
                                           else if (question.answerType === AnswerType.Input) {
                                               var input = document.createElement('input');
                                               input.type = 'text';
                                           }

                                           answer.appendChild(input);
                                           questionWrapper.appendChild(questionLabel);
                                           questionWrapper.appendChild(answer);
                                           target.appendChild(questionWrapper);
                                       }

                                       return {
                                           render: function(target, questions) {
                                                for (var i = 0; i < questions.length; i++) {
                                                    renderQuestion(target, questions[i]);
                                                };
                                           }
                                       };
                                   })();

                                            http://freshbrewedcode.com/derekgreer/2011/12/19/solid-javascript-the-openclosed-principle/
var AnswerType = {                 var view = (function() {
    Choice: 0,                         function renderQuestion(target, question) {
    Input: 1                               ... // create DOM nodes
};
                                            if (question.answerType === AnswerType.Choice) {
function question(label,                        var input = document.createElement('select');
             change here
       answerType,                              var len = question.choices.length;
                                                for (var i = 0; i < len; i++) {
       choices) {
    return {                                        var option = document.createElement('option');
         label: label,                              option.text = question.choices[i];
         answerType: answerType,                    option.value = question.choices[i];
         choices: choices                           input.appendChild(option);
    };                                          }
}                                           }
                                            else if (question.answerType === AnswerType.Input) {
                                                var input = document.createElement('input');
      change here                               input.type = 'text';
                                            }

                                            answer.appendChild(input);
                                            questionWrapper.appendChild(questionLabel);
                                            questionWrapper.appendChild(answer);
                       adding new answer types or
                                }
                                            target.appendChild(questionWrapper);

                     changing the set{ of answer types
                                return
                            requires for function(target,questions.length; i++) {
                                         changes 0; i < questions) {
                                    render:
                                            (var i =
                                                           renderQuestion(target, questions[i]);
                                                    };
                                            }
                                       };
                                   })();

                                                http://freshbrewedcode.com/derekgreer/2011/12/19/solid-javascript-the-openclosed-principle/
factory method + strategy pattern instead
    function questionCreator(spec, my) {
        var that = {};

        my = my || {};
        my.label = spec.label;

        my.renderInput = function() {
            throw "not implemented";
        };

        that.render = function(target) {
            var questionWrapper = document.createElement('div');
            questionWrapper.className = 'question';

             var questionLabel = document.createElement('div');
             questionLabel.className = 'question-label';
             var label = document.createTextNode(spec.label);
             questionLabel.appendChild(label);

             var answer = my.renderInput();

             questionWrapper.appendChild(questionLabel);
             questionWrapper.appendChild(answer);
             return questionWrapper;
        };

        return that;
    }

                          http://freshbrewedcode.com/derekgreer/2011/12/19/solid-javascript-the-openclosed-principle/
function choiceQuestionCreator(spec) {

    var my = {},
        that = questionCreator(spec, my);

    my.renderInput = function() {
        var input = document.createElement('select');
        var len = spec.choices.length;
        for (var i = 0; i < len; i++) {
            var option = document.createElement('option');
            option.text = spec.choices[i];
            option.value = spec.choices[i];
            input.appendChild(option);
        }

         return input;
    };
                                    function inputQuestionCreator(spec) {
    return that;
}                                         var my = {},
                                              that = questionCreator(spec, my);

                                          my.renderInput = function() {
                                              var input = document.createElement('input');
                                              input.type = 'text';
                                              return input;
                                          };

                                          return that;
                                    }



                                         http://freshbrewedcode.com/derekgreer/2011/12/19/solid-javascript-the-openclosed-principle/
var view = {
    render: function(target, questions) {
        for (var i = 0; i < questions.length; i++) {
             target.appendChild(questions[i].render());
        }
    }
};

var questions = [
    choiceQuestionCreator({
    label: 'Have you used tobacco products within the last 30 days?',
    choices: ['Yes', 'No']
}),
    inputQuestionCreator({
    label: 'What medications are you currently using?'
})
    ];
                                               var AnswerType = {
                                                   Choice: 0,
                                                   Input: 1
                                               };

                                                      function question(label,
                                                             answerType,
                                                             choices) {
                                                          return {
                                                               label: label,
                                                               answerType: answerType,
                                                               choices: choices
                                                          };
                                                      }
                                  http://freshbrewedcode.com/derekgreer/2011/12/19/solid-javascript-the-openclosed-principle/
Liskov Substitution
                Principle




„Derived classes must be substitutable
       for their base classes.“
function Vehicle(my) {
    my = my || {};
    my.speed = 0;
    my.running = false;

    this.speed = function() {                                function FastVehicle(my) {
        return my.speed;                                         my = my || {};
    };
    this.start = function() {                                       var that = new Vehicle(my);
        my.running = true;                                          that.accelerate = function() {
    };                                                                  my.speed += 3;
    this.stop = function() {                                        };
        my.running = false;                                         return that;
    };                                                       }
    this.accelerate = function() {
        my.speed++;
    };
    this.decelerate = function() {
        my.speed--;
    };
    this.state = function() {
        if (!my.running) {
            return "parked";
        }
        else if (my.running && my.speed) {
            return "moving";
        }
        else if (my.running) {
            return "idle";
        }
    };
}


                                  http://freshbrewedcode.com/derekgreer/2011/12/31/solid-javascript-the-liskov-substitution-principle/
function Vehicle(my) {
    my = my || {};
    my.speed = 0;
    my.running = false;

    this.speed = function() {                                function FastVehicle(my) {
        return my.speed;                                         my = my || {};
    };
    this.start = function() {                                       var that = new Vehicle(my);
        my.running = true;                                          that.accelerate = function() {
    };                                                                  my.speed += 3;
    this.stop = function() {                                        };
        my.running = false;                                         return that;
    };                                                       }
    this.accelerate = function() {
        my.speed++;
    };
    this.decelerate = function() {
        my.speed--;
    };

                            changes behavior, therefore
    this.state = function() {
        if (!my.running) {

        }
            return "parked";
                              breaks existing clients
        else if (my.running && my.speed) {
            return "moving";
        }
        else if (my.running) {
            return "idle";
        }
    };
}


                                  http://freshbrewedcode.com/derekgreer/2011/12/31/solid-javascript-the-liskov-substitution-principle/
Solutions?

    Design by Contract
(avoid inheritance principle)
  test-driven development


       but remember:
     its about behavior
       not inheritance
Interface Segregation
           Principle




„Make fine grained interfaces
  that are client specific.“
var exampleBinder = {};
exampleBinder.modelObserver = (function() {
    /* private variables */
    return {
        observe: function(model) {
             /* code */
             return newModel;
        },
        onChange: function(callback) {
             /* code */
        }
    }
})();

exampleBinder.viewAdaptor = (function() {
    /* private variables */
    return {
        bind: function(model) {
             /* code */
        }
    }
})();

exampleBinder.bind = function(model) {
    /* private variables */
    exampleBinder.modelObserver.onChange(/* callback */);
    var om = exampleBinder.modelObserver.observe(model);
    exampleBinder.viewAdaptor.bind(om);
    return om;
};



                     http://freshbrewedcode.com/derekgreer/2012/01/08/solid-javascript-the-interface-segregation-principle/
var exampleBinder = {};
exampleBinder.modelObserver = (function() {
    /* private variables */
    return {
        observe: function(model) {
             /* code */
             return newModel;
        },
        onChange: function(callback) {
             /* code */
        }
    }
})();


                                      implicit interface defined,
exampleBinder.viewAdaptor = (function() {
    /* private variables */
    return {
        bind: function(model) {
                                      callbacks are often similar
             /* code */
        }
    }
})();

exampleBinder.bind = function(model) {
    /* private variables */
    exampleBinder.modelObserver.onChange(/* callback */);
    var om = exampleBinder.modelObserver.observe(model);
    exampleBinder.viewAdaptor.bind(om);
    return om;
};



                     http://freshbrewedcode.com/derekgreer/2012/01/08/solid-javascript-the-interface-segregation-principle/
Dependency Inversion
         Principle




„Depend on abstractions,
  not on concretions.“
$.fn.trackMap = function(options) {
    ...

     var mapOptions = {
         center: new google.maps.LatLng(options.latitude,options.longitude),
         zoom: 12,
         mapTypeId: google.maps.MapTypeId.ROADMAP
     },
         map = new google.maps.Map(this[0], mapOptions),
         pos = new google.maps.LatLng(options.latitude,options.longitude);

     var marker = new google.maps.Marker({
         position: pos,
         title: options.title,
         icon: options.icon
     });

     marker.setMap(map);

     options.feed.update(function(latitude, longitude) {
         marker.setMap(null);
         var newLatLng = new google.maps.LatLng(latitude, longitude);
         marker.position = newLatLng;
         marker.setMap(map);
         map.setCenter(newLatLng);
     });
                                                      $("#map_canvas").trackMap({
                                                          latitude: 35.044640193770725,
     return this;
                                                          longitude: -89.98193264007568,
};
                                                          icon: 'http://bit.ly/zjnGDe',
                                                          title: 'Tracking Number: 12345',
                                                          feed: updater
                                                      });

                                      http://freshbrewedcode.com/derekgreer/2012/01/22/solid-javascript-the-dependency-inversion-principle/
$.fn.trackMap = function(options) {
    ...

     var mapOptions = {                                            depends on the Google
         center: new google.maps.LatLng(options.latitude,options.longitude),
         zoom: 12,
         mapTypeId: google.maps.MapTypeId.ROADMAP
                                                                         Maps API
     },
         map = new google.maps.Map(this[0], mapOptions),
         pos = new google.maps.LatLng(options.latitude,options.longitude);

     var marker = new google.maps.Marker({
         position: pos,
         title: options.title,
         icon: options.icon
     });                                                       depends on the feed API
     marker.setMap(map);

     options.feed.update(function(latitude, longitude) {
         marker.setMap(null);
         var newLatLng = new google.maps.LatLng(latitude, longitude);
         marker.position = newLatLng;
         marker.setMap(map);
         map.setCenter(newLatLng);
     });
                                                      $("#map_canvas").trackMap({
                                                          latitude: 35.044640193770725,
     return this;
                                                          longitude: -89.98193264007568,
};
                                                          icon: 'http://bit.ly/zjnGDe',
                                                          title: 'Tracking Number: 12345',
                                                          feed: updater
                                                      });

                                      http://freshbrewedcode.com/derekgreer/2012/01/22/solid-javascript-the-dependency-inversion-principle/
introduce implicit interface
$.fn.trackMap = function(options) {
    var defaults = {
        /* defaults */
    };

     options = $.extend({}, defaults, options);

     options.provider.showMap(
         this[0],
         options.latitude,
         options.longitude,
         options.icon,
         options.title);

     options.feed.update(function(latitude, longitude) {
         options.provider.updateMap(latitude, longitude);
     });

     return this;
};

$("#map_canvas").trackMap({
    latitude: 35.044640193770725,
    longitude: -89.98193264007568,
    icon: 'http://bit.ly/zjnGDe',
    title: 'Tracking Number: 12345',
    feed: updater,
    provider: trackMap.googleMapsProvider
});
                http://freshbrewedcode.com/derekgreer/2012/01/22/solid-javascript-the-dependency-inversion-principle/
trackMap.googleMapsProvider = (function() {
    var marker, map;

    return {
        showMap: function(element, latitude, longitude, icon, title) {
             var mapOptions = {
                 center: new google.maps.LatLng(latitude, longitude),
                 zoom: 12,
                 mapTypeId: google.maps.MapTypeId.ROADMAP
             },
                 pos = new google.maps.LatLng(latitude, longitude);

             map = new google.maps.Map(element, mapOptions);

             marker = new google.maps.Marker({
                 position: pos,
                 title: title,
                 icon: icon
             });

             marker.setMap(map);
         },
         updateMap: function(latitude, longitude) {
             marker.setMap(null);
             var newLatLng = new google.maps.LatLng(latitude,longitude);
             marker.position = newLatLng;
             marker.setMap(map);
             map.setCenter(newLatLng);
         }
    };
})();



                        http://freshbrewedcode.com/derekgreer/2012/01/22/solid-javascript-the-dependency-inversion-principle/
„Design principles are essential
 for healthy code. Think about
      them all the time.“
Q&A
and thank you for your attention




        Martin Lippert,VMware
mlippert@vmware.com, @martinlippert

Mais conteúdo relacionado

Mais procurados

Handling action bar in Android
Handling action bar in AndroidHandling action bar in Android
Handling action bar in Androidindiangarg
 
How to Mess Up Your Angular UI Components
How to Mess Up Your Angular UI ComponentsHow to Mess Up Your Angular UI Components
How to Mess Up Your Angular UI Componentscagataycivici
 
What's New in Android
What's New in AndroidWhat's New in Android
What's New in AndroidRobert Cooper
 
Android App Development - 05 Action bar
Android App Development - 05 Action barAndroid App Development - 05 Action bar
Android App Development - 05 Action barDiego Grancini
 
Practical AngularJS
Practical AngularJSPractical AngularJS
Practical AngularJSWei Ru
 
Upgrading from Angular 1.x to Angular 2.x
Upgrading from Angular 1.x to Angular 2.xUpgrading from Angular 1.x to Angular 2.x
Upgrading from Angular 1.x to Angular 2.xEyal Vardi
 
"Angular.js Concepts in Depth" by Aleksandar Simović
"Angular.js Concepts in Depth" by Aleksandar Simović"Angular.js Concepts in Depth" by Aleksandar Simović
"Angular.js Concepts in Depth" by Aleksandar SimovićJS Belgrade
 
Windows Store app using XAML and C#: Enterprise Product Development
Windows Store app using XAML and C#: Enterprise Product Development Windows Store app using XAML and C#: Enterprise Product Development
Windows Store app using XAML and C#: Enterprise Product Development Mahmoud Hamed Mahmoud
 
Building Reusable Custom Elements With Angular
Building Reusable Custom Elements With AngularBuilding Reusable Custom Elements With Angular
Building Reusable Custom Elements With AngularIlia Idakiev
 
Angular Mini-Challenges
Angular Mini-ChallengesAngular Mini-Challenges
Angular Mini-ChallengesJose Mendez
 
준비하세요 Angular js 2.0
준비하세요 Angular js 2.0준비하세요 Angular js 2.0
준비하세요 Angular js 2.0Jeado Ko
 
AngularJs Workshop SDP December 28th 2014
AngularJs Workshop SDP December 28th 2014AngularJs Workshop SDP December 28th 2014
AngularJs Workshop SDP December 28th 2014Ran Wahle
 
Presentation technico-commercial-ruby-on-rails
Presentation technico-commercial-ruby-on-railsPresentation technico-commercial-ruby-on-rails
Presentation technico-commercial-ruby-on-railsNovelys
 
Design Patterns for Tablets and Smartphones
Design Patterns for Tablets and SmartphonesDesign Patterns for Tablets and Smartphones
Design Patterns for Tablets and SmartphonesMichael Galpin
 

Mais procurados (20)

AngularJS Framework
AngularJS FrameworkAngularJS Framework
AngularJS Framework
 
Handling action bar in Android
Handling action bar in AndroidHandling action bar in Android
Handling action bar in Android
 
How to Mess Up Your Angular UI Components
How to Mess Up Your Angular UI ComponentsHow to Mess Up Your Angular UI Components
How to Mess Up Your Angular UI Components
 
What's New in Android
What's New in AndroidWhat's New in Android
What's New in Android
 
Android App Development - 05 Action bar
Android App Development - 05 Action barAndroid App Development - 05 Action bar
Android App Development - 05 Action bar
 
Practical AngularJS
Practical AngularJSPractical AngularJS
Practical AngularJS
 
Upgrading from Angular 1.x to Angular 2.x
Upgrading from Angular 1.x to Angular 2.xUpgrading from Angular 1.x to Angular 2.x
Upgrading from Angular 1.x to Angular 2.x
 
"Angular.js Concepts in Depth" by Aleksandar Simović
"Angular.js Concepts in Depth" by Aleksandar Simović"Angular.js Concepts in Depth" by Aleksandar Simović
"Angular.js Concepts in Depth" by Aleksandar Simović
 
Windows Store app using XAML and C#: Enterprise Product Development
Windows Store app using XAML and C#: Enterprise Product Development Windows Store app using XAML and C#: Enterprise Product Development
Windows Store app using XAML and C#: Enterprise Product Development
 
Building Reusable Custom Elements With Angular
Building Reusable Custom Elements With AngularBuilding Reusable Custom Elements With Angular
Building Reusable Custom Elements With Angular
 
Angular Mini-Challenges
Angular Mini-ChallengesAngular Mini-Challenges
Angular Mini-Challenges
 
준비하세요 Angular js 2.0
준비하세요 Angular js 2.0준비하세요 Angular js 2.0
준비하세요 Angular js 2.0
 
AngularJs Crash Course
AngularJs Crash CourseAngularJs Crash Course
AngularJs Crash Course
 
Angular In Depth
Angular In DepthAngular In Depth
Angular In Depth
 
Action bar
Action barAction bar
Action bar
 
Patterns in PHP
Patterns in PHPPatterns in PHP
Patterns in PHP
 
AngularJs Workshop SDP December 28th 2014
AngularJs Workshop SDP December 28th 2014AngularJs Workshop SDP December 28th 2014
AngularJs Workshop SDP December 28th 2014
 
Android 3
Android 3Android 3
Android 3
 
Presentation technico-commercial-ruby-on-rails
Presentation technico-commercial-ruby-on-railsPresentation technico-commercial-ruby-on-rails
Presentation technico-commercial-ruby-on-rails
 
Design Patterns for Tablets and Smartphones
Design Patterns for Tablets and SmartphonesDesign Patterns for Tablets and Smartphones
Design Patterns for Tablets and Smartphones
 

Destaque

Apply SOLID Design principles to javascript code with immediate function invo...
Apply SOLID Design principles to javascript code with immediate function invo...Apply SOLID Design principles to javascript code with immediate function invo...
Apply SOLID Design principles to javascript code with immediate function invo...Anuradha Bandara
 
Modern JavaScript Talk
Modern JavaScript TalkModern JavaScript Talk
Modern JavaScript TalkDerek Binkley
 
Solid JavaScript Coding
Solid JavaScript CodingSolid JavaScript Coding
Solid JavaScript CodingDiwa Del Mundo
 
JavaScript MV* Framework - Making the Right Choice
JavaScript MV* Framework - Making the Right ChoiceJavaScript MV* Framework - Making the Right Choice
JavaScript MV* Framework - Making the Right ChoiceDmitry Sheiko
 
Классическое программирование для фронтендеров
Классическое программирование для фронтендеровКлассическое программирование для фронтендеров
Классическое программирование для фронтендеровBadoo Development
 
How Angular2 Can Improve Your AngularJS Apps Today!
How Angular2 Can Improve Your AngularJS Apps Today!How Angular2 Can Improve Your AngularJS Apps Today!
How Angular2 Can Improve Your AngularJS Apps Today!Nir Kaufman
 
AngularJS application architecture
AngularJS application architectureAngularJS application architecture
AngularJS application architectureGabriele Falace
 
Rethinking Best Practices
Rethinking Best PracticesRethinking Best Practices
Rethinking Best Practicesfloydophone
 
AngularJS Architecture
AngularJS ArchitectureAngularJS Architecture
AngularJS ArchitectureEyal Vardi
 

Destaque (10)

Apply SOLID Design principles to javascript code with immediate function invo...
Apply SOLID Design principles to javascript code with immediate function invo...Apply SOLID Design principles to javascript code with immediate function invo...
Apply SOLID Design principles to javascript code with immediate function invo...
 
Modern JavaScript Talk
Modern JavaScript TalkModern JavaScript Talk
Modern JavaScript Talk
 
Solid JavaScript Coding
Solid JavaScript CodingSolid JavaScript Coding
Solid JavaScript Coding
 
JavaScript MV* Framework - Making the Right Choice
JavaScript MV* Framework - Making the Right ChoiceJavaScript MV* Framework - Making the Right Choice
JavaScript MV* Framework - Making the Right Choice
 
Классическое программирование для фронтендеров
Классическое программирование для фронтендеровКлассическое программирование для фронтендеров
Классическое программирование для фронтендеров
 
S.O.L.I.D-ый JavaScript
S.O.L.I.D-ый JavaScriptS.O.L.I.D-ый JavaScript
S.O.L.I.D-ый JavaScript
 
How Angular2 Can Improve Your AngularJS Apps Today!
How Angular2 Can Improve Your AngularJS Apps Today!How Angular2 Can Improve Your AngularJS Apps Today!
How Angular2 Can Improve Your AngularJS Apps Today!
 
AngularJS application architecture
AngularJS application architectureAngularJS application architecture
AngularJS application architecture
 
Rethinking Best Practices
Rethinking Best PracticesRethinking Best Practices
Rethinking Best Practices
 
AngularJS Architecture
AngularJS ArchitectureAngularJS Architecture
AngularJS Architecture
 

Semelhante a Why SOLID matters - even for JavaScript

Android Design Patterns
Android Design PatternsAndroid Design Patterns
Android Design PatternsGodfrey Nolan
 
That’s My App - Running in Your Background - Draining Your Battery
That’s My App - Running in Your Background - Draining Your BatteryThat’s My App - Running in Your Background - Draining Your Battery
That’s My App - Running in Your Background - Draining Your BatteryMichael Galpin
 
Google App Engine in 40 minutes (the absolute essentials)
Google App Engine in 40 minutes (the absolute essentials)Google App Engine in 40 minutes (the absolute essentials)
Google App Engine in 40 minutes (the absolute essentials)Python Ireland
 
Beautiful java script
Beautiful java scriptBeautiful java script
Beautiful java scriptÜrgo Ringo
 
Sharper Better Faster Dagger ‡ - Droidcon SF
Sharper Better Faster Dagger ‡ - Droidcon SFSharper Better Faster Dagger ‡ - Droidcon SF
Sharper Better Faster Dagger ‡ - Droidcon SFPierre-Yves Ricau
 
Web Components Everywhere
Web Components EverywhereWeb Components Everywhere
Web Components EverywhereIlia Idakiev
 
OBJECTS IN Object Oriented Programming .ppt
OBJECTS IN Object Oriented Programming .pptOBJECTS IN Object Oriented Programming .ppt
OBJECTS IN Object Oriented Programming .pptSaadAsim11
 
Creating an Uber Clone - Part XXIV.pdf
Creating an Uber Clone - Part XXIV.pdfCreating an Uber Clone - Part XXIV.pdf
Creating an Uber Clone - Part XXIV.pdfShaiAlmog1
 
The Principle of Hybrid App.
The Principle of Hybrid App.The Principle of Hybrid App.
The Principle of Hybrid App.musart Park
 
20180721 code defragment
20180721 code defragment20180721 code defragment
20180721 code defragmentChiwon Song
 
Creating lightweight JS Apps w/ Web Components and lit-html
Creating lightweight JS Apps w/ Web Components and lit-htmlCreating lightweight JS Apps w/ Web Components and lit-html
Creating lightweight JS Apps w/ Web Components and lit-htmlIlia Idakiev
 
Writing Maintainable JavaScript
Writing Maintainable JavaScriptWriting Maintainable JavaScript
Writing Maintainable JavaScriptAndrew Dupont
 
Ten useful JavaScript tips & best practices
Ten useful JavaScript tips & best practicesTen useful JavaScript tips & best practices
Ten useful JavaScript tips & best practicesAnkit Rastogi
 
Infinum Android Talks #20 - DiffUtil
Infinum Android Talks #20 - DiffUtilInfinum Android Talks #20 - DiffUtil
Infinum Android Talks #20 - DiffUtilInfinum
 
Your Entity, Your Code
Your Entity, Your CodeYour Entity, Your Code
Your Entity, Your CodeDrupalDay
 
Taming that client side mess with Backbone.js
Taming that client side mess with Backbone.jsTaming that client side mess with Backbone.js
Taming that client side mess with Backbone.jsJarod Ferguson
 

Semelhante a Why SOLID matters - even for JavaScript (20)

Android Design Patterns
Android Design PatternsAndroid Design Patterns
Android Design Patterns
 
Mpg Dec07 Gian Lorenzetto
Mpg Dec07 Gian Lorenzetto Mpg Dec07 Gian Lorenzetto
Mpg Dec07 Gian Lorenzetto
 
That’s My App - Running in Your Background - Draining Your Battery
That’s My App - Running in Your Background - Draining Your BatteryThat’s My App - Running in Your Background - Draining Your Battery
That’s My App - Running in Your Background - Draining Your Battery
 
Google App Engine in 40 minutes (the absolute essentials)
Google App Engine in 40 minutes (the absolute essentials)Google App Engine in 40 minutes (the absolute essentials)
Google App Engine in 40 minutes (the absolute essentials)
 
Beautiful java script
Beautiful java scriptBeautiful java script
Beautiful java script
 
Sharper Better Faster Dagger ‡ - Droidcon SF
Sharper Better Faster Dagger ‡ - Droidcon SFSharper Better Faster Dagger ‡ - Droidcon SF
Sharper Better Faster Dagger ‡ - Droidcon SF
 
Web Components Everywhere
Web Components EverywhereWeb Components Everywhere
Web Components Everywhere
 
OBJECTS IN Object Oriented Programming .ppt
OBJECTS IN Object Oriented Programming .pptOBJECTS IN Object Oriented Programming .ppt
OBJECTS IN Object Oriented Programming .ppt
 
Creating an Uber Clone - Part XXIV.pdf
Creating an Uber Clone - Part XXIV.pdfCreating an Uber Clone - Part XXIV.pdf
Creating an Uber Clone - Part XXIV.pdf
 
The Principle of Hybrid App.
The Principle of Hybrid App.The Principle of Hybrid App.
The Principle of Hybrid App.
 
20180721 code defragment
20180721 code defragment20180721 code defragment
20180721 code defragment
 
Creating lightweight JS Apps w/ Web Components and lit-html
Creating lightweight JS Apps w/ Web Components and lit-htmlCreating lightweight JS Apps w/ Web Components and lit-html
Creating lightweight JS Apps w/ Web Components and lit-html
 
Clean Javascript
Clean JavascriptClean Javascript
Clean Javascript
 
Writing Maintainable JavaScript
Writing Maintainable JavaScriptWriting Maintainable JavaScript
Writing Maintainable JavaScript
 
Ten useful JavaScript tips & best practices
Ten useful JavaScript tips & best practicesTen useful JavaScript tips & best practices
Ten useful JavaScript tips & best practices
 
Infinum Android Talks #20 - DiffUtil
Infinum Android Talks #20 - DiffUtilInfinum Android Talks #20 - DiffUtil
Infinum Android Talks #20 - DiffUtil
 
Your Entity, Your Code
Your Entity, Your CodeYour Entity, Your Code
Your Entity, Your Code
 
Your Entity, Your Code
Your Entity, Your CodeYour Entity, Your Code
Your Entity, Your Code
 
Android workshop
Android workshopAndroid workshop
Android workshop
 
Taming that client side mess with Backbone.js
Taming that client side mess with Backbone.jsTaming that client side mess with Backbone.js
Taming that client side mess with Backbone.js
 

Mais de martinlippert

WJAX 2013: Java8-Tooling in Eclipse
WJAX 2013: Java8-Tooling in EclipseWJAX 2013: Java8-Tooling in Eclipse
WJAX 2013: Java8-Tooling in Eclipsemartinlippert
 
WJAX 2013: Die PaaS-Parade - Teil 2 - Cloud Foundry
WJAX 2013: Die PaaS-Parade - Teil 2 - Cloud FoundryWJAX 2013: Die PaaS-Parade - Teil 2 - Cloud Foundry
WJAX 2013: Die PaaS-Parade - Teil 2 - Cloud Foundrymartinlippert
 
EclipseCon-Europe 2013: Optimizing performance - how to make your Eclipse-bas...
EclipseCon-Europe 2013: Optimizing performance - how to make your Eclipse-bas...EclipseCon-Europe 2013: Optimizing performance - how to make your Eclipse-bas...
EclipseCon-Europe 2013: Optimizing performance - how to make your Eclipse-bas...martinlippert
 
EclipseCon-Europe 2013: Making the Eclipse IDE fun again
EclipseCon-Europe 2013: Making the Eclipse IDE fun againEclipseCon-Europe 2013: Making the Eclipse IDE fun again
EclipseCon-Europe 2013: Making the Eclipse IDE fun againmartinlippert
 
Jax2013 PaaS-Parade - Part 1: Cloud Foundry
Jax2013 PaaS-Parade - Part 1: Cloud FoundryJax2013 PaaS-Parade - Part 1: Cloud Foundry
Jax2013 PaaS-Parade - Part 1: Cloud Foundrymartinlippert
 
JAX 2013: Modern Architectures with Spring and JavaScript
JAX 2013: Modern Architectures with Spring and JavaScriptJAX 2013: Modern Architectures with Spring and JavaScript
JAX 2013: Modern Architectures with Spring and JavaScriptmartinlippert
 
JAX 2013: Introducing Eclipse Orion
JAX 2013: Introducing Eclipse OrionJAX 2013: Introducing Eclipse Orion
JAX 2013: Introducing Eclipse Orionmartinlippert
 
Spring Tooling: What's new and what's coming
Spring Tooling: What's new and what's comingSpring Tooling: What's new and what's coming
Spring Tooling: What's new and what's comingmartinlippert
 
Modern Architectures with Spring and JavaScript
Modern Architectures with Spring and JavaScriptModern Architectures with Spring and JavaScript
Modern Architectures with Spring and JavaScriptmartinlippert
 
Scripted - Embracing Eclipse Orion
Scripted - Embracing Eclipse OrionScripted - Embracing Eclipse Orion
Scripted - Embracing Eclipse Orionmartinlippert
 
PaaS Parade - Cloud Foundry
PaaS Parade - Cloud FoundryPaaS Parade - Cloud Foundry
PaaS Parade - Cloud Foundrymartinlippert
 
Browser and Cloud - The Future of IDEs?
Browser and Cloud - The Future of IDEs?Browser and Cloud - The Future of IDEs?
Browser and Cloud - The Future of IDEs?martinlippert
 
Modern Architectures with Spring and JavaScript
Modern Architectures with Spring and JavaScriptModern Architectures with Spring and JavaScript
Modern Architectures with Spring and JavaScriptmartinlippert
 
What's new with tooling for Spring, Grails, and the Cloud
What's new with tooling for Spring, Grails, and the CloudWhat's new with tooling for Spring, Grails, and the Cloud
What's new with tooling for Spring, Grails, and the Cloudmartinlippert
 
Tooling for the JavaScript Era
Tooling for the JavaScript EraTooling for the JavaScript Era
Tooling for the JavaScript Eramartinlippert
 
Embracing Eclipse Orion
Embracing Eclipse OrionEmbracing Eclipse Orion
Embracing Eclipse Orionmartinlippert
 
JAX 2012: Moderne Architektur mit Spring und JavaScript
JAX 2012: Moderne Architektur mit Spring und JavaScriptJAX 2012: Moderne Architektur mit Spring und JavaScript
JAX 2012: Moderne Architektur mit Spring und JavaScriptmartinlippert
 
JAX 2012: Pimp Your IDE Productivity
JAX 2012: Pimp Your IDE ProductivityJAX 2012: Pimp Your IDE Productivity
JAX 2012: Pimp Your IDE Productivitymartinlippert
 
WaveMaker - Spring Roo - SpringSource Tool Suite - Choosing the right tool fo...
WaveMaker - Spring Roo - SpringSource Tool Suite - Choosing the right tool fo...WaveMaker - Spring Roo - SpringSource Tool Suite - Choosing the right tool fo...
WaveMaker - Spring Roo - SpringSource Tool Suite - Choosing the right tool fo...martinlippert
 
Spring Tooling Update - New & Noteworty (at SpringOne 2011)
Spring Tooling Update - New & Noteworty (at SpringOne 2011)Spring Tooling Update - New & Noteworty (at SpringOne 2011)
Spring Tooling Update - New & Noteworty (at SpringOne 2011)martinlippert
 

Mais de martinlippert (20)

WJAX 2013: Java8-Tooling in Eclipse
WJAX 2013: Java8-Tooling in EclipseWJAX 2013: Java8-Tooling in Eclipse
WJAX 2013: Java8-Tooling in Eclipse
 
WJAX 2013: Die PaaS-Parade - Teil 2 - Cloud Foundry
WJAX 2013: Die PaaS-Parade - Teil 2 - Cloud FoundryWJAX 2013: Die PaaS-Parade - Teil 2 - Cloud Foundry
WJAX 2013: Die PaaS-Parade - Teil 2 - Cloud Foundry
 
EclipseCon-Europe 2013: Optimizing performance - how to make your Eclipse-bas...
EclipseCon-Europe 2013: Optimizing performance - how to make your Eclipse-bas...EclipseCon-Europe 2013: Optimizing performance - how to make your Eclipse-bas...
EclipseCon-Europe 2013: Optimizing performance - how to make your Eclipse-bas...
 
EclipseCon-Europe 2013: Making the Eclipse IDE fun again
EclipseCon-Europe 2013: Making the Eclipse IDE fun againEclipseCon-Europe 2013: Making the Eclipse IDE fun again
EclipseCon-Europe 2013: Making the Eclipse IDE fun again
 
Jax2013 PaaS-Parade - Part 1: Cloud Foundry
Jax2013 PaaS-Parade - Part 1: Cloud FoundryJax2013 PaaS-Parade - Part 1: Cloud Foundry
Jax2013 PaaS-Parade - Part 1: Cloud Foundry
 
JAX 2013: Modern Architectures with Spring and JavaScript
JAX 2013: Modern Architectures with Spring and JavaScriptJAX 2013: Modern Architectures with Spring and JavaScript
JAX 2013: Modern Architectures with Spring and JavaScript
 
JAX 2013: Introducing Eclipse Orion
JAX 2013: Introducing Eclipse OrionJAX 2013: Introducing Eclipse Orion
JAX 2013: Introducing Eclipse Orion
 
Spring Tooling: What's new and what's coming
Spring Tooling: What's new and what's comingSpring Tooling: What's new and what's coming
Spring Tooling: What's new and what's coming
 
Modern Architectures with Spring and JavaScript
Modern Architectures with Spring and JavaScriptModern Architectures with Spring and JavaScript
Modern Architectures with Spring and JavaScript
 
Scripted - Embracing Eclipse Orion
Scripted - Embracing Eclipse OrionScripted - Embracing Eclipse Orion
Scripted - Embracing Eclipse Orion
 
PaaS Parade - Cloud Foundry
PaaS Parade - Cloud FoundryPaaS Parade - Cloud Foundry
PaaS Parade - Cloud Foundry
 
Browser and Cloud - The Future of IDEs?
Browser and Cloud - The Future of IDEs?Browser and Cloud - The Future of IDEs?
Browser and Cloud - The Future of IDEs?
 
Modern Architectures with Spring and JavaScript
Modern Architectures with Spring and JavaScriptModern Architectures with Spring and JavaScript
Modern Architectures with Spring and JavaScript
 
What's new with tooling for Spring, Grails, and the Cloud
What's new with tooling for Spring, Grails, and the CloudWhat's new with tooling for Spring, Grails, and the Cloud
What's new with tooling for Spring, Grails, and the Cloud
 
Tooling for the JavaScript Era
Tooling for the JavaScript EraTooling for the JavaScript Era
Tooling for the JavaScript Era
 
Embracing Eclipse Orion
Embracing Eclipse OrionEmbracing Eclipse Orion
Embracing Eclipse Orion
 
JAX 2012: Moderne Architektur mit Spring und JavaScript
JAX 2012: Moderne Architektur mit Spring und JavaScriptJAX 2012: Moderne Architektur mit Spring und JavaScript
JAX 2012: Moderne Architektur mit Spring und JavaScript
 
JAX 2012: Pimp Your IDE Productivity
JAX 2012: Pimp Your IDE ProductivityJAX 2012: Pimp Your IDE Productivity
JAX 2012: Pimp Your IDE Productivity
 
WaveMaker - Spring Roo - SpringSource Tool Suite - Choosing the right tool fo...
WaveMaker - Spring Roo - SpringSource Tool Suite - Choosing the right tool fo...WaveMaker - Spring Roo - SpringSource Tool Suite - Choosing the right tool fo...
WaveMaker - Spring Roo - SpringSource Tool Suite - Choosing the right tool fo...
 
Spring Tooling Update - New & Noteworty (at SpringOne 2011)
Spring Tooling Update - New & Noteworty (at SpringOne 2011)Spring Tooling Update - New & Noteworty (at SpringOne 2011)
Spring Tooling Update - New & Noteworty (at SpringOne 2011)
 

Último

Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Will Schroeder
 
Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1DianaGray10
 
9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding TeamAdam Moalla
 
Meet the new FSP 3000 M-Flex800™
Meet the new FSP 3000 M-Flex800™Meet the new FSP 3000 M-Flex800™
Meet the new FSP 3000 M-Flex800™Adtran
 
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online CollaborationCOMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online Collaborationbruanjhuli
 
Igniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration WorkflowsIgniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration WorkflowsSafe Software
 
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDEADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDELiveplex
 
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...Aggregage
 
UiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPathCommunity
 
Videogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdfVideogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdfinfogdgmi
 
UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7DianaGray10
 
Comparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and IstioComparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and IstioChristian Posta
 
Building Your Own AI Instance (TBLC AI )
Building Your Own AI Instance (TBLC AI )Building Your Own AI Instance (TBLC AI )
Building Your Own AI Instance (TBLC AI )Brian Pichman
 
Designing A Time bound resource download URL
Designing A Time bound resource download URLDesigning A Time bound resource download URL
Designing A Time bound resource download URLRuncy Oommen
 
Machine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdfMachine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdfAijun Zhang
 
UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8DianaGray10
 
How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?IES VE
 
AI You Can Trust - Ensuring Success with Data Integrity Webinar
AI You Can Trust - Ensuring Success with Data Integrity WebinarAI You Can Trust - Ensuring Success with Data Integrity Webinar
AI You Can Trust - Ensuring Success with Data Integrity WebinarPrecisely
 
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfJamie (Taka) Wang
 
Nanopower In Semiconductor Industry.pdf
Nanopower  In Semiconductor Industry.pdfNanopower  In Semiconductor Industry.pdf
Nanopower In Semiconductor Industry.pdfPedro Manuel
 

Último (20)

Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
 
Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1
 
9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team
 
Meet the new FSP 3000 M-Flex800™
Meet the new FSP 3000 M-Flex800™Meet the new FSP 3000 M-Flex800™
Meet the new FSP 3000 M-Flex800™
 
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online CollaborationCOMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
 
Igniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration WorkflowsIgniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration Workflows
 
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDEADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
 
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
 
UiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation Developers
 
Videogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdfVideogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdf
 
UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7
 
Comparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and IstioComparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and Istio
 
Building Your Own AI Instance (TBLC AI )
Building Your Own AI Instance (TBLC AI )Building Your Own AI Instance (TBLC AI )
Building Your Own AI Instance (TBLC AI )
 
Designing A Time bound resource download URL
Designing A Time bound resource download URLDesigning A Time bound resource download URL
Designing A Time bound resource download URL
 
Machine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdfMachine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdf
 
UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8
 
How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?
 
AI You Can Trust - Ensuring Success with Data Integrity Webinar
AI You Can Trust - Ensuring Success with Data Integrity WebinarAI You Can Trust - Ensuring Success with Data Integrity Webinar
AI You Can Trust - Ensuring Success with Data Integrity Webinar
 
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
 
Nanopower In Semiconductor Industry.pdf
Nanopower  In Semiconductor Industry.pdfNanopower  In Semiconductor Industry.pdf
Nanopower In Semiconductor Industry.pdf
 

Why SOLID matters - even for JavaScript

  • 1. Why the SOLID principles matter - even for JavaScript Martin Lippert,VMware mlippert@vmware.com, @martinlippert
  • 2. Why should I care?
  • 3. Its easy and smooth at the beginning...
  • 6. Change happens „Nothing endures but change“ Heraclitus
  • 7. Dependencies matter „Taking care of dependencies is one of the most critical success factors of healthy software.“
  • 8. Utilities structured object-oriented programming programming („Go To Statement Considered Harmful“, 1968) (Simula 1967) functional programming modular (Lambda calculus 1930ies) programming (Modula-2 1978) APIs component-oriented plugins software (Eclipse 2001)
  • 12. now everybody is programming in JavaScript
  • 14. Information Hiding Don‘t Repeat Yourself Interface Segregation Separation Of Concerns Liskov Substitution Simple Design Single Responsibility Avoid Inheritance Speaking Code Open Close Dependency Inversion Tell, Don‘t Ask Acyclic Dependencies
  • 15. Single Responsibility Open Close Liskov Substitution Interface Segregation Dependency Inversion
  • 16. Single Responsibility Principle „A class should have one, and only one, reason to change.“
  • 17. function Product(id, description) { this.getId = function() { return id; }; this.getDescription = function() { return description; }; } (function() { function addToCart() { function Cart(eventAggregator) { var productId = $(this).attr('id'); var items = []; var product = $.grep(products, function(x) { return x.getId() == productId; this.addItem = function(item) { })[0]; items.push(item); cart.addItem(product); }; } var newItem = $('<li></li>') .html(product.getDescription()) var products = [ .attr('id-cart', product.getId()) new Product(1, "Star Wars Lego Ship"), .appendTo("#cart"); new Product(2, "Barbie Doll"), } new Product(3, "Remote Control Airplane")], cart = new Cart(); products.forEach(function(product) { var newItem = $('<li></li>') .html(product.getDescription()) .attr('id', product.getId()) .dblclick(addToCart) .appendTo("#products"); }); })(); http://freshbrewedcode.com/derekgreer/2011/12/08/solid-javascript-single-responsibility-principle/
  • 18. function Product(id, description) { add the item to the cart this.getId = function() { }; return id; when an item is clicked this.getDescription = function() { return description; }; } (function() { function addToCart() { function Cart(eventAggregator) { var productId = $(this).attr('id'); updating the DOM to display var items = []; var product = $.grep(products, function(x) { return x.getId() == productId; the newly added item this.addItem = function(item) { items.push(item); })[0]; cart.addItem(product); }; } var newItem = $('<li></li>') .html(product.getDescription()) var products = [ .attr('id-cart', product.getId()) new Product(1, "Star Wars Lego Ship"), .appendTo("#cart"); new Product(2, "Barbie Doll"), } new Product(3, "Remote Control Airplane")], cart = new Cart(); products.forEach(function(product) { populate the initial list of var newItem = $('<li></li>') products on the page .html(product.getDescription()) .attr('id', product.getId()) .dblclick(addToCart) .appendTo("#products"); }); })(); http://freshbrewedcode.com/derekgreer/2011/12/08/solid-javascript-single-responsibility-principle/
  • 19. MVC pattern instead function Cart() { var items = []; this.addItem = function(item) { items.push(item); eventAggregator.publish("itemAdded", item); }; } var cartView = (function() { eventAggregator.subscribe("itemAdded", function(eventArgs) { var newItem = $('<li></li>') .html(eventArgs.getDescription()) .attr('id-cart', eventArgs.getId()) .appendTo("#cart"); }); })(); var cartController = (function(cart) { eventAggregator.subscribe("productSelected", function(eventArgs) { cart.addItem(eventArgs.product); }); })(new Cart()); http://freshbrewedcode.com/derekgreer/2011/12/08/solid-javascript-single-responsibility-principle/
  • 20. function Product(id, description) { this.getId = function() { return id; }; this.getDescription = function() { return description; }; } var productView = (function() { function onProductSelected() { var productId = $(this).attr('id'); var product = $.grep(products, function(x) { return x.getId() == productId; })[0]; eventAggregator.publish("productSelected", { product: product }); } products.forEach(function(product) { var newItem = $('<li></li>') .html(product.getDescription()) .attr('id', product.getId()) .dblclick(onProductSelected) .appendTo("#products"); }); })(); http://freshbrewedcode.com/derekgreer/2011/12/08/solid-javascript-single-responsibility-principle/
  • 21. Open Close Principle „You should be able to extend a classes behavior, without modifying it.“
  • 22. var AnswerType = { var view = (function() { Choice: 0, function renderQuestion(target, question) { Input: 1 ... // create DOM nodes }; if (question.answerType === AnswerType.Choice) { function question(label, var input = document.createElement('select'); answerType, var len = question.choices.length; choices) { for (var i = 0; i < len; i++) { return { var option = document.createElement('option'); label: label, option.text = question.choices[i]; answerType: answerType, option.value = question.choices[i]; choices: choices input.appendChild(option); }; } } } else if (question.answerType === AnswerType.Input) { var input = document.createElement('input'); input.type = 'text'; } answer.appendChild(input); questionWrapper.appendChild(questionLabel); questionWrapper.appendChild(answer); target.appendChild(questionWrapper); } return { render: function(target, questions) { for (var i = 0; i < questions.length; i++) { renderQuestion(target, questions[i]); }; } }; })(); http://freshbrewedcode.com/derekgreer/2011/12/19/solid-javascript-the-openclosed-principle/
  • 23. var AnswerType = { var view = (function() { Choice: 0, function renderQuestion(target, question) { Input: 1 ... // create DOM nodes }; if (question.answerType === AnswerType.Choice) { function question(label, var input = document.createElement('select'); change here answerType, var len = question.choices.length; for (var i = 0; i < len; i++) { choices) { return { var option = document.createElement('option'); label: label, option.text = question.choices[i]; answerType: answerType, option.value = question.choices[i]; choices: choices input.appendChild(option); }; } } } else if (question.answerType === AnswerType.Input) { var input = document.createElement('input'); change here input.type = 'text'; } answer.appendChild(input); questionWrapper.appendChild(questionLabel); questionWrapper.appendChild(answer); adding new answer types or } target.appendChild(questionWrapper); changing the set{ of answer types return requires for function(target,questions.length; i++) { changes 0; i < questions) { render: (var i = renderQuestion(target, questions[i]); }; } }; })(); http://freshbrewedcode.com/derekgreer/2011/12/19/solid-javascript-the-openclosed-principle/
  • 24. factory method + strategy pattern instead function questionCreator(spec, my) { var that = {}; my = my || {}; my.label = spec.label; my.renderInput = function() { throw "not implemented"; }; that.render = function(target) { var questionWrapper = document.createElement('div'); questionWrapper.className = 'question'; var questionLabel = document.createElement('div'); questionLabel.className = 'question-label'; var label = document.createTextNode(spec.label); questionLabel.appendChild(label); var answer = my.renderInput(); questionWrapper.appendChild(questionLabel); questionWrapper.appendChild(answer); return questionWrapper; }; return that; } http://freshbrewedcode.com/derekgreer/2011/12/19/solid-javascript-the-openclosed-principle/
  • 25. function choiceQuestionCreator(spec) { var my = {}, that = questionCreator(spec, my); my.renderInput = function() { var input = document.createElement('select'); var len = spec.choices.length; for (var i = 0; i < len; i++) { var option = document.createElement('option'); option.text = spec.choices[i]; option.value = spec.choices[i]; input.appendChild(option); } return input; }; function inputQuestionCreator(spec) { return that; } var my = {}, that = questionCreator(spec, my); my.renderInput = function() { var input = document.createElement('input'); input.type = 'text'; return input; }; return that; } http://freshbrewedcode.com/derekgreer/2011/12/19/solid-javascript-the-openclosed-principle/
  • 26. var view = { render: function(target, questions) { for (var i = 0; i < questions.length; i++) { target.appendChild(questions[i].render()); } } }; var questions = [ choiceQuestionCreator({ label: 'Have you used tobacco products within the last 30 days?', choices: ['Yes', 'No'] }), inputQuestionCreator({ label: 'What medications are you currently using?' }) ]; var AnswerType = { Choice: 0, Input: 1 }; function question(label, answerType, choices) { return { label: label, answerType: answerType, choices: choices }; } http://freshbrewedcode.com/derekgreer/2011/12/19/solid-javascript-the-openclosed-principle/
  • 27. Liskov Substitution Principle „Derived classes must be substitutable for their base classes.“
  • 28. function Vehicle(my) { my = my || {}; my.speed = 0; my.running = false; this.speed = function() { function FastVehicle(my) { return my.speed; my = my || {}; }; this.start = function() { var that = new Vehicle(my); my.running = true; that.accelerate = function() { }; my.speed += 3; this.stop = function() { }; my.running = false; return that; }; } this.accelerate = function() { my.speed++; }; this.decelerate = function() { my.speed--; }; this.state = function() { if (!my.running) { return "parked"; } else if (my.running && my.speed) { return "moving"; } else if (my.running) { return "idle"; } }; } http://freshbrewedcode.com/derekgreer/2011/12/31/solid-javascript-the-liskov-substitution-principle/
  • 29. function Vehicle(my) { my = my || {}; my.speed = 0; my.running = false; this.speed = function() { function FastVehicle(my) { return my.speed; my = my || {}; }; this.start = function() { var that = new Vehicle(my); my.running = true; that.accelerate = function() { }; my.speed += 3; this.stop = function() { }; my.running = false; return that; }; } this.accelerate = function() { my.speed++; }; this.decelerate = function() { my.speed--; }; changes behavior, therefore this.state = function() { if (!my.running) { } return "parked"; breaks existing clients else if (my.running && my.speed) { return "moving"; } else if (my.running) { return "idle"; } }; } http://freshbrewedcode.com/derekgreer/2011/12/31/solid-javascript-the-liskov-substitution-principle/
  • 30. Solutions? Design by Contract (avoid inheritance principle) test-driven development but remember: its about behavior not inheritance
  • 31. Interface Segregation Principle „Make fine grained interfaces that are client specific.“
  • 32. var exampleBinder = {}; exampleBinder.modelObserver = (function() { /* private variables */ return { observe: function(model) { /* code */ return newModel; }, onChange: function(callback) { /* code */ } } })(); exampleBinder.viewAdaptor = (function() { /* private variables */ return { bind: function(model) { /* code */ } } })(); exampleBinder.bind = function(model) { /* private variables */ exampleBinder.modelObserver.onChange(/* callback */); var om = exampleBinder.modelObserver.observe(model); exampleBinder.viewAdaptor.bind(om); return om; }; http://freshbrewedcode.com/derekgreer/2012/01/08/solid-javascript-the-interface-segregation-principle/
  • 33. var exampleBinder = {}; exampleBinder.modelObserver = (function() { /* private variables */ return { observe: function(model) { /* code */ return newModel; }, onChange: function(callback) { /* code */ } } })(); implicit interface defined, exampleBinder.viewAdaptor = (function() { /* private variables */ return { bind: function(model) { callbacks are often similar /* code */ } } })(); exampleBinder.bind = function(model) { /* private variables */ exampleBinder.modelObserver.onChange(/* callback */); var om = exampleBinder.modelObserver.observe(model); exampleBinder.viewAdaptor.bind(om); return om; }; http://freshbrewedcode.com/derekgreer/2012/01/08/solid-javascript-the-interface-segregation-principle/
  • 34. Dependency Inversion Principle „Depend on abstractions, not on concretions.“
  • 35. $.fn.trackMap = function(options) { ... var mapOptions = { center: new google.maps.LatLng(options.latitude,options.longitude), zoom: 12, mapTypeId: google.maps.MapTypeId.ROADMAP }, map = new google.maps.Map(this[0], mapOptions), pos = new google.maps.LatLng(options.latitude,options.longitude); var marker = new google.maps.Marker({ position: pos, title: options.title, icon: options.icon }); marker.setMap(map); options.feed.update(function(latitude, longitude) { marker.setMap(null); var newLatLng = new google.maps.LatLng(latitude, longitude); marker.position = newLatLng; marker.setMap(map); map.setCenter(newLatLng); }); $("#map_canvas").trackMap({ latitude: 35.044640193770725, return this; longitude: -89.98193264007568, }; icon: 'http://bit.ly/zjnGDe', title: 'Tracking Number: 12345', feed: updater }); http://freshbrewedcode.com/derekgreer/2012/01/22/solid-javascript-the-dependency-inversion-principle/
  • 36. $.fn.trackMap = function(options) { ... var mapOptions = { depends on the Google center: new google.maps.LatLng(options.latitude,options.longitude), zoom: 12, mapTypeId: google.maps.MapTypeId.ROADMAP Maps API }, map = new google.maps.Map(this[0], mapOptions), pos = new google.maps.LatLng(options.latitude,options.longitude); var marker = new google.maps.Marker({ position: pos, title: options.title, icon: options.icon }); depends on the feed API marker.setMap(map); options.feed.update(function(latitude, longitude) { marker.setMap(null); var newLatLng = new google.maps.LatLng(latitude, longitude); marker.position = newLatLng; marker.setMap(map); map.setCenter(newLatLng); }); $("#map_canvas").trackMap({ latitude: 35.044640193770725, return this; longitude: -89.98193264007568, }; icon: 'http://bit.ly/zjnGDe', title: 'Tracking Number: 12345', feed: updater }); http://freshbrewedcode.com/derekgreer/2012/01/22/solid-javascript-the-dependency-inversion-principle/
  • 37. introduce implicit interface $.fn.trackMap = function(options) { var defaults = { /* defaults */ }; options = $.extend({}, defaults, options); options.provider.showMap( this[0], options.latitude, options.longitude, options.icon, options.title); options.feed.update(function(latitude, longitude) { options.provider.updateMap(latitude, longitude); }); return this; }; $("#map_canvas").trackMap({ latitude: 35.044640193770725, longitude: -89.98193264007568, icon: 'http://bit.ly/zjnGDe', title: 'Tracking Number: 12345', feed: updater, provider: trackMap.googleMapsProvider }); http://freshbrewedcode.com/derekgreer/2012/01/22/solid-javascript-the-dependency-inversion-principle/
  • 38. trackMap.googleMapsProvider = (function() { var marker, map; return { showMap: function(element, latitude, longitude, icon, title) { var mapOptions = { center: new google.maps.LatLng(latitude, longitude), zoom: 12, mapTypeId: google.maps.MapTypeId.ROADMAP }, pos = new google.maps.LatLng(latitude, longitude); map = new google.maps.Map(element, mapOptions); marker = new google.maps.Marker({ position: pos, title: title, icon: icon }); marker.setMap(map); }, updateMap: function(latitude, longitude) { marker.setMap(null); var newLatLng = new google.maps.LatLng(latitude,longitude); marker.position = newLatLng; marker.setMap(map); map.setCenter(newLatLng); } }; })(); http://freshbrewedcode.com/derekgreer/2012/01/22/solid-javascript-the-dependency-inversion-principle/
  • 39. „Design principles are essential for healthy code. Think about them all the time.“
  • 40. Q&A and thank you for your attention Martin Lippert,VMware mlippert@vmware.com, @martinlippert