More on this book
Community
Kindle Notes & Highlights
One key task in designing a class is deciding which features should be known outside the class and which should remain secret.
The interface to a class should reveal as little as possible about its inner workings.
A good class interface is like the tip of an iceberg, leaving most of the class unexposed
Asking about what needs to be hidden supports good design decisions at all levels.
Accommodating changes is one of the most challenging aspects of good program design.
Design the interfaces so that changes are limited to the inside of the class and the outside remains unaffected.
Status variables indicate the state of a program and tend to be changed more frequently than most other data.
Use access routines rather than checking the variable directly.
A good technique for identifying areas likely to change is first to identify the minimal subset of the program that might be of use to the user.
Coupling describes how tightly a class or routine is related to other classes or routines.
Try to create modules that depend little on other modules.
A routine that takes one parameter is more loosely coupled to modules that call it than a routine that takes six parameters.
Flexibility refers to how easily you can change the connections between modules.
In creating a system structure, break up the program along the lines of minimal interconnectedness.
Patterns reduce complexity by providing ready-made abstractions. If
The Factory Method is a pattern that allows you to instantiate any class derived from a specific base class without needing to keep track of the individual derived classes anywhere but the Factory Method.
Patterns reduce errors by institutionalizing details of common solutions. Software
Patterns streamline communication by moving the design dialog to a higher level. In
Binding time refers to the time a specific value is bound to a variable.
A brute-force solution that works is better than an elegant solution that doesn't work.
When in doubt, use brute force.
Incremental refinement is a powerful tool for managing complexity.
Continue decomposing until it seems as if it would be easier to code the next level than to decompose it.
Sometimes the top-down approach is so abstract that it's hard to get started.
We try to solve the problem by rushing through the design process so that enough time is left at the end of the project to uncover the errors that were made because we rushed through the design process.
Have you tried decomposing the system in several different ways to see which way will work best?
Have you driven the design to the point that its implementation seems obvious?
A class is a collection of data and routines that share a cohesive, well-defined responsibility.
A key to being an effective programmer is maximizing the portion of a program that you can safely ignore while working on any one section of code.
An abstract data type is a collection of data and operations that work on that data.
One way of thinking of a class is as an abstract data type plus inheritance and polymorphism.
Each class should implement one and only one ADT.
When you design a class, check each public routine to determine whether you need its complement.
Look for ways to convert semantic interface elements to programmatic interface elements by using Asserts or other techniques.
Don't put a routine into the public interface just because it uses only public routines. The
Favoring a technique that speeds write-time convenience at the expense of read-time convenience is a false economy.
It ain't abstract if you have to look at the underlying implementation to understand what's going on.
Tight coupling occurs when an abstraction is leaky, or when encapsulation is broken.
Be critical of classes that contain more than about seven data members. The
The purpose of inheritance is to create simpler code by defining a base class that specifies common elements of two or more derived classes.
Inheritance helps avoid the need to repeat code and data in multiple locations by centralizing it within a base class.
If the derived class isn't going to adhere completely to the same interface contract defined by the base class, inheritance is not the right implementation technique.
Design and document for inheritance or prohibit it. Inheritance
If you want to use a class's implementation but not its interface, use containment rather than inheritance.
Move common interfaces, data, and behavior as high as possible in the inheritance tree. The
Be suspicious of base classes of which there is only one derived class. When
Be suspicious of classes that override a routine and do nothing inside the derived routine. This
Prefer polymorphism to extensive type checking. Frequently
For the sake of controlling complexity, you should maintain a heavy bias against inheritance.
If multiple classes share common data but not behavior, create a common object that those classes can contain.