OO languages are thus open-ended. They don’t limit you to a small set of built-in types and pre-predefined operations; you can invent brand new types of your own. Each OO application gradually becomes a unique programming language that is specifically tailored to your domain.
Class-based OO languages like Ruby allow you to define a class that provides a blueprint for the construction of similar objects. A class defines methods (definitions of behavior) and attributes (definitions of variables). Methods get invoked in response to messages.
Sometimes the value of having the feature right now is so great that it outweighs any future increase in costs. If lack of a feature will force you out of business today, it doesn’t matter how much it will cost to deal with the code tomorrow; you must do the best you can in the time you have. Making this kind of design compromise is like borrowing time from the future and is known as taking on technical debt. This is a loan that will eventually need to be repaid, quite likely with interest.
Metrics are useful because they are unbiased and produce numbers from which you can infer something about software; however, they are not direct indicators of quality but are proxies for a deeper measurement.
Agile processes guarantee change, and your ability to make these changes depends on your application’s design. If you cannot write well-designed code, you’ll have to rewrite your application during every iteration.
Agile works because it acknowledges that certainty is unattainable in advance of the application’s existence; Agile’s acceptance of this truth allows it to provide strategies to overcome the handicap of developing software while knowing neither the target nor the timeline.
If Agile is correct, two other things are also true. First, there is absolutely no point in doing a Big Up Front Design (BUFD) (because it cannot possibly be correct), and second, no one can predict when the application will be done (because you don’t know in advance what it will eventually do).
If you think of software as custom furniture, then principles and patterns are like woodworking tools. Knowing how software should look when it’s done does not cause it to build itself; applications come into existence because some programmer applied the tools. The end result, be it a beautiful cabinet or a rickety chair, reflects its programmer’s experience with the tools of design.
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.
Your job is one of synthesis; you must combine an overall understanding of your application’s requirements with knowledge of the costs and benefits of design alternatives and then devise an arrangement of code that is cost effective in the present and will continue to be so in the future.
Every application is a collection of code; the code’s arrangement is the design.
Object-oriented design is about managing dependencies. It is a set of coding techniques that arrange dependencies such that objects can tolerate change. In the absence of design, unmanaged dependencies wreak havoc because objects know too much about one another.
Object-oriented applications are made up of parts that interact to produce the behavior of the whole. The parts are objects; interactions are embodied in the messages that pass between them.
Changing requirements are the programming equivalent of friction and gravity. They introduce forces that apply sudden and unexpected pressures that work against the best-laid plans.
[...] something will change. It always does.
Failures of OOD might look like failures of coding technique, but they are actually failures of perspective.
When the cost of doing work exceeds its value, our efforts feel wasted. If programming gives joy it is because it allows us to be useful, when it becomes painful it is a sign that we believe we could, and should, be doing more.