20

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?

avismara
  • 5,141
  • 2
  • 32
  • 56
  • Interesting question. What do you mean by design-by-contract at compile time? Can you paste or reference an example in another language? – Mario Zannone Aug 04 '15 at 19:25
  • Yes and sure! Check out the edit. – avismara Aug 04 '15 at 19:52
  • Swift has `precondition` and `preconditionFailure`, however they act almost like `assert` and `assertionFailure`. I am not aware of any way of doing Design by Contract in Swift – David Skrundz Aug 04 '15 at 20:04
  • Well, isn't that sad? :( – avismara Aug 04 '15 at 20:19
  • 3
    A script that processes the source files for contract comments and produces the equivalent XCTest files would be one way around built in language / IDE support. – Jon Shier Aug 04 '15 at 20:40
  • Hmm... Interesting thought. Could be a good project. – avismara Aug 04 '15 at 20:44
  • 4
    I fear that the answer to the question as set is 'no'. But that's definitely not worth 50 points. – Tommy Aug 06 '15 at 19:57
  • As far as I know Tommy is correct. – Unome Aug 07 '15 at 17:46
  • If one were to design by contract in Swift, they would need [refinement types](https://en.wikipedia.org/wiki/Refinement_(computing)#Refinement_types). Considering Swift can't even do type inference in a timely manner in general (turns out Swift's unique mix of subtype inference is NP-complete) it's a bit of a stretch to think it can infer predicates ;) – CodaFi Aug 11 '15 at 03:23
  • This is breaking my heart, you guys! – avismara Aug 11 '15 at 18:13

2 Answers2

14

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?

Community
  • 1
  • 1
Stuart
  • 36,683
  • 19
  • 101
  • 139
-4

I'm not if this is what you're looking for but here is a suggestion you could try maybe. If you want to define a protocol where you can define the signature of the sqrt function and leave the implementation for other classes or structs to implement at a later point you could do something like the code below:

Note: the the sqrtf is just using the system implementation here.

public protocol Math {
    func sqrtf(f: Float) -> Float
}

struct NativeMath: Math {
    func sqrtf(f: Float) -> Float {
        return sqrt(f)
    }
}


println(NativeMath().sqrtf(2))
Edward Ashak
  • 2,411
  • 2
  • 23
  • 38
  • No, Edward, this is not what I want to do. The answer has got nothing to with design by contract. You can read about it here - https://en.wikipedia.org/wiki/Design_by_contract – avismara Aug 11 '15 at 18:12
  • Interesting concept, so help me understand more about it, is it like function signature but without the protocol wrapper ? If thats the case, I don't think Swift has that kind of support yet, but I might be wrong. – Edward Ashak Aug 11 '15 at 18:19
  • 2
    It is a type of Defensive Programming. Setting expectations as to what a function will do and what it is expected of the caller. By making these details explicit, the function is less prone to error since the specifications are explicit. Yes, Swift doesn't have a native support. But, libraries? Can be done? Cannot be done? That is the question. – avismara Aug 11 '15 at 18:23
  • thanks for the clarification @avismara, Sorry i can't provide you with the help you needed. – Edward Ashak Aug 11 '15 at 18:25