This article presents a interface IList<T>
containing Add(T item)
and Count()
methods. The interface contract expects that when an item is added, the Count()
method reflects the new quantity of items in the list. This can even be defined in the interface documentation (a contract postcondition).
However, the interface itself, in most languages, does not guarantee that this agreement will be fulfilled.
He proposes to solve this by creating a subclass CollectionContract<T>
that implements the contract fulfillment logic:
public abstract class CollectionContract<T> : IList<T> {
public void Add(T item){
AddCore(item);
this.count++;
}
public int Count {
get { return this.count; }
}
protected abstract void AddCore(T item);
private int count;
...
}
One of the comments argues that this approach can introduce unacceptable overhead at runtime even when this overhead is limited to builds of debug :
In computer science and software engineering, the terms and conditions on a contract are often referred to as pre- and post-conditions. While abstract classes could be used to validate these conditions are satisfied through the use of the template-method pattern, this approach can introduce unacceptable run-time overhead even when limited to debug builds.
He also says that in languages without multiple inheritance, such as C # (and Java), this approach has a profound impact on class design. Moreover, contract compliance logic is making assumptions that make the subclass rigid and inflexible (such as assuming that the counter should be stored in a private field, and that this field must be of integer type).
Finally, it proposes that contract fulfillment be guaranteed through unit tests performed on the classes that implement the interface (although this is not an ideal solution since it is external to the contract and language).
My questions are:
-
What kind of situation does the commenter refer to when he talks about overhead at run time?
-
Are these situations where overhead occurs as a rule are difficult or easy to predict? (for purposes of helping decide when it is feasible to adopt the article solution)
-
Incidentally, answer me directly: is it always wrong to try to secure a contract the way the article does?
-
Even in languages that allow multiple inheritance?
(For anyone interested in the subject context, I came up with this article on interfaces starting this here and going through this one . href="https://simpleprogrammer.com/2010/11/02/back-to-basics-what-is-an-interface/"> this here is also interesting).