scope keyword - a maintenance nightmare?

Guenther Brunthaler gb at dont.spam.me.invalid
Fri Aug 17 11:06:57 PDT 2007


When I evaluated D some time ago, I found it very interesting and promising.

I found its "Resource Acquisition Is Initialization" (RAII) paradigm especially appealing.

It really looked like a good candidate for replacing C++ at that time.

After toying around a couple of days with D, however, I found at least the following reasons why I chose *not* to use D, and rather stick with C++:

* While the closed source Digital Mars compiler really created small and nice executables, the GCC-backend created executables multiple times that size

* There is is no equivalent to MODULA 2s "Definition Modules". While I think it is a good idea to get rid of C++'s primitive "header" files, there must still be some means of separating interface descriptions from the actual code. Otherwise, you always have to ship the complete source code to anyone who just wants to use some interface as a client. Consider writing a plugin for OpenOffice.org that way...

* Maintenance-Nightmare with "auto" (now "scope").

When checking http://www.digitalmars.com/d/class.html for the new "scope"-class feature in more detail, I unfortunately had to learn that only half of my critique on D's synchronous destructors has been rendered obsolete by the new D 2.0 design.

What they have actually done was renaming "auto" into "scope", and forcing to add the "scope" declarator to both the class declaration as well as to object variable definitions.

While this is clearly an improvement, because the compiler can now detect missing "scope" declarators in object variable definitions and give an error message, it still does not solve the problem that it is necessary to write "scope" at the object variable definitions.

This can and will become a problem in evolving projects.

Of course, in a perfect world each application will be completely designed before even the first line of code is written.

In such an optimal scenario, all the classes will be properly defined before the actual coding starts, and for each class it will be thus known in advance whether it requires a "scope" declarator or not.

In this perfect world, it will always be clear from the beginning that all the object variables ever defined for objects of such classes must also include the "scope" declarator.

But in the harsh reality of real life, things rarely if ever work out as smoothly as in our perfect-world scenario.

Real programs evolve over time.

It is quite common to add functionality to classes later which no-one has thought of when they have been designed in the first place.

This is especially true in open source projects, where multiple external developers add code to an existing project, adding things the original author might have never dreamt of.

Now imagine there is a D class in such a project which initially did not manage any resources but memory.

Such classes usually don't have any special destructors, because they leave it to D's garbage collector to eventually deallocate the memory. Also, as such classes do not control any particular operating system resources, there is no need to declare them as "scope". And of course, no object variable throughout the project will have been declared "scope" in order to match the class declaration.

Let's assume 50 developer are working on such a project.

What happens if any of them decides to add a feature to our class which requires controlling some operating system resource other than memory - say the handle of a class-internal log file?

Note that the developer only added functionality to that class by adding some sort of logging framework interface to it; this is new functionality which does not interfere with any existing functionality if the class.

Adding such functionality is in fact quite common, and has never been a problem in C++: In this case, the header file will be updated and all dependent source files will have to be recompiled - a process automatically taken care of by the "make" utility (assuming a correctly written Makefile).

But the existing C++ source files do not have to be modified in any way because of this change.

Not so in D.

As adding something as a logfile feature to a class in a well-co-ordinated way usually requires some cleanup to be done in the destructor (such as closing the logfile) and this cleanup should be done in a predictable manner, it is necessary to convert the non-"scope" class into a "scope"-class.

But in contrary to C++, it is not enough to add "scope" to the class declaration in D.

No, in addition to that, all the source files of all the 50 programmers in the project have to be scanned for object variables defined for this class, and "scope" has to be added to any such instances found.

Just consider the "fun" those programmers might have, especially in a distributed development scenario, when they note their code no longer compiles after each couple of updates they receive from the main version control repository, and forces them to add dozens of "scope" declarations to their variable definitions, because "scope" has been added to the declaration of some class they are using.

I consider such a situation to be a maintenance nightmare.

The solution to that problem should also be obvious: The requirement to repeat the "scope" keyword from object variable definitions has to be dropped.

It seems to be unnessesary anyway, because the compiler will find the "scope" when it looks at the class declaration; it is pure nonsense to repeat that declarator at each object variable definition for that class over and over again. (That is, nonsense from the view of an application developer programming in D. Perhaps there is good reason to do so from a language designer's point of view. But that excuse won't help avoid the maintenance problem.)

Summing up: By changing "auto" into "scope", D 2.0 has been updated from "nearly unusable" to "just unmaintainable", at least for large-scale projects which are have a design based on RAII.

For smaller tasks D might be OK - but then, why not using a simpler language like Python, Perl or JAVA instead? (And Python, albeit "just a scripting language", is even more powerful than D regarding RAII, because it already has synchronous destructors - no need for any "scope"-like declarations there. Same for Perl.)

Another problem of D is inherent from its design decision to use garbage collection: As http://www.digitalmars.com/d/garbage.html states,
Zitat:
All threads other than the garbage collector thread must be halted while the collection is in progress.

In other words, even the most high-sophisticated multi-threaded web-server written in D must be expected to take a nap at any time - and all threads running will have to take a nap, too. Great - that was exactly what multi-threading was made for. :( And no-one can say how long this nap will actually take, because
Zitat:

The time it takes for a collection to run is not bounded. While in practice it is very quick, this cannot be guaranteed.

Such interruptions of normal service might be tolerable in many situations, but not in all.

D is therefore especially not well suited for real-time applications.

Of course, JAVA has the same problems. But it is D and not JAVA claiming C++'s crown.

Or let's put it the other way: D might be a valid competitor to JAVA, but it still has not got what it takes to replace C or C++ as system programming languages. It just takes more to challenge C++ than D can provide at the moment.

On the other hand, D is still an evolving language, and so there is still a chance left for hope that those shortcomings will eventually be eliminated.

=====

Note to the reader: I originally posted this article in a slightly modified form at

http://forums.gentoo.org/viewtopic-p-4190452.html#4190452

where other forum members encouraged me to also post it here, because it might perhaps provide some ideas to improve D even further.

Personal mail can be sent to me if necessary via the Gentoo forum, follow the link above.



More information about the Digitalmars-d mailing list