Makers Academy Bookclub: Our thoughts on Sandi Metz’s POODR (Chapters 2–5)
It was with great pleasure that we met for our third weekly session of the Makers Academy Bookclub. We were looking forward to learning about how to improve our understanding of object oriented programming and we all loved Sandi Metz’s thoughtful and clear style in explaining difficult concepts relating to program architecture with Ruby: http://www.poodr.com/. The promises of the book were huge. We would learn how to decide what belongs in a single class, avoid entangling objects that should be kept separate, define flexible interfaces among objects, reduce programming overhead costs with duck typing, successfully apply inheritance, build objects via composition, design cost-effective tests and craft simple, straightforward understandable code. We were quickly becoming evangelistic pooderers if that was the correct collective noun for our desired outcomes.
There was so much to learn and discuss and we turned first to chapter 2 and the acronym TRUE. This stood for Transparent (being descriptive about the dependency of various classes and seeing where the change is happening), Reasonable (recognising the costs of programming in terms of time and team expenditure and operating within our limitations), Usable (we needed to learn how to create code that others could understand and which would withstand change effectively) and Exemplary (we wanted our code to be so simple and clear that it stood as an example for others to follow).
The first big tip that we learnt was that we could create pared down versions of classes called structs. A struct was a light weight way to create a mini class within the class:
This would be different from a module because we could have instances of it however it allowed us to be very clear on dependencies. All knowledge of the structure of teh incoming array was isolated inside the wheelify method which converted the array of Arrays into an array of Structs. We could therefore use Structs to wrap structures.
Sandi Metz also helped up to determine when to make design decisions. We could delay the decision and aim to abstract the data that each class was being presented with. A great tip for working out whether a class was doing too much was to speak to the class and imagine what the answer would be. We needed to recognise dependencies and learn how to manage them.
We then moved on to duck typing. As Sandi Metz put it regarding the Gear and Wheel classes in her application: “Gear needs access to an object that can respond to diameter… Gear does not care and should not know about the class of that object. It is not necessary for Gear to know about the existence of the Wheel class in order to calculate gear_inches. It doesn’t need to know that Wheel expects to be initialized with a rim and then a tire; it just needs an object that knows diameter.” (Metz, POODR, 41). This was an important point because it reminded us that we could give classes a piece of information and decide how much we wanted to tell it. We took note and remembered that we needed to reduce dependency in our classes almost in the same way was we might reduce “alien” bacteria. Our dependencies needed to be “concise, explicit and isolated.” Sandi moved on from showing us how to use hashes as arguments for Classes in order to worry less about order to managing dependency direction. The main advice for classes was: “depend on things that change less often than you do.” (page 53).
In chapter four we then made the important discovery that object oriented programs are: “made up of classes but defined by messages. Classes control what’s in your source code repository; messages reflect the living, animated application.” (page 59). We learnt about the difference between public and private interfaces: private were less stable whereas the expectations of stability were higher for public methods. Finally, we learnt about Sequence Diagrams which were a handy way of learning about the messages that classes sent to each other:
These were helpful means to understand how classes sent messages to each other and reminded us that we didn’t send messages because we had objects but we had objects because we sent messages. Sandi explained that the class trip acted as an interfact between Moe Customer and class Bicycle. In my experience of the weekly challenges such as Oystercard and Takeaway I had noticed that it was possible have a kind of “god class” which acted as an interface between all the other classes and I also recognised that this interfacing could take the form of dependency inversion in which the way of designing a class structure is start from high level modules to the low level modules. So, for instance, in Oystercard we had an Oystercard class which communicated with a JourneyLog which then communicated with Journey:
Oystercard ===> JourneyLog ===> Journey
In JourneyLog we needed to create an abstraction layer to decouple the higher level class (Oystercard) from the lower level class (Journey). This meant that any changes made to either the Journey class or the Oystercard class cannot affect each other because we would be able to modify their interaction with each other through JourneyLog.
We finished our study session with a clear idea of the possibilities of excellent code structure and architecture. It was humbling to reread Sandi’s thoughts on the deep questions of Object Oriented Design and we looked forward to exploring these and other questions further in our next meeting.