Archive for January, 2016

Sorting and sharing playground pages

Sorting Playground Pages

If you keep a lot of playgrounds on hand in a single file (I do!), you may find it handy to sort your pages alphabetically. Use Edit > Sort > By Name to clean up your organization.

Screen Shot 2016-01-04 at 10.07.27 AM

Hopefully you’ve named each page logically, for quicker scanning.

Screen Shot 2016-01-04 at 10.08.16 AM

Unfortunately, as you add pages to playgrounds, Xcode performance takes a massive hit. While you can re-order by dragging, that starts to become impractical once you hit a couple of dozen playgrounds.

Copying Playground Pages

It can be simpler just to drag copies of a page into a new workspace with better performance. This screenshot shows dragging the “adding arrays” page over to a new playground file.

Screen Shot 2016-01-04 at 10.18.15 AM

You can also open a playground package (Control-Click/Right-Click > Show Package Contents) and access individual source files however you like.

Screen Shot 2016-01-04 at 10.22.04 AM

You cannot drag and drop these between packages unless you’re willing to start editing the contents.xcplayground XML. It’s not difficult, but it’s generally not worth your time.

Instead, consider opening the page in a text editor, and using copy/paste into a new page you manually add to another playground.

Searching Playgrounds

Xcode offers two search fields to help you locate material. The bottom search bar matches page names:

Screen Shot 2016-01-04 at 10.15.09 AM

The search at the top of the navigator finds matching text.

Screen Shot 2016-01-04 at 10.13.47 AM

Searching Playgrounds from the Command Line

A while back, I wrote pggrep to find playground files, which were not otherwise indexed by spotlight. Given how much material ends up in playground testbeds, pggrep has been a valuable tool for finding where I had explored some topic or another in the past.

Book

There’s also a book on all things Playground.

Another take on guard

Today, iOS Dev Weekly pointed to this writeup by Alexei Kuznetsov about eliminating guard from your code. “Why Swift guard Should Be Avoided” posits that Robert C. Martin’s rule of code parsimony (namely, “The first rule of functions is that they should be small. The second rule of functions is that they should be smaller than that.”) should drive your Swift output.

Kuznetsov writes, “The guard statement is a handy instrument for reducing the number of nested structures in functions. The problem lies not in the instrument itself but in its usage. The guard statement promotes the creation of bigger functions that do several things and act on multiple levels of abstractions. By writing small and focused functions, one can find herself not needing the guard statement at all.”

I’m sharing this article because I courteously disagree with this philosophy and I want to explain the factors that motivate my disagreement.

The Code

In the following snippet, Apple’s original example from the Swift Programming Language book designs a virtual Vending Machine. Its  vend function enables the machine, on successful payment, to dispense an item to a consumer.  If my math is right, the original function included 17 18 lines of code (lines 25-42). This count includes three original guard statements, and four action statements, along with surrounding whitespace:

Kuznetsov refactors Apple’s tutorial vending machine code to eliminate guard statements and minimize each function’s statement count. With respect, I’m not a fan of this refactor. And I want to explain why.

The refactor is too long and complicated.

Kuznetsov primary goal is to promote small function size. However, the refactor has replaced those 17 18 lines with 46, splintering the logic around no fewer than eight separate functions.  In doing so, the update introduced a high cognitive overhead. A simple linear story became a tangled  collection without clear task progression.

In the rewrite, seven dependent calls follow the new vend function. They must be read by moving your eyes and attention down and then up and then down again in order to comprehend the flow as you imagine a user pressing the vend button.

Kuznetsov took one unified function and splintered it. I’m going to quickly throw out a reference to George Miller’s “Magical Number Seven” here not just because eight is significantly larger than one but also because Martin’s rule of functional simplicity attempts to achieve a similar kind of focus, and I think this refactor misses the mark on addressing both concerns.

The refactor treats preconditions as separate tasks

This is the more substantial criticism, which is the misunderstanding of the role of guard. In Kuznetsov’s write-up, guard acts only to reduce nesting. I disagree, and as I pointed out in my write-up the other day, it is an important member of the assert/precondition family: “A general guard statement establishes requirements for execution. It also provides a safe path for transferring control if and when those requirements fail.”

In Kuznetsov’s redesign the assertions are subsumed into a validation tree. A primary function validateItemNamed calls validate. In turn, validate collects calls to each validation step, namely validateCount and validatePrice. I propose that this tree-based layout is hard to read, hard to maintain, and introduces unnecessary complexity.

You must trace the progression of the point of error back to the original try vend call. Insufficient funds that fail in validatePrice travel back to validate, back to validatedItemNamed, and from there fail in vend. It’s a long path for an extremely simple error and it inappropriately separates the validation tasks from the usage tasks.

In Apple’s version, the three guard statements limit access to core functionality by performing sanity checks on input and state before proceeding. Importantly, they act as formal specifications about code prerequisites. By including guard statements with the code they annotate, Apple established a direct relationship between the assertions and actions. The code says, in essence, “if these tests pass, perform these actions.”

Their co-location is vital. At some future code review, these tests can be inspected in the context of the actions and if needed, updated, modified, or removed with ease. Their proximity provides a vital connection to the code they’re guarding.

I would recommend using guard for essential code safety checks. I believe they’re being presented this way in Apple’s version of the vending machine code. To summarize: You may be able to write your way around guard but your code will not benefit from doing so.