New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

There is no One True Brace Style #81

Open
Jaykul opened this Issue Mar 11, 2017 · 18 comments

Comments

Projects
None yet
10 participants
@Jaykul
Member

Jaykul commented Mar 11, 2017

There are many brace and indent styles in programming, but in the PowerShell community, there are essentially three:

  • BSD/Allman style
  • K&R/OTBS
  • Stroustroup

I've briefly given an example and explained the rationale for each below
Feel free to comment, but please vote for your favorite by using the 👍
And of course, if there's one you can't stand, feel free to give it a 👎

@Jaykul

This comment has been minimized.

Member

Jaykul commented Mar 11, 2017

Allman style

The Allman style is named after Eric Allman, who wrote many of the BSD utilities. It puts braces on their own lines, indented to the same level as the control statement, and indents statements within the braces.

This style is the Visual Studio default indenting style for C# and is the standard for dotnet, PowerShell, asp.net, and basically, all Microsoft C# projects.

enum Color
{
    Black,
    White
}

function Test-Code
{
    [CmdletBinding()]
    param
    (
        [int]$ParameterOne
    )
    end
    {
        if(10 -gt $ParameterOne)
        {
            "Greater"
        }
        else
        {
            "Lesser"    
        }
    }
}

In PowerShell, braces sometimes are not for logic or flow-control, but function more like quotes: enclosing a script-block that you assign to a variable or pass as an argument. In those cases, the brace must be on the same line with the variable or command it's being passed to, so it will look wrong among Allman style indenting.

Built-in commands like ForEach-Object and Where-Object use script blocks as arguments, and there are a number of modules which emulate a sort-of DSL (Domain Specific Language) that require it as well, most prominently, Pester, which is shipped in Windows with PowerShell. Since most PowerShell coders who care about style are writing tests using Pester, the Allman style has had a disadvantage -- particularly since at PowerShell's beginning, Allman style didn't work for code you might want to type or paste into a command-line prompt.

@Jaykul

This comment has been minimized.

Member

Jaykul commented Mar 11, 2017

K&R (One True Brace Style variant)

K&R is named for Kernighan and Ritchie, who used it in their book The C Programming Language. According to Wikipedia it originated in Kernighan and Plauger's The Elements of Programming Style and Software Tools. It puts braces on the same line as control statements.

The One True Brace Style is the K&R style with every braceable statement always having the brace on the end of the line. The original K&R puts braces for functions on a new line, and gave you the option to leave off braces for one-line statement blocks (which you cannot do in PowerShell).

enum Color {
    Black, 
    White
}

function Test-Code {
    [CmdletBinding()]
    param(
        [int]$ParameterOne
    )
    end {
        if (10 -gt $ParameterOne) {
            "Greater"
        } else {
            "Lesser"    
        }
    }
}

The primary argument for OTBS is practical: when code is written following this style, new lines of code can be inserted between any two lines with no risk of accidentally breaking the code by separating braces from their statement blocks.

In PowerShell, this argument initially gained many adherents, because prior to the arrival of the ISE in PowerShell 3 and later the PSReadLine module, it simply wasn't possible to put most braces on a new line when typing them into the console, and this was the only place you could type that knew anything about the language! The console expected a single line of PowerShell, and would produce errors if, for instance, you didn't put a { at the end of the line after an if(...) block.

@Jaykul

This comment has been minimized.

Member

Jaykul commented Mar 11, 2017

Stroustrup

Named after Bjarne Stroustrup, who created it while writing his Programming: Principles and Practice using C++ and The C++ Programming Language, this style is a long time favorite of those who learned C++ as their first language. It is essentially a variant on K&R discussed earlier, with some variations: "else" blocks are placed on a new line. Unlike the OTBS variation, it follows K&R's suggestion that although the opening brace for a class and a struct are not on a separate line, for a function it is. It also allows skipping the braces for single line statements, but that's not allowed by PowerShell's parser.

enum Color {
    Black,
    White
}

function Test-Code
{
    [CmdletBinding()]
    param(
        [int]$ParameterOne
    )
    end {
        if(10 -gt $ParameterOne) {
            "Greater"
        }
        else {
            "Lesser"    
        }
    }
}

The changes Stroustrup makes means that this style looses the "insert a line anywhere" feature of OTBS, and looks somewhat like a cross between Allman and OTBS.

@Jaykul

This comment has been minimized.

Member

Jaykul commented Mar 11, 2017

It appears to me that PowerShell advocates of "Stroustrup style" don't actually care for anything he says except having the else on a new line. Other than that, they want to follow OTBS. If that's true for you... vote here instead of there ;-)

@Jaykul

This comment has been minimized.

Member

Jaykul commented Mar 11, 2017

P.S. As a side note (and I will brook no discussion on this): spaces won. In this guide, an indentation level is 4 spaces.

For thoroughness, I reviewed C, C++, BSD, Linux kernel, Google's JavaGuide and the dotnet, asp.net, and PowerShell guides -- they all use spaces, except the Linux Kernel. Google's Java guide uses 2 spaces. All of the others use 4 spaces.

The kernel coding style guide, being written by a dictator who still codes in a terminal, not only requires tabs, it specifies tabs as 8 characters, limits line length to 80 characters, and considers anything over 3 levels of indent to be a design flaw. It also refers to K&R as prophets, and to those who disagree with K&R as heretics, and considers the violation of naming conventions a "shooting offense" ...

@Jaykul

This comment has been minimized.

Member

Jaykul commented Mar 11, 2017

P.P.S. The Linux Kernel advocates for the pure K&R indentation style, with neither the OTBS variation forced upon PowerShell in the early days, nor Stroustrup's lonely else, in defense of this difference between function braces and everything else, they write:

Unlike the indent size, there are few technical reasons to choose one
[brace] placement strategy over the other, but the preferred way, as
shown to us by the prophets Kernighan and Ritchie, is to put the opening
brace last on the line, and put the closing brace first ...

Heretic people all over the world have claimed that this inconsistency
is ... well ... inconsistent, but all right-thinking people know that
(a) K&R are right and (b) K&R are right. Besides, functions are
special anyway (you can't nest them in C).

This was the best defense I found for that oddity of K&R's bracing style.

Obviously in the C# and PowerShell world, K&R are not considered "prophets" and the Allman style prevails -- but additionally, it's worth pointing out that functions are not special in PowerShell: they can be nested.

This may be sufficient reason for the PowerShell variant of Stroustrup's variant to choose to treat the braces for functions the same as other braces (putting them at the end of the line), but when combined with the prohibition on leaving braces off, it certainly argues that this PowerShell-Stroustrup style is no longer the C++ standard style, but something invented by PowerShell programmers....

@sergeytunnik

This comment has been minimized.

sergeytunnik commented Mar 14, 2017

Even though I had no idea what is OTBS I mostly use it in my code. I prefer it cause it is neat. Since most PowerShell function are really simple and short, scrolling tons of braces doesn't seem convenient.

@lwsrbrts

This comment has been minimized.

lwsrbrts commented Mar 17, 2017

I use OTBS with Stroustrup else. I believe i started my programming/scripting foray with PHP so it may have started there but I carried it in to VBscript and Powershell. Allman style is a waste of space, literally rather than figuratively, and OTBS with else on the same line is just unnecessarily confusing compared to the rest of the script. That's my two pence...🇬🇧

@TimCurwick

This comment has been minimized.

TimCurwick commented Jun 1, 2017

I use Allman style when writing code for clients and sometimes for colleagues. I use a variant on Allman when I don't care about anyone else.

@rismoney

This comment has been minimized.

rismoney commented Aug 1, 2017

P.S. As a side note (and I will brook no discussion on this): spaces won. In this guide, an indentation level is 4 spaces.

4 spaces is 2 too many.

@egypt egypt referenced this issue Mar 12, 2018

Open

Style fixes #12

lwsrbrts added a commit to tbyehl/PoSHue that referenced this issue Apr 1, 2018

Minor code formatting
I made some minor code formatting changes to fit with the code formatting in use throughout so far. I use the [PoshCode/PowerShellPracticeAndStyle#81 with Stroustrup else).
@BrucePay

This comment has been minimized.

BrucePay commented Apr 24, 2018

PowerShell doesn't use Allman style. It uses C#/.NET style (which is Allman style). So one degree of indirection. PowerShell is conventionally indented with 4 spaces because Windows. I came from a Unix background (East coast, Murray Hill by way of University of Wateroo) where we used OTBS and tabs. With tabs, you could set your editor to display 2, 4, 8 or however many spaces you wanted. Much less cursoring about too.

@Bill-Stewart

This comment has been minimized.

Bill-Stewart commented Aug 6, 2018

As Mr. Bennett noted, we can't use C#/.NET/Allman/Whitesmiths with cmdlets that use a scriptblock, as in:

Get-ChildItem C:\Windows | ForEach-Object
    {
    ...
    }

... due to the fact that the cmdlet needs the scriptblock as its next token (we can use `, but that adds ugliness and inconsistency). I can see advantages of the Whitesmiths style (e.g. see here), but for consistent look, it would seem we have to use some variant of OTBS.

My current preference is OTBS without the "cuddled else" (the "cuddled else" looks inconsistent IMO), with two spaces for indentation. (I don't understand why using more than 2 spaces is necessary. Perhaps someone could explain?)

@TheIncorrigible1

This comment has been minimized.

TheIncorrigible1 commented Aug 22, 2018

@Bill-Stewart 2 space indentation is something I've seen in serialized languages (such as XML), but no where else. I suspect because the code is less readable with everything scrunched together and a lack of whitespace.

@Bill-Stewart

This comment has been minimized.

Bill-Stewart commented Aug 22, 2018

I would say that "scrunched together" is a matter of opinion...I think 2-space indentation is actually more readable than 4-space. 3-space indentation is also pretty readable to me, but 4 spaces seems excessive.

@MartinSGill

This comment has been minimized.

MartinSGill commented Sep 20, 2018

While I generally prefer AllMan for "proper" programming (C#, C++ et. al.) I use K&R (One True Brace Style variant) for PS because I found it's a neater compromise for how the powershell interpreter works without having to provide it hints ( ` ) and because I personally dislike mixing styles for different constructs (class, functions, conditionals vs cmdlets etc).

function MyFunkyCode {
    DoGreatThings
}

Invoke-Something -ScriptBlock {
    MyFunkyCode
}

MyHash = @{
  a = 'b'
}

# Also consistent with arrays
MyArray = @(
    'a'
    'b'
)

I'm open on 2 vs 4 paces. Mostly I prefer 4, because if 4 starts looking "too big" it generally means I need to start refactoring.

@rismoney

This comment has been minimized.

rismoney commented Sep 20, 2018

so it sounds like the only agreement here, is that people disagree. Perhaps instead of community agreement, it should be left up to the project to denote the style. Items like the PSSA, if it were to validate spaces for example, should have a tunable convention.

Me personally, I want nothing to do with 4 spaces or tabs, Allman, Strousup, but rather I prefer 2 space modded K&R. IMHO, There is no point in offending communities of projects by purporting subjective standards as gospel and ultimately leading to community size shrinkage. Celebrate contributors instead of hampering.

@rkeithhill

This comment has been minimized.

rkeithhill commented Sep 21, 2018

@rismoney I think there are some advantages to languages having a "canonical" style. If anything, it helps when folks read books or look at docs if there is a semblance of a consistent style for the language. That said, if any individual wants to do things their way on their own project, I say knock yourself out. And the tools should support you i.e. they should be flexible enough so you can configure them to verify your chosen style. In this case, I have just two bits of advice. First, be self-consistent. It drives my OCD bonkers when looking at someone's code and they can't seem to make up their mind if they're using if(cond) or if (cond) or else { or } else {. So consider configuring a tool like PSSA to verify your script is self-consistent.

Second, when you are contributing to someone else's project - for the love of Jeebus - follow their project's coding style. It's like going into someone else's house - follow their house rules - if they want you to take your shoes off before proceeding, you do that. It's common courtesy. Now sometimes that can be hard if they're not self-consistent. So pick the style that's consistent with the majority of the existing script. Also, the last thing a maintainer wants to see is a one-line bug fix in a file that you've completely reformatted to your own style preferences. At the very least, keep semantic changes and style changes in separate PRs.

@MartinSGill

This comment has been minimized.

MartinSGill commented Sep 21, 2018

I agree with @rkeithhill .

The first rule of good style is to follow the existing style in the file/project. For new files you follow the company/team/project guidelines if you have them, if not use either the recommended style for the language or your preferred style.

If this guide were to recommend a style, I'd phrase it along the lines of "If you do not yet have a preferred style for PowerShell, we recommend starting with K&R OTBS, as it's the most common style and will be the one you encounter most often."

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment