why the solid - martinlippert · acyclic dependencies. liskov substitution dependency inversion...
TRANSCRIPT
![Page 1: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/1.jpg)
SOLIDMartin Lippert, VMware
[email protected], @martinlippert
principles matter - even for JavaScript
Why the
![Page 2: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/2.jpg)
Why should I care?
![Page 3: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/3.jpg)
Its easy and smooth at the
beginning...
![Page 4: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/4.jpg)
Sooner or later...
![Page 5: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/5.jpg)
But why?
![Page 6: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/6.jpg)
Change happens
„Nothing endures but change“Heraclitus
![Page 7: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/7.jpg)
Dependencies matter
„Taking care of dependencies is one of the most critical success factors of healthy software.“
![Page 8: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/8.jpg)
Utilitiesstructured
programming(„Go To Statement Considered Harmful“, 1968)
object-orientedprogramming
(Simula 1967)
functionalprogramming
(Lambda calculus 1930ies)
modularprogramming
(Modula-2 1978)APIs
component-oriented softwareplugins
(Eclipse 2001)
![Page 9: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/9.jpg)
Back to Reality
![Page 10: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/10.jpg)
„structured“programming
![Page 11: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/11.jpg)
then we gotobject-orientation
![Page 12: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/12.jpg)
now everybody is programming in
JavaScript
![Page 13: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/13.jpg)
Design Principles matter
![Page 14: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/14.jpg)
Liskov Substitution
Dependency Inversion
Single Responsibility
Open Close
Interface Segregation
Avoid Inheritance
Speaking Code
Information Hiding
Separation Of Concerns
Simple Design
Don‘t Repeat Yourself
Tell, Don‘t Ask
Acyclic Dependencies
![Page 15: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/15.jpg)
Liskov Substitution
Dependency Inversion
Single Responsibility
Open Close
Interface Segregation
![Page 16: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/16.jpg)
Single ResponsibilityPrinciple
„A class should have one,and only one, reason to change.“
![Page 17: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/17.jpg)
function Product(id, description) { this.getId = function() { return id; }; this.getDescription = function() { return description; };}
function Cart(eventAggregator) { var items = [];
this.addItem = function(item) { items.push(item); };}
var products = [ new Product(1, "Star Wars Lego Ship"), new Product(2, "Barbie Doll"), new Product(3, "Remote Control Airplane")], cart = new Cart();
(function() { function addToCart() { var productId = $(this).attr('id'); var product = $.grep(products, function(x) { return x.getId() == productId; })[0]; cart.addItem(product);
var newItem = $('<li></li>') .html(product.getDescription()) .attr('id-cart', product.getId()) .appendTo("#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/
![Page 18: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/18.jpg)
function Product(id, description) { this.getId = function() { return id; }; this.getDescription = function() { return description; };}
function Cart(eventAggregator) { var items = [];
this.addItem = function(item) { items.push(item); };}
var products = [ new Product(1, "Star Wars Lego Ship"), new Product(2, "Barbie Doll"), new Product(3, "Remote Control Airplane")], cart = new Cart();
(function() { function addToCart() { var productId = $(this).attr('id'); var product = $.grep(products, function(x) { return x.getId() == productId; })[0]; cart.addItem(product);
var newItem = $('<li></li>') .html(product.getDescription()) .attr('id-cart', product.getId()) .appendTo("#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/
add the item to the cartwhen an item is clicked
updating the DOM to display the newly added item
populate the initial list of products on the page
![Page 19: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/19.jpg)
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());
MVC pattern instead
http://freshbrewedcode.com/derekgreer/2011/12/08/solid-javascript-single-responsibility-principle/
![Page 20: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/20.jpg)
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/
![Page 21: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/21.jpg)
Open ClosePrinciple
„You should be able to extenda classes behavior, without modifying it.“
![Page 22: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/22.jpg)
var AnswerType = { Choice: 0, Input: 1};
function question(label, answerType, choices) { return { label: label, answerType: answerType, choices: choices };}
var view = (function() { function renderQuestion(target, question) { ... // create DOM nodes
if (question.answerType === AnswerType.Choice) { var input = document.createElement('select'); var len = question.choices.length; for (var i = 0; i < len; i++) { var option = document.createElement('option'); option.text = question.choices[i]; option.value = question.choices[i]; 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/
![Page 23: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/23.jpg)
var AnswerType = { Choice: 0, Input: 1};
function question(label, answerType, choices) { return { label: label, answerType: answerType, choices: choices };}
var view = (function() { function renderQuestion(target, question) { ... // create DOM nodes
if (question.answerType === AnswerType.Choice) { var input = document.createElement('select'); var len = question.choices.length; for (var i = 0; i < len; i++) { var option = document.createElement('option'); option.text = question.choices[i]; option.value = question.choices[i]; 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]); }; } };})();
change here
change here
adding new answer types or changing the set of answer types
requires changes
http://freshbrewedcode.com/derekgreer/2011/12/19/solid-javascript-the-openclosed-principle/
![Page 24: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/24.jpg)
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;}
factory method + strategy pattern instead
http://freshbrewedcode.com/derekgreer/2011/12/19/solid-javascript-the-openclosed-principle/
![Page 25: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/25.jpg)
function inputQuestionCreator(spec) {
var my = {}, that = questionCreator(spec, my);
my.renderInput = function() { var input = document.createElement('input'); input.type = 'text'; return input; };
return that;}
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; };
return that;}
http://freshbrewedcode.com/derekgreer/2011/12/19/solid-javascript-the-openclosed-principle/
![Page 26: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/26.jpg)
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/
![Page 27: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/27.jpg)
Liskov SubstitutionPrinciple
„Derived classes must be substitutablefor their base classes.“
![Page 28: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/28.jpg)
function Vehicle(my) { my = my || {}; my.speed = 0; my.running = false;
this.speed = function() { return my.speed; }; this.start = function() { my.running = true; }; this.stop = function() { my.running = false; }; 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 FastVehicle(my) { my = my || {};
var that = new Vehicle(my); that.accelerate = function() { my.speed += 3; }; return that;}
![Page 29: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/29.jpg)
function Vehicle(my) { my = my || {}; my.speed = 0; my.running = false;
this.speed = function() { return my.speed; }; this.start = function() { my.running = true; }; this.stop = function() { my.running = false; }; 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"; } };}
function FastVehicle(my) { my = my || {};
var that = new Vehicle(my); that.accelerate = function() { my.speed += 3; }; return that;}
changes behavior, therefore breaks existing clients
http://freshbrewedcode.com/derekgreer/2011/12/31/solid-javascript-the-liskov-substitution-principle/
![Page 30: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/30.jpg)
Solutions?
Design by Contract(avoid inheritance principle)
test-driven development
but remember:its about behavior
not inheritance
![Page 31: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/31.jpg)
Interface SegregationPrinciple
„Make fine grained interfacesthat are client specific.“
![Page 32: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/32.jpg)
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/
![Page 33: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/33.jpg)
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;};
implicit interface defined, callbacks are often similar
http://freshbrewedcode.com/derekgreer/2012/01/08/solid-javascript-the-interface-segregation-principle/
![Page 34: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/34.jpg)
Dependency InversionPrinciple
„Depend on abstractions,not on concretions.“
![Page 35: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/35.jpg)
$.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); });
return this;};
$("#map_canvas").trackMap({ latitude: 35.044640193770725, 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/
![Page 36: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/36.jpg)
$.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); });
return this;};
$("#map_canvas").trackMap({ latitude: 35.044640193770725, longitude: -89.98193264007568, icon: 'http://bit.ly/zjnGDe', title: 'Tracking Number: 12345', feed: updater});
depends on the Google Maps API
depends on the feed API
http://freshbrewedcode.com/derekgreer/2012/01/22/solid-javascript-the-dependency-inversion-principle/
![Page 37: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/37.jpg)
$.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});
introduce implicit interface
http://freshbrewedcode.com/derekgreer/2012/01/22/solid-javascript-the-dependency-inversion-principle/
![Page 38: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/38.jpg)
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/
![Page 39: Why the SOLID - martinlippert · Acyclic Dependencies. Liskov Substitution Dependency Inversion Single Responsibility Open Close Interface Segregation. Single Responsibility Principle](https://reader036.vdocuments.us/reader036/viewer/2022090610/6070f2d9990d3c11ea490271/html5/thumbnails/39.jpg)
„Design principles are essential for healthy code. Think about
them all the time.“