tddb84: lecture 09tddb84/lectures/2013/lecture09/...solid •single responsibility principle...
TRANSCRIPT
TDDB84: Lecture 09SOLID, Language design, Summary
fredag 11 oktober 13
SOLID
•Single responsibility principle
• Open/closed principle
• Liskov substitution principle
• Interface segregation principle
• Dependency inversion principle
fredag 11 oktober 13
SOLID
•Single responsibility principle
• Open/closed principle
• Liskov substitution principle
• Interface segregation principle
• Dependency inversion principle
fredag 11 oktober 13
Single responsibility• Encapsulate what varies
• Program to an interface, not to an implementation
• Favor composition over inheritance
• Classes should be open for extension but closed for modification
• Don’t call us, we’ll call you
• Depend on abstractions, do not depend on concrete classes
• Classes should only have one reason to change
• Strive for loosely-coupled design
fredag 11 oktober 13
Single responsibility• Encapsulate what varies
• Program to an interface, not to an implementation
• Favor composition over inheritance
• Classes should be open for extension but closed for modification
• Don’t call us, we’ll call you
• Depend on abstractions, do not depend on concrete classes
• Classes should only have one reason to change
• Strive for loosely-coupled design
fredag 11 oktober 13
Single responsibility• Encapsulate what varies
• Program to an interface, not to an implementation
• Favor composition over inheritance
• Classes should be open for extension but closed for modification
• Don’t call us, we’ll call you
• Depend on abstractions, do not depend on concrete classes
• Classes should only have one reason to change
• Strive for loosely-coupled design
fredag 11 oktober 13
Open/closed• Encapsulate what varies
• Program to an interface, not to an implementation
• Favor composition over inheritance
• Classes should be open for extension but closed for modification
• Don’t call us, we’ll call you
• Depend on abstractions, do not depend on concrete classes
• Classes should only have one reason to change
• Strive for loosely-coupled designfredag 11 oktober 13
Open/closed• Encapsulate what varies
• Program to an interface, not to an implementation
• Favor composition over inheritance
• Classes should be open for extension but closed for modification
• Don’t call us, we’ll call you
• Depend on abstractions, do not depend on concrete classes
• Classes should only have one reason to change
• Strive for loosely-coupled designfredag 11 oktober 13
Liskov substitution• Encapsulate what varies
• Program to an interface, not to an implementation
• Favor composition over inheritance
• Classes should be open for extension but closed for modification
• Don’t call us, we’ll call you
• Depend on abstractions, do not depend on concrete classes
• Classes should only have one reason to change
• Strive for loosely-coupled designfredag 11 oktober 13
Liskov substitution• Encapsulate what varies
• Program to an interface, not to an implementation
• Favor composition over inheritance
• Classes should be open for extension but closed for modification
• Don’t call us, we’ll call you
• Depend on abstractions, do not depend on concrete classes
• Classes should only have one reason to change
• Strive for loosely-coupled designfredag 11 oktober 13
Interface segregation• Encapsulate what varies
• Program to an interface, not to an implementation
• Favor composition over inheritance
• Classes should be open for extension but closed for modification
• Don’t call us, we’ll call you
• Depend on abstractions, do not depend on concrete classes
• Classes should only have one reason to change
• Strive for loosely-coupled designfredag 11 oktober 13
Interface segregation• Encapsulate what varies
• Program to an interface, not to an implementation
• Favor composition over inheritance
• Classes should be open for extension but closed for modification
• Don’t call us, we’ll call you
• Depend on abstractions, do not depend on concrete classes
• Classes should only have one reason to change
• Strive for loosely-coupled designfredag 11 oktober 13
Dependency inversion• Encapsulate what varies
• Program to an interface, not to an implementation
• Favor composition over inheritance
• Classes should be open for extension but closed for modification
• Don’t call us, we’ll call you
• Depend on abstractions, do not depend on concrete classes
• Classes should only have one reason to change
• Strive for loosely-coupled designfredag 11 oktober 13
Dependency inversion• Encapsulate what varies
• Program to an interface, not to an implementation
• Favor composition over inheritance
• Classes should be open for extension but closed for modification
• Don’t call us, we’ll call you
• Depend on abstractions, do not depend on concrete classes
• Classes should only have one reason to change
• Strive for loosely-coupled designfredag 11 oktober 13
Dependency inversion• Encapsulate what varies
• Program to an interface, not to an implementation
• Favor composition over inheritance
• Classes should be open for extension but closed for modification
• Don’t call us, we’ll call you
• Depend on abstractions, do not depend on concrete classes
• Classes should only have one reason to change
• Strive for loosely-coupled designfredag 11 oktober 13
Dependency inversion• Encapsulate what varies
• Program to an interface, not to an implementation
• Favor composition over inheritance
• Classes should be open for extension but closed for modification
• Don’t call us, we’ll call you
• Depend on abstractions, do not depend on concrete classes
• Classes should only have one reason to change
• Strive for loosely-coupled designfredag 11 oktober 13
• Encapsulate what varies
• Strive for loosely-coupled design
fredag 11 oktober 13
• Encapsulate what varies
• Strive for loosely-coupled design
Too general?
fredag 11 oktober 13
• Encapsulate what varies
• Strive for loosely-coupled design
Too general?
A consequence of applying SOLID?
fredag 11 oktober 13
• Encapsulate what varies
• Strive for loosely-coupled design
Too general?
A consequence of applying SOLID?
Too trivial?
fredag 11 oktober 13
Language Designvs
Design Patterns
fredag 11 oktober 13
• Open classes: The ability to redefine classes
• Metaprogramming: The ability to inspect and manipulate programs and their processes from within the language
• Multiple dispatch: The ability to select a function based on the runtime types of all arguments
• First-order functions: The ability to use functions as objects
Language features
fredag 11 oktober 13
Open classes
fredag 11 oktober 13
Open classes public static string ToXML(this object objectToSerialize) { MemoryStream mem=new MemoryStream(); XmlSerializer ser=new XmlSerializer(objectToSerialize.GetType()); ser.Serialize(mem,objectToSerialize); ASCIIEncoding ascii=new ASCIIEncoding(); return ascii.GetString(mem.ToArray()); }
public static class ObjectExtensions { ! ! ! 1.ToXML ();! ! ! new Person ().ToXML ();
C#
fredag 11 oktober 13
Open classes public static string ToXML(this object objectToSerialize) { MemoryStream mem=new MemoryStream(); XmlSerializer ser=new XmlSerializer(objectToSerialize.GetType()); ser.Serialize(mem,objectToSerialize); ASCIIEncoding ascii=new ASCIIEncoding(); return ascii.GetString(mem.ToArray()); }
public static class ObjectExtensions { ! ! ! 1.ToXML ();! ! ! new Person ().ToXML ();
C#
class Object
def to_xml vars = instance_variables.map do |var| name=var.to_s.sub('@','') "<#{name}>#{instance_variable_get(var)}</#{name}>" end.join(" ") "<root>#{vars}</root>" end
end
class Person attr_accessor :name, :ageend
p = Person.newp.name = "Ola"p.age = 34
irb(main):081:0> p.to_xml"<root><name>Ola</name> <age>34</age></root>"
Ruby
fredag 11 oktober 13
Metaprogramming public class FieldMappingConfigurator<T> where T: class, new() { private Configurator Configurator { get; set; } private string FieldName { get; set; } internal FieldMappingConfigurator(string fieldName, Configurator configurator) { Configurator = configurator; FieldName = fieldName; }
public void To<T1>(Expression<Func<T,T1>> propertySelector) { var selectorExpression = (MemberExpression) propertySelector.Body; var prop = (PropertyInfo) selectorExpression.Member; Configurator.CustomFieldsToPropertiesMap[FieldName]=prop; } }
GenericDAO<DomainObject>.Configure("some_StoredProcedure") .Map("AFieldInTheResultSetReturned") .To(s => s.Id);
C#
fredag 11 oktober 13
Metaprogramming public class FieldMappingConfigurator<T> where T: class, new() { private Configurator Configurator { get; set; } private string FieldName { get; set; } internal FieldMappingConfigurator(string fieldName, Configurator configurator) { Configurator = configurator; FieldName = fieldName; }
public void To<T1>(Expression<Func<T,T1>> propertySelector) { var selectorExpression = (MemberExpression) propertySelector.Body; var prop = (PropertyInfo) selectorExpression.Member; Configurator.CustomFieldsToPropertiesMap[FieldName]=prop; } }
GenericDAO<DomainObject>.Configure("some_StoredProcedure") .Map("AFieldInTheResultSetReturned") .To(s => s.Id);
C#
fredag 11 oktober 13
Metaprogramming public class FieldMappingConfigurator<T> where T: class, new() { private Configurator Configurator { get; set; } private string FieldName { get; set; } internal FieldMappingConfigurator(string fieldName, Configurator configurator) { Configurator = configurator; FieldName = fieldName; }
public void To<T1>(Expression<Func<T,T1>> propertySelector) { var selectorExpression = (MemberExpression) propertySelector.Body; var prop = (PropertyInfo) selectorExpression.Member; Configurator.CustomFieldsToPropertiesMap[FieldName]=prop; } }
GenericDAO<DomainObject>.Configure("some_StoredProcedure") .Map("AFieldInTheResultSetReturned") .To(s => s.Id);
C#
fredag 11 oktober 13
Metaprogramming public class FieldMappingConfigurator<T> where T: class, new() { private Configurator Configurator { get; set; } private string FieldName { get; set; } internal FieldMappingConfigurator(string fieldName, Configurator configurator) { Configurator = configurator; FieldName = fieldName; }
public void To<T1>(Expression<Func<T,T1>> propertySelector) { var selectorExpression = (MemberExpression) propertySelector.Body; var prop = (PropertyInfo) selectorExpression.Member; Configurator.CustomFieldsToPropertiesMap[FieldName]=prop; } }
GenericDAO<DomainObject>.Configure("some_StoredProcedure") .Map("AFieldInTheResultSetReturned") .To(s => s.Id);
Program analysisC#
fredag 11 oktober 13
Metaprogrammingclass SetupProjectBuilder
class << self
def setup_classes @setup_classes ||= [] end
def inherited(sub_class) setup_classes << sub_class end
def setup_project?(project_file) !setup_class(project_file).nil? end
def setup_class(project_file) setup_classes.find {|c| c.project_file_pattern =~ project_file } end end
end
class VDProjBuilder < SetupProjectBuilder
def self.project_file_pattern /\.vdproj$/ end
[ ... ]
end
Ruby
fredag 11 oktober 13
Metaprogrammingclass SetupProjectBuilder
class << self
def setup_classes @setup_classes ||= [] end
def inherited(sub_class) setup_classes << sub_class end
def setup_project?(project_file) !setup_class(project_file).nil? end
def setup_class(project_file) setup_classes.find {|c| c.project_file_pattern =~ project_file } end end
end
class VDProjBuilder < SetupProjectBuilder
def self.project_file_pattern /\.vdproj$/ end
[ ... ]
end
RubyProcess analysis
fredag 11 oktober 13
Metaprogrammingclass SetupProjectBuilder
class << self
def setup_classes @setup_classes ||= [] end
def inherited(sub_class) setup_classes << sub_class end
def setup_project?(project_file) !setup_class(project_file).nil? end
def setup_class(project_file) setup_classes.find {|c| c.project_file_pattern =~ project_file } end end
end
class VDProjBuilder < SetupProjectBuilder
def self.project_file_pattern /\.vdproj$/ end
[ ... ]
end
RubyProcess analysis
Method-related hooks
method_missingmethod_addedsingleton_method_addedmethod_removedsingleton_method_removedmethod_undefinedsingleton_method_undefinedClass & Module Hooks
inheritedappend_featuresincludedextend_objectextendedinitialize_copyconst_missing
fredag 11 oktober 13
Metaprogrammingclass SetupProjectBuilder
class << self
def setup_classes @setup_classes ||= [] end
def inherited(sub_class) setup_classes << sub_class end
def setup_project?(project_file) !setup_class(project_file).nil? end
def setup_class(project_file) setup_classes.find {|c| c.project_file_pattern =~ project_file } end end
end
class VDProjBuilder < SetupProjectBuilder
def self.project_file_pattern /\.vdproj$/ end
[ ... ]
end
RubyProcess analysis
Method-related hooks
method_missingmethod_addedsingleton_method_addedmethod_removedsingleton_method_removedmethod_undefinedsingleton_method_undefinedClass & Module Hooks
inheritedappend_featuresincludedextend_objectextendedinitialize_copyconst_missing
fredag 11 oktober 13
Metaprogrammingclass SetupProjectBuilder
class << self
def setup_classes @setup_classes ||= [] end
def inherited(sub_class) setup_classes << sub_class end
def setup_project?(project_file) !setup_class(project_file).nil? end
def setup_class(project_file) setup_classes.find {|c| c.project_file_pattern =~ project_file } end end
end
class VDProjBuilder < SetupProjectBuilder
def self.project_file_pattern /\.vdproj$/ end
[ ... ]
end
RubyProcess analysis
Method-related hooks
method_missingmethod_addedsingleton_method_addedmethod_removedsingleton_method_removedmethod_undefinedsingleton_method_undefinedClass & Module Hooks
inheritedappend_featuresincludedextend_objectextendedinitialize_copyconst_missing
Factory Method
fredag 11 oktober 13
Metaprogramming in Ruby
class YamlConf
def conf @conf ||= load(self.class.simple_name+".yml") end
# Look up keys in the configuration hash def method_missing(method,*args) method_name=method.to_s conf[method_name] end end
fredag 11 oktober 13
Metaprogramming in Ruby
class YamlConf
def conf @conf ||= load(self.class.simple_name+".yml") end
# Look up keys in the configuration hash def method_missing(method,*args) method_name=method.to_s conf[method_name] end end
class Mail < YamlConf; end
fredag 11 oktober 13
Metaprogramming in Ruby
class YamlConf
def conf @conf ||= load(self.class.simple_name+".yml") end
# Look up keys in the configuration hash def method_missing(method,*args) method_name=method.to_s conf[method_name] end end
class Mail < YamlConf; end from: "[email protected]"to: - "[email protected]" - "[email protected]"host: "smtp.somehost.com"
config/mail.yml
fredag 11 oktober 13
Metaprogramming in Ruby
class YamlConf
def conf @conf ||= load(self.class.simple_name+".yml") end
# Look up keys in the configuration hash def method_missing(method,*args) method_name=method.to_s conf[method_name] end end
class Mail < YamlConf; end from: "[email protected]"to: - "[email protected]" - "[email protected]"host: "smtp.somehost.com"
config/mail.yml
mail = Mail.new do from Conf::Mail.from to Conf::Mail.to subject s body b end
fredag 11 oktober 13
Metaprogramming in Ruby
class YamlConf
def conf @conf ||= load(self.class.simple_name+".yml") end
# Look up keys in the configuration hash def method_missing(method,*args) method_name=method.to_s conf[method_name] end end
class Mail < YamlConf; end from: "[email protected]"to: - "[email protected]" - "[email protected]"host: "smtp.somehost.com"
config/mail.yml
mail = Mail.new do from Conf::Mail.from to Conf::Mail.to subject s body b end
fredag 11 oktober 13
Metaprogramming in Ruby
class YamlConf
def conf @conf ||= load(self.class.simple_name+".yml") end
# Look up keys in the configuration hash def method_missing(method,*args) method_name=method.to_s conf[method_name] end end
class Mail < YamlConf; end from: "[email protected]"to: - "[email protected]" - "[email protected]"host: "smtp.somehost.com"
config/mail.yml
mail = Mail.new do from Conf::Mail.from to Conf::Mail.to subject s body b end
fredag 11 oktober 13
Metaprogramming in Ruby
class YamlConf
def conf @conf ||= load(self.class.simple_name+".yml") end
# Look up keys in the configuration hash def method_missing(method,*args) method_name=method.to_s conf[method_name] end end
class Mail < YamlConf; end from: "[email protected]"to: - "[email protected]" - "[email protected]"host: "smtp.somehost.com"
config/mail.yml
mail = Mail.new do from Conf::Mail.from to Conf::Mail.to subject s body b end
Proxyfredag 11 oktober 13
Metaprogramming in Java public State() { ClassWithState obj = ClassWithState.this;
manipulateFields(obj, new FieldManipulator() {
@Override public void manipulateField(Object obj, Field field) throws IllegalAccessException {
getState().put(field.getName(), field.get(obj)); }
}); }
private void manipulateFields(Object obj, FieldManipulator fieldManipulator) { Class<?> cl = obj.getClass(); for (Field field : cl.getDeclaredFields()) { field.setAccessible(true); try { fieldManipulator.manipulateField(obj, field); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } }
fredag 11 oktober 13
Metaprogramming in Java public State() { ClassWithState obj = ClassWithState.this;
manipulateFields(obj, new FieldManipulator() {
@Override public void manipulateField(Object obj, Field field) throws IllegalAccessException {
getState().put(field.getName(), field.get(obj)); }
}); }
private void manipulateFields(Object obj, FieldManipulator fieldManipulator) { Class<?> cl = obj.getClass(); for (Field field : cl.getDeclaredFields()) { field.setAccessible(true); try { fieldManipulator.manipulateField(obj, field); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } }
Mementofredag 11 oktober 13
Metaprogramming in Java
@Override public Object invoke(Object arg0, Method m, Object[] arg2) throws Throwable { Object result = m.invoke(instance, arg2); if (m.getName().equals("getEmployments") && result == null) {
System.out.println(MessageFormat.format( "Trying to access uninstantiated field {0}", m .getName().substring(3))); [ some magic happens ] Method setter = m.getDeclaringClass().getMethod( "setEmployments", Collection.class); System.out.println(MessageFormat.format( "Instantiated field {0}", m.getName().substring(3))); setter.invoke(instance, employments); } return m.invoke(instance, arg2); }
fredag 11 oktober 13
Metaprogramming in Java
@Override public Object invoke(Object arg0, Method m, Object[] arg2) throws Throwable { Object result = m.invoke(instance, arg2); if (m.getName().equals("getEmployments") && result == null) {
System.out.println(MessageFormat.format( "Trying to access uninstantiated field {0}", m .getName().substring(3))); [ some magic happens ] Method setter = m.getDeclaringClass().getMethod( "setEmployments", Collection.class); System.out.println(MessageFormat.format( "Instantiated field {0}", m.getName().substring(3))); setter.invoke(instance, employments); } return m.invoke(instance, arg2); }
Proxyfredag 11 oktober 13
Multiple dispatch(defclass duck () ((name :initarg :name :accessor name)))(defclass mallard-duck (duck) ())(defclass red-duck (duck) ())(defclass rubber-duck (duck) ())
;; In another file, we can add flying behavior
;; What design pattern is this an implementation of?
(defclass fly-behavior () ())(defclass fly-with-wings (fly-behavior) ())(defclass no-fly (fly-behavior) ())
(defgeneric fly (duck fly-behavior) (:documentation "A method to allow ducks to fly") (:method ((d mallard-duck) (b fly-with-wings)) (format t "The mallard duck ~A is flying with wings!" (name d))) (:method ((d rubber-duck) (b fly-with-wings)) (format t "Rubber duck ~A is flying with wings!" (name d))) (:method ((d rubber-duck) (b no-fly)) (format t "Rubber duck ~A is not flying at all" (name d))) )
fredag 11 oktober 13
Multiple dispatch(defclass duck () ((name :initarg :name :accessor name)))(defclass mallard-duck (duck) ())(defclass red-duck (duck) ())(defclass rubber-duck (duck) ())
;; In another file, we can add flying behavior
;; What design pattern is this an implementation of?
(defclass fly-behavior () ())(defclass fly-with-wings (fly-behavior) ())(defclass no-fly (fly-behavior) ())
(defgeneric fly (duck fly-behavior) (:documentation "A method to allow ducks to fly") (:method ((d mallard-duck) (b fly-with-wings)) (format t "The mallard duck ~A is flying with wings!" (name d))) (:method ((d rubber-duck) (b fly-with-wings)) (format t "Rubber duck ~A is flying with wings!" (name d))) (:method ((d rubber-duck) (b no-fly)) (format t "Rubber duck ~A is not flying at all" (name d))) )
Method description
fredag 11 oktober 13
Multiple dispatch(defclass duck () ((name :initarg :name :accessor name)))(defclass mallard-duck (duck) ())(defclass red-duck (duck) ())(defclass rubber-duck (duck) ())
;; In another file, we can add flying behavior
;; What design pattern is this an implementation of?
(defclass fly-behavior () ())(defclass fly-with-wings (fly-behavior) ())(defclass no-fly (fly-behavior) ())
(defgeneric fly (duck fly-behavior) (:documentation "A method to allow ducks to fly") (:method ((d mallard-duck) (b fly-with-wings)) (format t "The mallard duck ~A is flying with wings!" (name d))) (:method ((d rubber-duck) (b fly-with-wings)) (format t "Rubber duck ~A is flying with wings!" (name d))) (:method ((d rubber-duck) (b no-fly)) (format t "Rubber duck ~A is not flying at all" (name d))) )
Method description
;; CL-USER> (fly (make-instance 'rubber-duck :name "Ducky") (make-instance 'fly-with-wings));; Rubber duck Ducky is flying with wings!;; NIL;; CL-USER> (fly (make-instance 'rubber-duck :name "Ducky") (make-instance 'no-fly));; Rubber duck Ducky is not flying at all
fredag 11 oktober 13
Multiple dispatch(defclass duck () ((name :initarg :name :accessor name)))(defclass mallard-duck (duck) ())(defclass red-duck (duck) ())(defclass rubber-duck (duck) ())
;; In another file, we can add flying behavior
;; What design pattern is this an implementation of?
(defclass fly-behavior () ())(defclass fly-with-wings (fly-behavior) ())(defclass no-fly (fly-behavior) ())
(defgeneric fly (duck fly-behavior) (:documentation "A method to allow ducks to fly") (:method ((d mallard-duck) (b fly-with-wings)) (format t "The mallard duck ~A is flying with wings!" (name d))) (:method ((d rubber-duck) (b fly-with-wings)) (format t "Rubber duck ~A is flying with wings!" (name d))) (:method ((d rubber-duck) (b no-fly)) (format t "Rubber duck ~A is not flying at all" (name d))) )
Method description
;; CL-USER> (fly (make-instance 'rubber-duck :name "Ducky") (make-instance 'fly-with-wings));; Rubber duck Ducky is flying with wings!;; NIL;; CL-USER> (fly (make-instance 'rubber-duck :name "Ducky") (make-instance 'no-fly));; Rubber duck Ducky is not flying at all
Method dispatch
fredag 11 oktober 13
Multiple dispatch(defclass duck () ((name :initarg :name :accessor name)))(defclass mallard-duck (duck) ())(defclass red-duck (duck) ())(defclass rubber-duck (duck) ())
;; In another file, we can add flying behavior
;; What design pattern is this an implementation of?
(defclass fly-behavior () ())(defclass fly-with-wings (fly-behavior) ())(defclass no-fly (fly-behavior) ())
(defgeneric fly (duck fly-behavior) (:documentation "A method to allow ducks to fly") (:method ((d mallard-duck) (b fly-with-wings)) (format t "The mallard duck ~A is flying with wings!" (name d))) (:method ((d rubber-duck) (b fly-with-wings)) (format t "Rubber duck ~A is flying with wings!" (name d))) (:method ((d rubber-duck) (b no-fly)) (format t "Rubber duck ~A is not flying at all" (name d))) )
Method description
;; CL-USER> (fly (make-instance 'rubber-duck :name "Ducky") (make-instance 'fly-with-wings));; Rubber duck Ducky is flying with wings!;; NIL;; CL-USER> (fly (make-instance 'rubber-duck :name "Ducky") (make-instance 'no-fly));; Rubber duck Ducky is not flying at all
Method dispatch
Strategyfredag 11 oktober 13
(defclass expression () ())
(defclass compound-expression (expression) ((left :initarg :left :accessor left) (operator :initarg :operator :accessor operator) (right :initarg :right :accessor right)))
(defclass atomic (expression) ((value :initarg :value :accessor value)))
;;;;;;;; Independently of the classes above, we define a way to;;;;;;;; perform different operations on the objects of each class
;; What pattern would this correspond in the GoF book?
(defgeneric get-value (Expression) (:documentation "Calculates the value of the expression ") (:method ((self compound-expression)) (funcall (operator self) ! (get-value (left self)) ! (get-value (right self)))) (:method ((self atomic)) (value self)))
(defvar expression (make-instance 'compound-expression ! ! ! :left (make-instance 'atomic :value 3) ! ! ! :operator #'*! ! ! :right (make-instance 'atomic :value 4)))
(defvar expression2 (make-instance 'compound-expression! ! ! :left expression! ! ! :operator #'+! ! ! :right (make-instance 'atomic :value 5)! ! ! ))
(get-value expression2)
expression
compound-expression atomic
3
*
4
+
5
expression
expression2
fredag 11 oktober 13
(defclass expression () ())
(defclass compound-expression (expression) ((left :initarg :left :accessor left) (operator :initarg :operator :accessor operator) (right :initarg :right :accessor right)))
(defclass atomic (expression) ((value :initarg :value :accessor value)))
;;;;;;;; Independently of the classes above, we define a way to;;;;;;;; perform different operations on the objects of each class
;; What pattern would this correspond in the GoF book?
(defgeneric get-value (Expression) (:documentation "Calculates the value of the expression ") (:method ((self compound-expression)) (funcall (operator self) ! (get-value (left self)) ! (get-value (right self)))) (:method ((self atomic)) (value self)))
(defvar expression (make-instance 'compound-expression ! ! ! :left (make-instance 'atomic :value 3) ! ! ! :operator #'*! ! ! :right (make-instance 'atomic :value 4)))
(defvar expression2 (make-instance 'compound-expression! ! ! :left expression! ! ! :operator #'+! ! ! :right (make-instance 'atomic :value 5)! ! ! ))
(get-value expression2)
expression
compound-expression atomic
3
*
4
+
5
expression
expression2
Visitorfredag 11 oktober 13
First-order functions
[1,2,3].collect { |x| x+2 } => [3,4,5]
new List<int> () { 1, 2, 3 }.Select (x => x +2);=> { 3, 4, 5 }C#
Ruby
Lisp (mapcar #'(lambda (x) (+ x 2)) '(1 2 3))=> (3 4 5)
fredag 11 oktober 13
First-order functions
[1,2,3].collect { |x| x+2 } => [3,4,5]
new List<int> () { 1, 2, 3 }.Select (x => x +2);=> { 3, 4, 5 }C#
Ruby
Lisp (mapcar #'(lambda (x) (+ x 2)) '(1 2 3))=> (3 4 5)
fredag 11 oktober 13
First-order functions
[1,2,3].collect { |x| x+2 } => [3,4,5]
new List<int> () { 1, 2, 3 }.Select (x => x +2);=> { 3, 4, 5 }C#
Ruby
Lisp (mapcar #'(lambda (x) (+ x 2)) '(1 2 3))=> (3 4 5)
fredag 11 oktober 13
First-order functions
[1,2,3].collect { |x| x+2 } => [3,4,5]
new List<int> () { 1, 2, 3 }.Select (x => x +2);=> { 3, 4, 5 }C#
Ruby
Lisp (mapcar #'(lambda (x) (+ x 2)) '(1 2 3))=> (3 4 5)
fredag 11 oktober 13
First-order functions
[1,2,3].collect { |x| x+2 } => [3,4,5]
new List<int> () { 1, 2, 3 }.Select (x => x +2);=> { 3, 4, 5 }C#
Ruby
Lisp (mapcar #'(lambda (x) (+ x 2)) '(1 2 3))=> (3 4 5)
Strategyfredag 11 oktober 13
Open classes vs Design Patterns
Behavioral
Structural
Creational
Memento
Command
Interpreter
Facade
Prototype
Flyweight
Visitor
State Templatemethod
Iterator
Abstract Factory
Composite
Builder
Singleton
Proxy
Mediator
Adapter
Bridge
Observer
Chain of responsibility
Factory method
Decorator
Strategy
Highlighted patterns simplifiedfredag 11 oktober 13
Open classes vs Design Patterns
Behavioral
Structural
Creational
Memento
Command
Interpreter
Facade
Prototype
Flyweight
Visitor
State Templatemethod
Iterator
Abstract Factory
Composite
Builder
Singleton
Proxy
Mediator
Adapter
Bridge
Observer
Chain of responsibility
Factory method
Decorator
Strategy
Highlighted patterns simplifiedfredag 11 oktober 13
Metaprogramming vs Design Patterns
Behavioral
Structural
Creational
Memento
Command
Interpreter
Facade
Prototype
Flyweight
Visitor
State Templatemethod
Iterator
Abstract Factory
Composite
Builder
Singleton
Proxy
Mediator
Adapter
Bridge
Observer
Chain of responsibility
Factory method
Decorator
Strategy
Highlighted patterns simplifiedfredag 11 oktober 13
Metaprogramming vs Design Patterns
Behavioral
Structural
Creational
Memento
Command
Interpreter
Facade
Prototype
Flyweight
Visitor
State Templatemethod
Iterator
Abstract Factory
Composite
Builder
Singleton
Proxy
Mediator
Adapter
Bridge
Observer
Chain of responsibility
Factory method
Decorator
Strategy
Highlighted patterns simplifiedfredag 11 oktober 13
Multiple dispatch vs Design Patterns
Behavioral
Structural
Creational
Memento
Command
Interpreter
Facade
Prototype
Flyweight
Visitor
State Templatemethod
Iterator
Abstract Factory
Composite
Builder
Singleton
Proxy
Mediator
Adapter
Bridge
Observer
Chain of responsibility
Factory method
Decorator
Strategy
Highlighted patterns simplifiedfredag 11 oktober 13
Multiple dispatch vs Design Patterns
Behavioral
Structural
Creational
Memento
Command
Interpreter
Facade
Prototype
Flyweight
Visitor
State Templatemethod
Iterator
Abstract Factory
Composite
Builder
Singleton
Proxy
Mediator
Adapter
Bridge
Observer
Chain of responsibility
Factory method
Decorator
Strategy
Highlighted patterns simplifiedfredag 11 oktober 13
First-order functions vs Design Patterns
Behavioral
Structural
Creational
Memento
Command
Interpreter
Facade
Prototype
Flyweight
Visitor
State Templatemethod
Iterator
Abstract Factory
Composite
Builder
Singleton
Proxy
Mediator
Adapter
Bridge
Observer
Chain of responsibility
Factory method
Decorator
Strategy
Highlighted patterns simplifiedfredag 11 oktober 13
First-order functions vs Design Patterns
Behavioral
Structural
Creational
Memento
Command
Interpreter
Facade
Prototype
Flyweight
Visitor
State Templatemethod
Iterator
Abstract Factory
Composite
Builder
Singleton
Proxy
Mediator
Adapter
Bridge
Observer
Chain of responsibility
Factory method
Decorator
Strategy
Highlighted patterns simplifiedfredag 11 oktober 13
Summary
fredag 11 oktober 13
What is Good Design?
fredag 11 oktober 13
• Encapsulate what varies
• Program to an interface, not to an implementation
• Favor composition over inheritance
• Classes should be open for extension but closed for modification
• Don’t call us, we’ll call you
• Depend on abstractions, do not depend on concrete classes
• Classes should only have one reason to change
• Strive for loosely-coupled design
fredag 11 oktober 13
Or ...
fredag 11 oktober 13
• Testable programs
Or ...
fredag 11 oktober 13
• Testable programs
• Changeable programs
Or ...
fredag 11 oktober 13
• Testable programs
• Changeable programs
Or ...
fredag 11 oktober 13
• Testable programs
• Changeable programs
ChangeTest
Or ...
fredag 11 oktober 13
What is a Design Pattern?
fredag 11 oktober 13
What is a Design Pattern?
Why are there Design Patterns?
fredag 11 oktober 13
What is a Design Pattern?
Why are there Design Patterns?
How are Design Patterns used/recognized?
fredag 11 oktober 13
Why
fredag 11 oktober 13
1. There are OO Programming Languages™
Why
fredag 11 oktober 13
1. There are OO Programming Languages™
2. There are Common Problems™
Why
fredag 11 oktober 13
1. There are OO Programming Languages™
2. There are Common Problems™
3. There are Design Principles™
Why
fredag 11 oktober 13
1. There are OO Programming Languages™
2. There are Common Problems™
3. There are Design Principles™
➡1+2+3 = Design Pattern
Why
fredag 11 oktober 13
How
fredag 11 oktober 13
1. There are Structure Diagrams™
How
fredag 11 oktober 13
1. There are Structure Diagrams™
2. There are A Bunch of Other Attributes™
How
fredag 11 oktober 13
1. There are Structure Diagrams™
2. There are A Bunch of Other Attributes™
➡1+2 = Design Pattern
How
fredag 11 oktober 13
Other Patterns
fredag 11 oktober 13
Other PatternsSimpleton
The Simpleton Pattern is an extremely complex pattern used for themost trivial of tasks. The Simpleton is an accurate indicator of theskill level of its creator.
fredag 11 oktober 13
Other PatternsSimpleton
The Simpleton Pattern is an extremely complex pattern used for themost trivial of tasks. The Simpleton is an accurate indicator of theskill level of its creator.
Commando
The Commando Pattern is used to get in and out quick, and get the jobdone. This pattern can break any encapsulation to accomplish itsmission. It takes no prisoners.
fredag 11 oktober 13
Other PatternsSimpleton
The Simpleton Pattern is an extremely complex pattern used for themost trivial of tasks. The Simpleton is an accurate indicator of theskill level of its creator.
Commando
The Commando Pattern is used to get in and out quick, and get the jobdone. This pattern can break any encapsulation to accomplish itsmission. It takes no prisoners.
http://franksworld.com/blog/archive/2005/01/04/600.aspxfredag 11 oktober 13
The Exam
fredag 11 oktober 13
Oct 25th 8-12Bring written notes & the books. Justify all your
reasoning. Good luck!
fredag 11 oktober 13
Thank you!
fredag 11 oktober 13