bwh at wksoftware.com
Thu Sep 27 04:15:15 New Zealand Standard Time 2001
At 12:33 PM 9/26/01 -0700, Sean K. wrote:
> C++ leaves most things up to the programmer.
As does C or even assembly language, which is part of the problem --
C++ doesn't really make programming any easier, when it gets right
down to it. The code base on Quake3 (ANSI C) was more object
oriented than a lot of the C++ code I've seen, and it actually
supported encapsulation way better than the VAST majority of code
I've seen. It had four main subsystems -- client game, server,
client, and renderer. They were accessed through structs of
function pointers and their implementations were completely opaque
to each other. In C++ you often see programmers with wildly
differing styles and philosophies on how to create object
hierarchies, and it becomes a maintenance horror show.
C++ would have probably been a lot "better" if Stroustrup
et. al. had tried to push some basic idioms at the beginning instead
of making it a generic grab bag of functionality. This latter
flexibility really is what separates C++ from languages that
attempted to standardize somewhat on usage, e.g. Smalltalk, Eiffel,
> Modern programming style guidelines dictate that there should be a
> separation between these but few people actually do it.
That's because the language just flat out makes it difficult. If
you want to put member data (implementation) in your class, you HAVE
to expose it inadvertently to the rest of the world that may only
care about the interface. You can go through contortions to avoid
this, e.g. opaque pointers to private data where memory is allocated
and de-allocated in your constructors and destructors, but at that
point you're already fighting the language.
For example, if you have an Orc class that derives from Mobile, the
rest of the world should only really know what types of actions the
Orc can do. But if the Orc declaration has a member data Weapon,
then you've now got to include the definition for Weapon whenever
you try to grab the interface for Orc. That's a huge problem --
just because you need a class' interface doesn't mean you should
have to drag in all of its implementation dependencies too.
In C++ you can avoid this somewhat by using class factories that
export a pointer to a parent class, but you still have the
dependency problem within the class factory itself (which has to
know what an Orc is, and inadvertently how it's implemented).
For large scale object hierarchy design such as a MUD, weak binding
and dynamic typing just maps much better.
> ie. there is a rule that > public functions should not be pure
> virtual, instead have them call > pure virtual private
If it's a rule, why isn't it enforced? =)
> On a somewhat related note, Scott Meyers wrote an article saying
> that moving as much implementation as possible out of member
> functions into independent functions actually increases
> object-orientation. This is the beginning of the slide towards
> generic programming.
This is a similar point to what Design Patterns was basically saying
-- overriding member functions breaks encapsulation, which is
counter to what the C++ camp has been saying for the past 15 years.
The minute you override a parent's method, you're now in the
position of having to know _how_ your parent implemented a
particular function, especially if the function affects internal
state variables. This again points to the general confusion that
exists between inheritance for specialization (List->Stack)
vs. inheritance for abstraction (Monster->Orc). Both are heavily
used, and very often a hierarchy will use both because C++ language
allows it and, once again, doesn't really say anything about it.
It's a huge language with no guidelines on practical usage.
> People are discovering that pure OO programming is not a panacea.
I think people are discovering that "OO programming" just isn't very
well defined. They've come to associate it with specific languages
or dogmas without really thinking about whether or not it actually
makes the given problem any simpler to solve.
> I personally > subclass quite rarely. Templates and the STL
> also make subclassing > both less neccessary and less useful
> than it had been.
While STL often seems convenient, the compile times are horrendous
and the opacity of the implementation makes debugging a royal pain.
I also dislike templates because your entire implementation is
wedged into a header file -- nothing like a 2 hour recompile when
you change your list implementation. Not to mention the code bloat.
And yes, there are hacks around these problems (e.g. casting
everything back to a void *) but once again, I find myself fighting
the language instead of it helping me.
The fact that books such as Meyers, Coplien, etc. exist -- and the
fact that the patterns they talk about are so damn obtuse half the
time -- has really turned me off. I have about 10 books on the C++
language, and only one on Obj-C, and yet the latter is smaller than
any of the former books and pretty much describes the language and
its usage clearly and concisely.
> IMO this is Java's primary failing. It's statically typed but
> dynamically bound.
Worst of both worlds =) I used to think Java was great, primarily
because I thought of it as a "better C++ than C++". It got rid of a
lot of the baggage that C++ had been carrying around (and the
addition of GC was huge). But when I finally started to really
understand why C++ was broken, it dawned on me that Java at its core
had the same fundamental flaws that C++ had.
> Smalltalk went the right way by making both dynamic.
Like I said -- way ahead of its time. The main reason
Obj-C/Smalltalk never really caught on is because of their
requirement of a run-time environment coupled with performance
worries. C++ always had the advantage because it could cleanly
generate binaries on any platform; had a handy front-end that was
portable (cfront); and kept pushing the false promises of
performance (no overhead if you didn't want it) and flexibility (do
it how YOU want to do it).
C programmers REALLY didn't want to use a language that they
perceived was slower, bigger and less flexible than C -- and when it
gets right down to it, C is about as fast, small and flexible as you
can get in a portable language. C++ addressed these concerns but in
the process delayed OOP by about 20 years =)
> C++ templates provide a similar feature to Smalltalk's typing but
> at compile time.
That's a mighty big "but". One of the things that makes Obj-C so
powerful, for example, is that types are first class objects. So
you can have a mutable array class (NSMutableArray) and just pass in
the type as a run-time argument instead of as a compile time
argument. I find this AMAZING. I mean, it's such a simple concept,
yet it makes such massive leaps in productivity and code clarity.
> Between this and optional dynamic binding through virtual
> functions, C++ can accomplish everything that Smalltalk can, but
> it's not always as strightforward.
The same could be said for assembler ;)
MUD-Dev mailing list
MUD-Dev at kanga.nu
More information about the MUD-Dev