On Wednesday, 2 May 2012 at 06:10:04 UTC, Mehrdad wrote:
I don't think you answered my question.

What I said (or meant to ask) was this:
- OK, FINE, let's say I don't know what D's const() means, then. Maybe it isn't suitable for what I need. I just want to know: _How do you specify that the function process1() won't modify its 'student' parameter_?

If you want just to specify that (and not ask the compiler to check for you), documentation will do.


Your response was this:
- "Does const(Student) mean that it shouldn't write to the server?"

To which my answer is:
- I don't know, you tell me. (?) _Should_ I use 'const' to specify this? Or should I use something else?

I can't tell you what you want. You have to tell me. But no, you shouldn't use const to specify this. const means you're object won't be changed by you. Here's a decision tree for if you can use const and immutable

Will the object (including all of its fields) ever change?
no -> immutable (END)
yes ->
Will the object (including all of its fields) be changed by you?
no -> const (END)
yes -> No qualifier

That's _any_ kind of modification of state. If you change state, you can't use immutable/const (nor would you really want to).

The problem with your answer is that it implies D DOESN'T SUPPORT O.O.P. with const!!!

If D supported OOP, then why the heck would process1() know (or _care_) how Student works internally? Why (or how) should it know (or care) that Student uses a database connection?

When you say "const(Student)" you're saying that whatever Student does, you want to know whatever you do won't change its internal state.

I'm not sure you're using OOP properly. If you want to use OOP to solve the problem, my suggestion is closer to OOP than using const. If you don't want to talk about database connections and everything (i.e., you don't want to use D's outrageously nice templates), you can just have it be an interface instead. In fact an interface would probably be more appropriate.

interface ROStudent {
   getName();
   getAddress();
   ...
}

process1(ROStudent student);

Effectively, though, it's the same sort of thing.

D's const/immutable require a different way of thinking of it. What are they useful for? Consider a multithreaded program where some threads depend on information that others have. They need the information but they won't change state (which makes it much safer/faster to work with because locking isn't as necessary ... with immutable locking is actually silly). That's what const/immutable is for.

In C++, you'd be foolish to not have locks set up even for const variables because they can change at any time for any reason. It's hardly a guarantee and it's so common to violate (look at yourself, for instance) that it means _nothing_. I liked how it was described as a glorified comment, because that's precisely how I think of it.

Wasn't that information an implementation detail?


All process1() needs to know is the *PUBLIC INTERFACE* of Student. And all it cares to say is: "According to the public interface of Student, none of the methods I will use will modify the object." process1() has NO IDEA what goes on internally! It has NO IDEA that Student uses a database connection. Maybe it's a network connnection instead. Or maybe it's being unit-tested, and it's actually a dummy object, with no relation to the outside world. Or maybe it's a wrapper/proxy for another object.

The point is: _why should the code for process1() depend on this_?!

If that's what you want, then that's precisely what D does. "According to the public interface of Student, none of the methods I will use will modify the object." As opposed to C++'s method of "According to the public interface of student, these methods have comments that say that they say they won't change the object, but I can't tell if it does or not."

Again, using an interface ROStudent/StudentReader/etc is really your "OOP solution".





So, I'll ask my question again:

How should process1() tell the outside world that it will not be asking its parameter to manipulate itself, WITHOUT breaking the abstraction barrier and 'peeking' into the private world of Student?

I'll respond again: It depends on what you want. If you won't be changing the object, then const/immutable does that. If you will be changing the object, but you want guarantees that it won't write to some external source/data structure, you'll have to come up with the more precise way you want to define that. I gave you two potential approaches.


----

Really though, the C++ way is a complete and total minefield in this regard anyway. Consider Student defined like so:

Student {
name, id, address, phone_number;
connection;
getName() const {
    if(!name) {
        // cast away const
        thisnonconst.name = connection.get("name");
    }
    return name;
}
writeName() {
    connection.set("name", name);
}
}

Now this follows one particular understanding of const (the one I think you're getting at). However, imagine another person comes along and sees that "writeName" doesn't write to Student's state. Helpfully, he adds const to the end of writeName and breaks your type system. In fact, it's actually _easier_ to violate "that kind of const" than it is to use it, because your "getName" method has to do fancy casting away of const.

In fact, D's way, if you specify that Student can only use a ReadOnlyConnection (or if you use ROStudent/StudentReader interface), then the compiler will guarantee that it has a ReadOnlyConnection. If ReadOnlyConnection doesn't write to the database, then that Student is _guaranteed_ to not write to the database.

If you want the compiler to check that, the D offers the ability to. C++, on the other hand (using const), can barely suggest that possibility, since it's so easy to violate.


Reply via email to