"Regarding the issue of extending classes (and partial classes) I am very sorry it was ever invented. Developers should be encouraged to divide large classes by decomposing them into decoupled sub-components using design patterns and not by simply splitting them between files. Even though a feature is called "extending" a class it is in violation of the Open Closed Principle..."
Modules should be both open (for extension and adaptation) and closed (to avoid modification that affect clients)
It is easy to see the benefit of having a class that answers this principle: When you need to add a requirement, instead of breaking dependent code (and tests) you just extend it somehow and everything is nice and dandy. Furthermore, violating OCP can result in Rigidity,Fragility, and Immobility. But how do you do that? The obvious (and naïve) answer is inheritance. Every time something needs to change just add a sub-class. The parent class is not changes and voilà. However, if you add sub-classes all the time you'd get "lazy classes" or freeloaders--sub-classes without a real reason for existence not to mention a maintenance nightmare. Thus, sub-classing is an option but we need to consider carefully where to apply it. Other (more practical ) OCP preserving steps include: Marking class fields as private Not adding getters/setters automatically. You may want to read "Why getter and setter methods are evil" by Allen Holub, and Martin Fowler's rebuttal/refinement in "Getter Eradicator".Inversion of Control strategies TemplateMethod pattern Strategy Pattern Anonymous delegates (in C# 2.0) and Closures in dynamic languages (also in C# 3.5) And don't forget to hide implementation details behind (stable) interfaces
It is easy to see the benefit of having a class that answers this principle: When you need to add a requirement, instead of breaking dependent code (and tests) you just extend it somehow and everything is nice and dandy. Furthermore, violating OCP can result in Rigidity,Fragility, and Immobility.
But how do you do that? The obvious (and naïve) answer is inheritance. Every time something needs to change just add a sub-class. The parent class is not changes and voilà. However, if you add sub-classes all the time you'd get "lazy classes" or freeloaders--sub-classes without a real reason for existence not to mention a maintenance nightmare.
Thus, sub-classing is an option but we need to consider carefully where to apply it. Other (more practical ) OCP preserving steps include:
class Foo def bar puts "foo.bar" end end obj = Foo.new obj2 = Foo.new def obj.bar # redefining bar just for obj puts "foo.newbar" end obj.bar # prints foo.newbar obj2.bar # prints foo.bar
class Foo def bar(myProc) # accepts a callable object foobar = "foo.bar" myProc.call(foobar) # call the object with a parameter end end obj=Foo.new printer=Proc.new {|msg| puts msg} obj.bar(printer)
class Foo end obj=Foo.new # obj.bar - error Foo.class_eval do # this simplistic example can also use regular def define_method :bar do # but class_eval can also evaluate strings to create puts "foo.bar" # dynamic methods like setters etc. end end obj.bar
"Identify points of predicted variation and create a stable interface around them."
Subscribe to RSS headline updates from: