D
Dave Rahardja
OK, so I've gotten into a philosophical disagreement with my colleague at
work. He is a proponent of the Template Method pattern, i.e.:
class foo
{
public:
void bar() { do_bar(); }
protected:
virtual void do_bar() {}
};
class baz: public foo
{
protected:
virtual void do_bar() {} // overridden
};
As you can see, the non-virtual public method foo:bar() exists only to invoke
the virtual method do_bar, which derivatives of the class can override like a
regular virtual method.
The advantage to this method, my colleague claims, is that future implementors
may change the pre- and post-processing behavior of the virtual do_bar method
(such as adding semaphore acquisition/relinquishment calls before/after the
call to do_bar, respectively) without changing the classes that derive from
foo.
Furthermore, he claims that this separates the decision to make a method
public/private from the decision to make a method virtual--a significant
advantage, he claims.
He has pointed me to articles on C++ Users Journal which seems to support the
Template Method pattern, even going so far as to say that all public virtual
methods should be banned in favor of the Template Method.
See http://www.cuj.com/documents/s=8000/cujcexp1812hyslop/
I, on the other hand, prefer the simple
class foo
{
public:
virtual void bar() {}
};
class baz: public foo
{
public:
virtual void bar() {} // overridden
};
And being a big fan of Java, I also appreciate the Interface pattern:
class foo // interface
{
public:
virtual void bar() = 0;
};
class baz: virtual public foo
{
public:
virtual void bar() {} // implementation
};
Besides, the Template Method can be ruined if a derived class decides that it
needs a different pre- and post-operation for the virtual method...
class foo
{
public:
void bar() { do_bar(); }
protected:
virtual void bar() {}
};
class baz: public foo
{
public:
void bar() { frobnicate(); do_bar(); } // I need something different!
proctected:
virtual void bar() {} // overridden
};
In the above class hierarchy, the two calls...
baz baz_object;
foo& foo_reference(baz_object);
baz& baz_reference(baz_object);
foo.bar();
baz.bar();
....would yield two different call paths.
Of course you can say "don't do that", but I can also say "but I need to
override the default behavior for this class".
So what say you, gentle coders? Are Template Methods worth the hassle? Do they
trade one class of errors for another? Is the convenience of changing pre- and
post-operations at the base class actually masking the fact that we have made
a design error and honestly need to re-examine every descendant class?
The Template Method pattern is not compatible with the Interface method, not
because it can't be done, but because it makes no sense to combine them. Empty
non-virtual public methods whose jobs it is is to simply call pure virtual
protected methods--that's just silly.
So it's one or the other, then. What's the better design paradigm?
work. He is a proponent of the Template Method pattern, i.e.:
class foo
{
public:
void bar() { do_bar(); }
protected:
virtual void do_bar() {}
};
class baz: public foo
{
protected:
virtual void do_bar() {} // overridden
};
As you can see, the non-virtual public method foo:bar() exists only to invoke
the virtual method do_bar, which derivatives of the class can override like a
regular virtual method.
The advantage to this method, my colleague claims, is that future implementors
may change the pre- and post-processing behavior of the virtual do_bar method
(such as adding semaphore acquisition/relinquishment calls before/after the
call to do_bar, respectively) without changing the classes that derive from
foo.
Furthermore, he claims that this separates the decision to make a method
public/private from the decision to make a method virtual--a significant
advantage, he claims.
He has pointed me to articles on C++ Users Journal which seems to support the
Template Method pattern, even going so far as to say that all public virtual
methods should be banned in favor of the Template Method.
See http://www.cuj.com/documents/s=8000/cujcexp1812hyslop/
I, on the other hand, prefer the simple
class foo
{
public:
virtual void bar() {}
};
class baz: public foo
{
public:
virtual void bar() {} // overridden
};
And being a big fan of Java, I also appreciate the Interface pattern:
class foo // interface
{
public:
virtual void bar() = 0;
};
class baz: virtual public foo
{
public:
virtual void bar() {} // implementation
};
Besides, the Template Method can be ruined if a derived class decides that it
needs a different pre- and post-operation for the virtual method...
class foo
{
public:
void bar() { do_bar(); }
protected:
virtual void bar() {}
};
class baz: public foo
{
public:
void bar() { frobnicate(); do_bar(); } // I need something different!
proctected:
virtual void bar() {} // overridden
};
In the above class hierarchy, the two calls...
baz baz_object;
foo& foo_reference(baz_object);
baz& baz_reference(baz_object);
foo.bar();
baz.bar();
....would yield two different call paths.
Of course you can say "don't do that", but I can also say "but I need to
override the default behavior for this class".
So what say you, gentle coders? Are Template Methods worth the hassle? Do they
trade one class of errors for another? Is the convenience of changing pre- and
post-operations at the base class actually masking the fact that we have made
a design error and honestly need to re-examine every descendant class?
The Template Method pattern is not compatible with the Interface method, not
because it can't be done, but because it makes no sense to combine them. Empty
non-virtual public methods whose jobs it is is to simply call pure virtual
protected methods--that's just silly.
So it's one or the other, then. What's the better design paradigm?