Re: Cpp Considered Harmful
From: Paul Mensonides (leavings_at_comcast.net)
Date: 08/31/04
- Next message: Alf P. Steinbach: "Re: Linked list storing a queue"
- Previous message: Kay: "Linked list storing a queue"
- In reply to: Steven T. Hatton: "Re: Cpp Considered Harmful"
- Next in thread: Steven T. Hatton: "Re: Cpp Considered Harmful"
- Reply: Steven T. Hatton: "Re: Cpp Considered Harmful"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Mon, 30 Aug 2004 20:35:48 -0700
Steven T. Hatton wrote:
>> It buys you meaningful assertions with replicating code among other
>> things.
>
> Perhaps this is useful. I have never tried using assertions. When I
> read about them in TC++PL(SE) it basically went. 'Check this
> assertion thing out. Pretty cool, eh? They're macros. They suck!'
Assertions are invaluable tools.
> There are places where retaining some of the Cpp for the
> implementation to use seems to make sense. For example the various
> __LINE__, __FILE__, __DATE__, etc. are clearly worth having around so
> debuggers and other tools can use them.
Debuggers? Macros don't exist after compilation, so I'm not sure that __DATE__
and __TIME__ would have any useful meaning at all, and debuggers (if source
information is available) already know the line and file.
> They should not be
> considered part of the core language to be used by application
> programmers.
An immediate example comes to mind. What if I write a program that, when
executed with a --version option, outputs a copyright notice, version number,
and the build date and time? (This is a fairly common scenario, BTW.)
>>> One is to present the 'raw' interface of the template to the user.
>>> That is, you just parse the template and show the user code
>>> completion options in the 'raw' form, e.g., if the user is creating
>>> a deque the following completion options could be presented:
>>
>> The 'raw' interface of which specialization of the template?
>
> That seems like an ambiguity that could be resolved by examining the
> parameter when necessary.
Yes, but that means that the IDE has to be able to parse and semantically
analyze the entire source code--including doing overload resolution, partial
ordering, template declaration instantiation, etc..
>> The point is
>> that a tool, to be at all effective in modern programming, has to do
>> near full parse
>> of the code and semantic analysis. With C++ especially, that is
>> *far* from trivial.
>
> I agree. However, the presence of the CPP complicates this issue to
> the point where it seems to degenerate into an exercise in absurdity.
I think you have a serious misunderstanding of the preprocessor. How does CPP
complicate this issue?
> I will observe that many Java IDEs do this rather successfully.
Parsing Java is quite a bit simpler than parsing C++.
>>> Your observation regarding two phase lookup, if I understand your
>>> meaning, is relevant, but not a show-stopper.
>>
>> Actually, it pretty much is a show-stopper, more so than anything
>> else. A tool can trivially preprocess a file, but a tool cannot do
>> any meaningful code
>> completion inside a template. E.g. what options might a tool give
>> me at this point:
>>
>> template<class T> void f(T) {
>> X<T>:: /* here */
>> }
>
> Whatever can be extracted from X. If there are specializations of X
> the it seems reasonable to provide the superset of options with an
> indication of which are specific to a given specialization.
It doesn't know all of the specializations. As a general rule, it only knows
about a few general specializations.
>> The answer is "nothing" because it cannot know what T is, and
>> therefore cannot tell what specialization of X is chosen, nor can it
>> even tell what X specializations there might be.
>
> Why can't it tell what specialization for X exist?
Because they might not exist yet.
>> In generic programming, there is very little
>> code in a template body that is not dependent on template parameters.
>> This is second phase lookup (a very useful feature) at work. What it
>> boils down to is that code analysis such as completion is
>> fundamentally useless inside template code, and that is precisely
>> the place where it would be most useful.
>
> I'm not convinced that either of these assertions are correct. It
> may be more difficult to provide meaningful code completion inside a
> template, but I believe it is fundamentally possible to provide a
> significant amount of information in that context. Furthermore, I
> don't accept the notion that code completion inside a template is
> where it would be most useful. By their nature, templates are
> abstractions, and their use implies a certain amount of selective
> ignorance that would preclude your knowing the details of how
> specific template parameters would affect the context.
That's true, but (as a general rule) well-designed template code is also the
most complex code. Code completion outside of template code, while useful, is
only a small benefit.
>> Okay, I'll follow this line (even though "partially" compiling C++
>> as you type
>> would be incredibly expensive). If you say 'big deal' to that, than
>> what is the
>> problem with the preprocessor? Tools can trivially preprocess
>> source code much easier than they can parse the underlying language
>> itself.
>
> Well, to some extent there is syntax checking going on with KDevelop.
> It's not at the level I would like, but it continues to improve. As
> for the cost of compiling C++, I'm not convinced that the
> proprocessor and the compilation mechanisms it supports and
> encourages aren't a significant part of the problem.
Look, if a tool author is willing to fully parse the underlying language,
preprocessing the source as it does so is trivial in comparison. If you
disagree, tell me why.
>>> One might argue that the same could be done with the Cpp. My
>>> response
>>> is that the Cpp is far less structured, and trying to predict what
>>> someone might have done to his code with it, is beyond what I would
>>> expect a reasonable programmer to care to address.
>>
>> What on earth are you talking about? Cpp *is* well-structured, and
>> more importantly, it is a straightline process. If a tool cares to
>> look at the code
>> resulting from the preprocessor, it merely has to preprocess it. To
>> that I say 'big deal'.
>
> But now you are talking about something editing your code at the same
> time you are, but not displaying the results. What I should have
> said is that the result of using the Cpp is far less structured than
> the result of using a programming language.
No, I'm not. C and C++ code can be preprocessed as it is parsed into a syntax
tree in a single pass. It's not like when you type something, the IDE goes and
tries to find it in the source code--that would be *incredibly* inefficient. In
essence, it is already rewriting the code into an internal format that is
designed for algorithmic navigation that also discards information that it
doesn't care about.
>>> But there is no justification for
>>> this kind of anti-programming in any code written with the future in
>>> mind.
>>
>> Actually, there is. Because the underlying language is so complex,
>> there are numerous bugs and missing features in every single
>> existing C++ compiler (more
>> so for some than others). Even looking at the tiny snippet of code
>> above, which I know nothing about as a whole, I can tell that it is
>> working around that exact
>> issue. In this example, the preprocessor merely makes it possible
>> to do what otherwise could not be done.
>
> I see no reason to try to support a compiler that doesn't understand
> namespaces. What significant platform is restricted to using such a
> compiler?
I wish it was that simple. In many companies, there is a lot of inertia from a
compiler version. I.e. it often takes years to upgrade to new compilers (if at
all)--simply because the time required to make older code compatible with the
new compiler can be massively expensive. Thus, new code gets written for older
compilers all the time.
>>> I pretty much figured out what all the macro mangling does in the
>>> above sample. But by that time I was so disgusted, I lost interest
>>> in using the library. There are countless examples of such
>>> anti-code
>>> in most of the C++ libraries I've seen.
>>
>> There are plenty of ways to misuse the preprocessor, just as there
>> are plenty of
>> ways to misuse any language feature in any language. So what?
>> Further, the above code is 'anti-code' only in the sense that it is
>> working around flaws in the compiler, standard library, or isolating
>> inherent platform-related dependencies.
>
> As I said, there are historical reason for the code to be that way.
There are current reasons as well.
> That is far from the only place where the people used the CPP to
> rewrite code that should be straight forward C++.
The preprocessor does not 'rewrite' code--it expands macros which are *part* of
the code. In doing so, it can reap major benefits in readability and
maintenance.
>> What does this have to do with the C or C++ preprocessor? C++ does
>> not have a module system. You're talking about fundamental changes
>> to the language, not problems with the preprocessor.
>
> "I suspect my dislike for the preprocessor is well known. Cpp is
> essential in C programming, and still important in conventional C++
> implementations, but it is a hack, and so are most of the techniques
> that rely on it.
> *_It_has_been_my_long-term_aim_to_make_Cpp_redundant_*."
More than anything else, Bjarne hates #define, not #include, BTW. The
preprocessor is not a hack, it is an incredibly useful tool that can, like every
other tool, be misused.
>> Further, there are things called "good
>> organization" and "good code structure" that make dealing with these
>> issues trivial (e.g. to use interface X include file Y and link to
>> Z--well designed headers can be blackboxes).
>
> I try hard to get things right. There are some aspects of Xerces
> which do show a better face than what I previously introduced:
> http://cvs.apache.org/viewcvs.cgi/xml-xerces/c/src/xercesc/dom/
>
> The separation of interface and implementation is textbook proper
> C++. I still find the added level of complexity involved in using
> headers unnecessary, and a sgnificant burden.
What complexity are you talking about exactly? Separation of interface and
implementation is a cornerstone of separate compilation--which is one of the
fundamental reasons that C++ is able to scale to very large projects without
dropping efficiency.
> I'm currently working
> on a tool that will mitigate this drudgery by treating the class as a
> unit, rather than a composit.
What do you mean by 'composite', separation of interface and implementation?
>>> For anybody who wants to tell me that the reason that C++ code is
>>> this hard to understand is that C++ is more powerful, please explain
>>> to me why IBM-the company that wrote the Xerces C++ code-is using
>>> the Java counterpart to serve out IBM's latest online C++ language
>>> and library documentation.
>>
>> Because they felt like it? Honestly, who cares? In my opinion,
>> which is what matters to me, Java sucks on so many levels it is
>> unusable.
> That's a silly statement. I've seen it used to do losts of useful
> things.
That's not exactly what I meant. It is unusable to me because I am accustomed
to a much more complete toolset. With Java, you have to jump through a lot of
hoops to get around language-imposed limitations. Granted, there is a measure
of safety in some things, but then it is immediately lost by lack of generics
(real generics, not half-ass generics). Languages can be loosely classified by
how much safety they enforce by default. C++ is at one end. It allows many
things that could be unsafe because it allows access to the "details". Other
languages are at the other end, such as Scheme or Haskell. Such languages can
yield higher productivity because they rely much more on compiler optimization
of the details. Both are valid strategies. Java (and it isn't just Java) is
smack in the middle of the two approaches, which ends up providing only a small
fraction of the benefits of either. If I want control of details (for whatever
reason) I'll use a language (like C++) that doesn't actively work against me
controlling those details. If I want a higher-level language where I can
largely ignore many of those details, I'll use a real higher-level language
(like Haskell).
> This may be a fairly useless program, but I believe it
> demonstrates that Java is capable of supporting the development of
> fairly sophisticated programs.
I agree that Java is capable.
> It's my second Java3d project. It
> was pretty much a limbering up exercise.
> http://baldur.globalsymmetry.com//projects/math-3d/living-basis.html
>
>> Regarding C++ (in general)... C++ is more powerful--that is
>> unquestionable.
>
> What do you mean by powerful?
I mean that it gives you access to lower-level details while simultaneously
giving you tools to create higher-level abstractions.
> It seems clear that major players in
> the industry do not consider C++ to be appropriate for many major
> applications.
Ha. The opposite is true.
>> So what? Bjarne is not the ultimate authority on what is good and
>> bad.
>
> No, but I find it interesting that his thoughts on this matter seem to
> reflect my own - mostly independently formed - assessment. I believe
> it is also significant that he does hold such a strong opinion about
> the matter.
There are other people, also actively involved in the design of C++ and just as
authoritative, that have opposing viewpoints.
> He may not agree with me here, and even if he does, he may be
> unwilling to say as much for the sake of polity. The way the standard
> headers are used is a logical mess. It causes the programmer to
> waste valuable time searching for things that should be immediately
> accessible by name.
That is what documentation is for, which you need anyway. (Further, good
documentation is significantly more involved that what can be trivially put in
header file comments.) As an aside, the standard library header structure is
not that well organized--mostly because some headers contain too many things
(e.g. <algorithm>).
> The is true of most other libraries as well.
> There is no need for this lack of structure other than the simple
> fact that no one has been able to move the mindset of some C++
> programmers out of the Nixon era.
An interface is specified in some file, which you include to access the
interface. The documentation tells you what file you need to include and what
you need to link to (if anything) to use the interface. That's pretty simple
and well-structured.
>>> that the preprocessor undermines the integrity of the core
>>> C++ programming language and is the main reason for the comparative
>>> ease of use Java provides. The Cpp is not a strength, it is a
>>> liability.
>>
>> You're opinion, which you are entitled to, is simply wrong. The
>> preprocessor is
>> not to blame, the complexity of the language as a whole is. For an
>> experienced
>> C++ programmer, using Java is like tying your hands behind your
>> back. The language (Java) not only promotes, but enforces bad
>> design as a result of seriously lacking feature set--with the excuse
>> that it is protecting you from
>> yourself.
>
> In the case of the CPP, it isn't so much me I want to be protected
> from. It's the people who think it's a good idea to use it for
> anything beyond simple conditional compilation, some debugging, and
> perhaps for #including header files.
Give an example of why this protection is necessary. There is only one: name
conflicts introduced by unprefixed or lowercase macro definitions. That is just
bad design, and you need a whole lot more changes to the language to prevent
someone else's bad design from affecting you.
> I will admit that I still find
> the use of header files bothersome. They represented one of the
> biggest obsticles I encountered when first learning C++.
They are different than Java, but they aren't fundamentally complex.
>> C++ doesn't make such decisions for us, instead it gives us the tools
>> to make abstractions that do it for us. In other words, it isn't the
>> result of arrogance propelled by limited vision.
>
> Leaving some things to choice serves no usful purpose beyond pleasing
> multiple constituents.
I'm not talking about providing two or more near identical features that all
have the same tradeoffs. Fundamentally, it's about being able to pick which
tradeoffs are worthwhile for a particular thing--and that serves an incredibly
useful purpose.
> There are places where a lack of rule is not
> empowering, it is restricting.
Example?
> I hear diving in Rome is not what one
> could properly call a civilized affair. Personally, I like the idea
> that people stop at stoplights, use trunsignals appropriatly, stay in
> one lane under normal circumstances, etc.
I really dislike analogies because they are so readily available to support any
argument, but there are some key concepts in this one. First, what you describe
is a system that is enforced by convention rather than by the streets,
stoplights, signs, vehicles, etc. (i.e. the "language"). Second, the ability to
deviate from the conventions is vital because there are unforeseeable variables
(or foreseeable variables that are too costly to handle) that enter the
system--such as a power outage or severe whether. Under the Java model, when
those circumstances occur (i.e. when you know better than the system enforced by
the language) you can't do anything about it. In C++, when you know better than
the system enforced by conventions, you can. (Note that both of these
situations occur in both Java and in C++, it isn't nearly as black-and-white as
this generalization. However, as a generalization, it is true. C++ gives you
more flexibility by moving the system from the language to convention moreso
than Java does.)
Regards,
Paul Mensonides
- Next message: Alf P. Steinbach: "Re: Linked list storing a queue"
- Previous message: Kay: "Linked list storing a queue"
- In reply to: Steven T. Hatton: "Re: Cpp Considered Harmful"
- Next in thread: Steven T. Hatton: "Re: Cpp Considered Harmful"
- Reply: Steven T. Hatton: "Re: Cpp Considered Harmful"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|