Ruby style guide
github.com
github.com
"* The length of an identifier determines its scope. Use one-letter variables for short block/method parameters, according to this scheme:
a,b,c: any object
d: directory names
e: elements of an Enumerable
ex: rescued exceptions
f: files and file names
i,j: indexes
k: the key part of a hash entry
m: methods
o: any object
r: return values of short methods
s: strings
v: any value
v: the value part of a hash entry
x,y,z: numbers
And in general, the first letter of the class name if all objects are of that type."I cross-referenced to the Erlang documentation, and they provided no other real justification for this rule, other than to say that the burden lies on the caller. Is there a history behind this convention? Is there a considerable benefit, other than more stream-lined code, to coding this way?
Secondly, something I've noticed about defensive programming is that generally it creates a culture of "meta rules" that only exist in the system architect's head. When someone else reuses one of their models, then the danger is they don't know all these different rules because they are scattered around different controllers or scripts. This has been a particularly vicious source of bugs in our legacy systems. Domain experience becomes critical.
Lastly, defensive programming by its nature is also traditionally a big red warning sign that says "there is no data integrity strategy in place for this system." It doesn't matter if that data is coming from a CRUD form, a relational database or a file... there should be some validation layer that ensures the data is 'correct' before making it 'safe' to reuse across the rest of the system.
I've found that defensive programming is particularly rife in systems powered by MySQL databases. MySQL has traditionally lacked the data integrity mechanisms of Oracle or other Enterprisey systems and thus has created a whole bunch of MySQL 'experts' that actually don't know anything about data integrity. A system I'm working with this very minute has a function where the first 20 lines of code (out of 28 total) is compensating for potential orphan entries in the database. The reason? The admin tool for removing entries does not do cascading deletes. Rather than fix the root of the problem, we have this 20 line check everywhere that we need to access the data safely.
I could go on and on, but in short: defensive programming is one of the major 'code smells.'
For example, if I call a Draw method on an object, I assert if the object Color property hasn't been set. I don't create a default color for it. This makes sure that the Draw will work as it should, it will make no assumptions on how it is being called it just makes sure that when it was called it will have to be valid.
I find the former really useful in quickly finding bugs in my code and documenting the function input assumptions. In general, I'd rather my code fail early and visibly (e.g. crash in debugging environment, return error and log the problem in production environment) than produce garbage because the input was garbage.
I agree the latter bad for defending against inconsistencies in internal data model or as a "precaution" when using API you don't trust, but it's still vital if you're dealing with data from outside world, when you do want to try and behave sanely in possibly damaged input (e.g. not ignore the entire RSS feed if an item from it doesn't have pubDate set).
Defensive programming "done right" should be self documenting ("oh, I see this routine requires this parameter to be non-zero"), and throw exceptions back up to the ui/app layer so that unmet assumptions can't be ignored by the app programmer.
For many-layered code bases, there needs to be a level below which data is assumed to be valid and can go unchecked (at least in release builds) - otherwise a single check will be performed many times from a single high-level call.
http://www.reddit.com/r/programming/comments/8cm8w/defensive...
For example, I would had a stored procedure for validating the data.
Or I would have made the smartest decision of using Postgres and live happily there after.
How does using a decent DB remove the usefulness of stored procedures?
http://www.caliban.org/ruby/rubyguide.shtml
and
I'd say having a noteworthy developer write a style guide is noteworthy.
And "Read other style guides and apply the parts that don't dissent with this list" is a little too arrogant for any coder in the entire world -- perhaps should be "Replace any parts of this list that don't conform to your style".
On a 24" screen I like to have 2-3 files open side by side.
Having to scroll down is no big deal, scrolling sideways is pretty awkward. It also makes diffs harder to read if lines are too long.
I certainly wouldn't argue for a hard limit of 80, but I find it's generally a good idea to break up lines if they're getting too long.
Unlike in some other communities, there is no contention in the Ruby community over whether to use two, four or eight spaces. Everyone is happy to use just two. Furthermore, never use tabs, which includes the practice of mixing tabs with spaces.
That's not to say spaces are better than tabs, or two spaces are better than four spaces. Just that idiomatic Ruby code uses two spaces.
Two spaces are always two spaces.
key <tab> => <tab> value
This might look perfectly fine for someone using 8-width tabs, but it will most likely be screwy for anyone using 4-width tabs or smaller. The tab's location is calculated as the distance where the cursor position modulo the tab width is 0.
E.g. one key is 2 chars long and another is 5 chars long. You tabbed it using 8-width tabs. Looks fine. If someone loads it with 4-width tabs, they see the two lines aligned differently.
#!/usr/bin/ruby -w
#-*- standard-indent: 2; indent-tabs-mode: nil; -*-
[...]