Re: Getting started with object design



Responding to Andreagiorgetta...

Picasa is (Google's) application for organizing and cataloguing every
image (maybe I should say "photos"...) in someone's hard disk(s). The
idea is that you can create an album, add images to it, browse it,
view its pictures and, eventually, you can do some basic editing tasks
on them (rotate the image, cut and crop, adjust brightness, contrast,
reduce red eye effect, etc). The component suite we use to edit images
is ImageEn (www.hicomponents.com, which is probably the most powerful
for image processing in Delphi, and another of our non-functional
requirements). We created a class that interacts with those
components, and a Facade for it. We added a Facade because we suspect
that we will not use only ImageEn components, probably for some
editing tasks we'll need another, so we though that we would have an
"image processing subsystem" in the future (even today it has only one
class), and a Facade could provide a simple interface for it.

OK, the Facade sounds like a good idea for exactly the reason you gave; you can substitute behind it without affecting the clients.

We are just starting with the development of the application, but we
already have the (obvious) classes "Album" and "Photo" (Album contains
photos, a user can have several albums, etc). In GUI, we use a
miniature view component (ImageEnMView) which displays, for example,
all the photos of an album. We had no idea where we should insert the
code to update that miniature view when, for example, you select a
different album... so and we added a GUI class which does those kinds of
things (maybe the name of the class is not the best considering the
class' responsibility...).

OK, I misunderstood; I though the GUI object was managing the display directly (e.g., talking to an OS Window Manager). I'm not keen on the name but it seems like a good idea. B-) This sounds like the GUI object is a similar sort of Facade for the miniature view component as for the editor component above.

That allows you to dynamically define the album to display:

[Album]
| 1
| accesses
|
| R1
|
| current for
| 1
[GUI]
+ displayAlbum()
| 1
|
| R2
|
| knows how to talk to
| 1
[ImageEnMView]

When the user selects a particular album in the real GUI, that processing instantiates the R1 relationship. Then when it is time to actually display the album somebody invokes GUI::displayAlbum(). That method navigates the R1 relationship and does whatever it needs to do to present it to ImageEnMView.

ImageEnMView may not be an object per se; displayAlbum could just invoke a predefined API. It is just convenient here to think of it conceptually at the OOA/D level as an entity. If ImageEnMView is accessed through an API, then it would essentially be external to this subsystem and the API represents a subsystem interface. If that is the case, then GUI becomes a surrogate object that represents ImageEnMView in the current subsystem by providing a convenient interface for this subsystem's context.


In some part of the screen we need to show an image that represents an
album. It is composed of a base image of a folder in which we insert a
miniature of one of the images contained in that album (similar at
what Windows does). To create that composed image, we need to get the
base folder image, resize it, get other the image (from the album),
resize it, apply a mask to combine both, etc. All those steps are
image processing tasks, methods implemented by the class that
interacts with ImageEn components, and they must be called
sequentially in order to get the desired composed image of an album.
So, GUI class puts the final image of an album (beautifully composed)
wherever it must be on the screen, and the image processing class
performs each one of the steps needed to get that image... but the
question is: which class implements a method that calls those methods
one after the other?

I don't think there should be a single method that manages that sequence. That method would be equivalent to a high level node in a functional decomposition tree and we don't do that in the OO paradigm.

You have described several different activities needed to get the <beautifully> composed image. Each of those should be a distinct responsibility in one or more objects. That is, each activity would be encapsulated in a method that was self-contained and logically indivisible at the subsystem level of abstraction. One would then connect the dots of individual methods with messages that form a sequence in the overall flow of control.

Thus the method that gets the base folder image calls the method that resizes it once it is obtained. Then the method that resizes it either calls the method to get the next base folder image (if this is the first image) or calls the method to do the masking (if this is the last image). To do that all you need is a count of the base images to process in an attribute somewhere and you decrement it each time the resize method is invoked.

Why is this better? For one thing we have reduced the iteration to a message creation that is conditional. That is, the iteration has been cast into a decision about which message to issue and where it goes. That segues to the main advantage.

The flow of control is now orthogonal to the processing in the various methods. One can change the overall flow of control by simply placing the message generation in different methods. This is very important because it means one can change flow of control without touching the code that does useful work in the various methods. That limits the possibility of inserting errors during maintenance and makes changes easier in many situations.

Most important of all, though, it allows one to think about flow of control at a higher level of abstraction than object methods. (In UML one can define the messages in an Interaction Diagram, which is completely separate from the method descriptions.) That allows one to apply DbC techniques to rigorously determine the correct flow of control in complex situations.

Unfortunately this is not very apparent in the OOPLs because they are 3GLs and have made substantial compromises with the hardware computational models. One of those compromises is that a message is defined as a method signature in the 3GL type systems. That removes the separation of message and method. Worse, it encourages a procedural imperative view (Do This) because we name methods by what they do. In the OOA/D messages are supposed to be announcements (I'm Done) of something the sender did. If messages are announcements, then the sender implementation has no reason to depend on what some receiver may do in response. That removes the hierarchical dependencies that led to Spaghetti Code.

However, if one has the proper mindset and thinks of messages as announcements, then one has a better chance of constructing methods without context dependencies. Then the marriage of message and method in the OOPLs doesn't do any harm because the methods are pure of heart.



*************
There is nothing wrong with me that could
not be cured by a capful of Drano.

H. S. Lahman
hsl@xxxxxxxxxxxxxxxxx
Pathfinder Solutions
http://www.pathfindermda.com
blog: http://pathfinderpeople.blogs.com/hslahman
"Model-Based Translation: The Next Step in Agile Development". Email
info@xxxxxxxxxxxxxxxxx for your copy.
Pathfinder is hiring: http://www.pathfindermda.com/about_us/careers_pos3.php.
(888)OOA-PATH



.



Relevant Pages

  • Re: Getting started with object design
    ... that we will not use only ImageEn components, ... "image processing subsystem" in the future (even today it has only one ... all the photos of an album. ... sequentially in order to get the desired composed image of an album. ...
    (comp.object)
  • Re: [ANN] booh: static web-album generator
    ... the first time, and create a new album right away, it will abort on a ... bug because of missing config file. ... to quit the GUI at least once, so that the config file will be created ...
    (comp.lang.ruby)