Wednesday, July 1, 2015

Swift 2.0: Exit Early With guard

Does it surprise you that I’m dedicating a tutorial to a simple addition as the guard statement? I hope you’ll better understand my excitement at the end of this tutorial. During this tutorial, I hope to convince you that guard is anything but a redundant addition to the Swift programming language.

Minimizing Complexity

Conditionals are a fundamental component of every programming language. Objective-C and Swift are no exception to this rule. If you plan to write an application of any complexity, conditionals will cross your path, there’s no escaping them.

Unfortunately, conditionals are often the very cause of complexity. Nested conditionals in particular can lead to difficult to find bugs, hard to understand code, and easily overlooked edge cases.

To keep nested if statements to a minimum, I frequently use the following pattern in Objective-C.

The idea is to bail out as soon as possible. The if statements in the example represent a set of requirements that need to be met before the rest of the method’s body is executed.

The above example translates to the following slightly more complex equivalent.

Do you see the problem lurking in this example? We’re already nested two levels deep without having done anything interesting.

It’s easy to translate the above pattern to Swift. The syntax looks similar, but due to customers being an optional, we need to unwrap the customers argument before we can access its value.

Exiting Early

Swift 2 introduces the guard statement. It was designed specifically for exiting a method or function early. The guard statement is ideal for getting rid of deeply nested conditionals whose sole purpose is validating a set of requirements. Take a look at the updated example in which I’ve replaced every if statement with the new guard statement.

There are several things worth noting. Let’s start with the syntax.

Syntax

The guard keyword emphasizes that we are validating a requirement. We are guarding against something. In the example, we explicitly check if reachable and connected are true. If they aren’t, then we exit the method early. The point is that the syntax is more explicit about the requirements than a regular if statement.

Exit

Note that a guard statement always has an else clause. The else clause is executed if the condition of the guard statement evaluates to false. Using guard makes much more sense when you’re validating requirements.

In the else clause, you must transfer control away from the scope in which the guard statement appears. We use a return statement in the above example, but you could, for example, use a continuestatement if you’re in a loop or throw an error. Take a look at the updated example below in which we throw an error in the else clause. Note the throws keyword in the method declaration to indicate that fetchListOfCustomers(_:) is a throwing method.

Powerful

A guard statement is just as powerful as an if statement. You can use optional bindings and even the use of where clauses, introduced in Swift 1.2, is permitted. I’m sure you agree that the example is easy to understand, eliminating unnecessary nested conditionals.

Scope

An important difference with if statements is the scope of variables and constants that are assigned values using an optional binding. In the above example, the customers constant was assigned a value using an optional binding. The customers constant is accessible from the scope the guard statement appears in. This is an important detail and one of the key advantages of using guard.

Conclusion

If you thought that guard was a simple variation on Swift’s if statement, then I hope I’ve convinced you otherwise. While if statements will continue to be your tool of choice in most situations, guard has a number of advantages in certain situations. This is especially true if used in combination with error handling, which was also introduced in Swift 2.


by Bart Jacobs via Tuts+ Code

No comments:

Post a Comment