Jump to page: 1 2
Thread overview
scope keyword - a maintenance nightmare?
Aug 17, 2007
Deewiant
Aug 17, 2007
Radu
Aug 17, 2007
Sean Kelly
Aug 18, 2007
James Dennett
Aug 18, 2007
Sean Kelly
Aug 18, 2007
Walter Bright
Aug 17, 2007
Bill Baxter
Aug 17, 2007
Sean Kelly
Aug 18, 2007
Walter Bright
Aug 19, 2007
Walter Bright
August 17, 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.
August 17, 2007
Guenther Brunthaler wrote:
> * While the closed source Digital Mars compiler really created small and nice executables, the GCC-backend created executables multiple times that size

Running 'strip' makes them somewhat smaller. You might want to ask on the D.gnu newsgroup about why they grow so big.

> * 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...

http://www.digitalmars.com/d/dcompiler.html#interface_files

Unfortunately, this only separates interface descriptions from object code. What I miss is the ability to define a function's type and its implementation in two different locations.
August 17, 2007
Guenther Brunthaler wrote:

> 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
>
>   
strange, never tested myself but obviously it's a gdc problem not at D general problem
> * 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...
>
>   
it is .di files that are a general description file (headers). you can generate them by using dmd -H command. problems still exist with templates (as with c++)
> * Maintenance-Nightmare with "auto" (now "scope").
>
>   
*very long read :)* anyhow scope classes are  indeed somehow strange to use and especially design as there is limited scope (no pun intended) on their usage. I for one use only the scope storage declaration for local+stack allocated classes.
August 17, 2007
Guenther Brunthaler wrote:
> 
> * While the closed source Digital Mars compiler really created small and nice executables, the GCC-backend created executables multiple times that size

Valid point, though this isn't really a problem with D.

> * 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...

Sure there are.  In fact, DMD offers the -H option to generate header files during compilation.

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

I'm not sure I understand, but more later I suppose.

> 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.

It is exactly the same in 1.0, unless I'm missing something.  The only change I am aware of regarding this was the switch from "auto" to "scope" as the qualifier to use.

> 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.

How so?  Personally, I think that not requiring "scope" at the point of declaration would be more of a maintenance problem.  Without some sort of visual cue that a reference variable is scoped, it would be easy to unknowingly return references to destroyed objects from functions, etc.

> 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.

Certainly.  But it is generally a fundamental change in behavior to make a non-scoped class scoped.  Also, I don't believe it is always necessary to place the "scope" qualifier on the class definition.  In fact, I rarely use it (possibly a mistake on my part).

> 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.

I disagree.  There are many instances where the lifetime of an object must be deterministic but must also exist beyond the scope of a function call.  The scope qualifier does not apply here.

> 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.

I think a greater maintenance nightmare would the the lack of "scope" at the point of declaration, as it would be likely to cause a segfault if the maintainer is not aware that a particular type is scoped.

> 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.

This is true of the current garbage collector implementation.  There are real-time garbage collectors available which do provide guarantees about delay however.  That said, it's not entirely clear how easily such a GC would map into D.

> 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.

See above.  For what it's worth, the GCs to which I am referring are implemented for Java.

> 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.

Since C++ will be adding garbage collection in the next iteration of its standard, I don't see its presence in D as a particularly strong argument for why D cannot compete with C++.


Sean
August 17, 2007
Guenther Brunthaler wrote:
> * 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...

Like others have said, D has .di files that let you separate interface from implementation.  And the nice thing is the compiler can even generate them for you.  Unfortunately what it generates is pretty ugly.  It doesn't seem to expect that humans will be reading them for some reason.  But there's no reason why it couldn't do a better job.

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

I don't think scope is really meant to be used in the way that you want to use it.  Scope means the class is destroyed when it goes out of scope.  It is only meant to be for classes used within one scope. Period.  So if you had a pre-existing class that was already in use in lots of code, chances are good that they would be violating this "only one scope" rule, for instance by returning the scope class from a function.  So scope simply doesn't aim to be a general purpose mechanism for deterministic destruction.  It's probably most like using auto_ptr in C++.

What you want seems to be more like a reference counting scheme, like a C++ boost::shared_ptr, which gets destroyed immediately when all outstanding references to it are gone.  That would indeed be a nice addition to D, and has been discussed before.  It would be much more widely useful than scope.

--bb
August 17, 2007
Bill Baxter wrote:
> 
> Like others have said, D has .di files that let you separate interface from implementation.  And the nice thing is the compiler can even generate them for you.  Unfortunately what it generates is pretty ugly.  It doesn't seem to expect that humans will be reading them for some reason.  But there's no reason why it couldn't do a better job.

For what it's worth, I have the Tango snapshot process run uncrustify on these files before packaging them.  The result still isn't as good as a hand-crafted version, but it's readable.


Sean
August 18, 2007
Bill Baxter Wrote:

> It doesn't seem to expect that humans will be reading them for some reason.  But there's no reason why it couldn't do a better job.

I agree.

di files are exactly the type of thing I was looking for.

And even if they don't look as beautiful as manually-written files - in C++ there isn't even a way to extract header files automatically from the source files.

There is also no-one stopping the developer from manually "beautifying" what D's .di file extractor has output.

If di files only were part of the language rather than optional extensions!

> C++ boost::shared_ptr, which gets destroyed immediately when all outstanding references to it are gone.  That would indeed be a nice addition to D, and has been discussed before.

Well, in C++ object destruction is also not based on reference counts, and RAII still works fine.

Perl and Python already implement destructors the reference-counted way, and it surely is a nice feature to have at one's disposal.

But it's a convenience feature, and one can as well live without it with a little bookkeeping effort: In C++ it is quite possible to add an object controlling a resource as an instance data member to some other object which has dynamically controlled life-time, i. e. allocated with "new" rather than on the stack.

But the predictable automated destruction still works: As soon as the containing object gets destroyed by "delete", the destructor of the contained instance-data sub-object will be triggered and clean up the resource as expected.

This allows the outer object's lifetime to be controlled by whatever means considered appropriate, may it be lexical scope, reference counting or even some other technique.

I actually assumed the "scope" keyword would work in a quite similar way in D!

But, if i got you right, are you suggesting "scope" only works on a lexical scope basis?

That it, a "scope" class object's lifetime does *not* depend on the lifetime of the object the variable is allocated within (such as the lexical scope *or* another object), but is *always* controlled by the lifetime of the lexical scope only?

That would be indeed a bad thing, at least for the way I use RAII.
August 18, 2007
"Guenther Brunthaler" <gb@dont.spam.me.invalid> wrote in message news:fa610v$1j33$1@digitalmars.com...
>
> If di files only were part of the language rather than optional extensions!

But they _are_, as far as I know, part of the language.  They're probably just not documented as well as they could be (like many other features).

> I actually assumed the "scope" keyword would work in a quite similar way in D!
>
> But, if i got you right, are you suggesting "scope" only works on a lexical scope basis?
>
> That it, a "scope" class object's lifetime does *not* depend on the lifetime of the object the variable is allocated within (such as the lexical scope *or* another object), but is *always* controlled by the lifetime of the lexical scope only?

You've got it right, and I agree, we need 'scope' to be extended to mean 'the lifetime of this object is dependent upon where it was created'.  It would probably greatly reduce the need for the GC in many instances in fact, leaving the GC to deal with true garbage, rather than objects which just happened to be orphaned when the data structure they were part of was no longer needed.


August 18, 2007
"Jarrett Billingsley" <kb3ctd2@yahoo.com> wrote in message news:fa6s2j$2s36$1@digitalmars.com...
> "Guenther Brunthaler" <gb@dont.spam.me.invalid> wrote in message news:fa610v$1j33$1@digitalmars.com...
>>
>> If di files only were part of the language rather than optional extensions!
>
> But they _are_, as far as I know, part of the language.  They're probably just not documented as well as they could be (like many other features).

And I just noticed your other post, so nevermind :)


August 18, 2007
Sean Kelly wrote:
> Guenther Brunthaler wrote:

[snip]

>> 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.
> 
> Since C++ will be adding garbage collection in the next iteration of its standard, I don't see its presence in D as a particularly strong argument for why D cannot compete with C++.

There's one fundamental difference: C++ language features and standard library are GC-neutral, i.e., will work with or without GC.  GC is more inherent to D (which means that D can benefit from certain simplifications, but also that you can't use so much of D if you're in a situation where GC isn't an acceptable option).

-- James
« First   ‹ Prev
1 2