What Does OO Afford? — Sandi Metz
-->
Home
Products
Courses
Speaking
Blog
About
Contact
What Does OO Afford?
I've been thinking about the affordances of programming languages.
A Little Background
In my previous post,<br>Breaking Up the Behemoth, I posited an explanation for why OO apps so often evolve a few, disproportionally large, unmaintainable, condition-filled classes. Unfortunately, that post didn't offer a cure for this problem; it just gave the less-than-helpful advice that you avoid that situation.
This post continues to explore the problem of classes that get too large. My hope is by that learning to recognize the imminent appearance of the big-class-slippery-slope, you can avoid accidentally sliding down it.
Most of the ideas here are my opinion. Although this post starts out by examining a broad, general idea, I promise that it does, eventually, directly address object-oriented programming. Read on for the general introduction, or skip forward to the OO specifics, as your inclinations dictate.
Consider the Doorknob
So, what are affordances? Merriam-Webster defines<br>affordance<br>as "the qualities or properties of an object that define its possible uses or make clear how it can or should be used." Wikipedia's<br>affordance disambiguation page<br>more concisely suggests "a potential action enabled by an object."
The term was coined by psychologist<br>James J. Gibson<br>in his 1979 book<br>The Ecological Approach to Visual Perception<br>, where he offered this definition:
"The affordances of the environment are what it offers the animal, what it provides or furnishes, either for good or ill. The verb to afford is found in the dictionary, the noun affordance is not. I have made it up. I mean by it something that refers to both the environment and the animal in a way that no existing term does. It implies the complementarity of the animal and the environment."<br>--Gibson (1979, p. 127)
(I find myself tickled by his blithe confession that he just plain "made it up". If not for the fact that it would take us on a terrible tangent, I'd pause here and make up a few words myself.)
Here are a few real-world examples to illustrate the meaning of affordance.
Figure 1
Figure 2
Figure 3
Figures 1, 2 and 3 show examples of hardware used to unlatch and open doors. The different styles suggest different usages.
The knob in Figure 1 affords grasping by hand, turning to unlatch, and pulling to open. While it clearly offers grasping, turning, and pulling, it supplies no information about whether pulling on the knob will actually open the door. Even though the knob clearly can be pulled, pulling on it might not give you the results you want.
The lever in Figure 2 differs from the knob in that it affords unlatching by pushing up or down by any means, so you can use it even if your hands are occupied or unavailable. I have levers in my house and can highly recommend them. They are way more convenient than round knobs.
Figure 3 is Figure 2 but with an added sign to solve the push-or-pull-to-open-the-door problem. The need for a sign suggests that the design of the hardware fails to offer a complete set of affordances. If the usage were clear from the design, there'd be no need for additional, written directions.
In contrast, here are three other styles of door hardware. The first thing to notice is that these options are just for opening the door, that is, they don't have any responsibility for unlatching.
Figure 4
Figure 5
Figure 6
The styles above convey all of the information you need to use them correctly. The ring in Figure 4 makes it obvious that the door swings towards you, i.e. that pulling opens the door.
The reason Figure 5 feels wrong is that it's over-specified. The handgrip suggests pulling so strongly that the sign feels a bit insulting.
The push plate in Figure 6 is what you'd expect to find on the opposite side of the doors shown in Figures 4 and 5. Plates very obviously afford pushing, and so pair naturally with things that want to be pulled.
Different Programming Languages Offer Different Affordances
Just like varying styles of doorknob, different programming languages offer their own unique affordances. Language designers have preconceived ideas about the best way to model reality, and their creations reflect these biases. Thus, programming languages are explicitly designed to "enable" certain kinds of thinking.
I'm talking about something that's deeper than syntax. Languages have points-of-view: they're designed to be used in certain stylized ways. The mere fact that code compiles doesn't mean it's arranged as the language designer intended.
While it's possible to warp most any programming language into use by an alternate way of thinking, working at cross-purposes from your language's intentions is not the most efficient way to write code. Don't roll this rock uphill. If you don't understand your language's affordances, learn them. If your coding inclinations conflict with the...