Code Complete

5.3 Design Building Blocks: Heuristics

Steps in designing objects (p. 87)

Abstraction is the ability to engage with a concept while safely ignoring some of its details—handling different details at different levels (p. 89).

Encapsulation helps to manage complexity by forbidding you to look at the complexity (p. 90).

Hide Secrets (Information Hiding)

Two reasons to hide information (p. 94):

  1. Hiding complexity so that your brain doesn't have to deal with it unless you're specifically concerned with it.
  2. Hiding sources of change so that when change occurs, the effects are localized.

Minor changes to a system might affect several routines within a class, but they should not ripple beyond the class interface (p. 93).

The interface to a class should reveal as little as possible about its inner workings (p. 94).

Hiding a design decision makes a huge difference in the amount of code affected by a change (p. 95).

While the road to programming hell is paved with global variables, class data presents far fewer risks (p. 95).

Get into the habit of asking, "What should I hide?" You'll be surprised at how many difficult design issues dissolve before your eyes (p. 97).

Identify Areas Likely to Change

Two areas likely to change that stood out to me (because of what I'm currently working on):

  1. Business rules - try to keep them all contained and in the same place, rather than strewn througout your code.
  2. Status variables - Use enums instead of booleans, and use getters rather than accessing the status variables directly.

Keep Coupling Loose

Types of Coupling (best to worst) (p. 101-102)

Look for Common Design Patterns

If you stick to common design patterns, you can speak the same language as other engineers you're working with. Thinking in design patterns allows you to work from a list of constraints for solutions to your problem, rather than designing something completely from scratch. Finally, design patterns allow you to speak at a more abstract level about the architecture.

Nearly all the patterns he lists on p. 104 are unrecognizable to me 😳

Guidelines for Using Heuristics

If you feel like you're getting stuck designing something, try a completely different approach:

5.4 Design Practices

Iterate

Top-down & Bottom-up Approaches

Top-down (decomposition) is generally easier for our brains, because we're naturally good at taking one large problem and breaking it down into smaller, manageable problems. Bottom-up (composition) is helpful because it helps you identify utility functionality and reuse code early. But it's pretty difficult (and not recommended by the authors) to solely rely on bottom-up composition. They aren't competing approaches, and you can switch back and forth between the two when needed.

When do you stop decomposing?

Just keep going until you become slightly irritated at how simple it is, and you realize that it would be easier to write the actual code than to decompose the design of the system one level deeper.

Experimental Prototyping

Helps to combat the "wickedness" of design (the fact that you sometimes have to actually build something in order to design it).

Writing the absolute minimum amount of throwaway code that's needed to answer a specific design question.

Pitfalls of Prototyping

Collaborative Design

Perfectionism loves isolation. It would prefer you go it alone, convincing you that relying on others is cheating.

Most of the worst decisions you've ever made were made alone.

How Much Design is Enough?

This depends on the team and the project. If the team is really experienced and familiar with the application area, you probably don't need to go into as much detail.

The author errs on the side of doing too much design, because most of the design problems he has observed arose from stopping design too early. Another thought is that I read somewhere that the vast majority of bugs are do to missing or unclear requirements, rather than typos or incorrect code.

5.5 Comments on Popular Methodologies

Apparently the pendulum swings back and forth between it being on vogue to do design up front, or to do no design at all. The author advocates for doing "Enough Design Up Front." The extremes—designing every detail up front or doing no design at all—are not the way to go.

The more dogmatic you are about applying a design method, the fewer real-life problems you are going to solve. —Plauger 1993

I think the quote above also applies to being dogmatic about how exactly your code should be written. Try to see the forest through the trees.

6.1 Class Foundations: Abstract Data Types (ADTs)

Abstract Data Type - a collection of data and operations that work on that data.