Linux-Advocacy Digest #840, Volume #26 Fri, 2 Jun 00 21:13:04 EDT
Contents:
Re: Would a M$ Voluntary Split Save It? ("Daniel Johnson")
----------------------------------------------------------------------------
From: "Daniel Johnson" <[EMAIL PROTECTED]>
Crossposted-To:
comp.os.os2.advocacy,comp.os.ms-windows.nt.advocacy,comp.sys.mac.advocacy
Subject: Re: Would a M$ Voluntary Split Save It?
Date: Sat, 03 Jun 2000 00:13:15 GMT
"Bob Hauck" <[EMAIL PROTECTED]> wrote in message
news:[EMAIL PROTECTED]...
> On Fri, 02 Jun 2000 12:00:30 GMT, Daniel Johnson
> <[EMAIL PROTECTED]> wrote:
[snip]
> >I disagree. Consider min(x,y):
>
> I thought we were talking about "fancy stuff". It is easy to show that
> a is better than b in a toy example.
It's hard to *give* non toy examples on Usenet. Who'll read 'em?
What the heck. I'll give you a less toyish one.
Consider MFC's message map. You say:
class myclass : public mysuperclass
{
afx_msg void OnSomething();
DECLARE_MESSAGE_MAP()
};
in your classs and
void myclass::OnSomething()
{
// dosomething
}
BEGIN_MESSAGE_MAP(myclass,mysuperclass)
ON_WM_SOMETHING() // just knows about OnSomething by macro magic
// more of the same
END_MESSAGE_MAP()
This is really gross, unextendable, and weird. As a learning
experience (tm), I worked out how to do it with templates:
class myclass :
public mysuperclass,
public winmsg::handler< winmsg::something >
{
virtual void do_something();
}
void myclass::do_something()
{
// do something
}
This turns out to be vastly more extensible and more
functional.
winmsg::someting is declared like this:
class winmsg::something : public winmsg::msg<WM_SOMETHING>
{
public:
bool really_do_something;
inline bool setup()
{
really_do_something=wParam!=0;
return true;
}
};
The template class msg<id> is a subclass of MSG
and its method setup gets to parse out the arguments
in members wParam, lParam, and so on. You can
define your own subclasses for new messages,
and provide your own parsing; MFC's message maps
do not support this. Also, the destructor of this message
object can be used for cleanup after processing a message;
in my tests I used such a technique to make sure
::EndPaint() was called for the WM_PAINT message. You can
provide utility methods as well if appropriate.
For this example to work, handler<T> must be specialized:
/* this is in namespace winmsg:: */
template<>
class handler<something>
{
public:
virtual void do_something()=0;
virtual void trigger(something &m);
{
if (m.really_do_something)
{ do_something(); }
}
};
the template class handler<T> provides a virtual
method process_message() which calls trigger(T &).
It also has a virtual base class, win::window. The
handler<T> constructor registers each handler in
a std::vector<handler_base &> in this base class; the
handler_base is an interface that lets the base
class call each subclasses process_message
method.
The specialization of handler<T> can do a lot of stuff. For
instance, I was able to create handler<hscroll> and handler<vscroll>
that implemented horizontal and vertical scrolling, respectively. This
kind of thing cannot be done within the message map structure. Instead
you inherit from superclasses that provide such things; but
you are constrained by the inheritance heirarchy MFC provides:
I can't be both a CScrollWnd and a CDialogBar, for instance. You
can work around this stuff, but the template approach I provide
lets you mix in message support at any point you need it. It is
a compiler error to mix the same handler twice, but virtual methods may be
overriden.
Now, there's readability. This template-based solutions is blatantly
*much* easier to read if you are looking at its implementation; if
you've looked at MFC's message maps, you know what a bloody
nightmare they are inside. If you haven't, don't- you *will* go insane
and start drooling on your keyboard. Even for macros, these
ones are pretty obscure.
It's not as clear cut in the point of usage. But I think the templates
have the edge. Both have the disadvantage that there is some
function you must override, but it is often nonobvious which, or
what you are expected to do inside. Both produce compiler
errors if you fail to override what you must override.
The macro's supply additional busywork: you must add
DEFINE_MESSAGE_MAP to your class, which is purely
an artifact of the macro. The BEGIN_MESSAGE_MAP(x,y)
and END_MESSAGE_MAP() macros are also artifacts,
if less blatantly. They are essentially a kind of new syntax, with
their own gramatical rules to learn.
They also mean that if you change your superclass, you've one
extra place to update it. Failure to update it is *not* a compiler
error so long as the old superclass is still an accessible base
class, so this can lead to subtle bugs.
So, what do you think?
Prolly that I've picked a darn weak target to beat up on, but
hey, that's me: find the weakest, most helpless victim, and
pound the tar out of it. I can't help being who I am, can I? :D
> I'm not a particular fan of macros as you seem to be assuming. I'm just
> not convinced that templates are really that much better. They seem to
> create similar problems regarding write-only code.
What problem do they create in this area? Does Ada also suffer it? Eiffel?
If not, why not?
> Both have their evils.
> The principal problem with macros is that they are a language unto
> themselves. They don't understand anything about C or C++ per se.
>
> The principal problem with templates is that they are also a language unto
> themselves. However, they do understand a bit about C++, so maybe that's
> a win. The syntax sure is impenetrable though, once you get beyond toy
> examples, another disadvantage shared with macros.
I don't find the syntax difficult. It's not C, but that's a plus in my book.
:D
> >Second, using Macros demands that you know some special
> >rules that don't apply to normal functions, and these rules
> >are obscure.
>
> It seems to me that templates have some "special rules" of their own.
> There is specialization and the rules that determine what order they will
> be applied in.
Yes, there is a declare-before-use rule that does not match what normal
functions show; template implementers must worry about this. It's kind of
like a struct that way.
> There are rules about what happens when you inherit from a
> template.
It behaves exactly like inheriting from a non-template class, no?
If not, what's the difference?
> And so on. Are these rules less obscure than the macro rules?
> Maybe they are.
I think so.
> It is the case that when I come upon code written by someone else that has
> a lot of tricky macros _or_ tricky templates, I end up spending a lot of
> time figuring out what they do. I don't think I'm the only one.
I think that's true of tricky *anything*.
*Any* feature can be misued, you know.
> >Well, okay, but if you want to write Smalltalk, you would be well advised
> >to write it *in* Smalltalk. C++ does not support the Smalltalk style of
> >programming at *all* well.
>
> Mostly because the standardizers elected to go with a generic-programming
> style of standard library.
IMHO that's an effect of an earlier decision- Bjarne Stroustrup's decision
to
go with strong static typing, on the Simula model.
*That* is why Smalltalk style contains work poorly in C++.
> The language itself is perfectly capable of
> handling the "one big tree" approach, and suitable container classes have
> been designed (e.g. Borland's original container classes represented a
> start in that direction).
I don't agree. Consider the a 'one big tree' vector:
vector v;
v.insert(new MyThing);
v.insert(new MyOtherThing);
MyThing *t=dynamic_cast<MyThing *>(v[0]);
This is way longwinded, redundant, annoying, and for
your trouble what do you get?
Lousy performance.
> >Those of us who like the generic programming approach to
> >containers would seem to gain some benefit from templates,
> >no?
>
> Sure. You pretty much have to have a mechanism like that to do generic
> programming. The one in Ada was much easier to understand though.
<shrug> Probably so.
[snip]
> >Can macros help with Smalltalk style containers?
>
> Hopefully not too much.
You don't *want* help? Or you just don't want templates? :D
> >> It adds an "inline" keyword, used the same way as in C++.
> >
> >Oh. That's fine, but it is not C.
>
> I think I said that before, that it was non-standard.
Oh. I did not understand you then. But don't worry, my brain is
working *now*. Honest. :D
> Another poster says
> that at least his version of gcc will inline small static functions too.
> I didn't know that (and I'm still using an older version for most work for
> various reasons).
Despite my hyperbole, it isn't actually impossible to inline in standard
C; it's just harder, and there's no way to control it.
> >It so happens that the they *did* build the edifice that is STL, but if
> >you really can't stand it you can use templates to get a sort.
>
> I'll _use_ STL, I just don't want to have to _build_ anything like it.
Hmm. I somehow had thought you didn't like it.
I think the point of having it in a library is so you don't have to build
it yourself. No? I wouldn't want to do that, either.
(Well, maybe once. Just to learn how. :D )
> >Well, forgive me, but it sounds very much like you are saying "ignore
> >performance, it'll take care of itself. Except for *my* work."
>
> No. For one thing, I didn't write most of the assembler. And in looking
> at the actual timings, I think that a lot of it does not need to be in
> assembler. But I'm not going to go back and re-write the thing on that
> basis. I did re-write a lot of the top level logic to make it clearer.
> It got smaller too, without my having that as a goal.
Well, that's suggests you had a good design to impose on the chaos.
That's what happens when I have such.
> >Saying "don't optimize stupidly" isn't controversial, but it isn't
relevant
> >either.
> >
> >Saying "don't optmize, ever" *is* controversial.
> >
> >Which are you saying?
>
> I'm saying "don't write your code based on what you think is the fastest,
> write it based on what is clear". And then, if it isn't fast enough (and
> it almost always will be), go back and optimize.
I thikn this is noncontroversual. But leave out "go back and optimize",
and I'll disagree with it.
> If that isn't relevant, well, sorry to have wasted your time. There seem
> to be lots of programmers out there who don't follow that "conventional"
> advice.
I don't know; I have no way to tell how many there are ignore this
pearl of conventional wisdom.
> >Forgive me for saying it, but there's a lot of denial about MS out
> >there. MS's success has a lot to do with the quality of their work.
>
> Some of their important products, like Win95, do represent amazing
> programming prowess. Win95 has no right to work _at all_ given the way
> they took a DOS extender and made it into...something. It was sort of
> like building a 747 incrementally starting with a '67 VW Beetle.
*What* it does is pretty impressive. 32-bit operating systems aren't suposed
to be able to use use real mode DOS drivers...
> And they are capable of making good products when prodded. Then again,
> many of their products have become so overbloated with "features" that I
> can no longer stand to use them. Visual Studio being a prime example.
> That's more of a marketing thing than a technical one though.
Well, yes. Features *sell*; that a small percentage of users turn their nose
up at the bloat does not change this fact.
Personally, I've not found an IDE I like better than Visual Studio.
> >Many people see unwilling to face this; all too often they can't
> >acknowledge that MS's products have any virtues at all, still
> >less that their favored solutions might lack virtues that are
> >important to customers.
>
> What I think is that when MS is in a competitive situation they can make a
> good product. When that pressure goes away, they revert to making junk. I
> actually liked Word 2 quite a bit. They still had to compete with
> Wordperfect back then.
Well, this is not an uncommon tendency to see in this business, more's
the pity. But I think MS has got a relatively light dose of it; I do not
think
that Win 98 is 'junk' compared to Win 95, or Win 95 compared to Win 3.
Is the pressure still on? I'm not sure I see much.
Not that their immune, but there've been worse, if you ask me.
> >> Well, Borland's OWL was also written for such a compiler and it is far
> >> more elegant.
> >
> >I don't know OWL. I've looked at Delphi, but it uses nonstandard
> >language extensions. Does OWL?
>
> Delphi is Pascal isn't it? Standard Pascal is pretty much useless, so of
> course they extended it.
Actually, Delphi can be used from C++- with langauge extensions to C++.
Which is fine, but you aren't talking about what can be done in C++
anymore, exactly.
> OWL (Object Windows Library) extended C++ by providing a way to bind a
> message to a member function. I forget the details now, but do remember
> it being controversial at the time. They could have done what Troll Tech
> did with Qt and used a pre-processor instead.
Or they could use templates. :D
> >If it does, then I think it had an unfair advantage. As I said,
> >MFC indulges in a lot of grossness to deal with the limits of C++
> >as implemented by MS way back then.
>
> MFC was designed in a hurry "way back then" specifically to compete with
> OWL. Borland had a really cool OO framework and was threatening to win
> the compiler wars because of it. MS had to respond and MFC was the
> result.
Yes. And such is the reality of the business, even though we'd like a
framework less gross than MFC and compatible with standard C++. Such
a thing is possible, but I don't see it happening too easily.
> >I don't know Qt, but I'm inclined to think one of the nastiest things
> >about MFC is that it does exactly this: uses the preprocessor to
> >handle message dispatch.
>
> Not "the" preprocessor, but "a" preprocessor. They call it "moc". There
> are disadvantages to this approach of course, which is surely one reason
> Borland elected to add compiler extensions instead. However, it seems to
> work just fine and it keeps the grossness out of the code you have to
> write and maintain.
I don't know. Theoretically this sould apply to MFC too, should it not?
I feel its the opposite: MFC's use of macros puts the grossness
exactly where I have to deal with it.
> >All to often, MFC just turns Foo(bar,baz) into bar.Foo(baz).
> >Now *that's* what I call too low a level of abstraction.
>
> Yes, that is the basic problem. Then they started adding stuff to MFC
> instead of to the API in order to hinder Borland.
This isn't really all that true. MFC contains a *lot* of very thing
C++->C wrappers and very few meaty features.
If it were otherwise, I'd object to your saying to used too low
a level of abstraction so cavalierly.
> >I really don't see that you have any evidence that MS is
> >involved in premature micro-optimization.
>
> Often, what I call "premature micro-optimization" results in not only more
> bugs, but also worse performance as well. That's my point. But I guess
> until they go Open Source I'll not be able to prove anything.
Probably not; you can prove the MFC is junk, but that's no
challenge, is it? :D
> >But this is no argument for disregarding the performance characteristics
> >of your tools. One hopes you'll find that 5% eventually, and then
> >you had better have some way to address it.
> >
> >"Switch to assembler" is, sad to say, not a very good option.
>
> You seem to be attributing absolutes to me that I don't intend. Maybe I'm
> not being clear.
Maybe not. I thought you were saying "don't ever try to write fast
code in C++; switch to assembler when speed is needed."
Sounds pretty absolute.
> My basic complaint is against programmers who think of speed, speed, and
> only speed. They write code that they think is "fast" without doing any
> measurements, and they are willing to commit all kinds of sins in the name
> of speed (including inlining the whole world, parameter-less functions
> with dozens of global variables, etc). Yet, in the real world, most of
> that effort is wasted, and furthermore it is wasted over and over again as
> maintenance programmers come along.
I am not such a programmer. I have always been clear in this thread
about the cost of C++'s inlining; to get a speed boost as if by magic
in the 5% where it matters, you pay a price in bloat in the 95% where
it does not matter. Hence, large fast code.
I am talking about using the 'inline' keyword, which does not impose
a maintainence cost; not manual inlining. Using that keyword
means doing more inlining that is really needed; but better that
than doing it by hand.
> That's all. As amazing as it may seem, there are a lot of these people
> out there in the world.
Maybe so.
> My point is that if you write code that is understandable and has a
> reasonable structure that's reflective of the problem you are trying to
> solve, then you will more often than not meet your performance goals
> without having to go out of your way to do so. Your design should of
> course take into account the tools you will be using, but clarity and
> simplicity should take priority over speed until you have concrete
> evidence otherwise.
I agree with this too. I'm getting the feeling you aren't aware of
what I was saying: that C++ is suitable for OS work.
> Again, this is just KISS and is "conventional wisdom". Yet too many
> programmers don't follow it and feel the need to be clever.
>
> Your argument that C++ is "faster" because of "inlining" struck me as
> something one of these "speed" folk might come up with. Yes, we saved 2%
> on execution time by making the code 200% bigger.
Taint quite *that* bad. :D
Well, usually. :/
Well, okay, sometimes. :/
> Cool. If that is your
> argument for using C++, then you aren't thinking. It seems that isn't
> your only argument, so I don't have anything to bitch about 8->
It was put forward that C++ could not be used for OS development;
I argued that it *could* and that it could actually be faster than C-
at the price of increased executable size. This is a price MS is more
than willing to pay.
Perhaps you were unaware of the question I was trying to answer?
It was *not* "why should I use C++"?
------------------------------
** FOR YOUR REFERENCE **
The service address, to which questions about the list itself and requests
to be added to or deleted from it should be directed, is:
Internet: [EMAIL PROTECTED]
You can send mail to the entire list (and comp.os.linux.advocacy) via:
Internet: [EMAIL PROTECTED]
Linux may be obtained via one of these FTP sites:
ftp.funet.fi pub/Linux
tsx-11.mit.edu pub/linux
sunsite.unc.edu pub/Linux
End of Linux-Advocacy Digest
******************************