Organisation of this book There are three parts to this story. The first, and necessarily the longest, antithesis: a deconstruction of the state of OOP as it exists today. To get to the kernel of a good idea, you have to crack a few nuts. Part one is the agitation that necessarily precedes revolution. The second part, thesis: a reconstruction of OOP using only the parts that were left over after the antithesis. Part two is the manifesto: once we’ve seen that the last few decades of status quo haven’t been working for us, we can evaluate something that will. The third, synthesis: a discussion of the ideas from OOP that aren’t being provided by today’s object systems, and the ideas and problems that OOP doesn’t yet address at all. These are the next steps to take to pursue the ideas behind object thinking. Part three is the call to action. This is not a pure takedown, a suggestion that we have been monotonically doing it wrong for three decades: the antithesis part of this book questions, rejects and destroys a lot of built aspects of OOP, but by no means all of them. And by no means purely the later ones, either: the message is not that Smalltalk was created in some computational garden of Eden and that Sun tasted of the forbidden fruit which doomed us all to Java. Belief in a primaeval wisdom (urwissenheit) leads to an uncritical “tradition for tradition’s sake” in the same way that belief in primaeval stupidity (urdummheit) leads to an uncritical “novelty for novelty’s sake”. Rather this is an attempt to find a consistent philosophy, a way of thinking about software, and to find the threads in the narrative and dialectic history of the making of software that are supportive and unsupportive of that way of thinking. Because OOP is supposed to be a paradigm, a pattern of thought, and if we want to adopt that paradigm then we have to see how different tools or techniques support, damage, or modify our thoughts. — 6: 60-74
It means relinquishing the traditional process-centered paradigm with the programmer-machine relationship at the center of the software universe in favor of a product-centered paradigm with the producer-consumer relationship at the center. — 12: 156-158
This comes from a good intention - inheritance was long seen as the object-oriented way to achieve reuse - but promotes thinking about reuse over thinking about use. — 19: 274-275
Bertrand Meyer’s principle of Command-Query Separation, in which a message either instructs an object to do something (like add an element to a list) or asks the object for information (like the number of elements in a list) but never does both. — 24: 350-352
A similar partial transfer of ideas can be seen in Test-Driven Development. A quick summary (obviously if you want the long version you could always buy my book) is — 44: 665-667
Behaviour-Driven Development marries the technical process of Test-Driven Development with the design concept of the ubiquitous language, by encouraging developers to collaborate with the rest of their team on defining statements of desired behaviour in the ubiquitous language and using those to drive the design and implementation of the objects in the solution domain. In that way, the statement of what the Goal Donor needs is also the statement of sufficiency and correctness - i.e. the description of the problem that needs solving is also the description of a working solution. This ends up looking tautological enough not to be surprising. Constructing Independent Objects The theme running through the above is that sufficiency is sufficient. When an object has been identified as part of the solution to a problem, and contributes to that solution to the extent needed (even if for now that extent is “demonstrate that a solution is viable”), then it is ready to use. There is no need to situate the object in a taxonomy of inherited classes - but if that helps to solve the problem, then by all means do it. There is no need to show that various objects demonstrate a strict subtype relationship and can be used interchangeably, unless solving your problem requires that they be used interchangeably. There is no need for an object to make its data available to the rest of the program, unless the problem can be better solved (or cheaper solved, or some other desirable property) by doing so. I made quite a big deal above of the open-closed principle, and its suggestion that the objects we build be “open to modification”. Doesn’t that mean anticipating the ways in which a system will change and making it possible for the objects to flex in those ways? To some extent, yes, and indeed that consideration can be valuable. If your problem is working out how much to bill snooker players for their time on the tables in your local snooker hall, then it is indeed possible that your solution will be used in the same hall on the pool tables, or in a different snooker hall. But which of those will happen first, will either happen soon? Those are questions to work with the Goal Donor and the Gold Owner (the person paying for the solution) on answering. Is it worth paying to solve this related problem now, or not? Regardless of the answer, the fact is that the objects are still ready to go to work as soon as they address the problem you have now. And there are other ways to address related problems anyway, which don’t require “future-proofing” the object designs to anticipate the uses to which they may be put. Perhaps your SnookerTable isn’t open to the extension of representing a pool table too, but the rest of the objects in your solution can send messages to a PoolPlayer in its stead. As the variant on the Open-Closed Principle above showed, these other objects could be ignorant of the game played on the table. Some amount of planning is always helpful, whether or not the plan turns out to be. The goal at every turn should be to understand how we get to what we now want from what we have now, not to already have that which we will probably want sometime. Maybe the easiest thing to do is to start afresh: so do that. — 52: 782-807