Practical Object-Oriented Design: An Agile Primer Using Ruby
Rate it:
Kindle Notes & Highlights
Read between November 26, 2019 - July 21, 2020
4%
Flag icon
Object-oriented design is about managing dependencies.
4%
Flag icon
devise an arrangement of code that is cost effective in the present and will continue to be so in the future.
4%
Flag icon
The purpose of design is to allow you to do design later, and its primary goal is to reduce the cost of change.
5%
Flag icon
The project gradually becomes doomed as participants switch from working to make it succeed to striving to avoid being blamed for its failure.
6%
Flag icon
At this stage, your first obligation is to take a deep breath and insist that it be simple. Your goal is to model your application, using classes, such that it does what it is supposed to do right now and is also easy to change later.
7%
Flag icon
You will never know less than you know right now.
7%
Flag icon
Code that is Transparent, Reasonable, Usable, and Exemplary (TRUE) not only meets today’s needs but can also be changed to meet the needs of the future. The first step in creating code that is TRUE is to ensure that each class has a single, well-defined responsibility.
7%
Flag icon
A class should do the smallest possible useful thing; that is, it should have a single responsibility.
9%
Flag icon
“Please,  Mr. Gear, what is your tire (size)?” is just downright ridiculous.
9%
Flag icon
The most cost-effective course of action may be to wait for more information.
12%
Flag icon
All the same design techniques work; ask them questions about what they do and try to describe their responsibilities in a single sentence.
17%
Flag icon
Despite its daunting reputation, dependency injection truly is this simple.
17%
Flag icon
if you cannot remove unnecessary dependencies, you should isolate them within your class.
22%
Flag icon
One could infer that the direction of the dependency does not matter, that it makes no difference whether Gear depends on Wheel or vice versa. Indeed, in an application that never changed, your choice would not matter.
22%
Flag icon
depend on things that change less often than you do.
22%
Flag icon
Depending on an abstraction is always safer than depending on a concretion because by its very nature, the abstraction is more stable.
23%
Flag icon
Depend on things that change less often than you do is a heuristic that stands in for all the ideas in this section.
23%
Flag icon
Classes control what’s in your source code repository; messages reflect the living,  animated application.
24%
Flag icon
The design goal, as always, is to retain maximum future flexibility while writing only enough code to meet today’s requirements.
25%
Flag icon
Changing the fundamental design question from “I know I need this class, what should it do?” to “I need to send this message, who should respond to it?”
25%
Flag icon
You don’t send messages because you have objects, you have objects because you send messages.
25%
Flag icon
When Moe knows how to decide if a trip is suitable, he isn’t ordering behavior off of a menu, he’s going into the kitchen and cooking.
25%
Flag icon
Because Mechanic promises that its public interface is stable and unchanging, having a small public interface means that there are few methods for others to depend on.
26%
Flag icon
You already know the technique for collaborating with others without knowing who they are—dependency injection.
26%
Flag icon
: “I know what I want, and I trust you to do your part.” This blind trust is a keystone of object-oriented design.
27%
Flag icon
Your goal is to write code that works today, that can easily be reused, and that can be adapted for unexpected use in the future.
27%
Flag icon
Ruby provides three relevant keywords: public, protected, and private. Use of these keywords serves two distinct purposes. First, they indicate which methods are stable and which are unstable. Second, they control how visible a method is to other parts of your application.
28%
Flag icon
Demeter is often paraphrased as “only talk to your immediate neighbors” or “use only one dot.”
29%
Flag icon
replacing costly dependencies on class with more forgiving dependencies on messages. Duck typed objects are chameleons that are defined more by their behavior than by their class.
31%
Flag icon
Every sequence diagram thus far has been simpler than its corresponding code, but this new diagram looks frighteningly complicated. This complexity is a warning. Sequence diagrams should always be simpler than the code they represent; when they are not, something is wrong with the design.
32%
Flag icon
It is relatively easy to implement a duck type; your design challenge is to notice that you need one and to abstract its interface.
35%
Flag icon
Well-designed applications are constructed of reusable code. Small, trustworthy self-contained objects with minimal context, clear interfaces, and injected dependencies are inherently reusable.
41%
Flag icon
You might be tempted to skip the middleman and just leave this bit of code in Bicycle to begin with, but this push-everything-down-and-then-pull-some-things-up strategy is an important part of this refactoring.
41%
Flag icon
When deciding between refactoring strategies, indeed, when deciding between design strategies in general, it’s useful to ask the question, “What will happen if I’m wrong?”
41%
Flag icon
Promotion failures thus have low consequences.
41%
Flag icon
Untrustworthy hierarchies force objects that interact with them to know their quirks.
41%
Flag icon
The consequences of a demotion failure can be widespread and severe.
41%
Flag icon
The general rule for refactoring into a new inheritance hierarchy is to arrange code so that you can promote abstractions rather than demote concretions.
41%
Flag icon
“What will happen when I’m wrong?”
44%
Flag icon
document template method requirements by implementing matching methods that raise useful errors.
67%
Flag icon
When composition is used in this stricter sense, you know not only that meals have appetizers but also that once the meal is eaten the appetizer is also gone.
67%
Flag icon
Aggregation is exactly like composition except that the contained object has an independent life. Universities have departments, which in turn have professors.
67%
Flag icon
The university–department relationship is one of composition (in its strictest sense) and the department–professor relationship is aggregation.
67%
Flag icon
Composition contains far fewer built-in dependencies than inheritance; it is very often the best choice. Inheritance is a better solution when its use provides high rewards for low risk.
67%
Flag icon
benefits of inheritance was careful to qualify its assertions as applying only to a “correctly modeled hierarchy.” Imagine reasonable, usable, and exemplary as two-sided coins.
67%
Flag icon
The flip side of the reasonable coin is the very high cost of making changes near the top of an incorrectly modeled hierarchy. In this case, the leveraging effect works to your disadvantage; small changes break everything.
68%
Flag icon
As these costs and benefits illustrate, composition is excellent at prescribing rules for assembling an object made of parts but doesn’t provide as much help for the problem of arranging code for a collection of parts that are very nearly identical.
68%
Flag icon
“Inheritance is best suited to adding functionally to existing classes when you will use most of the old code and add relatively small amounts of new code.”
68%
Flag icon
“Use composition when the behavior is more than the sum of its parts.”
68%
Flag icon
Use Inheritance for is-a Relationships
« Prev 1