Scott's Rules of Reuse
I present to you, the first publication of Scott's Rules of Reuse. Applying the following five rules results in an incredibly safe & reusable class. Such a class can be reused through extension or composition keeping consistent use of state in the original class.
Scott's Rules of Reuse state:
- All variable data must be private.
- Most data should be JavaBean Properties.
- Data must only be used in get/set methods.
- Most methods should be public or protected.
- Final methods and class are evil.
Details of Scott's Rules of Reuse follow.
When to break the Rules of Reuse
As in all rules in life, rules are made to be broken. However, keep in mind that rules are also made to be adhered to!
First, never break rule #1. There is never any valid reason to directly access a class' variable (non-constant) data from outside the class itself. You can always add a get/set method to provide this functionality.
Otherwise, the rule of thumb for the other rules is "if you can argue your case to the Supreme Court of the United States of America, with Bobcat Goldthwait as your Lawyer, and win, then you may break the rule." These rules have some very important effects, and if followed, will greatly increase maintainability and reusability of your code.
Scott's Rule of Reuse # 1:
ALL VARIABLE DATA MUST BE PRIVATE
NOTE: There is only one exception to this rule: final static variables (aka class constants). Otherwise, there are to be no exceptions to Scott's rule #1. Ever.
The reason for this is that a class must be in total control of its state. If someone makes a change, the class must have a chance to know about it. If we leave variables non-private, some other class can change our state w/o us knowing.
The only way variables are to be changed is via methods defined in the class, preferably a setXXX() method. Initially the set method is simply changing the value. However, later on, we can add code to the set method to
- add validation to ensure the value is acceptable
- fire events to tell others that the value has changed
- update other state when the value changes
- log that the value has changed
If the variable is non-private, the set method might not be called when it changes, so we cannot guarantee to be able to fire a property change, validate, etc.
For more details on this rule, see Using Accessors.
Scott's Rule of Reuse # 2:
MOST DATA SHOULD BE JAVABEAN PROPERTIES
(Details on this accidentally deleted -- I'll need to add them back later. The basic gist of this is that there's usually no reason to disallow controlled access to your data. By controlled, I mean access via methods. It's rare that you want to really disallow get, and only occasionally useful to disallow a set. By providing get/set methods for most (if not all) of your data, a subclass can easily modify the state of its superclass in a safe manner.
Scott's Rule of Reuse # 3:
DATA MUST ONLY BE USED IN GET/SET METHODS
NOTE: There are to be no exceptions to Scott's rule #3 in your handwritten code. Ever.
The only places in your code where a variable should appear are:
- the variable definition
- the get method to read it (or a single, designated access method)
- the set method to modify it (or a single, designated mutation method)
This has two very desirable effects:
- the code in set (like firing property changes) always has a chance to run, even when you're updating the variable from within its own class
- subclasses can override the way the data is get/set (the subclasses cannot touch the variable, but can call the superclass set with modified parameters or modify the result of a call to the superclass get)
Note that rule #3 is sometimes broken in code generated by GUI builders. VisualAge for Java is one that does a pretty good job following this rule, though.
Also note that some methods act in place of get/set methods to access data. As long as you limit the number of places that actually do the reading and writing of the data to a single reader and a single writer, you are adhering to rule #3.
Scott's Rule of Reuse # 4:
MOST METHODS SHOULD BE PUBLIC OR PROTECTED
Note the weasel words "MOST" and "SHOULD"; there are a few reasonable exceptions (mainly for generated code).
The reason for rule #4 is to allow subclasses to override any method they want. This allows your superclass to just to its job w/o worrying about what a subclass might need. The subclass can override anything that it wants, either extending or replacing the superclass behavior for that method.
Anything that you want to "hide" from general public use should be protected; that still allows subclasses to override and call the superclass version (as well as allowing other classes in the same package to call them). All other methods should be public, letting anyone call them.
Private methods should only be used by builder tools/wizards to prevent accidental overriding of implementation details, or in extreme cases of security issues. A good example I heard once was that someone distributed an online game and didn't want people to override pieces to cheat...
If you want to make a method neither public nor protected, you had better be able to present your case to the Supreme Court. You're basically asserting that noone will ever want to change that behavior. You had better have an incredibly good reason to use such behavior.
NOTE: "Performance" is not a valid reason to use private methods. This can result in a minor, almost negligible, performance improvement by inlining methods under some circumstances, but that minor improvement is a bad trade for maintainability/extensibility.
Scott's Rule of Reuse # 5:
FINAL METHODS/CLASSES ARE EVIL
The last rule of reuse concerns the use of the final keyword when applied to methods and classes. Final is evil. Plain and simple.
When you make a method or class final, you cut off any chance of extension. This should only be used in exceeding rare circumstances, usually security-related, such as the game cheating example in rule #4. If you want to make a method or class final, it's Supreme Court case time again.
NOTE 1: "Performance" is not a valid reason to use final methods. This can result in a minor, almost negligible, performance improvement by inlining methods under some circumstances, but that minor improvement is a bad trade for maintainability/extensibility.
NOTE 2: Rule #5 does not apply to final variables -- there are very legitimate reasons to use final variables.
RE performance of inlined methods (private/final) -- there are a few highly-computational applications where inlining makes a noticeable difference, but all other methods of improving performance should be exhausted before making methods private or final. These other methods include but are not limited to:
- profiling to find bottlenecks
- choosing better algorithms
- using other compilers that might optimize code better
- using Hotspot to execute the code (it inlines where possible even if not private/final)
The above methods usually result in a higher gain than inlining can ever accomplish.
Notes on my personal application of these rules
- I have upheld rule #1 for a very long time
- I've really only realized the benefit of #2 and #3 fairly recently, and my past code does not follow it
- I've followed #4 for quite some time (generated code being the exception)
- I always follow #5
And a final note, the JavaBean spec uses getters and setters to be able to determine "properties" in your bean to show them in a GUI builder.