More on this book
Community
Kindle Notes & Highlights
The opposite of information hiding is information leakage.
pernicious
One of the best skills you can learn as a software designer is a high level of sensitivity to information leakage.
Information leakage occurs when the same knowledge is used in multiple places, such as two different classes that both understand the format of a particular type of file.
In temporal decomposition, the structure of a system corresponds to the time order in which operations will occur.
When designing modules, focus on the knowledge that’s needed to perform each task, not the order in which tasks occur.
information hiding can often be improved by making a class slightly larger.
Defaults illustrate the principle that interfaces should be designed to make the common case as simple as possible.
Whenever possible, classes should “do the right thing” without being explicitly asked.
If the API for a commonly used feature forces users to learn about other features that are rarely used, this increases the cognitive load on users who don’t need the rarely used features.
general-purpose or special-purpose
The general-purpose approach seems consistent with the investment mindset discussed in Chapter 3, where you spend a bit more time up front to save time later on.
The phrase “somewhat general-purpose” means that the module’s functionality should reflect your current needs, but its interface should not.
Generality leads to better information hiding
One of the most important elements of software design is determining who needs to know what, and when.
What is the simplest interface that will cover all my current needs?
In how many situations will this method be used?
Is this API easy to use for my current needs?
Making your modules somewhat general-purpose is one of the best ways to reduce overall system complexity.
In a well-designed system, each layer provides a different abstraction from the layers above and below it;
If a system contains adjacent layers with similar abstractions,
A pass-through method is one that does little except invoke another method, whose signature is similar or identical to that of the calling method.
This typically indicates that there is not a clean division of responsibility between the classes.
“Exactly which features and abstractions is each of these classes responsible for?”
The decorator design pattern (also known as a “wrapper”)
The motivation for decorators is to separate special-purpose extensions of a class from a more generic core.
Pull Complexity Downwards
Most modules have more users than developers, so it is better for the developers to suffer than the users.
it is more important for a module to have a simple interface than a simple implementation.
Configuration parameters are an example of moving complexity upwards instead of down.
the complexity being pulled down is closely related to the class’s existing functionality,
pulling the complexity down will result in many simplifications elsewhere in the application,
pulling the complexity down simplifies the cl...
This highlight has been truncated due to consecutive passage length restrictions.
Bringing pieces of code together is most beneficial if they are closely related. If the pieces are unrelated, they are probably better off apart.
They share information;
They are used together:
They overlap conceptually,
It is hard to understand one of the pieces of code without looking at the other.
Bring together if information is shared
Bring together if it will simplify the interface
Bring together to eliminate duplication
Separate general-purpose and special-purpose code
If the same piece of code (or code that is almost the same) appears over and over again, that’s a red flag that you haven’t found the right abstractions.
This red flag occurs when a general-purpose mechanism also contains code specialized for a particular use of that mechanism.
The key design decision was the one that separated the general-purpose part of the undo mechanism from the special-purpose parts and put the general-purpose part in a class by itself.
Each method should do one thing and do it completely.
someone reading the child method doesn’t need to know anything about the parent method
someone reading the parent method doesn’t need to understand the implementation of the child method.
I use the term exception to refer to any uncommon condition that alters the normal flow of control in a program.
“code that hasn’t been executed doesn’t work”).