Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Design by Contract in Swift

Does Swift provide a native Design by Contract support? I understand that it can be done during runtime through assertions, but could it be done during compile time? Or, are there any external plugins/libraries that do this?

EDIT

By saying "during compile time Design by Contract", I do not mean the library to be an all powerful static analyser that C# has. It would be enough for me if it is something like the one that iContract provides for Java. Let us look at an example:

A DBC code for the square root evaluation in Java using iContract could be written as :

/** 
 * @pre f >= 0.0
 * @post Math.abs((return * return) - f) < 0.001 
 */ 
public float sqrt(float f) { ... } 

Now, this keeps my contract as a part of my API specification rather than a part of its implementation which I believe is a cleaner way. The caller will know what his responsibilities are and the callee is setting its expectation, all in albeit clearer manner. Do we have something like this in Swift?

like image 837
avismara Avatar asked Aug 04 '15 19:08

avismara


People also ask

What is Design by Contract in programming?

What is Design by Contract? Created by Bertrand Meyer in the 1980s, Design by Contract (DbC) is an approach to software design that focuses on specifying contracts that define the interactions among components.

Why is design by contract useful?

Design by contract can also facilitate code reuse, since the contract for each piece of code is fully documented. The contracts for a module can be regarded as a form of software documentation for the behavior of that module.

What is DBC Java?

The Design by Contract (DBC) software development technique ensures high-quality software by guaranteeing that every component of a system lives up to its expectations. As a developer using DBC, you specify component contracts as part of the component's interface.

What is contract based development?

Contract-Driven Development is a new approach to systematic software construction combining ideas from Design by Contract, from Test-Driven Development, from work on formal methods, and from advances in automatic testing as illustrated for example in our AutoTest tool.


1 Answers

TL;DR

As @Tommy points out in the comments under your question, it would appear that the plain & simple answer to your question is "No, compile time DbC is not currently a feature of Swift".


What's built in right now?

For built-in support for this type of design strategy, you currently have to look at the runtime I'm afraid. Swift appears to prefer runtime assertions for enforcing preconditions currently, although the language seems generally to be putting more emphasis on safety at compile time (more on this below). The global functions assert, assertionFailure, precondition and preconditionFailure are designed to be sprinkled liberally throughout code without impacting release build performance.

Unit tests are, of course, another strategy for checking that API contracts are fulfilled, but these must be thought of and implemented manually, and so are error prone.

Something else that is perhaps interesting to note is that amongst the better documentation comment support of Swift 2, "requires", "precondition" and "postcondition" are recognised markup keywords, such that they are displayed prominently in quick help documentation:

/// - precondition: f >= 0.0
/// - postcondition: abs((return * return) - f) < 0.001
/// - returns: The square root of `f`.
func sqrt(f: Float) -> Float { ... }

So does this emphasis on being able to provide good documentation for API contracts mean that the Swift development team clearly cares about it, and this is a stop-gap until they incorporate something into the syntax in the future, or does it mean that they think this sort of information belongs in the documentation? Pointless postulation, perhaps. Regardless, despite the fact it's not proper DbC, I think it's a handy thing to be aware of right now.


What can I do about it now?

With Objective-C, macros could be used to essentially implement basic DbC, however the lack of macros in Swift means you would have to resort to some kind of function/generics-based wrapper, which I think would look like a really awkward bodge.

Xcode's support for adding custom scripts to a target's build phases – as suggested by @JonShier in the comments – is perhaps the closest you will get to useful & automatic DbC without waiting for the language to (maybe / maybe not) introduce such a feature. With the aforementioned documentation markup keywords, a script that analyses documentation comments to build unit tests could even be incorporated retrospectively to projects with only a small amount of learning/effort on the part of the user. As you say, I think this could make a very interesting project!


Will it be a built-in feature in the future?

It is not clear whether or not native DbC might be incorporated into Swift in the future. Arguably, it is a feature that is well suited to the mission of the Swift language, which is to say that it promotes safer code and reduced risk of runtime errors. Should it become a part of the language, I would suggest that we would be more likely to see them appear as declaration attributes than as interpreted comment markup, for example:

@contract(
    precondition = f >= 0.0,
    postcondition = abs((return * return) - f) < 0.001
)
func sqrt(f: Float) -> Float { ... } 

(But that is just speculation, and of no use to us right now!)

From what I know of the topic, compile-time DbC can be a very complex problem. But who knows... work on the Clang Static Analyzer has certainly shown that there is an underlying desire to drag identification of runtime bugs back to compile time. Perhaps this is the perfect problem to put a Swift static analyser to work on in the future?

like image 70
Stuart Avatar answered Sep 19 '22 14:09

Stuart