August 9, 2013

...Learn TDD with Codemanship

The Trouble With OO Design...

Every week in Codemanship training courses I see teams struggling to get their heads around what some might call "proper" object oriented design.

For sure, they're usually experienced programmers who've been working in the OO paradigm throughout their careers. But they've been the victims of a misconception about object oriented design that is so pervasive that it's widely accepted as the received wisdom.

I think, instinctively, we want our OO designs to make sense in the real world.

In the real world, there are inanimate objects like chairs and money and museum exhibits and invoices and such like. Animate objects act upon these inanimate objects to make useful stuff happen. Therefore, in our minds, agency and data tend to be separated. Objects tend to become one of two things: agents who act on objects, or objects who are acted upon.

This can lead to a style of design where objects that do stuff query and manipulate objects that know stuff, which tends to require lots of low-level coupling between the do-ers and the know-ers in our software.

As Uncle Bob Martin and others are keen to point out, the real goal of good OO design is to minimise coupling between the different components in our software.

When we don't minimise coupling - by internalising dependencies as much as we can inside classes, and by favouring dependencies on abstractions between classes to make substituting implementations ("swappability") easier - we end up with software in which even the tiniest changes can cause big ripples to spread out along those couplings, causing a higher cost of making those changes.

While it's highly desirable for our code to make sense in the context of the problem it's designed to solve, so we can better understand it, we must try to remember that we're not necessarily building a model of the real world.

In OO, the cat kicks itself, so to speak.

For example, in my TDD course, participants are asked to come up with a high-level OO design for a simple theatre box office that allows us to reserve and pay for seats at a performance. Despite pre-warnings about what we call "data-centric" architectures, where agency and data tend to be separated (e.g., services acting on business objects), and strong encouragement to follow a "Tell, Don't Ask" style in which objects that know stuff should take responsibility for doing stuff with the stuff they know, I see week after week very capable developers struggling to accept that a seat can indeed reserve itself. Surely the box office reserves the seat? That's what happens in the real world.

But if the seat is the object that knows who it is reserved for, then we can minimise the knowledge that gets spread around our system by telling it to record that information itself. It's the seat's business.

Put the behaviour where the data is.

Posted 7 years, 4 months ago on August 9, 2013