Growing Object-Oriented Software, Guided by Tests (Addison-Wesley Signature Series (Beck))
Nat Pryceamazon.com
Growing Object-Oriented Software, Guided by Tests (Addison-Wesley Signature Series (Beck))
Loosely speaking, we use the message-passing style we’ve just described between objects, but we tend to use a more functional style within an object, building up behavior from methods and values that have no side effects.
Break up an object if it becomes too large to test easily, or if its test failures become difficult to interpret. Then unit-test the new parts separately.
When we want to mark a new domain concept in the code, we often introduce a placeholder type that wraps a single field, or maybe has no fields at all. As the code grows, we fill in more detail in the new type by adding fields and methods. With each type that we add, we’re raising the level of abstraction of the code.
One of the symptoms of an unstable development environment is that there’s no obvious first place to look when something fails.
Never write new functionality without a failing test.
Our purpose, in the end, is to achieve more with less code. We aspire to raise ourselves from programming in terms of control flow and data manipulation, to composing programs from smaller programs—where objects form the smallest unit of behavior.
We value code that is easy to maintain over code that is easy to write.1 Implementing a feature in the most direct way can damage the maintainability of the system, for example by making the code difficult to understand or by introducing hidden dependencies between components.
We should be taught not to wait for inspiration to start a thing. Action always generates inspiration. Inspiration seldom generates action. —Frank Tibolt
When extracting implicit components, we start by looking for two conditions: arguments that are always used together in the class, and those that have the same lifetime. Once we’ve found a coincidence, we have the harder task of finding a good name that explains the concept.