Tim Jansen's blog


2003/12/22
Programming-by-contract in C-based languages
Programming-by-contract in C-based languages I do not know much about Eiffel (and I can’t stand its Pascal-like syntax…), but the Eiffel feature that I like is design by contract. Design by contract means that function interfaces, the APIs, are seen as a contract between the creator and the user. In most languages this contract is mostly written down in the documentation. Eiffel has them written in the source code. It is also possible to do this in a language like Java, but Java’s syntax needs a small modification to make this really comfortable. Let’s take this function as an example:
        /**
         * Computes the speed in meter per second from the given distance 
         * and time. The time can be given in seconds, minutes or hours, 
         * depending on the content of timeUnit.
         * @param distance the distance in meters, always >=0
         * @param time the time, either in seconds, minutes or hours, depending
         *              on timeUnit. Must never be <=0.
         * @param timeUnit the unit of the time. Can only be "s" for seconds, 
         *              "min" for minutes or "h" for hours. Other strings are 
         *              not allowed
         * @return the speed in m/s. Guaranteed to be always >= 0.
         */     
        float computeSpeed(float distance, float time, String timeUnit) {
                if (timeUnit.equals("s"))
                        return distance / time;
                else if (timeUnit.equals("min"))
                        return distance * 60 / time;
                else
                        return distance * 3600 / time;
        }
This example will work fine, as long as the user does not violate the API contract. But if the user breaks the contract, the function will either crash (time == 0 causes a division by zero), violate its contract (negative return value if distance or time are negative) or silently return a wrong result (unknown unit in timeUnit). What Eiffel does is having a special syntax for assertions that are executed before and after the actual function. You can find out more about Eiffel’s syntax here. When writing in a language like Java, assertions in the function head are easy to do with either ‘assert’-statements or a couple of ‘if’s. I prefer the latter for argument checks in APIs, since a assert will not produce an error message that is useful for the user: only the function’s developer knows the internals of the function and thus will be able to understand the assert’s error message. For the return value ‘asserts’ are ok, because every error in the return value is a bug in the implementation. The problem with assertions for the return value is that they are quite ugly if your function has more than one return statement and they blow up the code:
        float computeSpeed(float distance, float time, String timeUnit) 
                throws IllegalArgumentException {
                if (distance < 0)
                        throw new IllegalArgumentException("distance must not be < 0");
                if (time <= 0)
                        throw new IllegalArgumentException("time must be > 0");


                if (timeUnit.equals("s")) {
                        float r = distance / time;
                        assert r >= 0;
                        return r;
                }
                else if (timeUnit.equals("min")) {
                        float r = distance * 60 / time;
                        assert r >= 0;
                        return r;
                }
                else if (timeUnit.equals("h")) {
                        float r = distance * 3600 / time;
                        assert r >= 0;
                        return r;
                }
                else
                        throw new IllegalArgumentException("Unknown value in timeUnit");
        }
The code can be simplified using a try/finally, but the syntax is not much shorter (I know that the try/finally does not make much sense in this example, but when the function modifies an object it is often neccessary that you check the object when the code threw an exception):
        float computeSpeed(float distance, float time, String timeUnit) 
                throws IllegalArgumentException {
                if (distance < 0)
                        throw new IllegalArgumentException("distance must not be < 0");
                if (time <= 0)
                        throw new IllegalArgumentException("time must be > 0");
                
                float r = 0;
                try {
                        if (timeUnit.equals("s")) 
                                r = distance / time;
                        else if (timeUnit.equals("min"))
                                r = distance * 60 / time;
                        else if (timeUnit.equals("h"))
                                r = distance * 3600 / time;
                        else
                                throw new IllegalArgumentException("Unknown value in timeUnit");
                } 
                finally {
                        assert r >= 0;
                }
                return r;
        }
A more elegant way to solve the problem is to extend the Java language a little bit and to add a feature that I call ‘method finallys’. They work like the ‘finally’ clause of a ‘try’ statement, but use a function body and allow the inspection of the function’s return value. The syntax would like this:
        float computeSpeed(float distance, float time, String timeUnit) 
                throws IllegalArgumentException {
                if (distance < 0)
                        throw new IllegalArgumentException("distance must not be < 0");
                if (time <= 0)
                        throw new IllegalArgumentException("time must be > 0");
                
                if (timeUnit.equals("s")) 
                        return distance / time;
                else if (timeUnit.equals("min"))
                        return distance * 60 / time;
                else if (timeUnit.equals("h"))
                        return distance * 3600 / time;
                else
                        throw new IllegalArgumentException("Unknown value in timeUnit");
        }
        finally (float r) {
                assert r >= 0;
        }
The ‘method finally’ makes it possible to check the return value and optionally also the object’s state when the function did not throw an exception. To allow the check for void functions I would suggest the syntax
        void methodname() {
        }
        finally (void) {
        }
and for checks that are always executed, even when the function threw an exception, the syntax
        void methodname() {
        }
        finally {
        }
And, of course, it should be possible to use both ‘finally’ variants for a single function.


 

This blog is my dumping ground for thoughts and ideas about Eek. Someday Eek will be a programming language and system, somewhat comparable to Java in scope. It is my attempt to bring sanity to the world of computing.
At least I hope so. Right now it is far from being finished and I can't guarantee that it ever will be. I am still working on the specification, but I won't release anything before I got my first prototype running. The world does not need more vapourware and unusable beta-software. All publicly available information about Eek is contained in this blog. You can find the latest summary here.
This page is powered by Blogger. Isn't yours? Creative Commons License
This work is licensed under a Creative Commons License.