Swift bracing

By convention, Swift embraces the “One Truce Brace Style” or 1TBS as its standard for laying out code. A variation of K&R bracing, 1TBS adopts the following features:

  • Opening braces appear at the end of the statement that establishes a clause
  • Else statements appear between paired close and open braces
  • All clauses are braced. Single-line clauses use mandatory bracing, just like multi-line clauses. Bracing ensures that all code line insertions will be safely added, and cannot break the intended flow.

A typical Swift if-statement looks like this, incorporating the 1TBS features listed above.

if let value = key {
   // ...do something
} else {
   // ...do something else
}

Xcode automatically styles code using 1TBS and Apple’s sample code and standard library use it as well. Despite this, you can easily override Xcode to incorporate Allman style, also known as “BSD style”.

Unlike 1TBS, Swift Allman wraps its opening brace so there’s always a clear visual path between opening and closing braces. Here is the Allman adaptation of the if-statement you saw previously.

if let value = key
{
   // ...do something
}
else
{
   // ...do something else
}

You can easily trace each opening brace to its closing partner and the else statement sits on its own line.

I mention Allman because Swift is not a language demanding vertical compactness. Clarity and safety should always win over succinct form.  Apple writes,

Clarity is more important than brevity. Although Swift code can be compact, it is a non-goal to enable the smallest possible code with the fewest characters. Brevity in Swift code, where it occurs, is a side-effect of the strong type system and features that naturally reduce boilerplate.

It’s a shame then that the language has adopted 1TBS over Allman when the latter exposes scope so beautifully and the former can be quite hard to follow, especially with respect to complex declarations that include external and internal labels, default values, and other complicating features:

Compare this example in 1TBS:

public extension Contextualizable {
    public func BuildContextError(
        items: Any...,
        file: String = (__FILE__ as NSString).lastPathComponent,
        function: String = __FUNCTION__,
        line: Int = __LINE__
        ) -> CoreError {
        
            let reasons = items.map({"\($0)"}).joinWithSeparator(", ")
            let context = "\(function):\(self.dynamicType):\(file):\(line) "
        
            return CoreError(reasons, context)
    }
}

with its Allman counterpart.

public extension Contextualizable 
{
    public func BuildContextError(
        items: Any...,
        file: String = (__FILE__ as NSString).lastPathComponent,
        function: String = __FUNCTION__,
        line: Int = __LINE__
        ) -> CoreError 
    {
        
        let reasons = items.map({"\($0)"}).joinWithSeparator(", ")
        let context = "\(function):\(self.dynamicType):\(file):\(line) "
        
        return CoreError(reasons, context)
    }
}

The Allman example simplifies the layout, making it far clearer where each declaration (Contextualizable, and BuildContextError) begin and end.

Swift’s worst bracing sin actually appears in switch statements (although get and set for properties are also not without sin). Left-aligned cases and defaults make its switches a horror to scan.

switch item {
case "B", "C", "D": print("Hello")
default: print("World")
}

Bracing also plays an in-line role due to Swift’s functional programming support. An in-line map can appear with or without parentheses (I use the Rule of Kevin, which supports parens) and with or without in-brace padding.

This example skips that padding:

items
    .map({"\($0)"})
    .joinWithSeparator(", ")

This example uses padding:

items
    .map({ "\($0)" })
    .joinWithSeparator(", ")

I am currently leaning (slightly) towards the padding side of things although my personal style to date has not incorporated it. This example also uses indented dot-prefixed fluent chaining, although that’s probably a better subject for another post.

 

27 Comments

  • Allman is an unholy abomination and must die, die, die. 🙂

    In all seriousness, it pushes code way down the page. It makes it common to have to scroll down to see code. And I don’t see how the blocks of code are any clearer.

  • Although I prefer Allman, I can live with K&R. I absolutely can’t stand “} else if (…) {“.

    I agree wholeheartedly with your position wrt left-aligned switch statements.

  • I absolutely agree that every colon of a switch must be followed by newline.

  • Allman Is ugly. It’s also a bit idiotic. If you want additional white space, simply put an extra blank line in the appropriate places.

    • @h4labs

      I saw someone do exactly what you describe in response to Allman style while he was clearly more of a K&R or 1TB habituated coder and it actually annoyed me a lot that I sometime give it as a bad example. 😉 — Then I understand why he did it even if I don’t “like it”.

      The reason lot of people like Allman style is that they like the fact that opening and closed symbol (braces) are visually aligned. That way, they can scan easily the beginning and end of a block (without having to read the code details for example). It is not about creating “space” around the code. See it as à big block of code that can have brace or not, multiple statements or not.

      There is pros and cons to everything. Coding style included. I can or try to understand that even if I may have preferences.

      Try for a month with good will it might be intersting, then let’s see how you feel. I would be curious.

  • There is a reason its called the one true brace style, it will have no other brace styles before it.

  • I am a mutant. https://github.com/bustoutsolutions/siesta/blob/master/Source/Support/WeakCache.swift

    But in my defense: indenting the braces the same as the code they surround reduced visual noise by creating a single clean line down the entire length of a block of code. I learned C that way circa 1990 and still go back to that style when I’m writing code for myself.

  • When in doubt, go back to basics. Read code as if it were a set of English statements. If you do this, it becomes obvious that Allman has big issues. It’d be like writing the following, complete with the blank lines:

    if something is true
    then
    …do something

    otherwise

    …do something else

    Yuck. It doesn’t make much sense.

    Compared to:

    if something is true then
    …do something
    otherwise
    …do something else

    Of course, both are infinitely superior to coding crimes like:

    if(something is true)then do something
    otherwise do something else
    otherwise etc.

  • I resepect you, and your books are nice, but Allman is stupid and must cease to exist!

  • What Erica meant to write when showing off 1TBS: https://gist.github.com/verec/dfd220d0751f3f74d702 🙂

    BTW, method names, in Swift, never ever start with an uppercase.

  • What I really want is a code editor that shows me either 1TBS or Allman (whichever I decide) regardless of how it’s been typed by someone.

    And to those who use the word ‘stupid’ and ‘Allman’ in the same sentence, might I suggest that you stop the name calling. We all think and perceive in different ways. Just because your brain works one way and the next guy’s work another doesn’t make one way right, wrong, stupid or smart. In fact, I think my idea of having a button in the code editor to switch it gives us the best of all worlds. Maybe you use 1TBS by default, but once in awhile, you want to see the structure in a different way, so you hit the Allman button and see clearly where you’ve missed a brace.

  • Allman fan here. The code is easier for me to follow, and that’s what I find most important. I don’t mind scrolling a bit more. My retina display can show many characters at once and my multi-touch trackpad “scrolls like butter.” If your classes/methods are too big, then they’re probably doing too many things and should be refactored into multiple, smaller chunks.

  • I started with 1TBS at the end of the 90’s and four years ago changed to Allman Style. Reason? Visual clarity. I recommend everybody use Allman for one day.

  • Have my own style which sits midway between these two extremes, and I’ve been using it since I was a Perl developer, then JavaScript, then Objective-C.

    Basically, opening brackets are on the line end, unless the opening statement itself is multi-line, in which case the opening bracket sits on it’s own line too. Else statements always sit on their own line too.

    I find this style maintains compactness but allows for clarity when it’s really essential.

  • […] Erica Sadun: […]

  • I honestly can’t stand Swift syntax whole cloth, so I fail to see the point where dredging up this old argument when there are question marks and exclamation points just littered everywhere. ?

  • [i] easily override Xcode to incorporate Allman style[/i]

    Pardon my ignorance, but is this a preference? I can’t find any such thing.

    • You put the cursor before the { and press return, overriding Xcode’s natural 1TBS disposition to incorporate Allman

      • Ha OK, I was hoping there might be something a little more automatic. I already do what you described 🙂

  • Why is this even a question these days? It’s white space. The code is being parsed constantly with every character stroke to show syntax with not just indentation but color coding for various keywords, constants, etc. How many years has Xcode had the ability to let a user specify which color to use for the different categories? Why doesn’t Xcode have settings to let each user specify how they want to see the white space formatted in their editor regardless of how anyone else wants to see it in their own editor?

  • At my job, we had a horrible bug that took three people two weeks to find, which occurred because a programmer who edited an Allman-style file and failed to notice that an ELSE occurred on the line beneath what he thought was a complete IF statement. I believe the brace was the last visible line on the screen, and he didn’t scroll down to see if anything followed. Because the new code he added also ended with an IF, the whole addition compiled just fine–but now the ELSE corresponded to the wrong logical test. Fixing the bug was easy, but finding it was annoying and expensive, and the whole thing would have been avoided by just keeping “} else {” on the same line. I use 1TBS because it’s safer.

    • This is a great story. And not only is `} else {` _safer_, it simply makes sense. There is no such thing as an “else statement” so placing `else` on the next line following the if-statement is in a real sense wrong. Doing says that the program author does not feel that the textual structure of the code should match its internal structure, which is a shame.

    • Hmm I cannot get your story. Is it still a problem in Swift?

  • Allman fan. I despise the starting brace at the end of the line because my eye tracks the starting and end brace, and don’t get me started on people that don’t respect indentation.

    Looking at 1TBS code gets me anxious because some people try to be clever and not indent properly, so instead of seeing what should be two indents for two if statements, some yahoo instead makes it one indent for BOTH if statements. So now I have to do extra work because I don’t trust that people do the right thing™. Tell me again how 1TBS is safer? At some point I have to do a search for ‘{‘ because of someone’s laziness in indenting properly.

    You should see the code my coworker does on PHP. No respect for indents. If a function started on indent 2 (let’s say..4 ‘spaces’ per tab), he’ll randomly put lines of code willy-nilly on column 0, column 3, column 7. Try looking at that with 1TBS.

    As for “it takes up too much space”, these aren’t the 80s anymore. Nobody’s printing on paper anymore and retina displays exist.

    And there’s nothing “idiotic” about Allman. For me, it’s about visual alignment, not saving trees.

  • Allman fan as well here – well at least I believe that I should have a choice. For us here in an enterprise organisation when we are reviewing other peoples code – it’s easy to scan an Allman code quicker than 1TBS – plus I hate being told what to do because of a choice made by the creator of an IDE or language. I still have nightmares from doing COBOL at Uni – in those days you had to have stuff in the right COLUMN – this smacks of that for me. The compiler should not care HOW I format the code as long as it’s parsable – how it looks on the screen is for me and my team.

  • Allman for clarity, every time. So much clearer, in fact, that I find myself questioning the sanity, morals and character of anyone who advocates K&R. Yes, I’ve encountered a few lost souls along the way who didn’t know any better – one of which felt ‘liberated’ (his word) by switching to Allman. Don’t try and defend the indefensive, K&R fans, don’t forget: Kernighan and Ritchie were only saving print costs, they never meant for *this* to happen.

  • “Xcode automatically styles code using 1TBS and Apple’s sample code and standard library use it as well. Despite this, you can easily override Xcode to incorporate Allman style, also known as “BSD style”.

    How? I loathe 1TBS and with utter OCD turn every code file into Allman with padding before I even attempt to read the code properly.

    So how do I make Xcode 8 do this by default?