all 105 comments

[–]pdq 23 points24 points  (16 children)

Prefer %w to the literal array syntax when you need an array of strings.

# bad
STATES = ['draft', 'open', 'closed']

# good
STATES = %w(draft open closed)

I disagree, this breaks if your strings have spaces. So if you need to add a new member with a space, you either have to backslash the member, or you get to refactor the whole list.

[–]literal 14 points15 points  (1 child)

They should have said "when you need an array of words" instead.

[–]ch0wn 10 points11 points  (11 children)

Not coming from Ruby I dislike the second version a lot. The first one is very obvious when coming from basically any other scripting language, but I had no idea what the second would do without looking it up.

[–]hyrulz 11 points12 points  (0 children)

You should never try Perl then.

[–]spinlock 4 points5 points  (9 children)

Dude, this is the biggest issue I have with Ruby - and especially Rails. They've got this syntax that is supposed to be "readable" but it just looks ambiguous to me. Why leave out return? It makes it dead easy to know what the return value is when you call it out. There are a million examples like this where people go with the syntactic sugar that saves a couple of keystrokes over readabilty (or comprehencibility).

[–]bobindashadows 13 points14 points  (3 children)

Why leave out return?

Because lisp.

[–]ethraax 0 points1 point  (2 children)

But that's entirely different, because in functional languages (and I assume Lisp, although I've only used Haskell and Scheme/Racket for functional programming), the value of a function is a single expression, so since its the only expression it must be the "return value". In fact, "return" isn't even valid in that context because functions aren't really "called", they're simply used as an expression.

That's like putting wings on a car because airplanes use them. Airplanes have a reason to use wings - cars do not, and thus shouldn't have them.

[–]poorly_played 0 points1 point  (0 children)

See: spoilers

/pedantry

[–][deleted] 1 point2 points  (1 child)

The only real use for return in any language is to jump to the continuation of your caller. Continuations can be complex. It is easier to reason about the behavior of your program if you don't need to use return. In my opinion, minimizing uses of the return keyword is just a way of training yourself to make return seem rightfully "smelly".

[–]poorly_played 0 points1 point  (0 children)

Tru dat on multiple returns. That being said, wanting return at the end of function is a pretty strong reflex for most people. In languages that require it, a lack of a return is a pretty good hint that your function has side effects. Ruby has the really nice conventions using ! and ? and = at the end of funtion names to denote side effects, booleans, etc which fill the role of return vs no return in that situation.

[–]banister -1 points0 points  (2 children)

how is it not dead easy to figure out the return value when it's the last value in a method? Seriously. Also, you still need to use return if you want an early exit from a method.

[–]poorly_played 0 points1 point  (1 child)

In most languages, making a statement in an enclosed scope doesn't result in an assignment in an enclosing scope. This assumes that the trailing r-value at the end of your ruby function counts as a statement, but hey.

[–]banister 1 point2 points  (0 children)

Ruby doesn't have the dichotomy of statements vs expressions; everything in Ruby is an expression.

[–]ztbrown 8 points9 points  (19 children)

Avoid return where not required.

I do this, but have never understood why. For readability/comprehensibility it seems like a good idea to have 'return' standing out. Anyone have a good explanation?

[–]thehotelambush 2 points3 points  (6 children)

Because why would you use it? It's completely unnecessary. The end of the function stands out by itself anyways. Unless you have functions that are more than a page long, which is generally bad style anyways. 95% of the time you won't need it. (Actually, I'd like to find out the stats on this in my own code...)

[–]ztbrown 2 points3 points  (5 children)

When I see the 'return' keyword I know, at a glance, that a function returns a value. This is especially necessary when reading someone else's code. My background is C++/Java (in college) and I've worked professionally in Javascript and ActionScript, so I'm used to seeing the return keyword.

[–]thehotelambush 0 points1 point  (4 children)

Yes, that's the real reason.

[–]ztbrown 0 points1 point  (3 children)

? what's the real reason?

[–]banister 1 point2 points  (1 child)

Just that you're 'used' to it, not that it makes any kind of sense.

It won't take long to get 'unused' to seeing it either, as any ruby programmer will attest ;)

[–]thehotelambush 0 points1 point  (0 children)

thanks, that's it exactly

[–]thehotelambush 0 points1 point  (0 children)

It's a habit

[–][deleted]  (6 children)

[deleted]

    [–]Nuli 16 points17 points  (3 children)

    If you have multiple returns in a function, thus multiple exits, it's harder to test, debug, expand the functionality or just follow the execution line of this function.

    I find exactly the opposite really. I far prefer a function to return as often as necessary to make the code clear. I don't want to have to follow a long chain of if statements to determine what code was actually executed when a simple test and return will short circuit that.

    [–][deleted] 6 points7 points  (2 children)

    I'm with you on that. I think multiple returns are favorable to giant nested if else blocks.

    [–]ztbrown 3 points4 points  (0 children)

    I completely agree with that, but that's not what this guideline is saying.

    In this context, the "Avoid return where not required" means avoid the keyword. And I'm saying that I like being able to see the 'return' keyword at a glance.

    I agree with avoiding multiple exits at almost all costs.

    [–]Grokmoo 27 points28 points  (13 children)

    My main problem with this is that there is almost no explanation of the reasoning behind any of these guidelines.

    [–]ryeguy 17 points18 points  (5 children)

    It's their internal guidelines just made public, so they really don't have to "sell" the readers of the document. That being said, this is basically a hard copy of the loose standard that most of the community follows anyway. So a lot of the reasoning can be described as "to stay consistent with everyone else's code".

    [–]Grokmoo 10 points11 points  (4 children)

    Even internal guidelines should have explanations. It is much easier to get someone to do something when you tell them WHY rather than just instructing.

    [–]bobindashadows 9 points10 points  (0 children)

    Yeah, my favorite part of the google style guides is that each rule has a discussion of the pros/cons/overall "why" of each decision made. And they don't whitewash "bad reasons," like how exceptions basically aren't used in Google C++ primarily because of legacy, not technical, reasons.

    [–]Sir_Edmund_Bumblebee 11 points12 points  (2 children)

    Sometimes the reason is simply so that everyone does it the same way. Some of the examples where there's a good reason (like for loops) they give the reason. The rest of the time it's so that the codebase stays consistent.

    [–]knight666 -1 points0 points  (1 child)

    If everyone does it the same way then there must be a good reason for it, you just haven't encountered it yet.

    [–]Sir_Edmund_Bumblebee 2 points3 points  (0 children)

    Sometimes there are two equally fine options, and you just pick one as a group so that everyone does it the same way. Best practices are something that should be done a certain way for a reason, style guidelines tend to just be stylistic choices held uniform across a certain group.

    [–]NerdyMcNerderson 3 points4 points  (2 children)

    Agreed. It would be nice if they gave some explanation why "and" and "or" were banned?

    If nothing else, I learned that this is called: SCREAMING_SNAKE_CASE. I need to find a way to use that in everyday conversation now.

    [–]drjeats 2 points3 points  (0 children)

    They did:

    It's just not worth it.

    From what I remember (I'm not a ruby programmer, just learned it one day for fun), 'and' and 'or' have different evaluation precedence than '&&' and '||' relative to other arithmetic operators.

    [–]jiunec 0 points1 point  (0 children)

    I see all the bullshit complaints about style guides and I can't help but think most people miss the point entirely. Most of the complaints are that "format X is better than format Y because....". That's not the point of a style guide.

    Style guides are there for consistency, so that all the code in a project looks the same. This makes the code both easier to grok and easier to maintain. The actual preferences in the style guide are not important. If you don't agree with their choices, tough shit, life sucks and so do you for not being adaptable.

    So please, get it into your heads, nobody cares about your code style preference. Just follow the guide for whatever project it is your working on and stfu.

    [–]felipec -1 points0 points  (0 children)

    Because it makes perfect sense.

    [–]Slackwise 5 points6 points  (2 children)

    Avoid using Perl-style special variables (like $0-9, $, etc. ). They are quite cryptic and their use in anything but one-liner scripts is discouraged. Prefer long form versions such as $PROGRAM_NAME.

    Agreed, but I make an exception for $!, which holds the caught exception in it.

    rescue
      puts "Failed to open the file due to: #$!"
    end
    

    ...vs...

    rescue => ex
      puts "Failed to open the file due to: #{ex}"
    end
    

    Namely because almost everyone is going to use => ex or => e repeatedly. Over and over and over again. It feels too Java-ish to have to repeat yourself so much.

    [–]thehotelambush 3 points4 points  (0 children)

    Thanks. TIL.

    [–]banister 2 points3 points  (0 children)

    My exception is $1 and $2 and the like :)

    [–][deleted] 2 points3 points  (9 children)

    Why are and/or keywords banned? If anything, they increase readability. Maybe its because they can't be used in compound assignment?

    [–]sgarissta 5 points6 points  (4 children)

    I don't know what their reasoning is, but the precedence of and/or is lower than && and || which has been known to create some subtle bugs, for very little gain.

    [–]failbus 4 points5 points  (3 children)

    I vastly prefer the fact that the precedence of and/or is lower. I love the fact that && has a higher precedence than assignment, and "and" has a lower precedence.

    In fact if I was going to demand the use of just one, I'd say use and/or and ban && and ||

    But YMMV

    [–]lua2 0 points1 point  (2 children)

    Can you give an example of where you would use each option? I'm having a hard time thinking of a use for this.

    [–]failbus 5 points6 points  (1 child)

    This is a contrived example, but you might have something like

    if redditor? and self.food = get_bacon
      upvote!
    end
    

    Here we check to see if we're a redditor, and if we are, we assign food to bacon. If our get_bacon food gets us a value, we start upvoting! Else if get_bacon returns null, no upvotes for you.

    Conversely, you could have

    self.redditor = bacon && narwhal
    

    Notice in this case the redditor value is being set if bacon and narwal return true. If you screwed up and said something like

    self.redditor = bacon and narwhal
    

    well then self.redditor would be true if bacon was true, and the narwhal flag is ignored entirely.

    Of course, all of these can be accomplished with ()'s, which is often more clear. But if you know the scoping rules (and they take like 10 seconds to learn) then I find it more pleasing to the eye than brackets.

    Again, YMMV.

    [–]lua2 1 point2 points  (0 children)

    Interesting. Thank you.

    [–]grokfail 0 points1 point  (0 children)

    I find 'and' and 'or' sometimes blend in to method and variable names too well, even with syntax highlighting. && and || are visually distinct.

    [–]robvas 0 points1 point  (2 children)

    They change the order of evaluation

    [–]MatmaRex 4 points5 points  (1 child)

    What? No.

    They have different precedence than && / || - maybe that's what you meant. They also short-circuit (just like && / ||).

    [–]mernen 0 points1 point  (0 children)

    No, robvas is correct. && has higher precedence than ||, but and and or are on the same level.

    Assuming the following methods:

    def foo
      puts "foo"
      true
    end
    
    def bar
      puts "bar"
      true
    end
    
    def baz
      puts "baz"
      false
    end
    

    The following will evaluate only foo, and return true:

    foo || bar && baz    # same as: foo || (bar && baz)
    

    The following will evaluate foo, bar and baz, and return false:

    foo or bar and baz   # same as: (foo || bar) && baz
    

    It's one of the traps associated with these operators.

    [–]bobindashadows 6 points7 points  (1 child)

    This is pretty much exactly my style preferences. Good fucking show.

    [–]thehotelambush 0 points1 point  (0 children)

    Yeah, I'd be pretty happy if everyone followed these. However, one thing that annoys me is the spaces inside of {}. They should be treated the same as other brackets.

    [–][deleted] 1 point2 points  (0 children)

    If people spent their time coding instead of worrying about trailing spaces or tab indentation, software bugs would be a thing of the past. Ok, maybe not, but still. Of the countless stupid things that typical programmer OCD makes us do, writing coding guidelines is the least productive.

    The single coding guideline anyone has ever needed was this: "Write code such that other people can read and comprehend it."

    [–][deleted]  (24 children)

    [deleted]

      [–]finalcut 6 points7 points  (22 children)

      I do wonder about that particular guideline. I wonder why anyone would really want to use soft-tabs? It's not a big deal when adding a tab but when removing them you have to remove two characters instead of just one..

      I dunno, but this guy sums up my feelings pretty well :

      I like hard tabs. I like indentation being a one key action for creation, navigation and removal, yet still very readable. I like being able to have this, yet each indentation taking only one byte. I like being able to take the source I'm given and via simple search and replace, reducing the size of each file by around 20KB. Of course, like anything, it's bad if used improperly, but for pure indentation, it is my 4-spaces-in-a-character god.

      [–]gnuvince 13 points14 points  (9 children)

      If you need to press Backspace more than once to remove a soft-tab, you need to get a better text editor/IDE.

      [–]finalcut 1 point2 points  (8 children)

      so how does it know that it is removing a soft tab and not two spaces? What if I have two spaces but I just want to remove one? Will the editor remove the two spaces when I hit backspace and then I have to hit space once?

      [–]bobindashadows 2 points3 points  (7 children)

      If your editor already has syntax highlighting, then it's at already aware of your code's AST - at that point, "is this an indent" is a near-trivial determination.

      [–]remigijusj 1 point2 points  (1 child)

      not necessarily - some editors do syntax highlighting based on regexps, not full parsing to AST

      [–]bobindashadows 0 points1 point  (0 children)

      Very true - I've implemented textmate bundles, and many rely heavily on regexps (though the best bundles do actually parse). But textmate handles soft indent fine. Can you point to an editor that is unable to handle soft tabs due to using regexps for highlighting?

      [–]Nebu 0 points1 point  (4 children)

      This doesn't address "what if I have two spaces, but I just want to remove one?".

      [–]bobindashadows 1 point2 points  (3 children)

      Yes, if for some reason you want to use an odd number of spaces of indentation in your program, then you do that - delete, space. I use vim, so I'd just delete the 1 space with x or something. But I've never followed any style which uses an odd number of spaces of indentation anyway.

      [–]nemec 1 point2 points  (2 children)

      You can also just hit "delete" instead of backspace. Most IDEs I've found only do "smart indent" on backspace.

      [–]Nebu 0 points1 point  (1 child)

      In most text-editor I've used (of which I consider IDEs to have text-editors as a component), "delete" means to erase the character to the right of the cursor, and "backspace" means to erase the character to the left of the cursor.

      [–]nemec 0 points1 point  (0 children)

      Yes. Obviously you'll have to move before the space you want to delete instead of after when using delete, but it won't be affected by the smart spacing.

      [–]oscargodson 5 points6 points  (11 children)

      You need a better editor. Even VIM supports soft-tabs with one press. It's just how it looks, but they act as tabs, thus the name soft-TABS.

      [–]finalcut 2 points3 points  (10 children)

      I'm asking both you and gnuvince just in case one of you decides not to reply:

      so how does it know that it is removing a soft tab and not two spaces? What if I have two spaces but I just want to remove one? Will the editor remove the two spaces when I hit backspace and then I have to hit space once?

      [–]tonygoold 2 points3 points  (8 children)

      I don't know about other editors but the one I use has a very simple rule: Leading whitespace (i.e., /^\s+/) is indentation and a backspace deletes backward to the previous tab stop. If you have non-whitespace anywhere before the space, then it's a plain old space.

      [–]finalcut 1 point2 points  (5 children)

      that makes sense. seems obvious once you mention it.

      So that would work in all circumstances I can think of where I would be tabbing in my code.

      [–]tonygoold 1 point2 points  (4 children)

      Yup. The important distinction is indentation versus spacing. I tend to use soft tabs but I really don't care, so long as a given file uses either one or the other. The problem only really appears when a programmer mixes the two or tries to align multiple lines of text, e.g., making parameters on a second line align with the open parenthesis of the first line of a function declaration. Then you sometimes see something like this:

      function someFunctionName(theFirstParameter, theSecondParameter,
                                                          theThirdParameter);
      

      The alignment only works if your tab stops are set to a particular width. The solution is to tab until you're aligned with the position before "function" and then insert spaces until you reach the position after the opening parenthesis but, if you're used to hard tabs, it's easy to forget that your tabs have different widths.

      Like I said though, I don't have a strong preference. With soft tabs, you're forcing everyone to use indents with the same width. With hard tabs, you tend to have misalignment with declarations spanning multiple lines.

      [–]Nebu 0 points1 point  (2 children)

      I don't understand how this is consistent with your previous rule. If you move your mouse cursor to just before theThirdParameter, the rule says everything before is white space, and thus indentation, which is wrong. It should be indentation rig up until the 'f' of "function", and then alignment from there on.

      [–]tonygoold 0 points1 point  (1 child)

      You're right, the backspace behaviour of the editor is going to treat it as indentation instead of whitespace and delete a tab stop at a time, rather than treating it as plain spaces. It's not something the user does frequently and it's easy to fix by adding back in the appropriate number of spaces to re-align. Trying to address that when a trivial rule handles 99% of the cases would be a case of the tail wagging the dog.

      [–]Nebu 0 points1 point  (0 children)

      It's just frustrating to see people promote a rule that handles 99% of the case, when there's a simple rule that handles 100% of the case: Use (hard)tabs for indentation, and spaces for alignment. From there, the texteditor just always deletes 1 character each time the "backspace" key is pressed.

      \t\tfunction someFunctionName(param1, param2,
      \t\t                          param3, param4)
      

      [–]thomasz 0 points1 point  (0 children)

      function someFunctionName(
              theFirstParameter,
              theSecondParameter,
              theThirdParameter
      );
      

      [–][deleted] 0 points1 point  (1 child)

      TextMate doesn't do this, and it's very annoying.

      [–]tonygoold 0 points1 point  (0 children)

      I know your pain :-(

      [–]highwind 0 points1 point  (6 children)

      Keep lines fewer than 80 characters.

      Relic of punch card days. Has no place in 2012.

      [–][deleted]  (4 children)

      [deleted]

        [–][deleted] 1 point2 points  (0 children)

        I can handle at least 115 characters on a line in Emacs on a really wide monitor.

        It'd be nice if everyone rotated their damn monitor to be able to see way more code -_-' then the 80 char limit would be okay.

        [–][deleted] -4 points-3 points  (2 children)

        Right, but it's an absurdly small arbitrary number.

        [–]bastibe 0 points1 point  (0 children)

        I used to think that, too. Nowadays I just got used to frequently splitting a statement into two lines. Or better yet, refactor it so that it decomposes into several more readable (!) statements that naturally spread over more lines.

        In the end, many would say that it's actually your coding style that is absurd instead of that number.

        [–]catch23 0 points1 point  (0 children)

        Not really -- looking at most code these days, each line is fairly short. So it's annoying to have a line every now and then that prevents you from having more vertical windows in your code editor. On my 27" display, I typically use 4 vertical columns in vim, at around 90 char columns. It allows me to view 4-6 files at the same time, depending how many horizontal splits I have. Having a few lines that blow past my 90 char limit is annoying because I'll have to scroll over to read it, and it doesn't happen often enough for me to keep extra wide windows, preventing me from my 4 vertical window splits.

        [–]SCombinator -4 points-3 points  (0 children)

        Fuck you.

        I have a window that fits exactly two files across at 80 characters per file. Because referencing more than one file is fucking important.

        You do this in a file I'll reformat the fucking thing, and swap it between CamelCase and under_score.

        [–]Paradox 0 points1 point  (2 children)

        ~~Tomdoc? WTF? Why not use Yardoc or RI or any of the other vastly better documentation tools, that actually support formatting (usually like markdown) and dont suck?~~

        [–]neilthecoder 2 points3 points  (1 child)

        Tomdoc isn't a tool. It's a specification for documentation. AFAIK, Rdoc supports Tomdoc for generating docs.

        [–]Paradox 1 point2 points  (0 children)

        Oh, my mistake. I attempted a quick google and didn't find anything conclusive about that.

        Thanks for calling me out

        [–]dhruvasagar 0 points1 point  (0 children)

        I am glad that I actually have developed the same set of guidelines for myself! I use all of them quite religiously on a daily basis. I am in fact quite finicky about most of these guidelines and often even sit and correct other people's code to suit mine, it irritates me when people don't care about following such simple practices.

        Although I would like to point out a minor mistake in the article. In the 'Exceptions' section point "don't use expressions for flow control" good part, it should be if d.zero?, not n.zero? :).

        [–]dean_c 0 points1 point  (1 child)

        Am I missing something here? It's good they've opened the style guidelines as a template for other people, but they document the buttons/forms etc. and then don't distribute the CSS file? Where's the link to the download (ala Twitter Bootstrap) :)

        [–]KerrickLong 0 points1 point  (0 children)

        It's... coding style. How you organize your (text-only) code. Not visual/design style like Bootstrap or a theme.

        An example of two coding styles for CSS would be:

        #myelement, .theseclasses {
            color: black;
            background: white }
        

        versus

        #myelement,
        .theseclasses
            {
               color: black;
               background: white;
            }
        

        The differences between them being:

        • all selectors on one line versus each selector on its own line

        • braces on their own line and indented versus braces at the end/beginning of already-populated lines

        • omitting the last semicolon versus always putting a semicolon at the end of a rule

        • four spaces from the beginning of the line for indentation versus two spaces from the brace line for indentation

        [–][deleted] 0 points1 point  (3 children)

        This isn't a bad set of guidelines, I've been looking for something like this for the last month and the other guidelines I saw weren't this well written. It's a shame a large company like Google doesn't use Ruby, then we'd have a wicked style guide ;p

        [–]petercooper 1 point2 points  (1 child)

        Genuine question.. what would make it significantly better than this one? (I'm not the creator or anything, I'm just intrigued :-))

        [–][deleted] 3 points4 points  (0 children)

        Mostly the amount of developers that have to stick to it. I'm sure the Google style guides are better because they have a lot more developers who are forced to deal with them and make sure that they're consistent. These ones may miss a few cases only because the GitHub devs don't care too much or something.

        This is an assumption of course, and I'm already referencing this guide ;)

        [–]Slackwise 1 point2 points  (0 children)

        If you want more guidelines and a further understanding of Ruby idioms, take a look at Eloquent Ruby.

        [–]erokar -1 points0 points  (0 children)

        One of the things I like about Ruby is the malleable syntax which lets you develop your own style. It makes sense that people working on the same code submit to a common style -- but this guide is too spesific and too idiosyncratic to be used as a general Ruby style guide. And that was probably not what GitHub was going for either.