Showing posts with label design patterns. Show all posts
Showing posts with label design patterns. Show all posts

Friday, October 10, 2008

Rules of Thumb

Well, these aren't patterns, but just principles we should use when writing softwares, brought up by Russ Olsen in his Design Patterns in Ruby:
  • Separate out the things that change from those that stay the same ... identify aspects of the system design that are likely to change, isolate them from the stable parts. Thus, when requirements change or bug fix comes along, even if we still need to modify the codes, the changes can be localized and the rest of the code can live on without changes.
  • Program to an interface, not an implementation ... write code that uses the most general type possible. For example, by writing plane.fly & ship.sail, we are getting very specific, this results in tight coupling, the code using these objects needs to know the exact traveling mode. To loosen things up, we can generalize these vehicles by writing plane.travel & ship.travel instead, thus, the client code no longer needs to know the traveling mode, it just ask the objects to travel.
  • Prefer composition over inheritance ... instead of saying an object is a kind of something, we say that it has something. We assemble the behaviors we need through composition, by supplying an object with objects that provide the needed functionalities.
  • Delegate, delegate, delegate ... by preferring composition over inheritance, instead of being almighty (or inheriting from the almighty parent), an object can delegate the required functionality to another object.
  • You ain't gonna need it (YAGNI) ... if you are not sure that you need something right now, postpone its implementation until you really need it. Why? Cos we tend to be wrong when we try to anticipate exactly what we will need in the future. And we should focus our time and energy implementing things that we definitely need right now.

Thursday, October 9, 2008

Template Method

It has been said that in the software engineering field, the classic GOF book is a MUST READ bible. I never doubt this. However, i have always found it hard to digest. Not too long ago, i've found another book Design Patterns in Ruby, and i love it. It really makes all the concepts easier to grasp.

The first pattern it brought up is the 'template method', which is probably the easiest of all. Here's how it goes:
1.  class Report
2. def initialize(content)
3. @content = content
4. end
5. def output # template/skeletal method
6. output_header
7. output_body
8. output_footer
9. end
10. def output_body # abstract method
11. raise "Subclass MUST implement output_body"
12. end
13. def output_header ; end # hook (non-abstract) method
14. def output_footer ; end # hook (non-abstract) method
15. end
Notice the followings:
  • lines 5-9 ... defines the template (aka skeletal) method that delegates specific output actions individual methods
  • lines 10-12 ... defines the abstract method that MUST be implemented by subclasses, throwing of error is a workaround for the absence of abstract method in ruby (actually this is unnecessary, since ruby throws an undefined method error if it cannot find, anyway, its good to be informative)
  • lines 13 ... defines a hook method, which provides minimal default implementation and is meant to be overridden by subclasses (when appropriate)
Subclasses can be written and used as follows:
1.  class TextReport < Report
2. def output_body
3. puts @content.body
4. end
5. end
6.
7. class HtmlReport < Report
8. def output_header
9. puts "<html>"
10. end
11. def output_body
12. puts "<body>#{@content.body}</body>"
13. end
14. def output_footer
15. puts "</html>"
16. end
17. end
18.
19. [ TextReport, HtmlReport ].each do |report_class|
20. # outputs the appropriate report depending on report_class
21. report_class.new(content).output
22. end
SIMPLE !?

I've realized that without ever reading abt design patterns, i've already implemented this pattern in my php code, here's a fragment of my past php4 controller code:
1.  class AbstractWebController {
2. function process() { // template method
3. $action = $_POST['action']; // eg. destroy
4. $this->$action(); // variable method
5. }
6. }
7.
8. class MonsterController extends AbstractWebController {
9. function destroy() {
10. // monster destroying something ...
11. }
12. }
Well, it differs slightly from the original template method, as there is no distinct abstract or hook method. Instead, depending on value of $_POST['action'] (line 3), we call a variable method (line 4) in any subclass (line 10). By applying this pattern in any web framework, we can support arbitrary posted actions. NEAT rite ?!