Monolithic software products (those with a multitude of highly coupled components) are often blamed on the use of procedural languages, but it’s just as easy to produce overly interdependent classes in object-oriented languages. Stephen B. Morris shows how using the mediator design pattern can help reduce class interdependencies, aid componentization & ultimately help make classes service-oriented.
Eugenia I noticed it’s not the first time you are linking articles from Mr Morris. This time I took time to read the resume of Mr Morris, and he is definetly an experienced programmer.
I am a young programmer passioned about C++ (I take this languaged in high esteem, please no trolling on this) I would not encourage other programmer to read this article for 2 reason:
1. As the beginning of the article you can read:
In software, the area in which individual objects interact seems to present much difficulty. If we get the interaction patterns wrong, the possibility of successful reuse and componentization is also reduced.
This is very very true. So true that I spend most of my time rewritting my code and the code of others (more experienced than me sometime) to provide better reusabilty. And it’s difficult to do, but it is possible. So if one spend time writting a good class using the correct pattern, why would he need a “mediator” in the first place? Furthermore there is chances that if the implementation is already wrong, the mediator won’t make things more right.
2. Nowaday C++ is still evolving very fast and it’s been some time that one major improvement have been around, and this improvement helps a lot to solve the problem tackled by the mediator: it is called a “concept”. Typically “concept” are used with “templates”. As in the exemple you want to allow a certain number of interaction with your class. Instead of writing a “mediator” that you have to maintain, you write your class using a template argument and define your template with a serie of concept. Those concept will garantie that requirement for your templates are met and it with template you gain genericity: which helps a lot in protability.
These technics are gather as a common name: meta-programing. There is wonderful books about combining design pattern and metaprograming, and the great effectiveness and portability of the code that results.
Reading this article will IMHO lead the programmer in the wrong direction, ie away from the power of metaprogramming, forcing him to add always more and more classes to its code, which in most of the case result in “complicated design”.
This is very very true. So true that I spend most of my time rewritting my code and the code of others (more experienced than me sometime) to provide better reusabilty. And it’s difficult to do, but it is possible. So if one spend time writting a good class using the correct pattern, why would he need a “mediator” in the first place? Furthermore there is chances that if the implementation is already wrong, the mediator won’t make things more right.
2. Nowaday C++ is still evolving very fast and it’s been some time that one major improvement have been around, and this improvement helps a lot to solve the problem tackled by the mediator: it is called a “concept”. Typically “concept” are used with “templates”. As in the exemple you want to allow a certain number of interaction with your class. Instead of writing a “mediator” that you have to maintain, you write your class using a template argument and define your template with a serie of concept. Those concept will garantie that requirement for your templates are met and it with template you gain genericity: which helps a lot in protability.
That is a completely naive proposition you make. There are times were you need to use such patterns or similar. In fact, this pattern is most commonly used when designing plug-in systems. You have an object, a mediator, that acts like a manager. Its sole purpose is to inform other objects of what is going on in the system. I prefer to use a signals system for communication. In a very well designed system, objects interact with themselves and the mediator only. This is essential to reduce coupling. The alternative is having objects in each others business and dangerously playing around with each others properties. Using a mediator is not bad practice. In fact it’s one of the easiest ways to reduce coupling in systems. Almost all large scale systems use mediator-like patterns to allow objects to communicate with each other via an established protocol, plug-in systems especially.
Edit: Removed repeatition.
Edited 2006-05-22 17:11
It’s an interesting reply.
You bring a good point with “reducing coupling”. However my feeling is that mediator is often too simple in implementation, an unecessary abstraction if you prefer, and it can be “removed” with templates: without the cost of “coupling the class to another”.
However I disagree when you talk about plug-in. I think what you are refering to is a Facade and not a Mediator when it comes to plug-in. Facade because the plugin knows and interact with the application only through what is exposed in the Facade. I think that’s what you meant with:
Almost all large scale systems use mediator-like patterns to allow objects to communicate with each other via an established protocol, plug-in systems especially.
That definitly looks like you are talkin about Facade http://en.wikipedia.org/wiki/Facade_pattern
Just browsing wikipedia I found a good critic about insufisant abstraction caused by the will to use design pattern, it goes further than my real opinion about it, but I kinda feel the same way as that guy: http://en.wikipedia.org/wiki/Software_design_pattern#Design_pattern…
However I disagree when you talk about plug-in. I think what you are refering to is a Facade and not a Mediator when it comes to plug-in. Facade because the plugin knows and interact with the application only through what is exposed in the Facade. I think that’s what you meant with:
Again, this is application dependent. For example, in my
application, the mediator object could be the only plug-in
API. Why? Because the mediator object is the focal point of
the system. All objects interact with the mediator and
themselves and nothing more. Plug-ins therefore only need
the mediator object to extend the application. It’s not
necessary to use the Facade pattern. In fact, I don’t like
the Facade pattern. It’s just more code to hide ugly code.
My opinion is if code is well designed, you won’t need to
add more cruft to make its interface prettier. I call it
code bloat.
Just browsing wikipedia I found a good critic about insufisant abstraction caused by the will to use design pattern, it goes further than my real opinion about it, but I kinda feel the same way as that guy:
I don’t like design patterns either. Because they are filled
with pompous theoretical assumptions, they make code more
complex, and they give developers a false sense of security.
I prefer customized solutions to programming problems. I guess
it’s because I tend to view each problem in unique light and
in terms of the surrounding problems. A pattern might be
useful to solve a problem, but it might break in light of
surrounding problems associated with the main problem. If
my solution ends up being an established pattern, then
that’s just a bonus. I notice when people start indulging in
design patterns they tend to write code around the patterns
as opposed to focusing on practical issues related to the
problem. This often leads the complex code for sometimes
very simple problems. I have the same problem with OO,
but I’ll leave my rant for another day.
what is “service oriented”? and what was a class before it because service oriented?
From TFA:
class LspDirector : public ConnectionDirector
{
public:
…
private:
int lspId;
PathWidget* _lspPath;
QosWidget* _qosDescriptor;
};
LspDirector::~LspDirector(void)
{
}
Listing 10 does the following:
1. Creates a mediator instance.
2. Creates some widgets.
3. Changes the widget configurations.
4. Deletes the mediator.
He left off:
5. Creates a memory leak from two orphaned objects.
Other than that, the article was passable. As a previous poster mentioned, there are better ways to do what he intended without resorting to an intermediary class. Being more careful with the up-front design can aviod having to use band-aid solutions like this. That is not to imply that an intermediary class is never needed, but the example given hardly seemed an appropriate use for one.
LOL
Actually, I didn’t wanted to point that out in my first post… but with all due respect: an experienced programmer in C++ that uses pointers everywhere in its prototyping without using one single reference, look a lot to me like an experienced C programmer that discovered C++ years later.
I tend to read their articles quite quickly just for the ideas, and forget the bad programing practices…