SE-0250: Swift Code Style Guidelines and Formatter

  • What is your evaluation of the proposal?

    +1 -- The proposal doesn't force any use of the style but I believe having a style and tool that people can choose to ignore if they want is better than not having any at all

  • Is the problem being addressed significant enough to warrant a change to Swift?

    Yes -- Its a problem in most languages where no style guidance is proposed, everyone has their slight flavour which causes the issues described in the proposal

  • Does this proposal fit well with the feel and direction of Swift?

    Yes -- Swift, while not a simple language, is striving to make itself more accessible to a wider audience. Having taught the language to a number of people now, there is generally an issue of not understanding where spaces go, alignment of colons etc. Having a guide for this and a way to force the style if needed, helps newcomers to understand the code quicker.

  • If you have used other languages with a similar feature, how do you feel that this proposal compares to those?

    Not in a position to answer.

  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

    Read through some of the original thread (it was massive so not all of it), and read through the proposal.

1 Like

I really like how the Dart team did that.
Probably we can have a look:
dart_style
Effective Dart: Style

2 Likes

What is your evaluation of the proposal?

I’m in favour of it.

Is the problem being addressed significant enough to warrant a change to Swift?

Yes. The amount of time spent discussing style issues is huge and could be better invested somewhere else.

Does this proposal fit well with the feel and direction of Swift?

Yes, since Swift tries to be an opinionated language.

If you have used other languages with a similar feature, how do you feel that this proposal compares to those?

I’ve written some code in Elm that has an official, non-configurable formatter (elm-format). I wasn’t perfectly happy with the formatter, but at the end of the day I prefer having common code style rather than having the formatting just my way. I’ve also created a poll to see how the Elm community likes the formatter – TLDR they do. (Caveat: Elm is a much simpler language, so I’m not sure how much the reasoning applies.)

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

I’ve tried to read as much of the discussion as humanely possible. And read the proposal, of course.

2 Likes

I'm neutral on the idea of having an official style guide and formatter. If this proposal is adopted however, I would prefer that the implementation be a somewhat configurable formatter, or if not configurable, one that only dictates a few things, while leaving more complex rules to a more powerful linter.

2 Likes
  • What is your evaluation of the proposal?

Huge +1 from my side.

  • Is the problem being addressed significant enough to warrant a change to Swift?

Yes, too much time is spent in discussing style and formatting. Developers shouldn't spend time in getting used to a new style every time they switch company or project, so I hope we can reach a point where most of the projects will simply follow the Swift Code Style Guidelines. This step would save up an enormous amount of workload both when writing and reviewing code. I think it makes sense for some dedicated people that are willing to invest time in this task to improve the future developer experience for the whole community.

  • Does this proposal fit well with the feel and direction of Swift?

Yes, it does.

  • If you have used other languages with a similar feature, how do you feel that this proposal compares to those?

I wish every language would have default style guidelines. Developers shouldn't spend time in evaluating multiple tools and configuring them, just give them what they need to do their work well.

  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Read the original pitch and proposal as well as the updated pitch and this discussion thread.

1 Like

I think this meta-proposal doesn't answer enough questions. But I certainly have concerns.

The ability to blend imperative, functional and mini-DSL styles is one of the biggest strengths of Swift as a modern hybrid language. Swift is not a minimalist, one-size-fits-all language like Go; pursuing a single global style would be a bad move and readability would suffer. Consider...

// Declarative
let myModel = MyModel(
   Configuration(
      a
   )
)

// Imperative
let myTableCell = MyTableCell()
myTableCell.configure(a)

// Reactive/fluent
let myDataStream = MyService()
   .configure(a)

The differences between these is not purely formatting but formatting is an essential part of each style. Having these multiple coding styles in one codebase helps. It communicates design patterns and intent through visual structure, even when there are no differences in the syntax or types involved.

And look, maybe the planned scope of swift-format is just to fix the most glaringly obvious mistakes like accidental double spaces or missing spaces around braces, while not really doing any reformatting of statement structures. In that case... whatever.

But if swift-format dooms pattern-specific styles like these, it will be a serious loss to readability.

27 Likes

Thank you for bringing up this excellent point and those examples—it's something that we've put a lot of thought into. I personally do the same thing; my Package.swift files look more like your declarative example, but I would never break regular function calls that way.

The same thing can happen at a finer granularity, too. For example, even if the following wrapping would fit within the column limit:

let bounds = CGRect(
  x: someValue, y: otherValue, width: theWidth,
  height: theHeight)

It would be totally reasonable for someone to want to group the arguments like this instead:

let bounds = CGRect(
  x: someValue, y: otherValue,
  width: theWidth, height: theHeight)

swift-format handles that today by respecting existing line breaks that the user has already placed in their code, anywhere that a break would be permitted in an automatic line-wrapping situation. All three of your examples would be valid and remain untouched.

So, while we could envision a stricter approach that would canonicalize formatting by ignoring line breaks and compacting what the user has written, the examples you gave provide ample reason (IMO) that we should respect those choices.

10 Likes

Actually, it looks like a tool that is still in the early stages of development which has yet to reach a state that I would consider useful given the competition (if the output example in the NSHipster article is representative of overall tool behavior).

I am very appreciative of the effort Tony and his team are putting in and agree in theory with their choice of implementation strategy assuming that strategy doesn’t run into difficulty in the face of concrete requirements.

That said, the tool portion of the proposal really looks like it is a request to bless Tony and his team as the “core team” of the Swift formatting tool and adopt their code as the basis for development of a tool that will eventually become the official formatter (after the recommended style guidelines are accepted). That is an unusual request for SE and is not how the proposal is actually worded. Maybe that’s ok, but it is much different from reviewing a tool that provides an actual implementation of concrete requirements. I think it’s important to be clear about what the community is actually being asked to accept.

I agree with everything @Matt_Gallagher has said above. It provides some concrete examples of why I said in the pitch thread I would be opposed to an unconfigurable formatter even if it implemented my current style preferences. Occasionally new contexts require new idioms. It would be extremely troublesome if our style guidelines and formatter get in the way of creating new idioms (where appropriate). This is a very legitimate concern that should be taken seriously as we consider specific style guidelines and tool configurability.

I think it’s also worth pointing out that Swift has more syntactic complexity than the languages I am aware of that have had succes with standardized formatters. I think it is unlikely that its syntactic complexity and idiomatic diversity can be well served by a single set of style guidelines.

There are legitimate trade offs to be made in choosing a style and I don’t think it’s reasonable to expect everyone to accept the same trade offs. In the NSHipster article we see that most of the tools choose to prioritize saving vertical space over a consistent application of line breaks in comma separated lists while prettier chooses a simple and consistent rule: when a line break is necessary in comma separted list, each entry appears on its own line and indentation follows the conventional rules almost everyone uses for multi-line collections.

(An important observation here is that these are fundamentally different formatting algorithms: you can’t just provide simplistic configuration options like line length and indentation width. You actually need to support multiple line wrapping algorithms and allow users to choose between them.)

There are legitimate reasons why a team would prefer each of these styles and there is not a compelling reason to “recommend” that all Swift teams adopt the same style in this area. At the same time, it is best if every team chooses one of these styles and uses it consistently and we want a formatting tool to be usable without requiring configuration so one of these must be the default. There is a huge distinction between having to choose a default for a tool and asserting that it is the “best practice” or recommending that every team adopt a specific approach.

I think it would be wise to recognize this difference: some decisions are less “obvious” or broadly conventional than others. It’s ok to have a default without blessing it as a “best practice” or “recommending” that teams use it.

10 Likes

I agree with this decision but I also think it’s worth pointing out that this defeats the objective many reviewers seem to have of ending style debates on teams. For example, it sounds like if I write code using the style of the Prettier example in the NSHipster article swift-format would leave that untouched. So there is still room for debate over manual formatting choices that the tool leaves untouched.

I think that’s ok (although it would be even better if the tool was able to understand some of my style rules at a high enough level to actually apply this formatting for me). However, it sounds like many supporters of this proposal may be disappointed by a solution that leaves this door open, especially if their team chooses some style rules that the tool cannot apply automatically. This is why I think configurability where legitimate and important trade offs exist should be taken very seriously. The more automation this tool is able to provide the better off we’ll be.

7 Likes

And we've considered that as well. As swift-format is implemented today, teams that are interested in having a more opinionated formatter with respect to canonicalizing line breaks can turn off that option (it's configurable).

2 Likes

Sure, although that’s a pretty heavy-handed mechanism if you don’t provide other ways to support legitimate style trade offs, idioms that require specific handling of line breaks, etc. I think it’s good to have this option - I would love to use a formatter good enough where I could accept all line break decisions made by the formatter. But I don’t think it should in itself be considered sufficient. I am willing to bet that many people arguing for an unconfigurable tool still expect to be able to adopt idioms such as the ones @Matt_Gallagher posted examples of.

3 Likes

And that's why part of the process here is to determine, if that in itself is not sufficient, what the other requirements are. That will manifest as style guidelines are discussed, and the concern about whether the implementation of the specific tool being proposed here can address those requirements is not unique to this specific tool.

Given the quite opinionated nature of code style, I hope we would agree that satisfying every Swift developer by this process is not a feasible outcome, and I'd consider it a non-goal. The best goal we can hope for is to strike balance in a way that (1) meets the needs of as large an audience as we can and (2) successfully applies whatever default style guidelines are ratified.

On point #2, earlier in the thread you asked about implementation cost/time involved if style discussions went in a direction that we didn't anticipate. I can't predict the future, and this isn't something I can objectively prove, but I'm confident in the approach that we took in our implementation to be able to adjust well to shifting needs, as it already has done during its development. Much of this is thanks to our choice to apply and extend existing code formatting research to create a generalized and parameterized algorithm instead of building something unique from scratch that might end up being unconsciously biased toward one particular style or another. (This is a hypothetical, not a comparison to or assessment of any other existing tools.)

I would also respectfully disagree with the assessment that it's in the "early stages" of development. While it's certainly by no means bug-free or complete, our testing against several non-trivial code bases (both internal to Google and external) is what led us to decide that this was the appropriate time to take it to this stage of evolution.

1 Like

Absolutely, that's why it makes sense to review and accept requirements for a tool before reviewing a specific tool. Please don't read my comments as being opposed to your team or the tool you're building. It may well be the right thing for Swift. But it's speculative to determine that right now.

Of course we will never satisfy the needs of everyone with any tool. The enormous unknown for me is how large an audience we can satisfy and what constraints determine the size of that audience. We won't be able to begin to answer this question until specific style guidelines and configuration options are proposed and reviewed.

Personally, I would find it pretty disappointing if we conclude that the audience this tool is willing to satisfy is smaller than other already existing tools can satisfy, especially if those tools were also able to correctly apply the default style guidelines.

This sounds neat!

I may have partly misunderstood and the issue is largely at the level of refining the default and available configurations. Regardless, I think it's fair to say this tool is less mature than other Swift formatters given its handling of the code in the NSHipster article. The handling of var region :String; in particular is not good regardless of what style rules are in effect.

5 Likes
  • What is your evaluation of the proposal?
    +1
  • Is the problem being addressed significant enough to warrant a change to Swift?
    Yes
  • Does this proposal fit well with the feel and direction of Swift?
    Yes
  • If you have used other languages with a similar feature, how do you feel that this proposal compares to those?
    Good
  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
    Careful reading

I’m a -1 on this whole venture for several related but independent reasons:

The stated motivation is a non-issue

I don’t find it difficult to read Swift from unfamiliar projects — or rather, when I do, it’s rarely because of formatting issues.

I don’t find it difficult to adapt myself to per-project styles.

I don’t think this problem is worth the energy it will suck out of this community.

Experience with similar tools suggests standardization won’t work

In the pitch thread, many people praised Go and Rusts’s standardized formatting.

My own most extensive experience with enforced formatting has been Rubocop, and that experience hasn’t been lovely. Unlike Go and Rust’s formatters, Rubocop is extensively configurable — yet somehow still manages never to quite fit code on the projects that use it. Its formatting rules harm readability more often than they help, and I’m often forced to make a tradeoff between writing more confusing code or the littering it with inline ad hoc Rubocop directives. A GitHub search for inline RuboCop directives gives a sense of the many ad hoc adjustments people find necessary. Rubocop is a frequent source of complaints and wisecracks on social media.

Many teams do find Rubocop a useful tool. You’d be hard pressed, however, to find somebody in the Ruby community who thinks its defaults should be an officially endorsed universal default.

Is Swift more like Go and Rust? In terms of language features, yes. In terms of language style, however, it is closer to Ruby in two significant ways:

  1. Swift has a high degree of plasticity. Like Ruby, Swift is a language that adapts to a wide range of uses and programming styles. Swift can look Java-like, ML-like, Objective-C-like, Python-like. IIRC, Chris Lattner has stated it is Swift’s explicit goal to be good for everything from systems programming to scripting to apps to code-as-configuration to ML to a beginner’s teaching language. Unlike Rust and Go, Swift projects encompass a wide array of underlying programming idioms. Its expressive flexibility is not an accident.

    It is entirely reasonable to expect that different Swift projects that use different idioms will need different rules. A “lots of operators” functional reactive style will probably want different rules about line breaks, whitespace, and expression indentation than a TensorFlow project where operators mostly appear in equations.

    (Edit: For comparison, I have worked with Elm and its autoformatter. It was pleasant. But Elm is an extremely narrow language with a narrow purpose — even a standard program structure. It doesn’t take many forms and many styles the way that Swift and Ruby do.)

    RuboCop’s high degree of configurability is necessary in a language that takes so many forms. Swift formatting rules would need a similar degree of configurability to be widely adopted — but this undermines the stated motivation of the proposal.

    The proposal’s stated goal is widespread consistency across projects. This requires two things: (1) widespread adoption and (2) narrow rules. In a language with Swift’s plasticity, these two are in conflict: any proposal that could encompass a broad enough range of Swift projects to achieve the stated goal would have to be so minimal in its rules as to undermine it.

  2. Swift gained widespread adoption before its formatting was standardized. Because of the plasticity I mention above, I’d say this is a strength of the language. Even if you are inclined to see it as a weakness, however, it’s simply the fact that developers already have tastes and preferences around which it will be difficult to achieve consensus.

    This is going to be a long, ugly slog. Which brings me to….

Forum discussion is a terrible way to decide style rules

We’ve all heard the jokes about swift-evolution’s frequent and extreme descent into bikeshedding. I certainly don’t have the stomach to wade through a 200-message chain about whether to put spaces after colons in type names. The proposed process will bring out the worst of swift-evolution — and the outcome will be determined by those few who are willing to participate in the forum at its worst.

If we do proceed down this path, I would strongly suggest that we:

  1. Use forum discussion only to nominate formatting questions, e.g. “spaces before/after colons in type names?”.
  2. Gather empirical data on how widely people use different possible style options for each question.
  3. Adopt only rules that meet some predetermined threshold in some sample set of projects.

So, for example: We nominate brace placement for standardization, and find that (say) 96% of Swift projects use K&R style, so that becomes a rule. However, we find a 60%/40% variation between var a = [String]() versus var a: [String] = [], we decide not to make a rule for it.

Open-ended forum argument sounds hellish to me. In a discussion, even a focused discussion, we will rediscover that Swift formatting is nuanced and difficult. I say re-discover because…

The proposal ignores prior art from the community

Want to know how nuanced and difficult Swift style is?

Ask @Erica_Sadun, who literally wrote the book on the subject. Have you read it? Read it. Note how many places she’s identified tradeoffs between alternate approaches instead of making a single universal recommendation.

Ask the authors of SwiftFormat and SwiftLint how many configuration rules they’ve had to add — and how many requests they get for more. They know from real experience how many conflicting demands the community will place on a formatter.

And, with all due respect, the proposal authors don’t. The fact that the proposal not only doesn’t explain how it is usefully different from SwiftFormat, but doesn’t even mention it, is a serious oversight. It even feels insulting. That’s not just about hurt feelings, though; it’s dangerous because…

Ignoring community prior art has a past record of causing harm

We have past precedent of a high-minded specification-first design-by-forum-committee tool ignoring existing open source projects: the Swift Package Manager.

SwiftPM addressed a real need — CocoaPods and Carthage are Xcode-dependent and don’t support Linux — but its approach of declaring itself the standard before it had been tempered through widespread real-world use was the wrong one.

SwiftPM is promising, exciting, full of interesting ideas. But I can’t use it in practice: it’s too immature, and doesn’t even support iOS development. There were already good, if imperfect, tools in the problem space. SwiftPM ignored them, to its detriment. I think in particular of the convoluted “pinning” debate, in which a tangled proposal and then a do-over proposal ended up arriving at nearly the exact same version locking strategy that CocoaPods, Carthage, and every other mature package manager in the world already used. The wheel reinvention by committee was painful to watch.

SwiftPM, the official package manager of Swift, despite its great promise, remains the least used — and least useful — package manager for Swift. It sucked the air out of CocoaPods and Carthage without usefully replacing them.

Let’t not make that mistake again.

This proposal is treading on community work with giant feet. It should instead study and learn from the work others have already done, and enhance — not awkwardly half-supplant — that work.

43 Likes

I feel the same. I don’t have the energy to live through the war this will unleash, and also don’t have the energy to live with the tool that results from my not having had a voice in its creation.

5 Likes

While I'm not a hard -1 on this like @Paul_Cantrell, his post articulates the concerns I have very well. If we go down this path I very much like the idea of adopting a strategy for making decisions about recommended styles that is empirical and does not involve style debates on SE. That wouldn't go as far as many might prefer, but code transformations that do not meet this empirical standard could be made available as options that can be enabled in Swift's formatting tool.

I very much agree with this sentiment.

13 Likes

What is your evaluation of the proposal?

I will be giving a piecewise evaluation; there are some parts towards which I'm generally favorable, and some towards which I'm not.

Is the problem being addressed significant enough to warrant a change to Swift?

Although there are some good ideas, I think that this issue is generally of the absolute least importance. people. This is the Oxford comma of programming.

Does this proposal fit well with the feel and direction of Swift?

As an opinionated language, probably? But I don't think that it's a good direction.

If you have used other languages with a similar feature, how do you feel that this proposal compares to those?

I have not consistently used languages with official style guides.

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

I have not followed any of the previous discussion. I'm almost certainly going to bring up boring points that have already been brought up by hundreds of people more passionate than I am.

And now, for the evaluation...

Should the Swift language adopt a set of code style guidelines and a formatting tool?

I see an impossible duality in the proposal:

  • On one hand, we ask whether the Swift language should adopt an official style.
  • On the other hand, we assert that no one will be required to follow the official style.

The second bullet leads me to ask why we're even considering the first one! Reading the motivation section, I find that the reasons offered are consistent with the creation of a formatting tool, but not consistent with the creation of a style guide:

  • Style guidelines meaningfully represent best practices only in languages where stylistic elements subtly matter. In this category, we find C and rules like "do not have identifiers that start with __ or _[A-Z]". In Swift, this possibly only extends to @objc projections, which I believe will be decreasingly important as the language ages.
  • It is entirely a tooling problem, not a language problem, that code style is difficult to set per-project in certain IDEs. I find that the concern of the mental overhead associated to switching styles is exaggerated.
  • Points 3 and 4 are about having a tool.

I am globally -1 on having an official style. In my opinion, the bar for setting one should be as high as the bar for a source-breaking change. My perception is that adopting an official style guide would be me intruding into other people's code base (on which I will almost certainly never work) and dictating changes, and the proposal does not convey arguments that make me feel that the high bar for this level of interference is met. It is a fallacy to suggest that good code looks one specific way.

I am worried that this guide will be developed overwhelmingly by abled English speakers, with accidental disregard for users that are greatly helped by certain accessibility features, or that want to use conventions that match their natural language better. I do not trust that the current Swift evolution community is diverse enough to represent these interests, and I think that it may never be.

I would be in favor of an official guide for naming public symbols, since the surface of an API is typically a relatively small amount of code, and there are benefits to having everyone on the same page. However, I'm worried that by being favorable to a style guide in general, I would be opening the door to much more sweeping changes that I would struggle to justify.

Should the Swift language have an official formatting tool?

The only way that I can rationalize the structure of this proposal is that the authors are not interested so much in having a style guide as they are in having a formatting tool within the Swift codebase, in which the style guide serves as a starting point for what the formatting tool needs to support. I'm not sure that I can support a tool whose founding point is that it creates an optional style guide. To be clear, I would like to have a very configurable (scriptable?) tool for the code bases that I work on, but I don't want it to be at the expense of other people being blamed for not writing "good Swift" (which would be an unavoidable consequence of an official style guide).

For that reason, I'm not comfortable with the Swift project having formatting tools that have been decided by committee. However, I would get behind solutions that could establish a protocol for code formatting tools that could integrate with SwiftPM, for instance. These tools would have to be independent of the Swift project.

10 Likes

For the sake of completeness: there are grave security concerns regarding having a tool that is merely specified in a SwiftPM package description run on your computer. With that said, there are also grave security concerns regarding package descriptions being arbitrary Swift, too, so it’s probably not really making anything worse than it already is.

1 Like

I am -1 for all the reasons Paul wrote in his Post above. Thanks for writing this great explanation.

7 Likes