Swift One Year On

With WWDC 2015 just a few weeks away, now seemed to be the perfect time to reflect on a year with Swift. When Apple’s Craig Federighi (SVP of Software Engineering) announced Swift there was an almost euphoric response from many parts of the Apple developer community. 

The sheer level of technical ambition was breath-taking. Apple had built a brand-new language that could be fully integrated with existing code, all of the Cocoa APIs, was easy to learn, encouraged crash resistant code and even delivered a performance boost. John Siracusa was lifted above the Ewokian throng and carried out of Moscone West on a throne. You get the idea. 

However, our response was ultimately tempered by the initial quality of the tools. This reality should not have surprised anyone. Apple had kept the language a secret even internally, and with little (not quite no) dog-fooding . Eager developers downloaded the first betas of XCode 6 and got started; many could see promise, the experience was painful. Playgounds (designed to make learning and experimenting in the language easy) were actually unstable and frustrating. Some of the language fundamentals were poor; copy semantics for arrays were confusing at best, and whilst the language came baked with arrays and dictionaries sets were nowhere to be seen. All of these problems paled into insignificance when compared to a truly explosive XCode. Not only did core parts of the build chain crash frequently with painful build times for even medium size projects  when they did work, but the interactive experience was just horrific

 Where 'temporarily limited' means "get used to this, you'll be seeing it a lot for the next 8 months. 

Where 'temporarily limited' means "get used to this, you'll be seeing it a lot for the next 8 months. 

Iterate

With each new beta, the situation improved, some of the highlights included

Despite these developments, it was clear that by the time Apple threw the switch on iOS 8 and released it along with the first Swift apps to the world, that Swift was still a long way from finished. It would have been reasonable to assume that we would hear little else from Lattner and his team until WWDC 2015. Reasonable, but wrong. Swift has continue to develop with language updates (we are now at 1.2) as well performance and bug fixing. 

Swift 1.2 in particular seemed to signal more clearly than any of the other updates that Apple was serious about Swift, and serious about its claim that whilst binary compatibility would be maintained, the language itself was not done. 

What defines Swift?

Few areas of Swift are as distinctive (and sometimes as divisive) as optionals. Optionals force the developer to consider if it is possible for a pointer (a reference to an area of memory that stores an object in a program) to be nil. That is, point to nothing. C or C++ code would crash if you tried to use one of these nil pointers to call a method on that object (do something with it). In Swift you must declare that something can be nil by appending a ? to its type. When you use it, you must acknowledge the result of any method you call could be nil (?) too. Or force it to assume it’s not nil with the ! character. What this does it make it hard for the developer to hide from the fact that their code can’t assume a pointer points to a valid value. The initial release of Swift provided mechanisms for helping the developer work with these optionals. 

Some of the biggest changes in Swift 1.2 increased a developer’s ability to minimise the number of lines required to check to see if optionals had a valid value. 

Swift 1.0 [1]

//Check all my pointers are valid and a property is over 100
if let myObject = myObject
    if myOtherObject = myOtherObject
        if myObject.property > 100 {
            //Do something cool
        }
    }
}

Swift 1.2

//Check all my pointers are valid and a property is over 100
if let myObject = myObject, myOtherObject = myOtherObject where myObject.property > 100 {
    //Do something cool
}

It’s hard for a seasoned developer like myself to know if these things make it harder (?! Everywhere and lots of checking might increase the complexity to a beginners mind) OR they actually reduce the number of time a beginners program inexplicably [to them] crashes. What is clear is that in a rather intensive period of development with Swift 1.2 I was able to focus purely on the algorithms I was developing, and let Swift focus on potentially explosive nils. Every time you consider adding a ! to force the optional to be treated as a valid pointer… you feel dirty. You don’t do it. Your code doesn’t crash. Despite having a large number of beta-testers, we’ve only had functional defects, no crashes. None. I’m not an expert on all current languages, but for me optionals set Swift apart from every other language I have used, and certainly from other languages that are good candidates for developing on Apple platforms. They are unique and valuable.  

In Summary

Where are we now? The development process for Swift is now stable. Although the language has evolved and improved XCode has enabled early adopters of Swift to keep up with the changes as they happened. I’m not convinced Swift is an easy first language to learn. Were someone with another language under their belt to start now they would find themselves working with a mature language supported both online and in-print. For anyone wishing to start development for Apple platforms, they should start with Swift. For those of us with over a decade invested in Objective-C & Cocoa the decision is more personal. I believe Swift is ready for us, but exactly when you chose to jump is something that Apple has, for the time-being at least, left to each individual developer. 

However, I know that every time Swift reminds me that the variable is optional, I’ve just avoided a bug and saved time. Maybe just a minute, but maybe a few hours, and for any independent developer time is money. 

 

Footnotes

1. This could have been done more briefly of course, but I believe that the Swift 1.2 approach is as concise but more explicit. 

if myOtherObject!= nil && myObject != nil && myObject!.property > 100 {
    //Do something cool
}

 

 

 

Optional methods in pure Swift protocols

Ash Furrows wrote a very interesting post on optional conformance to a contract, and described the challenge of wanting to have two classes talk to each other without being tightly coupled (it's well worth reading David Owens response too), but I wanted to jump in and just share a pattern I used for a completely different reason (and something which is likely to be the topic of another post, so I won't go into it here). 

One of the challenges Ash highlighted (can one blogger just call another by their first name without permission? I'll assume that's OK) is that to have optional parts of a protocol it must be an @objc protocol. The challenge Ash highlights is that this then means you can apply it to all of the Swift types (struct and enum, we are looking at you).  

Well that's not very Swift is it? There is a different (note I didn't say better, just different) solution. 

In his example he highlights an optional var, but the example below covers functions too. Here's a protocol that has an optional var and an optional function. I'm jumping through some hoops to support structs (which can't mutate self in a block)

protocol Food{
    var caloriesPerGram : Double {get}
    var milliLitresWaterPerGram : Double? {get}
    var addWater : ((milliLitres:Double)->(Food))? {get}
}

struct Kibble : Food{
    var caloriesPerGram : Double {
        return 1.0
    }
    
    var milliLitresWaterPerGram : Double? { return nil }

    var addWater : ((milliLitres:Double)->(Food))? { return nil }
}

struct Flakes : Food{
    var absorbedWater = 0.0
    
    var caloriesPerGram : Double {
        return 0.5
    }
    
    var milliLitresWaterPerGram : Double? {
        return absorbedWater
    }
    
    var addWater : ((milliLitres:Double)->(Food))? {
        return { (milliLitres:Double)->Food in
            Flakes(absorbedWater: self.absorbedWater+milliLitres)
        }
    }
}

class Powder : Food{
    var absorbedWater = 0.0
    
    var caloriesPerGram : Double {
        return 0.5
    }
    
    var milliLitresWaterPerGram : Double? {
        return absorbedWater
    }
    
    var addWater : ((milliLitres:Double)->(Food))? {
        return { [unowned self] (milliLitres:Double)->Food in
            self.absorbedWater += milliLitres
            
            return self
        }
    }
}

var myFlake : Food = Flakes()
myFlake = myFlake.addWater?(milliLitres: 10.0) ?? myFlake

var myPowder : Food = Powder()
myPowder = myPowder.addWater?(milliLitres: 15.0) ?? myPowder

As I'm jumping through hoops to support structs. In case it's not obvious (??) any optional chain has an optional result, so I must use ?? to provide a value to use if the chain did result in nil. Another disadvantage is that with optional you can just ignore the var or func entirely in the implementing Type. Not so here, I must create something that returns nil

If you ignored structs you could just call the block with an optional chaining, and there would be no need for any returned object in the block declaration

protocol Food{
  // as before, except 
  var addWater : ((milliLitres:Double)->())? {get}  
}

myPowder.addWater?(15.0)

But I agree with Ash, any Swift solution that does support all Types, isn't really Swift. This solution is more than a little anguished (at least for the method case, I'm OK with the the nil returning var to be honest), but surely they could coax the compiler into doing this bit for us? 

On Typed Tuples in Swift

Tuples are a wonderfully powerful thing... from iterating a dictionary getting both key and value

for (key,value) in myDictionary{
  println("My key is \(key) and it has a value of \(value)")
}

To returning richer data from functions

func getResponse()->(responseCode:Int,payload:String?){
  //
  // Do stuff
  //
  return (404,nil)
}

All the way to augmenting enums

enum ServerResposne{
  case Error(Int)
  case Success(String)
}
  
let response = ServerResponse.Error(404)

I have found them particularly useful when you don't want to define an entire new type (be it struct, enum or class), but do need to compose a couple of things together into a package (our second case, richer data from functions). However, like so many convinces they come at a cost when you think about future you. You are both dependant on nice meaningful variable names, and even though you can name the fields of the tuple, you can't provide a hint as to exactly what the tuple is intended to encapsulate. You don't get compiler type checking, and if you decide to replace them there is no way to easily identify everywhere that particular structure is used. 

Except of course there is a one line way to protect against all of these issues, just define the tuple as a type alias

typealias ServerResponse = (responseCode:Int,payload:String?)

That's it. Now if you decide you want to capture this in a stronger type you can just replace that alias with the desired type, and the compiler will pick out everything that needs updating as a result. If you are lucky, that may even just be fixing the places where the tuples were created and the rest will just fall out. 

So we have a rule, if a tuple leaves a function scope (or greater), it gets a typealias. It's been a wonderful way of avoiding unnecessary additional types, but allowing your code to grow into them if needed. 

Writing our first Swift app

Just released Yearn (shameless plug time: app store link, or  mini-site), which has been entirely developed in Swift, and I wanted to do something green-field in Swift (before looking at a transition plan for other apps if Swift proved to be mature enough), and this was an app idea that had been bubbling away for a while. Swift and iCloud Photos beta made it feel like the timing may be right.

TLDR? Swift itself was an real win, although the tools have some catching up to do. 

The Language

Swift had two clear design goals (at least, two that really resonated with me): Be concise, be robust. In the first, I really feel Swift excels. Even simple things like dropping semi-colons clears a lot of useless noise from your screen, add in other small details like removal of brackets for conditions and I felt that my code was and remained highly readable. 

I think the second will be tested as the App gets used on a broader range of devices, but I can comment on beta testing results (for which Test Flight performed admirably). 

After writing about the language features of Swift, I settled on a list of rules that I would follow. The one I felt was most important was that I would avoid forced unwrapping at all costs. I think this is key. There are other language features (requiring forced fall-through for switch statements,  generics, forcing braced if's) but making you think about how nil can propagate through your code drives some important behaviours, it must be handled. Of course you can force unwrap with the ! operator, but as stated I decided that this would be a real no-no. However, there are those that argue that this drives clutter into the language, directly in opposition to the goal of concise and clear code. It's worth looking at a few common patterns used to deal with optionals.

The first concerns methods or variables that may be nil. Swift makes it very easy to deal with these with unwrapping. If we have a function

func myFunc()->MyObject?

We can still chain other methods calls against the returned MyObject? 

let result = myFunc()?.objectMethod()

Of course, result is now optional too, but as we know Swift has another language short-cut to make that situation easy to deal with 

if let result = myFunc()?.objectMethod()?.anotherValue?.serverResponse {
    //Everything went well
} else {
    //Handle the problem
}

The same pattern can be employed on longer method chains, but of course each step obfuscates the root cause of the issue; which call returned nil? If you want to respond intelligently, or report a useful actionable message to the user, We found a useful pattern to deal with this using switch. 

//Break out my chained calls, not worrying about optionals on the way
let myFuncResult = myFunc()
let anotherValue = myFuncResult?.anotherValue
let serverResponse = anotherValue?.serverResponse

//Deal with any failure in the chain
switch (myFuncResult,anotherValue,serverResponse){
    case (nil,_,_):
        println("Couldn't get my object")
    case (nil,nil,_):
        println("No value available")
    case (nil,nil,nil):
        println("Couldn't get response string from response tuple")
    default:
        println("Server responded \(serverResponse!)")
}

Of course this is a trivial example that leaves more boiler plate than code, but I'm sure you can see the strategy here. Stop at each point in the chain where nil would be indicative of a actionable or communicable state, and then at the point where you are either done or in trouble have a single chunk of code that will either move forward with a usable result or respond to a problem.

The key thing here is that the application logic is left unadulterated by risk from nil, but the error handling is able to use information about the chain. 

Otherwise Swift was a pleasure to use. We didn't start until close to the GM, and by that time Swift churn had calmed down enough to mean we had little if anything to do in each subsequent release. The language feels ready for prime time, with perhaps one plank in its eye.

The tools

I'm not going to spend too long here, if you you've XCode with Swift you already know what I'm going to say

 

It doesn't get really annoying until that has been flickering up a boing-ing message so much that the main thread is blocked. By the time XCode 6.1.1 had rolled around almost everything else that felt it was getting in the way had been fixed, but this really breaks your flow as you work. So work still to be done editing code... what comes after editing... oh yes compilation

Whilst the situation improved during the various beta's, there were (and are) two major bugs that caused me to change the structure of our code (both around protocols and class/static variables with generics). I'm sure they will be solved, but these issues need to be at the top of Apple's list. 

So you've edited (boing boing boing boing boing, beach ball, back), compiled (1 error, segfault in the compiler, refactor to carry on), which just leaves debugging... To be fair to Swift the aggressive avoidance of forced unwrapping meant that we only needed the debugger for functional problems rather than crashes. However, all to often the debugger is unable to tell me what is in self, let alone things that might live a little further out of scope. One can work around this (although I can't add po's to the breakpoints as they deliver the same result) with println's and similar techniques, but it's frustrating and difficult at times. 

So you know, apart from editing, compiling and debugging the tools are in great shape. I'm not an idiot, and I am deeply impressed that Chris and the rest of the Apple team have come this far in such a short space of time since beta 1, but there is still a way to go and to ignore that would be fool-hardy. 

Conclusions

Overall, it was a pleasure. Of course I've need to work in other languages during the period, and Swift has managed to make all of them (strangely with the exception of JavaScript) feel heavy and cluttered (especially Java). The tooling issues are an annoyance, and they have cost me hours of time. However, overall my feeling is that it has taken me less time, not more, to develop the app, and that it is more stable as a result. I have been able to focus on the functionality, when I have had to spend time on other projects it has been easier to settle back in to Yearn, Swift leaves your logic exposed and readable. 

That has to be a major win just 6 (ish) months after the release of a brand new language. Here's to the future. 

 

 

Swift Access Control - I don't need protectin'

There has been a lively debate about the absence of protected (or some other keyword) in Swift (David Owen's stands out as a reasoned request and Apple's response (oh and can we take a minute to enjoy the fact that there actually is an Apple response?)). In short, I find Apple's arguments compelling. They can be distilled into two simple points (there is a third about potential complexities around extensions, but I think these are less compelling and their job to solve)

  • Protected conflates access control with inheritance, making access control harder to reason about
  • It offers no real protection... you can just sub-class and provide public thunking methods

As a Java from 1.0... I have to say I agree with these two points. I've seen 100's of cases of people working around protected, allowing something that was supposed to be restricted to an expected small set of sub-classes to become a dependency throughout a large code base. 

Protected provides a perceived safe middle ground... I can expose it, but consumers can't abuse it. It stops me making a real decision... should this be available to all, just to those working within the module, or just this one class? At the end of my time as a java developer I had come to the conclusion that things would either be public, private or package private. Sound familiar? 

There are certainly times I would have liked to make something protected. I would like to make the class less complex for consumers (driving me towards private), but enable re-use by sub-classers (driving me towards public). Do your-future-self a favour. Make it private if you intend the class to be used outside your organisation. Within your organisation, make it internal.

Swift Beta 4 Updates

Superb list of updates from Apple, here's a summary

  • Access control: Private (same file), Internal (same module, default), Public (anyone)
  • Improvement to range iteration (stride()). More to come in subsequent releases
  • final, lazy, optional and required all lose the @ prefix, more to come later
  • Comment "landmarks" //TODO: //MARK: //FIXME: also listed in the jump bar
  • Fixes to unicode string iteration (phew)
  • Complete Swift language supported in REPL

There's some more, but these are the real highlights. I have to be honest, best update yet. Love how this language is evolving and maturing in front of us. 

 

Comment

Swift Studies

Nigel has been developing software for over 30 years. Starting with the ZX Spectrum and moving through the Commodore 64, Amiga, the Windows PC area and for the last 6 years the Mac.

Interactive Swift Tokenizer Definition and Testing

Just a quick post showing the latest OysterKit example project with interactive Tokenizer example that allows you to define your own Tokenizer and build/use it straight away!


Comment

Swift Studies

Nigel has been developing software for over 30 years. Starting with the ZX Spectrum and moving through the Commodore 64, Amiga, the Windows PC area and for the last 6 years the Mac.