Homage to Sandi Metz
A year or so ago, Ruby Hero and author of Practical Object-Oriented Design in Ruby Sandi Metz gave us her four rules of Ruby Development. As stated, her four rules are:
- Classes can be no longer than one hundred lines of code.
- Methods can be no longer than five lines of code.
- Pass no more than four parameters into a method. Hash options are parameters.
- Controllers can instantiate only one object. Therefore, views can only know about one instance variable and views should only send messages to that object (@object.collaborator.value is not allowed).
While her rules are rather specific to Ruby development, I believe the ideas behind them are fairly universal and useful. With that in mind, here are a set of rules for Apex development, along with the rationalization behind it.
My highly opinionated rules for Apex Simplicity
- Classes can be no longer than 300 lines of code. — I took three classes from production Apex projects and ported the code to idiomatic Ruby. Each of my Apex classes used aproximately three times the number of lines that the Ruby code took, hence 300 lines. Putting a cap on the number of lines has a number of benefits, but perhaps the biggest is found by enforcing a clarity of purpose on the class. Recently, I had the opportunity to work with a 2k line class “Coupon”. It handled five types of discounts. Breaking those five discounts into five classes helps convey what class had responsibility for what.
- 20 lines per method — This is easily the most contentious rule. The primary benefit of following this rule is that your code will necessarily be simpler. Nested if statements, and long blocks of code for edge cases are now tucked away in other, more tightly focused — and more easily tested — methods. Like Thoughtbot’s implementation of Metz’s rules, I think this could use some explaination though, as not everything makes sense as a ‘line’. Conditional logic keywords like if/else each count as a line. The line constraint will also likely reduce your use of
else if()constructs keeping your code simpler as well! So why 20 lines? Well Ruby has an implicit return structure, whereas Apex requires explicit return statements adding at least one extra line per method. Couple that with a generally more verbose language and I felt like 20 was the sweet spot. It’s a fairly arbitrary choice, I admit but in some testing I’ve found that I can usually get my methods into 20 lines (not counting comments. You are commenting right?)
- Only four method arguments per method — First, let me state an exception to this rule. Factory methods for producing test data are immediately exempt from this rule. For instance, a factory method for returning an Order may require passing in: a User, an Account, a Contact, an Opportunity as well as… well you get the idea. Unlike test methods, most ‘live’ methods accept parameters for one of two reasons: direct manipulation of data or conditional logic. Again, simplicity is the real reason and winner here. Limiting each method to no more than four incoming parameters forces you to have different methods for different conditional branches making your methods are short, concise and tightly focused.
- Visualforce Controllers can only talk to a single instance variable. I admit, I have a hard time following this one. The idea here, is to expose the entirety of your data through a single wrapper object. This forces architectural changes on down the line. Your controller or controller extension becomes focused not on gathering data, but preparing it for the view. This has a number of benefits, but code simplicity and testability are the best. Note, this doesn’t include controller methods, just the data being exposed on the page.
If you’re sensing an underlying theme to these, it’s simplicity – keeping the code as simple as possible. These rules help enforce simplicity. Of course sooner or later we’ll hit a class with 350 lines and no good refactoring path. And thats ok too, Break the rules when you have to, not just because you can.