|
Re: The Elephant in the Living Room
|
Posted: Apr 10, 2005 5:12 PM
|
|
> > Does it have to be that hard? > > Most definitely not. C++ can be as clean, elegant and > discoverable as Ruby or Python. I think many experienced > C++ programmers make C+++ too complicated, because they > won't let themselves write libraries which are simply good > enough, and are inflexible with regards to exchanging > efficiency and portability for ease of use and speed of > development.
I agree that a lot of libraries are inefficient. But I think it's not because they are favouring ease-of-use and speed of development. In fact, with respect, I find that almost laughable. I think what people are unwilling to eschew is intellectual challenge and "power".
I regularly get emails from folks who have undertaken huge effort to encapsulate several roles in one "smart" pointer. One might also say that the current sole example in the standard library - auto_ptr - has taken on too much. (Actually, the next instalment of Smart Pointers with Bjorn Karlsson will say exactly that, and demonstrate a simplification.)
I say this because I tend to do it myself, and I have to smack myself about a fair bit and consider whether something's useful or not.
> > It may seem strange to advocate writing inefficient > libraries, but I am simply suggesting that C++ programmers > need to know when good is good enough. I believe that the > an important part of being a software developer is to know > where to draw that line.
I think the issue is to write simple libraries, and I aver that simple libraries are more likely to be efficient, and quicker to develop.
With STLSoft (http://stlsoft.org/) I've tried to take this approach: thus there are a large family of very simple, non-template, scoping classes - most employing immutable RAII (it cannot be assigned to, only constructed; see Ch 3 of Imperfect C++) - rather than "smart" pointers types that generalise. In the main, these classes are widely appreciated by users, and I have hardly had any requests for feature change, bug fixes, or (he he) documentation.
Naturally, there are a few smarter types, and there's a template class scoped_handle (see <stlsoft/scoped_handle.hpp>) which can handle any calling-convention, any resource-type, any null-value, and without allocating memory or using vtables. (This is the subject of the second Smart Pointers instalment from Bjorn and I, which we'll finish off as soon as we get our fingers out of some other pies.) e.g.
::stlsoft::scoped_handle<int> h1(::open("file.ext"), ::close);
FILE *file = ::fopen("file.ext", "r");
::stlsoft::scoped_handle<FILE*> h2(file, ::fclose);
::stlsoft::scoped_handle<void*> h3(::malloc(100), ::free);
::stlsoft::scoped_handle<BSTR> h3(::SysAllocString(L"And you can handle __stdcall? :-)"), ::SysFreeString);
But the reason it works is that, despite genuine complexity in the implementation, it limits itself to immutable RAII.
When I constrast the implementation of that type with a generic class, Resource_ptr<>, from old libraries of mine circa 1997, which did try to be all things to all people, using, there's a huge difference in simplicity of use. Resource_ptr takes 5 template parameters, scoped_handle takes 1.
typedef Resource_ptr<HANDLE, HANDLE, Win32File_IsNull, FindFirstChangeNotification_Close, Win32File_SetNull> FindFirstChangeNotification_ptr;
Perhaps of more significance, is that since I wrote scoped_handle I've never once had to look in its implementation to use it, nor had any problem with it in use. And I've had no emails from STLSoft users seeking clarification. (It's a relatively new addition, so the absence of problems might just be an absence of use <g>.)
Contrarily, Resource_ptr<> has - since it's in many of the internal libraries of my company - been a constant source of problems, and quite the most baneful component I've ever written. (Maybe I should release it sometime, to show just how badly one can go ... <g>)
> For instance I believe Matthew is one of the leading C++ > portability expert in the world (not something I say > lightly).
Piffle. (But nice piffle. <g>)
> His C++ code is tested on literally dozens of C++ > compilers simultaneously, but even for someone as clever > and knowledgable as himself, all of that effort still > takes a lot of time and energy.
True. Very true. :-(
> I hypothesize this is why he and many other experienced > C++ programmers start taking such an active interest in > languages like Ruby/Python/D. These languages don't have > the same portabilitiy issues because they are supported on > much fewer platforms, have far fewer implementations, as > well as having a myriad of other restrictions (due mainly > to their relative immaturity). > > I think it comes down to the fact the the key to > productivity and elegance is restraint.
Yes! Like Harrison, I think you've hit a key point. Restraint. I guess that's kind of what I've been coming to myself subconsciously, but it's good to hear it from others. :-)
> We can either rely > on a language to provide it for us, or we can do it > ourselves. For example it is hard to do functional > programming using idiomatic C++, but if we restrict > oureselves to using only two kinds of types: for instance > Atom and List, and only use functions with the > signature: Atom function(AtomList& x) { } > functional programming becomes almost trivial.
Hmmm. Your words intrigue me. Perchance, sir, thou mightest post such a thing on a bloglet of thine own, upon which I could whine, dine, and opine?
> Anyway, I hope to eventually prove through my own work on > the OOTL (and the continued help and guidance of Matthew) > that with the right libraries C++ can be wielded just as > effectively as any other high-level language.
I remain to be convinced, but look forward to seeing you try.
|
|