The programming techniques that make code a joy to write overlap with those that most efficiently produce software
The techniques of object-oriented design solve both the moral and the technical dilemmas of programming; following them produces cost- effective software using code that is also a pleasure to work on.
Design does not matter unless there will be change to the application - but there is always change to the application
Object-oriented design is about managing dependencies. It is a set of coding techniques that arrange dependencies such that objects can tolerate change.
Dependent objects would wreak havoc because changing one object forces change upon another, leading another object to change etc.
You must not only write code for the feature you plan to deliver today, you must also create code that is amenable to being changed later.
Practical design does not anticipate what will happen to your application, it merely accepts that something will and that, in the present, you cannot know what. It doesn’t guess the future; it preserves your options for accommodating the future. It doesn’t choose; it leaves you room to move.
The purpose of design is to allow you to do design later and its primary goal is to reduce the cost of change.
Studies were done to measure code quality, and indeed these design principles lead to high quality code
The Agile experience is that this collaboration produces software that differs from what was initially imagined; the resulting software could not have been anticipated by any other means.
BUFD stands for Big Up Front Design
Because Agile processes guarantee change, the ability to make changes to the code is necessary. Otherwise, everytime you would need to rewrite a bunch of code.
SLOC (source lines of code) to measure programmer contribution says nothing about overall equality
Object-oriented programming is object-oriented relative to non object-oriented, or procedural, programming.
Class-based OO languages like Ruby allow you to define a class that provides a blueprint for the construction of similar objects.
The trick to getting the most bang for your design buck is to acquire an understanding of the theories of design and to apply these theories appropriately, at the right time, and in the right amounts. Design relies on your ability to translate theory into practice.
The classes you create define a virtual world, and will affect how you think about your application forever.
Code should be TRUE
A class should do the smallest possible useful thing; that is, it should have a single responsibility.
A class that has more than one responsibility is difficult to reuse. The various responsibilities are likely thoroughly entangled within the class. If you want to reuse some (but not all) of its behavior, it is impossible to get at only the parts you need. You are faced with two options and neither is particularly appealing.
How can you determine if the Gear class contains behavior that belongs somewhere else?
One way is to pretend that it’s sentient (act as if it has feelings) and to interrogate it.
Another way is to attempt to describe it in one sentence
or, then it most likely has more than one responsibility.
When everything in a class is related to its central purpose, the class is said to be highly cohesive or to have a single responsibility.
When faced with an imperfect and muddled class like Gear, ask yourself: “What is the future cost of doing nothing today?”
This “improve it now” versus “improve it later” tension always exists. Applications are never perfectly designed. Every choice has a price. A good designer understands this tension and minimizes costs by making informed tradeoffs between the needs of the present and the possibilities of the future.
Methods should also only have one single responsibility
If code inside a method needs a comment, extract that into a seperate method - the method name will serve the same purpose as the old comment.
Small methods encourage reuse
If you have a muddled class with too many responsibilities, seperate those responsibilities into different classes.
An object has a dependency when it knows
A class should know just enough to do its job and not one thing more
Dependency Injection - moving an explicit dependency to an implicit one.
When a message requires arguments, not only can you not avoid having knowledge of those arguments, you also require that those arguments be passed in a specific fixed order.
Use the fetch method to set defaults instead of using ||
Depend on things that change less often than you do
When a class reveals al, it causes difficult to reuse objects
Comparison of classes vs kitchens - the class exists to fulfill a single responsibility but implements many methods
The context that an object expects has a direct effect on how difficult it is to reuse.
Distinction between what what and how
Blind trust is a keystone of object-oriented design. It allows objects to collaborate without binding themselves to context and is necessary in any appliation that expects to gow and change
Duck types are public interfaces that are not tied to any specific class
Inheritance at its core is a mechanism for automatic message delegation