Object-Oriented Analysis and Design: A lost art?
At the 93rd SPIN meeting, Herman Lintvelt (@hermanlintvelt) of Polymorph gave an impassioned talk about Object-Oriented Analysis and Design. He encouraged lots of audience interaction: asking for definitions of and opinions on the concepts he was discussing, and made great use of the flipboard for sketching out examples. Below are my notes from his talk. View his slides.
Herman is passionate about OO, when it's done well. He believes that Agile is the best way to build software, whether you're a small company, or a large multi-national corporate. Agile and OO are often in conflict, though. His talk was about going back to basics for OO, and seeing how OO Analysis and Design complements Agile development.
What is OO Design?
What is an Object? It's a thing that has properties and performs action / it has attributes and has behaviours.
Why do OO Design? It works well, it's logical, and creates reusable code. It's closer to the real word, to our mental model.
What is OO Analysis?
An example: Customers. Who, what, what do they do, etc. It's figuring out what they are and do: the conceptual objects and tasks.
People often skip this stage, but they shouldn't. It can be done iteratively. Do Agile modelling, lightweight UML modelling, for understanding and communication rather than producing documentation.
This should include modelling with others and creating several models in parallel (some will die, and that's okay. It's exploration, and it's cheap to do on a whiteboard). The final code design will probably diverge from this.
Static vs Dynamic modelling
Class diagrams are a classic example of static modelling. Dynamic modelling helps design system logic, behaviour of bodies. It's often the most difficult, so we often skip it, but it's also the most interesting. It's much richer than Static Modelling. Use a UML sequence diagram.
On Dynamic Modelling
Tip #1: Spend time on **interaction** diagrams, not just class diagrams.
It will force you to think about the exact details of what objects exist and how they collaborate with messages and methods.
This is the core of OO. Herman recommends checking out Craig Larman's book on the topic.
RDD (Responsibility Drive Development): think about responsibilities, roles, and collaboration. There are two types of responsibilities: doing and knowing.
RDD views OO Design as a community of Collaborating Responsible Objects.
CRC (Class Responsibility Collaboration) Cards
Tip #2: Use CRC Cards.
CRC Cards were popularised by Kent Beck and Ward Cunningham as part of XP (Extreme Programming). An index card containing containing the name, responsibilities and collaborators of an object.
They're useful when talking in a group, after the analysis phase (use cases, user stories), making objects from nouns in user stories. It can be useful to play "What If?" games with the cards: pick a few cards and try to minimise the responsibilities of them. This is good for figuring out what should do what.
Object-oriented design with GRASP (General Responsibility Assignment Software Patterns)
Tip #3: Use GRASP guidelines
GRASP defines 9 basis OO principles / patterns: basic building blocks to use. Herman uses these in the OO workshop that he runs at Polymorph. The guidelines help you to understand OO reasoning.
Herman ran through an example on a whiteboard of this, and recommended reading Martin Fowler's article on UI design patterns.
Herman talked through SOLID principles for OO Design.
- Single Responsibility principle. "Just because you can, doesn't mean you should." Makes your code more flexible, loosely coupled.
- Open / Closed principle. "Open chest surgery is not needed when putting on a coat." Classes are open for extension, but closed for modification.
- Liskov Substitution principle. "If it looks like a duck, quacks like a duck, but needs batteries: maybe you're using the wrong abstraction." Subtypes must be substitutable for their base types.
- Interface Segregation principle. "You want me to plug this in, where?" Clients should not be forced to depend upon interfaces they don't use.
- Dependency Inversion principle. "Would you solder a lamp directly to the electrical outlet?" High level modules should not depend on low level modules: they should both depend on abstractions.
Doing Dynamic modelling finds problems that Static modelling doesn't.
Tip #4: Use Use Cases to test your design.
Look at the behaviour of objects.
Tip #5: Use TDD (Test Driven Development) to test the design.
Herman said Tip #5 was the most important tip of the night.
Tip #6: Remember the Law of Demeter.
Also known as the principle of least knowledge.
Ask, Don't Tell.
Tip #7: Use OO Design Patterns.
You are doing OOD if your code is:
- can be changed with minimal effort
- can be extended without changing existing code
This doesn't mean big, upfront, planning.
Herman recommended reading the article "How I explained OOD to my wife".
Discussion after the talk
In the discussion after the talk, an audience member asked if Herman could suggest an approach for good Dynamic modelling. He suggested thinking of your system as a black box at first, and looking at System events that trigger Use Cases. Start with a high level Sequence Diagram, and look System -> Objects -> System Diagram.