CompSci 307
Fall 2021
Software Design and Implementation

Code Design Habit 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:

  1. Easy to understand
  2. Classes have small, useful interfaces
  3. 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

  1. Communication: code is for humans, so make your code clear, concise, and easy to understand
    1. Use meaningful names: give variables, methods, classes, and packages non-abbreviated, intention-revealing names
    2. No magic values: use named constants for all specific values used multiple times or in program logic
    3. Write readable code: use function/variable names and shorten code to organize it (use comments only to explain important design decisions or purpose of code)
    4. Use scope wisely: variables should be declared when they can be assigned, as close as possible to where they are used
    5. Code to expectations: use booleans wisely, for-each loop where possible, use Java API calls instead of implementing yourself
    6. "Outline" your code: methods should be implemented "at one level" (try not to mix method calls and low-level if logic in same method)
    7. Read warnings: understand and appropriately fix warnings from Java compiler or IntelliJ (or comment to show you understand why the warning is there and are choosing to leave it as is)

     

  2. Modularity: classes represent an abstraction and thus have coherent, closed, and useful interfaces
    1. No public instance variables: keep implementation details of your class hidden from the public interface
    2. No static variables: there should be no reason for shared global public state
    3. Tell, don't ask: classes should be responsible for their own data and delegate to other objects instead of doing it themselves
    4. 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
    5. Superclasses are their own class: thus should not contain instance variables or methods specific to only some subclasses
    6. No "manager" classes: create several classes that work together distributing intelligence, rather than one "smart" class and a few "dumb" helpers

     

  3. Flexibility: help users of you code by clearly organizing your classes for extension
    1. DRY: no duplicated code, either exactly (from cutting and pasting), structurally (in flow of control or decisions), or in setup ("boilerplate" code)
    2. Single Purpose: keep classes, methods, and variables short and well named by giving them only one purpose
    3. Use Abstractions: Declare variables types to be as general as possible (i.e., ArrayList should never be publicly visible in your code)
    4. Polymorphism: use subclassing to avoid "case-based code logic" (i.e., conditional chains or case statements on "type" information)
    5. Behavior Driven Design: give each class a purpose by focusing on the behavior (or services) it provides first, its state later