A look at how to keep your code clean and lean using TDD. Notes inspired heavily by Freeman and Pryce's 'Growing Object-Oriented Systems Guided By Tests'.
that writing tests: • makes us clarify the acceptance criteria for the next piece of work—we have to ask ourselves how we can tell when we’re done (design); • encourages us to write loosely coupled components, so they can easily be tested in isolation and, at higher levels, combined together (design); • adds an executable description of what the code does (design); and, • adds to a complete regression suite (implementation);
while the context is fresh in our mind (implementation); and, • lets us know when we’ve done enough, discouraging “gold plating” and unnecessary features (design).
Pryce suggest that a couple of important questions aren’t easy to answer: • How do we know where to start writing code? • More importantly, how do we know when to stop writing code?
• When we’re implementing a feature, we start by writing an acceptance test... • While it’s failing, an acceptance test demonstrates that the system does not yet implement that feature; when it passes, we’re done. • When working on a feature, we use its acceptance test to guide us as to whether we actually need the code we’ re about to write—we only write code that’s directly relevant.
of a recipe for achieving lean BDD with Rails. We can do something similar: 1. Start by writing your acceptance tests. Identify any required changes to the UI (i.e. fragments or activities). 2. Drive out the UI changes with unit tests, using the red/green/refactor cycle. 3. Drive out any necessary changes to models/providers using the red/green/refactor cycle. 4. Drive out any necessary changes to the gateway/endpoints using the red/green/refactor cycle. 5. Run your acceptance tests, to demonstrate the acceptance criteria are satisfied.
• Increases the burden of maintenance and testing. • Adds further complexity to the codebase, which must be understood by others on the team. The best kind of code is no code! Write only what you need, not what you think you might need.
code you write: • When clauses can help you identify the “outside” code to start with. • Then clauses can help you identify what code is necessary. Don’t write anything which doesn’t help you meet the acceptance criteria.
smallest possible increments: • Only write the next test you need (as suggested by your acceptance criteria). • Only implement the next lines you need to make your test pass. • Only refactor the code you’ve written. Avoid gold- plating or over-generalizing.
design. • As Bob Martin puts it: “To write clean code, you must first write dirty code and then clean it”. • If you try to write clean code first: ◦ You’ll make assumptions about your design, and probably introduce unnecessary complexity. ◦ These assumptions may make it harder to clean your code, because you’ve anchored yourself with extraneous code. • Refactor, separate concerns and clean your code all you like: but only do so with the code you know you need.
to guide the code you write. 2. Follow the red-green-refactor cycle using the smallest possible increments. 3. Apply “Successive Refinement”; avoid significant upfront design.