Don't draw yourself.

One of the first practices taught in CS on OO design is that objects should encapsulate most of operation required by a system it is intended to run.
Thought this does make initial sense and has been a workable solution for some time it simply does not scale and contradicts real world scenarios.
For example let’s take the same “draw yourself” scenario.

In software:

You are required to write a GUI application where you need to load geometries from database and show it on GUI screen.
According to aforementioned popular practice a shape class hierarchy will be defined were the top level abstraction will contain some type of “drawYourself(…)” method.

Now this will work were UIComponent is used and default shape drawing is good enough.
What if later new requirements come forcing us to implement HTML client where UIComponent cannot fit?
Should we extends each shape type and define additional method that will write HTML tags?
What if under certain circumstances we want different drawing behavior from shape objects, for example Picasso style of drawing? Should we modify “drawYourself(…)” to take additional draw type parameter?
How can we be sure we have modeled all possible drawing types?
The solutioin to this will be to externalize the drawing logic from shape and define contract of what shape object can provide to satisfy drawing abstraction, in this case it will be set of XY points.

This will allow us to leave shape class hierarchy intact and at the same time to plug as many DrawHandler as we wish.

In real world:

In real world it much more obvious. For example the person (shape) in Mona Lisa portrait probably could not paint at all but her appearance (light reflection instead of xy points) was used by help Da Vinci (draw handler) in painting that portrait.

This might seem trivial by some, but is repeatedly misused by most (even veteran programmers).
Even worse under different scenarios that might not be as obvious as “draw yourself” example.

Conclusion:

This article tries to highlight the case that not all objects need to implement particular functionality directly but can provide hints for some type of handlers to represent them in particualr environment the handler has closer ties with. Its worth mentioning that this approach is not always the optimal solution and there are cases that direct implementation of functions is desirable when the object and environment and tightly coupled together, such as in case of java.awt.Component (the object) and java.awt.Graphics (the environment) case.

1 comment to Don't draw yourself.

  • tsolakp
    1. You have got to put “drawing” logic somewhere and having it separately
      encapsulated in parallel class hierarchy is totally acceptable.
      What do you prefer? Keep on adding more code to support different “drawing”
      logic into Shape classes or simply adding additional Handler?

    1. With your re-factored approach we still ended up with Handler class
      hierarchy but at the same time managed to pollute Shape with “drawing”
      responsibility.
      For example to draw the Shape like Picasso, as you suggested, you need to
      add “drawPicasso” or “draw(PICASSO)” support into Shape class, making the
      Shape class bigger and unmanageable as we start adding more drawing logic.

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>