A paper about traps and programming stress

bearophile bearophileHUGS at lycos.com
Mon Mar 15 08:08:37 PDT 2010


F:

>would like to verify the robustness of D with respect to the issues presented in the paper...<

In some of those cases D gives tools to solve the problem, but to use those tools the programmer must already know about those problems.

--------------------

Illusory protection: D classes of the same package can't access each other protected members.

But in a D module even private attributes can be accessed by everyone else in the same module. The compiler here doesn't even try to give warnings. This can lead to bugs. A @superprivate or @module property can help here :o)

This D characteristic of allowing free access in a module is bad for newbies because this langage sloppiness does not help learn the meaning and usefulness of the public/ protected/ private attributes.

--------------------

Constructor confusion:

In D this prints:
3
3

import std.stdio: writeln;
import std.math: PI;

class Super {
    this() { printThree(); }
    void printThree() { writeln("three"); }
}

class Test : Super {
    int indiana = cast(int)PI; // That is, pi=3 in Indiana.
    override void printThree() { writeln(indiana); }
}

void main() {
    auto t = new Test;
    t.printThree();
}

--------------------

Initialization follies: in D I think D Scope Guard Statement as scope(exit) can help here.

--------------------

Inheritance without specialization: in D there are class mixin that can be useful to use aggregation instead of inheritance (but they are a low-level feature that can cause other problems). Some templates can be used to inject other functionality in class templates. The @disable can be used to hide inherited members:

class Foo {
    void method() {}
}
class Bar : Foo {
    @disable override void method() {}
}
void main() {
    auto b = new Bar;
    b.method();
}


It raises a compilation error like:
test.d(9): Error: function test.Bar.method is not callable

Even if something like this can be better:
test.d(9): Error: function test.Bar.method is not callable, annotated with @disable.

--------------------

Container limitations: D has templates that were designed to solve this problem. In the meantime part of this problem has being solved for Java too, this article if from year 2000.

--------------------

Not-so-final parameters: the D const system is transitive, this solves the problem with method/function arguments. const can be used to state that a nonstatic method doesn't change the object state:

class Foo {
    int x;
    const void bar() { x++; }
}
void main() {}

--------------------

Initialization diffusion: D classes don't have instance initialization blocks. But both modules and classes can have multiple static this, so they can suffer the same diffusion problem:

int a, b;
static this() { a = 10; }
class Foo {
    static this() { Foo.x = 10; }
    static int x, y;
    static this() { Foo.y = 20; }
}
static this() { b = 10; }
void main() {}


Allowing only one static this() in a module/class can help. I don't think a class/module can necessitate more than one static this, so this can become a bug report. Others here can give their opinion on this.

--------------------

Other worries:

No separate class-specification: I don't agree this is a problem. (dmd can generate 'header' files, but they are for performance purposes).

No support for assertions: D has asserts and Contract programming. Phobos2 has enforce.

Array type-checking failures: this D version of the program doen't fail at runtime:

class A {}
class B : A {}
void proc(A[] x, A y) {
    x[0] = y;
}
void main() {
    B[] anArrayOfB = new B[5];
    A a = new A();
    proc(anArrayOfB, a);
}

--------------------

bye,
bearophile



More information about the Digitalmars-d mailing list