Models are a convenient approximation, not a complete account

by Jason Swett,

Someone recently criticized some code I wrote in a class called SomeNamespace::File. (The particular namespace is not important.) Here’s the criticism:

I’d argue that the class name is misleading here: it does not represent a file, it does not read it or check its chmods. It’s a file writer.

The implication seems to be that a class can’t truthfully be called File unless the object does certain “filey” things, like reading the file and checking its chmods, in addition to just writing to the file.

I think this is a mistaken outlook. However, it is intuitive outlook, and one I used to share myself. I’ll explain why I think the outlook is mistaken via a couple examples.

Two pocketknives

Let’s say I own a pocketknife. In different scenarios this pocketknife can serve me in different ways. For example, I might take my knife camping and use it to chop vegetables for dinner. At another time, I might take my knife into a dark alley where I use the knife to stab people.

In one scenario I could conceive of my knife as a Camping::PocketKnife. In the other scenario I would conceive of it as a DarkAlley::PocketKnife. It wouldn’t serve me well to merge all of the knife’s potential uses into one class. This would make the code harder to understand and change.

And it certainly wouldn’t be necessary or desirable to model all the characteristics of the knife including the material it’s made out of, the brand of the knife or any other details that aren’t relevant to the aspects of the knife that we need to work with.

A model is a convenient approximation, not a complete account. Just because a complex item exists in the real world doesn’t mean that a model has to represent all parts of that item’s complexity. It’s also true that a real-world item can have multiple different models that each look at the item from different angles.

Appointments in different contexts

I think my pocketknife example is a good illustration because it’s easy to understand but it’s also a bad example because we’d never model a pocketknife in such a way. Here’s a more realistic example.

Let’s say we have a medical application. In our application, patients schedule appointments with doctors. Sometimes we care about appointments in a clinical sense. Sometimes we’re interested in an appointment in a scheduling sense. At other times we’re interested in an appointment in a billing sense.

If I have a model called Billing::Appointment, someone could conceivably criticize that class as being inappropriately called an Appointment, because the class doesn’t include anything to do with scheduling. They’d be missing the point though. I’m not trying to model a whole appointment at a time, in all its possible aspects, just as I’m never trying to model a whole pocketknife at a time in all its possible aspects. I’m only trying to model the part I care about in a certain context.

Takeaway

A model is a convenient approximation, not a complete account. A model only needs to represent the slice of reality that we care about in that particular context.

Leave a Reply

Your email address will not be published. Required fields are marked *