Re: [Ekiga-devel-list] Design of the engine : why abstract Ekiga::Foo and Ekiga::FooImpl matter



On 14/01/15 08:43, Julien Puydt wrote:
Hi,


this mail is meant to explain why having two classes doesn't make the
code more complex just for the sake of it, but because it brings nice
features.


The fact that Ekiga::Foo is purely abstract means :

1. that anyone trying to write an instance of it, say Bar::Foo, will get
notified by the compiler if they forget to implement one of the methods,
or if they mispell one of them -- the compiler is helpful!

2. that anyone trying to write a very specific implementation is
completely free to do so, as the abstract class is, well, abstract ;

3. that anyone trying to write an implementation with no special needs
can just inherit Ekiga::FooImpl and be done!


So when writing new code, the presence of two classes doesn't get in the
way, and even gets the compiler to help : that is a bonus.


Now, now... we decide that Ekiga::Foo is too weak and add a method. This
immediately :

1. breaks Ekiga::FooImpl, which immediately gets fixed ; of course it
also breaks every class inheriting from Ekiga::FooImpl, but they all get
fixed at the same time -- and the fix can only be correct (more on that
later) ;

2. breaks every class inheriting from Ekiga::Foo, and the compiler says
so : the code won't compile as-is, someone will have to have a look at
all classes with very specific needs, and write correspondingly specific
implementations, so everything is correct.


And that's all : we made sure we either had all methods reimplemented or
none -- no in-between! So when modifying existing code, the presence of
the two classes ensures that the compiler will push every problem
explicitly under our eyes : there will be no silent break.


Compare with a situation where Ekiga::Foo has naive implementations of
everything directly in the base class:

1. Anyone writing an instance of Ekiga::Foo with an overriden
populate_memu (where the base had populate_menu) will have a hard time
knowing they made a typo : the compiler won't catch it. Silent break!

2. Anyone writing an instance of Ekiga::Foo may implement only two
thirds of the method, get something which won't run, but will gladly
compile. Silent break!

3. Anyone writing an instance with very specific needs will find the
variables used by the base class implementation in the way : if they
want to put some information in a 'tokens' variable the base class said
was a list of strings, but should now be a list of Bar::Token, will need
to name it my_tokens, but "tokens" will still take some room, and if
they forget a my_ somewhere, the compiler might not complain if they
don't use string/Bar::Token-specific api. Silent break!

4. You've been lucky : you only reimplemented populate_menu, and kept
the other base implementations because they fit. Someone modifies the
base implementation (added a method and made the default implementations
follow : all nice and clean!). Your code still compiles, but of course,
won't work. Silent break!


I think the purely abstract Ekiga::Foo and Ekiga::FooImpl is better : it
is more expensive, but you do get what you paid for.

Hi Julien,

In case my opinion is useful: I think you are right in theory and also in a big program with many developers working 100% on it. However, I personnaly vote for pragmatism, for simple code ("simple is better!") In our case, each time the code gets better from theory point of view, gets harder to understand by someone wishing to be involved of.

Cheers!
--
Eugen


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]