[penguicon-general] A couple of thoughts about programming

Rob Landley rob at landley.net
Tue May 1 10:55:10 CDT 2007


On Tuesday 01 May 2007 1:40 am, Charles Ulrich wrote:
> On 4/28/07, Clay Dowling <clay at lazarusid.com> wrote:
> > Catherine Olanich Raymond wrote:
> > > On Friday 27 April 2007 6:19 pm, Rob Landley wrote:
> > >> Why to program in C.
> > > Sounds like fun.  Anybody want to join Rob for any of these?
> >
> > I'd be up for this one.  I have a couple of projects at the moment that
> > demonstrate -exactly- why C is great.
> 
> Yeah, Clay is your guy for this. He did a GLLUG presentation once on
> why C doesn't have to be a bad choice for web apps and I have to
> admit, he made a pretty convincing case.

Also "the advantages of C over C++".

C is simple, a small compact language you can fit in your head.  C++ stopped 
being so in about 1992.

C has a clear design goal: it's a portable assembly language that fairly 
closely matches what the computer is actually doing.  C++ adds things like 
templates, subclassing, and operator redefinition to intentionally hide what 
the machine is doing, but C++ doesn't go all the way to a modern 4th 
generation language.

Due to its clear role as a portable assembly language, at a low level most 
other software is written in C.  Not just your operating system kernel, but 
the compilers and runtimes for other languages like perl, python, java, ruby, 
and php.  It makes less sense to write application software (like a word 
processor) in C these days because a programmer can get 10 times as much 
functionality implemented per hour in a higher level language like python.  
But your speed-constrained video codec and flash runtime are probably going 
to be C.

A modern language (like python or ruby) has a runtime and references instead 
of pointers.  This makes it easy to do bytecode, exceptions, garbage 
collection, and true runtime type identification (where you can attempt to 
access an arbitrary member of an arbitrary object, and if it doesn't have a 
member by that name you can catch the exception and add such a member to the 
object).  These all go together as a package (explaining this properly is a 
panel of its' own).

C++ instead went with object orientation as its central theme, which was the 
Hot New Thing in the 1990's but turned out not to be such a big deal.  You 
can do object oriented design in C; have a structure with data shared by a 
bunch of functions, make the functions take a "this" pointer as their first 
argument and dereference this inside the function.  If you want virtual 
methods, put function pointers in the structure and call 'em.  The Linux 
kernel is full of object oriented pure C (the VFS layer).  The syntax for 
doing this in C is actually only about 5% more verbose than doing it in C++, 
and it's a lot clearer what the machine is actually _doing_.

When modern languages started to emerge, C++ went "oops, THAT'S what we should 
have been thinking about" and started retrofitting the new concepts.  But it 
didn't have a runtime (instead it links in a big library).  Its' attempt at 
exceptions bloated the heck out of both the stack and the code.  Garbage 
collection is really hard in C++, because it requires references instead of 
pointers.  (A reference is a pointer you can't do math on, it _always_ points 
to either a valid object or to NULL; without this property doing garbage 
collection is insanely complicated.)  But C++ can't give up pointers without 
losing the underlying C, which was part of the definition of the language, so 
garbage collection never made it into the standard.

And then there's templates, which are C++'s attempt to do runtime type 
identification at compile time.  This makes about as much sense as attempting 
to do garbage collection at compile time.  Templates pretend to hide 
complexity, but you have to understand exactly what the template expands to 
in order to have any hope of reliably using (or debugging) it.

C++ tried to leverage the popularity of C (it's the universal assembly 
language everything else is written in), but got the disadvantages of C too 
(pointers, manual memory allocation, static typing fixed at compile time).  
As a result C++ wound up in a weird no-man's land between C and Python, 
neither fish nor fowl and sucking at both niches.  It has managed to con some 
people into thinking it's as good as C++ for writing low level infrastructure 
(qt is a big case in point), but when successful such projects generally 
refuse to use things like templates and instead use C++ it in its original "C 
with classes" intent, as a slightly smaller syntax for doing object 
orientation and nothing more.

C++ has grown lots of mechanisms to "manage" complexity, and in doing so 
actually _encourage_ complexity.  (For example, classes weren't enough so 
they had to add scopes.)  In C, the solution to this problem is to step back 
and clean up the code, removing stuff to REDUCE complexity.

"public/protected/private" are based on a mindset of not trusting programmers 
to be any good or to understand how the thing actually works.  Not only is 
hiding the implementation antithetical to both good programming and to open 
source, but if you expect bad programmers you GET bad programmers.

C++ is popular in corporate environments for the same reason cobol is: it's 
designed to satisfy managers, not programmers.  It's a "drone language", 
aimed at faceless worker bees.  The fundamental assumptions are that 
programmers are interchangeable cogs, and programmers can't be trusted.  If 
it was actually true that a random programmer off the street couldn't do much 
worse than the people who originally wrote the code (which 
public/protected/private attempt to enforce), this would not be an 
_advantage_ of the language.  But it seems like one to pointy-haired types.

The other big corporate assumption is that once code is written and working, 
it should never be touched again.  Corporations treat code as an asset, which 
means that existing code, once written, has a dollar value attached.  
Therefore, removing old code is a waste of money.  If throwing old code away 
makes no economic sense, then the only thing you can ever do is add more 
code, layer upon layer of subclasses, to get the behavior you want.  This 
sounds crazy but it's VERY common in corporate environments: we paid for that 
code, and you WILL use it.  Corporations LOVE subclassing.

Management types think the urge to rewrite is simple programmer ego: obviously 
every programmer thinks they're better than every other programmer because 
they're all arogant, and this must be repressed.  In reality, programmers not 
only try to constantly improve code, but try to adapt code to the task in 
front of them.  If the current task is not the same as the previous task, why 
would you assume the code from the previous task is a perfect fit for the 
current task.  Good programmers also constantly strive to remove unneeded 
code, to clean things up.  If you want to share code between projects, use a 
shared library; otherwise code that this project isn't using shouldn't be in 
this project.

Oh, don't combine C++ and shared libraries.  Just don't.  That's a can of 
worms that would require a whole post of its own to even START to address, 
but the big one is you have to build the library and everything using the 
library with the exact same compiler version.  And no, wrapping "extern C" 
around a function that returns a pointer to a class instance doesn't actually 
help matters, and yes I've seen this.  C++ pretends you don't have to 
understand what's going on under the covers (so it gets people who don't even 
try) and then makes 10 times as much stuff happen under the covers because 
nobody's watching to keep the complexity down...

I'll stop now.

Rob


More information about the penguicon-general mailing list