Andrei Alexandrescu Wrote:

> In this article:
> 
> http://www.gotw.ca/publications/mill18.htm
> 
> Herb Sutter makes a powerful argument that overridable functions 
> (customization points) should actually not be the same as the publically 
> available interface. This view rhymes with the Template Method pattern 
> as well.
> 
> This leads to the interesting setup in which an interface should ideally 
> define some signatures of to-be-defined functions, but disallow client 
> code from calling them. For the clients, the same interface should 
> expose some higher-level final functions.
> 
> Ignoring for the moment access protection semantics in D (which are 
> broken anyway), let's say this would work:
> 
> interface Cloneable(T) if (is(T == class))
> {
>      private T doClone(); // must implement but can't call
>      T clone()            // this is what everybody can call
>      {
>          auto result = doClone();
>          assert(typeof(result) == typeof(this));
>          assert(this.equals(result));
>          return result;
>      }
> }
> 
> So clients must implement doClone, but nobody can ever call it except 
> Cloneable's module. This ensures that no cloning ever gets away with 
> returning the wrong object.
> 
> Pretty powerful, eh? Now, sometimes you do want to allow a derived class 
> to call the base class implementation. In that case, the interface 
> function must be protected:
> 
> interface ComparableForEquality(T)
> {
>      protected bool doEquals(T);
>      final bool equals(T rhs)
>      {
>          auto result = doEquals(rhs);
>          assert(rhs.equals(cast(T) this) == result);
>          return result;
>      }
> }
> 
> The difference is that now a derived class could call super.doEquals.
> 
> This feature would require changing some protection rules, I think for 
> the better. What do you think?


I read Sutter's 2001 article just now and thought that he eloquently put into 
easy to understand language the same design principle I've used in C++ since 
circa 1990.  I didn't recall the name of that particular design pattern but in 
my own terminology I've always referred to the publicly callable methods as the 
"driver" methods; meaning those methods that may only be called to drive the 
low-level contracted and customizable interface.

The beauty of this design pattern as articulated is of course, that before and 
after code can be used in the public driver methods to call down to and receive 
results from the interface for assertion, argument and return value type 
conversion, filtering purposes etc.  Naturally to enforce what I call the 
driver principle you need to make the publicly callable "driver" methods final 
as indicated (I think?) in the article but certainly as in the 
ComparableForEquality.equals() method of your example.

>From what I can see of your proposal, this makes for better DBC 
>(design-by-contract) software engineering, and, especially given that there 
>are only benefits and no downsides, the concept is a no brainer.

So I vote, yay, go for it, Andrei!

-- Justin Johansson

Reply via email to