Manuel is back from his post-release-pre-Christmas vacation all tanned and refreshed and fired up to talk about UML again.
In this post he’ll look at generalization, substitution and inheritance and will realize his genius.
I’m about to do a check-in of code that just passed the unit tests, when I sense my manager Fossey’s figure approaching. This is never good…
“Hey Manuel, how’s it going?”
It’s even worse than I expected – this level of politeness normally means disaster…
With eyes firmly fixed on a corner of my desk he continues:
“Er, I got a call about that meeting with marketing and apparently they want a developer present there. “
“Oh?”
“How’s your schedule looking on Friday?”
“This Friday? Oh, gee… We were supposed to have all the conformance tests out of the way until then and it’s a lot of work…”
Fossey is a man of few words, but, to balance that, his body usually speaks volumes. Eyes drilling a hole in the carpet and right hand rubbing the chin tell me that he’s not going away until he gets the answer he wants to hear…
“I’ll see what I can do.”
And there we have it. I’m a total pushover, but at least that’s made Fossey retreat back to his room.
Marketing meetings are a pain in the neck even on a good day. I think I have a solution, though: the Liskov Substitution Principle. Finally those four years in university are starting to pay off…
Liskov Substitution Principle
“…If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.” (Barbara Liskov)
This may sound a bit abstract, but it actually translates quite well to my situation. And it’s going to save my skin. Hopefully.
Meet Jimmy.
Jimmy is a junior developer, sort of under my wing. Young, enthusiastic, bright. Sometimes too bright for his own good. And in need of a haircut.
They want a developer in that meeting. Jimmy is a junior developer. Jimmy is a developer. That should do!
Generalization
When we have an ‘is a’ relationship, we can talk about generalization. Junior Developer is a Developer. Developer is a generalization for Junior Developer. Ditto for Senior Developer. Both Senior Developer and Junior Developer are subtypes of the Developer type. In UML this is shown with a triangular arrow pointing from the subtype to the base type:
Let me try and translate the Liskov Substitution Principle to our situation:
We have a program P (the meeting), which requires an object o1 of type S (Developer) to be present. If we substitute O1 (me) with an object o2 (Jimmy) of type T (Junior Developer), this should affect the proceedings of the meeting.
Inheritance
In Object Oriented Programming generalization is often expressed through inheritance, where one or more classes inherit or descend from a base class.
On the diagram above Developer is the base class, which Senior Developer and Jinior Developer inherit. In other words, they are subclasses (or subtypes) of Developer.
And, to illustrate the example again, this time with pseudocode, here is an example of how the principle of substitution is applied by sending a subtype of Developer to a meeting, where Developer is expected:
class JuniorDeveloper : public Developer{...};
void attend_meeting( Developer devRepresentative ){...}
Developer jimmy = new JuniorDeveloper();
attend_meeting( jimmy );
Realization
This is where I realize my genius…
Unfortunately not. It’s just a last paragraph, meant to introduce another OOP term. Realization is generalization, looked at from the back. There.
What I mean is that in the examples we saw Junior Developer realizes or implements the behaviour defined by Developer: what a Developer is expected to do, a Junior Developer should be able to do too.
Of course, in OOP a subtype is free to override some of that behaviour and implement it in its own way. For example, if Developer defines a method fix_bug(), the JuniorDeveloper subclass may implement it like this:
void JuniorDeveloper::fix_bug( int bugId )
{
read_bug_description( bugId );
while ( !bugReproducable )
{
poke_around();
}
put_breakpoints();
trace_code();
}
And the implementation for SeniorDeveloper may look like this:
void SeniorDeveloper::fix_bug( int bugId )
{
Developer jimmy = new JuniorDeveloper();
jimmy.fix_bug( bugId );
}
But, the important thing is: for the substitution principle to work, both subclasses must provide an implementation.
Resources
As much as I would like to take credit for the knowledge in this article, all the UML stuff comes from:
- Liskov Substitution Principle: Barbara Liskov, Data Abstraction and Hierarchy, SIGPLAN Notices, 23,5 (May, 1988)
- The UML Standard
- UML Distilled: A Brief Guide to the Standard Object Modeling Language (3rd Edition) by Martin Fowler
- “UML 2 for Dummies” by Michael Jesse Chonoles, James A. Schardt
- The wonderful Wikipedia
The cool cartoons are courtesy of zlotence.
Lol, poor Jimmy!
Yeah, man, that meeting was NOT fun…