Over on the digitalmars.D newsgroup,
On 11/8/2011 2:35 PM, Alex Rønne Petersen wrote (in a thread
entitled "assert(obj) is an atrocity"):
> Hi,
>
> As the title suggests, I'm going to be rather blunt about this.
> assert(obj) testing the invariant *without* doing a null check is insane
> for the following reasons:
>
> 1) It is not what a user expects. It is *unintuitive*.
> 2) assert(!obj) does an is-null check. assert(obj) is a completely
> broken opposite of this.
> 3) No AssertError is thrown, which is the entire point of the built-in
> assert().
> 4) The few added instructions for the null check hardly matter in a
> *debug* build of all things.
>
> I don't mind assert(obj) testing the invariant of obj. In fact, that
> very much makes sense. But please, please, *please* check the object for
> null first. This is a random inconsistency in the language with no other
> justification than "seg faults are convenient in a debugger". By the
> same logic, we might as well not have array bounds checks. However, the
> state of things is that array bounds checks are emitted by default and
> users can disable them for e.g. a release build. I don't see why this
> case is any different.
>
> - Alex

OK. Not addressing Alex's objections at all, it's not clear to me why anyone would *need* to test the invariant of an object. Aside from the fact that, anytime you actually use the object, its invariant will get tested (twice)...

Unless I misunderstand something about design-by-contract (always a possibility), the invariant of an object holds anytime you have access to an object outside of its public interface. The only times an invariant does *not* hold are (a) while the object is being constructed -- in fact, the *whole purpose* of the constructor is to establish the invariant! +++ (b) while an object is executing "private code", i.e. internally during a method
(c) after the object has been destroyed

In that light, it seems to me that if you can get a non-null reference to obj at all, its invariant must hold. Stating that another way, if you *can* get a non-null reference to an object whose invariant does not hold, the_language_itself_is_broken! No?

What am I missing here? What is the purpose of assert(obj) having semantics beyond assert (obj !is null) ??

-- Davidson

+++ The notion that the ONLY purpose of the constructor is to establish the invariant is a strict formalism. In practice, many constructors perform additional initialization beyond invariant-establishment, as a convenience. Such additional initialization could be factored out into separate methods.

Also, D's insistence that an object be fully-fledged once each of its member fields receives its .init value -- which could happen if the later stages of a constructor throws, or if a live object's .clear() method is called -- constrains what the invariant can guarantee. For that reason, you need to take care that the constructor does *not* throw, and that .clear() is not called, if you have an object that really isn't "live" without some fancy work having been completed on it.






Reply via email to