Contracts for delegates
Routines that simply forward the request to another object (a delegate) typically have the same signature and contract (possibly strengthened) as the delegate's routine. In which case it is slightly tedious to write out the duplicate assertions (especially if the delegating routine is using different names for the arguments), and a potential maintenance problem too.
It appears that there is a simple, problem-free, extension to the assertion syntax to improve this situation - reusing the
The suggested syntax looks like this:
It is an error if
The preconditions for
Similarly for the postconditions.
may be problematic
what about contracts involving queries and not just the feature arguments? just ignore them?
Query renaming must be dealt with also
Yes, it's an interesting point. Assuming the delegate is class A, and the delegating class is class B, and both classes A and B inherit from class C, and class A uses a query from class C in one of the preconditions, and class B renames this query, then the expansion of the like precondition will involve using B's name for the query.
That isn't actually a problem. For Manu's suggestion of a tool solution, it means the tool has to be ever-so-slightly more sophisticated.
For my language enhancement suggestion, it's a no-op (that is, it's just part of the semantics). Colin Adams
We certainly need something like that, but I wonder whether it should be a language change or a tool change. I'm favoring the tool because when you have the call
a.f' and you want to extract the assertions, then in your model you need to make sure thata' is also available to the client which is not always the case. With a tool, then the tool can basically expand your `like a.f' notation in usable assertions.
Not maintenance proof
Yes, that is helpful, but it doesn't help if the author of the delegate class realizes (s)he made a mistake, and strenghtens the precondition or weakens the postcondition. Of course, this is a more general problem, and my proposal only helps for a small subset of such cases.
I'd like it!
I had a similar idea for a Eiffel-based language compiler I was working on for Lego MINDSTORMS NXT.
In your example there's a couple of issues. First you are using a variable/argument to access the conditions. What if the variable is unattached? Are you using the dynamic type or the static type? You cannot use the dynamic type because the client cannot verify the contracts as well as the possibility of 'my_object' resting in an detached form. Usage in a form of a static access call instead ensures the the routine 'my_feature' is borrowing the contract from is assured and clear.
I like the reuse of
like. And I'd never thought about trying to reuse contracts from a feature with a differing signature. However, there are problems in borrowing contracts from features of differing signatures:
The first issue is that 'feature_name' has an additional parameter 'c', which must be attached and is used to validate the argument 'b'. How can we borrow the contracts for 'feature_name' when there is no specification in 'my_feature' for it?
Also, in the above example 'feature_name' requires 'is_initialized' to be
True but 'my_feature' does not. How do you selectively exclude contracts?
You might use a tuple to select the contracts you want to borrow:
But with this we are already becoming more verbose, less readable and are not saving a whole lot on typing.
There's also the problem that borrowing contracts from 'feature_name' might break clients of 'my_feature', if contracts are added or removed from 'feature_name'. Unless you keep a vigilant eye on it the contracts of 'feature_name', 'my_feature' may be broken unnecessarily or allow invalid state to pass through. This a maintenance nightmare!
I really like the idea but it requires a lot of thought.
Unattached variables not a problem
It doesn't matter if the variable is attached or not (for the contract - the body will require a suitable invariant, but that has nothing to do with the contract) - it is the static type of the variable that is used.
I hadn't thought about borrowing contracts with a different signature. That is a minefield that I am not eager to explore.
As for contracts being added or removed from the delegated feature, the whole point of making it a language enhancement is that the delegating class remains correct.
As for the clients of the delegating class, they are no worse off than if the class itself is edited.
Just coming back to add another couple of cents to this; I would say that using a variable isn't the best idea and using static access is better. It's clear where the feature invariants are taken from, it resolves using attributes/routine parameters using anchored types (This could make assertions differ depending on descending classes), and finally solves any issues when a class attribute/routine parameter is not available. You could argue to provide both ways, but Eiffel's principles prohibit multifaceted mechanisms unlike our friend Perl :)