Article
The Complex World of Patching Medical Devices
This post was previously on the Pathfinder Software site. Pathfinder Software changed its name to Orthogonal in 2016. Read more.
Next week marks the publication of the 50th Anniversary edition of the Strunk & White’s The Elements of Style, a critically important work for anybody who puts words together on a regular basis.
In that spirit, here are some thoughts on good Ruby & Rails style — I’m mostly focusing on Ruby-specific guidelines here. This is somewhat closer to a brain dump than a fully-baked style guide, so it’s something I intend to come back to, especially after hearing everybody tell me exactly where I’m wrong, wrong, wrong.
UPDATE: There were some comments about the formatting being messed up. Apparently, whatever tool we’re using for code coloring doesn’t work well with Safari. In Firefox, the formatting is as intended. We’ve cleaned this up — thanks for your patience.
I don’t want to pretend that it’s not important for code to be correct. Still, I think that functionally correct code is not the last step. For me, the best order is: Make it Work, Make it Clean, Make it Fast (if necessary).
This should be uncontroversial, right? Indenting Ruby code four spaces indicates that you are a very recent convert from Java.
I also think that ERb and HTML within ERb should be indented two spaces. Indentation inside an ERb Ruby block should be aligned with the ERb delimeter, not the the Ruby statement, so this:
<% if something %> two spaces <% end %>
Not this:
<% if something %> too many spaces <% end %>
This one may be a little idiosyncratic, since I tend to use a narrower edit window than a lot of people. That said, it’s still a good idea to have a hard right margin to your code. Whether it’s 80 or 100 characters is less relevant than that all of the code can fit on the screen without scrolling. If you have to scroll to see code, eventually, you’ll make mistakes based on code that you can’t all see at once. (I find this especially true in HTML/ERb, where you can easily mangle a closing tag in column 125 and lose your mind trying to find the problem).
There are two possibilities for indenting the second part of a long line. The first, which is the one recommended in Code Complete, is to double indent it compared to the top line:
a_very_long_method_name(argument1, a + b, arg 3)
The other is to indent to the level of the parenthesis in the statement, like Emacs Lisp does:
a_very_long_method_name(argument1, a + b, arg 3)
In either case, you should never break up individual sub statements — in the above examples, never split up a + b
— you should try to keep entire expression, hash or array arguments on the same line even if that means the line above is shorter.
Anyway, both choices have tradeoffs. The double-indent is the easiest to maintain as the code changes but can make it tricky to follow the logical structure of the code. The longer indent makes it generally clear what goes together, but it’s a little hard to keep up, and can look kind of ragged.
I tend to prefer the first form for Ruby, although I do use the second sometimes, especially for, say, hash options inside a larger statement.
Parenthesis make the code easier to follow. General Ruby style is to use them, except in the following cases:
Not this — it’s overlong, kind of redundant, and not in the spirit of Ruby as I understand it:
if boolean x = 3 else x = 5 end
But this:
x = if boolean then 3 else 5 end
I prefer the use of the explicit if statement to the ternary operator. In the case where the if statement becomes too long to fit on one line, I tend to indent to the level of the if statement:
x = if boolean then 3 else 5 end
I also tend to keep the then
in the line, although it’s technically not needed.
There are a couple of idioms that, although they are sort of opaque the first time you see them, are commonly used enough that they should be used in place of wordier alternatives. Right now the list starts at three:
||=
as in, @user ||= User.find(params[:id])
&&=
as in, @user.name &&= @user.name.downcase
Symbol#to_proc
as in, array.map(&:upcase)
I realize some people don’t like Symbol#to_proc — I really do, though.
Ruby lets you write statements that are only executed conditionally UPDATED for syntactic correctness
return if x.nil?
In general, these statements can get hard to read (people tend to overlook the if part) and should only be used if:
You will sometimes read people who say that a method should only have one return statement. I disagree with that — I’d rather get out of the method early if the data is wrong then have the guts of the method indented inside an if statement.
In Ruby, every method returns the value of its last expression, so you only need to explicitly include a return
statement when you are bailing out of a method. That’s a useful enough distinction that I don’t use the actual return
statement on the last line of code even if it’s a simple statement of the return value.
The convention is braces for single line blocks and do/end
for multi-line blocks:
list.map { |x| x + 3 } list.map do |x| x + 3 end
I’m okay with using braces for a multi-line block if you are using the result of the entire statement in a chain (but see below):
list.map { |x| x + 3 }.sort
Ruby tends to encourage stringing method results together, especially for a bunch of enumeration methods:
all_users.select(&:is_active).map(&:name).sort
Although you can go overboard with this, I think it’s okay as long as the logical chain makes sense as a single operation — I’d avoid it if it was genuinely chaining through a series of different objects (I probably would avoid doing something like user.manager.company.name.size
as a single line).
Anyway, if this goes over a single line, that’s the time to break the chain up into two statements.
What’d I miss? What’s wrong?
Related Posts
Article
The Complex World of Patching Medical Devices
Article
Help Us Build an Authoritative List of SaMD Cleared by the FDA
Article
SaMD Cleared by the FDA: The Ultimate Running List
Article
Essential SaMD Regulatory Documents: Curated List