On Monday 21 February 2005 17:56, Marty Kraimer wrote:
> Benjamin Franksen wrote:
> > First, I don't understand why every library is specified as as a structure
> > of function pointers ("interface"). IMO, this only makes sense if you
> > anticipate the interface to be passed as an argument, because there might
> > be different implementations of the same interface. If all you ever use
> > is one and the same global pXYZInterface, then all this gives you is the
> > run-time overhead caused by the additional level of indirection.
>
> One reason is that the epicsShare nightmare almost goes away. Instead of
>
> epicsShareFunc <type> epicsShareAPI xxxFunc(...
>
> for every function in a library . By using an interface there is just
> one definition such as
>
> epicsShareExtern asynManager *pasynManager;
Ok.
> Another reason is "Everything is an interface" seems like a good idea.
>
> Note that most interfaces will have multiple implementations just like
> for asynDriver.
But the basic data type libraries? These routines are probably quite heavily
used. OTOH maybe this is premature optimization. We can always make the calls
static later, if it turns out to cost too much performance.
> A comment about using C++ instead of C. This could all be done in C++
> using pure abstract classes. But when I think about the syntax, the C++
> version looks worse (at least to me) than the C version with one exception.
>
> C forces the definition
>
> typedef struct <someInterface> {
> <type> (*method)(<args>);
> ...
>
> Rather than
>
> struct <someInterface> {
> <type> method(<args>);
> ...
>
> Other than that the C++ syntax is more verbose than C.
I may be missing something but this talk about syntactical verbosity sounds a
bit superficial to me. If we would use templates instead of void* and
casting, the interface would be alltogether even more verbose, but it would
be type safe and thus a lot easier to use.
The main point is that C++ offers much better facilities for abstraction than
C. Classes and inheritance -- if used judiciously and with a knowledge of
their limitations and dangers -- are only one point. Even more important IMO
are templates (and to a lesser extent, overloading), especially since they
are not nearly as broken as the inheritance stuff.
I think a lot of Jeff's arguments in favor of DataAccess are sound. IIRC the
first versions of DA used inheritance for polymorphism (i.e. virtual
functions) whereas later on this was changed to use overloading and
templates, albeit mainly for performance reasons. [OTOH, what I have seen of
DA is not exactly easy to understand. E.g. it was not obvious for me what all
them 'adaptor' classes are needed for.]
As I understand it, the epicsTypes library is supposed to implement a number
of ADTs, one for each way to construct a dbd type. With C++ these could be
non-virtual (i.e. not-to-be-inherited) but templatized classes. The API, even
the implementation, could be designed to be completely type safe. This alone
is a considerable improvement over any C variant, IMHO.
Sure, there remain a number of problems with C++.
A problem with overloading in C++ is that it can interact with overriding via
inheritance in a very confusing way; to avoid this, virtual methods should
never be overloaded or have default arguments.
A great problem with C++ templates has been that many C++ compilers couldn't
produce good code from them (and in finite time). I don't know if the
situation has improved during the last year(s).
Many problems with OO and in particular C++ have been due to misconceptions
(fueled by commercial buzz) about what inheritance is good for. For instance,
while inheritance can be a wonderful tool for structuring a library, the API
should, as a general rule, not be designed around the notion that the user
has to inherit from library classes, adding data members and overriding
virtual functions (an exception being pure virtual classes, i.e.
'interfaces'). [NB: Yes, I know that there are still many popular libraries
around that use this misguided idiom.] The subclass relation inherently
breaks the abstraction barrier; it is practically impossible to safely
prevent inadvertant violations of base class invariants. (If you don't
believe me, please read http://okmij.org/ftp/Computation/Subtyping where this
is shown with a simple example.) Thus, while it is important for client code
to *see* the inheritance relations, adding application classes to the
library's inheritance graph is usually not a good idea. Even for callbacks I
think explicit passing of closures is arguably superior to overriding of
virtual methods.
Another very important point is that static objects must be avoided at all
costs.
All in all, I think there is still a good argument in favor of using C++ over
C. That is, provided we avoid the typical C++/OO errors of the past and that
C++ compiler support has improved to the point where heavy use of templates
is no longer a show-stopper.
Cheers,
Ben
- References:
- Re: EPICS base V4: iocCore database Marty Kraimer
- Navigate by Date:
- Prev:
Re: EPICS base V4: iocCore database Benjamin Franksen
- Next:
Re: EPICS base V4: iocCore database Andrew Johnson
- Index:
2002
2003
2004
<2005>
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
- Navigate by Thread:
- Prev:
Re: EPICS base V4: iocCore database Benjamin Franksen
- Next:
Re: EPICS base V4: iocCore database Marty Kraimer
- Index:
2002
2003
2004
<2005>
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
|