P&P Summit Day Two: Evolving to Patterns
The second talk of the day was given by James Newkirk, one of the original drivers behind NUnit. He starts with discussing the underlying longevity of the principles of software patterns. His example was the fact that the Design Patterns book was written in 1995, but is still relevant today and sits on the shelf of most of the people in the room.
James talks about the Open/Closed principle. Open for extension, closed to modification. His example is using the strategy pattern to allow for extension, but the use of the code using the various strategies doesn’t change so it’s closed. This has both benefits and liabilities, for example, it abstracts the algorithm from the code and allows for extension, but also produces increased number of objects.
The importance of Context is important in that a pattern is a definition of a problem and a solution within a context. A different context may make a pattern not usable to solve the problem that it solved in another context. He gives an example where the observer pattern described in the Design Patterns book may lead you to inherit from the subject class, whereas in the context of .NET you could use delegates and events rather than the inheritance since we have single inheritance.
James then goes on to talk about when should patterns be added to a system. His answer is both during design of new systems and when you see bad code in existing systems. Another rule of thumb to ensure you don’t over-engineer you should use the rule that says “the second person pays”. He describes this by saying the second person should pay the cost for implementing the pattern when it is necessary due to a requirement. The original developer should not implement a pattern unless they need it via a requirement, but should also ensure they don’t implement something that will keep them, or the second person, from implementing this later.
This practice of developing only what’s needed at the time leads to what people call “Evolutionary Design”. It’s programming in the presence of change of scope, requirements, and technology.
James wants to create a new metaphor for software architecture. Instead of using the metaphor of software architecture is like building architecture, he would rather use software is like landscape architecture (as in parks). Since code is more malleable than steal, it’s easier to change code structure and purpose. Just like it’s easy to move landscape elements around to construct a more beautiful park and outdoor space that adapts to its uses, it’s easy to move code around and repurpose it for other uses and extensibility. We do this with software by refactoring our code.
He uses the example of “Broken Windows”, which is not a metaphor for a blue screen, but a reference to a crime study about as buildings are left to deteriorate more crime starts to appear around the building that were not taken care for. Refactoring says we will not live with broken windows in our software and we revisit it when necessary to ensure it stays up to date and useful. Since I have a law enforcement background I was one of two people that were familiar with the origin of his metaphor. I guess that’s my Police Administration degree at work.
He talks about when to Refactor. He uses the example of his wife agreeing to cook if he cleaned. Since she didn’t have a reason to clean up as she went since she was not responsible for cleaning the kitchen looked like a bombshell went off. His point is that we should “clean as we go” so that we are ready for the unexpected, such as a guest showing up at the last minute, etc. Interesting metaphor. Of course, for refactoring to work you have to have tests that will back up the fact that refactoring didn’t break anything.
He switches gears to talk about some test cases and the propagation of errors in your testing. If you make one of your test cases fail and then there is a waterfall effect that kills the rest of your tests (or a good deal of them) your tests are NOT isolated enough. This is where Dependency Injection will help out.
To close he gave some resources:
- Working Effectively with Legacy Code
- Refactoring to Patterns