SE-0250: Swift Code Style Guidelines and Formatter

(Matthew Johnson) #63

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
(Matthew Johnson) #64

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
(Tony Allevato) #65

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
(Matthew Johnson) #66

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
(Tony Allevato) #67

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
(Matthew Johnson) #68

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
(Chéyo Jiménez) #69
  • 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
(Paul Cantrell) #70

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
(Paul Cantrell) #71

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
(Matthew Johnson) #72

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
#73

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
#74

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
(Boris Triebel) #75

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

7 Likes
(Goffredo Marocchi) #76

The more I read this thread and the discussion it is generating, the more I am moving towards a -1.

It feels a bit swatting away prior art, apparently disregarding what brought success to tools like SwiftFormat over the years (sensible defaults, lots of configurability, etc...), and trying to impose on a not newborn language an “opinionated” (which many times it means not very flexible, taking decisions, owing no justifications) style guide and default formatted tool. The SwiftPM evolution over time is quite an apt experiment

I see the LSP work and any major improvements over SourceKit/SourceKitten or new libraries that could make the code of existing or new linters easier (and support of more IDE’s easier too) as more useful to the community than enabling the hope that “something close to the style I like may be chosen and this will help me settle team disputes” will actually happen and have the mother of all bike-sheddings and people will still be angry.

I apologise if I offend anyone there saying this and it may be just a stupid rushed feeling, but it is just that sometimes this discussion reads a bit like “guys this is what is happening, unless really everyone is really mega super against it... so just FYI”.

7 Likes
(Šimon Javora) #77

Same here. Thank you for so clearly stating what would have taken me a much longer post.

6 Likes
(Rudolf Adamkovič) #78

+1 from me; I would love to see an official (ideally non-configurable) formatter for Swift a là ”gofmt” and “elm-format”.

(Karoy Lorentey) #79

I'm hugely in favor of introducing a single official style guide for Swift code, and of adopting a single tool to automate code formatting.

The tool should have a minimal set of configurable options -- preferably none.

(The maximum line length is perhaps the only reasonable option. I yearn for a world where all code editors/viewers would follow guidelines when automatically wrapping lines that don't fit in the display window, so that we need not set an arbitrary limit -- alas, we aren't there.)

The tool should not come with its own source-level markup syntax: it should not be possible to disable formatting for particular sections in source files.

The specific formatting details are irrelevant, as long as the choices are sensible and consistent with existing influential bodies of code, especially the code samples in the official Swift documentation. People learning Swift get intensely familiar with the code sample style exhibited in the docs; major deviations would hurt chances of adoption.

Any new coding style feels intensely weird and obnoxious at first, however well-considered. But as soon as we get used to it, it becomes the new Obviously Correct style, and any deviation will feel like an outrage. I have personally felt this many times over my carrier: I have used (and I've got used to) tabs and spaces, many variations of the Allman style, the K&R style, and even the official GNU coding standards. I've lived with and without spaces and newlines at perhaps every possible position. Each of these stylistic arrangements felt completely natural after a short adjustment period. Almost all of them had something to love about them -- some unique practical advantage, or a particularly beautiful aesthetic arrangement. The human mind seems driven to find these superficial points and attach disproportionate value to them. However, at the end of the day, the differences are trivial, and they are a needless distraction. I find arguing about formatting minutiae intensely boring; it's an extraordinarily unproductive way to spend time.

At the same time, formatting details do matter when working in unfamiliar codebases. While working on Swift issues, I regularly need to work with Other People's Code, and I find projects that use peculiar styling conventions to be definitely more difficult to read and understand. The shock of a new style hits immediately, and I may not have time to get used to it before switching to another project.

Stylistic differences have a way of fracturing communities -- at minimum, they are an obstacle to cooperation; at worst, it leads to a divisive "us vs. them" mentality. I feel it's important that we as a community come up with an official set of guidelines. The official Swift repositories should then lead the way in adopting it for all Swift source that they contain, and strictly enforcing it in all new contributions.

I believe the official coding style should not be written by a committee, or developed as a series of formal votes on specific points. It should not be a mishmash of unrelated random decisions, or an unlovable mess of mutual compromises. It should be tastefully designed, strongly opinionated, unambiguous and self-consistent. It should also be a boring formalization of some preexisting rules, with no radical new formatting innovations.

To prevent endless discussions on what the official coding style should be, I would be in favor of appointing a single person to serve as the Editor / Emperor in charge of the official coding style proposal. (To be clear, I definitely aren't volunteering myself.) The editor's role would be to cut off arguments about specific points before they get out of hand, to carefully consider the points made, and to update the draft guideline with a binding decision, allowing the discussion to progress to some other detail.

24 Likes
(👑🦆) #80

I'm -1 on this.

I very much like that there's a good formatting tool (really - Hallelujah!), but I think we should refrain from blessing anything as being "official". Since it's all optional anyway, what really is the benefit?

We can ship the tool with the toolchain as a convenience (maybe configurable if we feel like it -- if the developer doesn't like it, they can always use their own tool), and the default rules can become a de-facto standard for those who don't care to customise them, but I don't see the benefit in saying one style is somehow "better" or "official", but also not mandatory.

It just seems like a totally artificial distinction to me. I want the tool, but don't tell me my code is somehow inferior or non-standard because I like to place curly braces or case statements differently to how you like it. If the compiler can understand it, it is de-facto valid Swift.

13 Likes
(Tino) #81

I'm suprised that there isn't already an official style for the official Swift repositories, and wouldn't speak against it — but this proposal is more and less at the same time:
It aims to affect all Swift code out there (not only a single organization); and it explicitly says that it doesn't want to enforce a single style, so there will still be stylistic differences with all their downsides.

I don't think anyone can actually claim to be qualified for this task, but I agree that this would be the only good process. I consider this to be another argument against the proposal, which would incorporate an existing formatter with existing defaults — and afaics any change of those would need to pass the full Evolution process (imho that basically means there won't be any fundamental changes of the original style).

1 Like
(Karoy Lorentey) #82

The compiler will still accept code bases with coding styles deviating from The Standard.

Programming communities tend to spend untold amounts of energy on endlessly rehashed bickering over petty formatting details. If the introduction of an Official Style Guide would direct some of that energy to go towards encouraging people to adopt it, then that would be a great outcome in my book!

Some poor soul needs to be appointed by the core team. Any veteran Swift programmer with a calm demeanor, an open mind and a modicum of good taste would do. Those who volunteer for the job on their own should be automatically disqualified.

If it was up to me, I'd personally nominate someone who worked on the Swift programming books.

6 Likes