Re: Nil and nil Macro Conflict
Re: Nil and nil Macro Conflict
- Subject: Re: Nil and nil Macro Conflict
- From: Don Quixote de la Mancha <email@hidden>
- Date: Tue, 01 May 2012 22:46:54 -0700
Are not both Objective-C and C++, as well as Objective-C++
case-sensitive? If so, Nil and nil should be different symbols. If
they should be, and really are different symbols, but still conflict
somehow, then you've actually got a different problem than you think
you do.
Do Not Let The Sun Go Down Until You've Read John Lakos' excellent
book "Large Scale C++ Software Design", published by Addison-Wesley.
Much of what he proposes will contribute to the solution of your
conflicting symbol problem.
Even if one's project isn't written in C++, even if one does not have
a clue about C++ it's quite likely there is something in Lakos' text
that will help one out in a substantial way.
Lakos' employer Mentor Graphics - a leading Electronic Design
Automation (EDA) vendor - was one of the very first adopters of one of
the very first releases of the C++ programming language. Their first
attempts at writing EDA tools in C++ failed miserably, with their
"finished" programs being huge, bug-laden, crashy and leaky rats'
nests that they had no hope of ever debugging. EDA tools have a lot
of source; the computers of the day would take days on end to do a
single build!
Rather than abandon C++, Lakos and his people figured out how to write
C++ the way C++ wants to be written, with "Large Scale C++ Software
Design" being the written report of what they figured out.
That is, Bjarne Stroustrup and his people at AT&T figured out the
Computer Science of C++. John Lakos and his people at AT&T figure out
C++'s Software Engineering. It's important to understand that
Software Engineering and Computer Science are COMPLETELY different
things!
Primary among Lakos recommendations is that one should not create just
one single header file - allegedly "for convenience" - that client
coders #include from everywhere.
He states all manner of good reasons for not doing that. Long, long
before I read his book, among my main practices at many of the coding
shops where I worked was breaking up just such monolithic headers into
much smaller headers, so that each source or intervening header could
#include just what it needed.
Note that Apple's SDK engineers are the worst offenders with this,
with "#include <Cocoa.h>", "#include <Carbon.h>" and so on.
Quite a long time ago I figured out how to get the ZooLib C++
Cross-Platform Application Framework to build _without_ using #include
<Carbon.h>, only to be informed by some Apple engineer - who
undoubtably spoke with authority - that Carbon was not at all
guaranteed to even work if one #included individual framework headers,
rather than just the top-level header.
Another of Lakos' recommendations, which apply even for languages that
use no header files, is to "levelize" your codebase.
That is, a very poorly structured codebase will have most modules
depending in some way on most other modules. You'll find that you'll
never get the bugs out of that code. You'll also find that it's very
difficult for newly-hired engineers to understand enough of your
codebase to begin working productively at your company.
The dependencies in a poorly levelized program will resemble the
"string art" that was so popular in the late sixties and early
seventies. We were heavily into string art during my elementary
school days.
One drives a bunch of finishing nails into a piece of wood, spaced
evenly say in an elliptical shape. Then one ties some brightly
colored string to one nail, stretches the string across the middle of
the ellipse, around another nail, back across the middle and so on,
finally tying it off after wrapping around a few other nails. Every
nail is connected to at least a few other nails by several pieces of
string.
Close examination of most of your codebases is quite likely to find
that the dependencies of your compilation units on each other is just
like the connections between pairs of nails by strings!
By "module" Lakos means a "compilation unit", that is, a source file
and everything that source file depends on to build - its headers,
their headers and so on.
The first step in levelizing your codebase is to edit the source of
each module just so that it is broken into several new smaller and
simpler pieces. For object-oriented code, permit no more than one
class per source file or header.
Occasionally one has "helper" or C++ friend classes that are required
for a particular class to work. If those classes will _never_ be used
by other than the main class they contribute to, it would be
permissible to place them in the SOURCE FILE but not in the header
file for that class. One places them in the source rather than the
header so they are totally invisible to any other source.
Similarly the headers for templates should be split into multiple
files so that unrelated templates are in separate header files.
Start with the simplest of your classes, and get just those classes to
build all by themselves, to generate object files but not a full
executable.
For templates, create some manner of test driver that instantiates
only the templates included in each particular template header in a
few different ways - Foo<int>, Foo<int*>, Foo<vector<int> > and so on.
Don't worry for now whether this broken up code actually works, just
get it to build after having been broken up.
These simplest classes or templates should have no dependencies other
than what are supplied with your development system or the OS.
Now identify the next-simplest classes and templates, in that they
depend only on the first level of classes and templates that you
previously built, or on the OS or SDK. Again get just those
next-simplest modules to build.
Continue on in a heirarchical fashion, at the very end getting the
compilation unit that contains main() to build.
The chances are quite good at this point that the modules that require
Objective-C's nil will be in a completely different sub-heirarchy of
your codebase than the modules that require boost's Nil.
If you edit your sources carefully enough, and set up your new builds
carefully enough, you won't introduce any new bugs during the
levelization process.
But if you do find that you've introduced bugs - or really, if you
have ANY bugs at all - fix them by writing automated tests just for
the very lowest level of your heirarchy, then after fixing any bugs
you discover in just that lowest level, write tests for just the
second level.
Do not proceed to writing new tests, or fixing any bugs for higher
levels until you've fixed the bugs in the lower levels! It ought to
be plainly apparent as to why.
I'll send you my bill in the mail. ;-)
--
Don Quixote de la Mancha
Dulcinea Technologies Corporation
Software of Elegance and Beauty
http://www.dulcineatech.com
email@hidden
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden