At the API level we have pimpl simply because everything is implemented
through a C call
interface over the underlying data structures.
Internally, the headers are divided into I_ for interface and P_ for
private or implementation.
Given that this is open source, we have to count on the honor system in
any case to keep
folks from using implementation internals, so that is pimpl-ish as well.
Some interfaces, in particular the CacheProcessor (and to some extent
the NetProcessor)
use a more heavyweight interface wrapper class to hide the
implementation. In
general I don't think this is necessary/useful when convention works
just as well without the
overhead of repeating the prototypes ad-nauseam and extra indirections,
however in this
case it has the practical application of supporting clustering and SSL
(again to some extent).
So I agree with pimpl, but not that it should be enforced by code. The
KISS principle
is also, perhaps more, important, and that is something one can loose
with cool C++ tricks.
C++ features are like health food, a little is good for you, but a lot
of a good thing can
still be bad for you when you stand back and look at it from the macro
level. I have
seen too many projects degenerate into heaps of boilerplate C++ with
layer after layer
of interface and indirection which I think of as the goto spaghetti of
modern programming.
john
On 12/11/2009 3:56 AM, D.J. Stachniak wrote:
To me something that is extremely valuable is something like pimpl/compiler
firewall towards not exposing any of your implementation (even when your
data members are private) across a binary boundary. This can be huge in
avoiding an impact when you're patching code, etc. A lot of things like
that seem counter-intuitive when you first come across them (you mean I have
*all* that overhead of accessing data members through a pointer? ;)) but end
up being life savers down the road. John Lakos' Large Scale C/C++ Design
has a lot of great pragmatic examples of choices made that seem
counter-intuitive but end up being life savers.
Maybe it's worth creating a checklist of items to use/not use from things
like Lakos, Sutter/Alexandrescu's C++ Coding Standards or Meyer's Effective
series - even Wilson's Imperfect C++ or Seacord's Secure Coding Standard.
Anyway, I don't want to stray too far off onto a tangent but to toss in one
item I think pimpl is very important to be aware of for those designing
classes that sit at the edge of a library's interface/exported API/ABI.
Now, if patching or not worrying about re-compiling the world is not an
issue then pimpl's benefits quickly go out the window when compared against
its added complexity but I think it's worth thinking about.
For that matter any exported library function returning a pointer should
seriously consider something like boost/tr1/soon-to-be-std::shared_ptr to
take advantage of its deleter. This can also be a life saver when in the
presence of different versions of the C/C++ runtime, determining clean-up
responsibilities, etc.
I just think *anything* at the ABI boundary deserves scrutiny as that's a
big *gotcha* area.
D.J.
-----Original Message-----
From: Belmon, Stephane [mailto:sbel...@websense.com]
Sent: Thursday, December 10, 2009 3:29 PM
To: trafficserver-dev@incubator.apache.org
Subject: RE: coding style - simple vs. complex C++
(I feel funny throwing my 2c on these generic threads when I've contributed
zip, but John opened it up so...)
- Exceptions, a.k.a. the surest way to templates-everything (via
RAII-everything).
- State. When performance allows, avoid storing duplicate state in members;
instead have methods ask when they need. The plugin SDK rule is "release
handles before re-enabling the HTTP transaction", which means the same
thing; state you don't have can't go stale, pointers you don't have can't be
dangling :-)
- STL/standard library usage? std::string is handy, so is std::map...
slippery slope.
-----Original Message-----
From: John Plevyak [mailto:jplev...@acm.org]
Sent: Thursday, December 10, 2009 10:45 AM
To: trafficserver-dev@incubator.apache.org
Subject: Re: coding style - simple vs. complex C++
I would like to open up discussion on the simple vs. complex C++/OO issue.
There is a continuum between basic K&R C and full-blown meta-template
programming,
virtual everything, multiple-inheritance, massively overloaded, super
Object-Oriented C++.
Somewhere there is a happy point where most contributors can read the
code and understand
it and make useful contributions while still taking advantage of the
power that C++ offers
where necessary and useful.
Such a middle ground might include (these are some topics we might want
to discuss):
- favor shallow class hierarchies
- try not to use multiple-inheritance
- use templates only when necessary and in the simplest form
necessary to accomplish the goal
- don't use trivial accessors:
int getFoo() { return _foo; }
void setFoo(int foo) { _foo = foo; }
which are a huge waste of time and energy and are less readable
and no safer than just accessing the variable directly.
- don't include gobs of boilerplate code on the off chance that someone
might decide to extend the class unless you really are planning to
extend
the class in that way
- don't make functions virtual unless you *are* overloading them and even
then, consider if a conditional might not just be clearer and faster
and result
in a shallower class hierachy
- don't overload operators except in truly special cases (e.g. smart
pointers)
- don't new/free things which are really static parts of another object
just because
that is how Java does it
- don't have constructors and destructors do lots of complicated stuff
as a side
effect of creating/destroying the object
- think of new things to add to this list :)
Many of these things were hugely popular in the blush of first love with
the OO paradigm, but have since fallen from favor. Nevertheless it might
be helpful to discuss this as part of coding style.
john
Protected by Websense Hosted Email Security -- www.websense.com