Code Design Checklist
The only way to make the deadline — the only way to go fast — is to keep the code as clean as possible at all times. — Robert Martin on LeBlanc's Law: "Later equals Never."
Good design is not simply following a formula. Although people will often make lists of "rules" for good design, the reality is that good designers will occasionally break the rules. In this class, you will be asked to design code that has three basic characteristics:
- Easy to understand
- Classes have small, useful interfaces
- Avoid duplication of all kinds
Within this basic structure, we will have some "rules". But these rules won't cover every possible instance, and sometimes you might have good reason to break a rule to accomplish these goals. But we hope that these rules will help you get started making good designs. If you feel you must violate one of the conventions, you must document the reason within your code (a good reason for comments!).
Guidelines
- Communication: code is for humans, so make your code clear, concise, and easy to understand
- Meaningful names: give variables, methods, classes, and packages non-abbreviated, intention-revealing names
- No magic values: use constants for all values used multiple times or in program logic
- Write readable code instead of comments: use comments only to explain important design decisions or purpose of code, not to restate code logic
- Use scope wisely: variables should be declared as close as possible to where they are used
- At all points, code should be "at the same level" (try not to mix method calls and low-level if logic in same method)
- Code should be "concise" (use booleans wisely, for-each loop where possible, use Java API calls instead of implementing yourself)
- Code should contain no warnings from Java compiler or CheckStyle
- Modularity: classes represent an abstraction and thus have coherent, closed, and useful interfaces
- Tell, don't ask: classes should be responsible for their own data and delegate to other objects instead of doing it themselves
- No public instance variables: keep implementation details of your class hidden from the public interface
- No "manager" classes: create several classes that work together distributing intelligence, rather than one "smart" class and a few "dumb" helpers
- No static variables: there should be no reason for shared global public state
- Active classes: classes should not consist of only get/set methods and, in general, should minimize their use.
When necessary:- get methods should give away the minimal information possible
- set methods should validate data received
- Superclasses are their own class: thus should not contain instance variables or methods specific to only some subclasses
- Flexibility: help users of you code by clearly organizing your classes for extension
- DRY: no duplicated code, either exactly (from cutting and pasting), structurally (in flow of control or decisions), or in setup ("boilerplate" code)
- Declared types should be as general as possible (i.e.,
ArrayList
should never be visible in your public interface) - Single Purpose: keep classes, methods, and variables short and well named by giving them only one purpose
- Behavior Driven Design: give each class a purpose by focusing on the behavior (or services) it provides first, its state later
- Polymorphism: use subclassing to avoid "case-based code logic" (i.e., conditional chains or case statements on "type" information)