On monday I left to go to my first day of RailsConf, and as I left housekeeping was making the rounds. One of them who did not speak very much english (which I can’t fault him for since I don’t speak much spanish) asked me something to the effect of “Is everyone out of the room?” and I said yes, because it was true. During my favorite talk that day – Jim Weirich and Joe O’Brien’s Testing, Design, and Refactoring – Joe O’Brien made an offhanded comment something to the effect of:
“As a construction worker, if you put in a light switch six inches too low your boss may be mad, but it’s basically no big deal. In software, if you put in a light switch six inches too low, the stage falls down… what??”
It was a nice little anecdote, and it stuck with me. I had no idea that it would be prophetic.
The talk ended and I milled around a bit and had a chance to talk to some other rubyists/railsists(?), at least somewhat about a word that Jim Weirich had used: Connascence. I am a fan of large, obscure words, but this one relates to something I’ve been thinking about a lot in our code base. I continued to think about it as I went back to my room for the evening to collect my thoughts and hopefully get a blog post together. I jotted down some notes and fell asleep. More on that in a bit. Back to the word of the day: Connascence
Its etymology would lead to a definition something like simultaneous birth, but in software it extends to a sort of simultaneous existence. One thing cannot change without the other changing with it. I’ll explain the first two kinds as they can be explained somewhat concisely.
The weakest form of Connascence is of Name. This is the problem that you want to have. At its base it means that the name of one thing necessitates changing the name of something else.
class User
def name=
...
end
end
def change_name(some_user)
some_user.name = something_else
end
If I decided that the name method on User would be more explicit as full_name, I would have to change any references to that method. Pretty simple.
Next is Connascence of Position, which is still somewhat straightforward:
class Taxi
def drive(from, to)
...
end
end
def transport(some_taxi)
some_taxi.drive(fare.start, fare.destination)
end
In the above piece of code when I call the drive method on taxi, the position of the start and end are implicit. For just two arguments it’s a fairly trivial bit of coupling going on, but say the drive method actually was more like:
class Taxi
def drive(from, temperature, barometric_pressure, rarely_used_parameter, to)
...
end
end
At this point, you can see there is a problem. When I call this method not only do I need to pass in every single parameter, I have to remember the order. What was once a simple method call now turns into something like:
drive("123 45th St", "98F", "119kPa", :with_fish_sauce, "987 65th St")
This can be solved in many ways, like passing in default values, or turning it into an options hash. This would bring us back up to the first we described, CoP.
Although I’d love to write about all of them, I’m sure you’d like me to get to the point, or at least the anecdote I alluded to. If you are interested I recommend you take a look at Jim’s slides from the lecture, and from his talk on fixtures.
The next morning I woke up and went about my business until it came time to take a shower. I opened the drawer and all of my clothes were gone! I stormed down to the front desk with my righteous indignation in full swing and demanded an explanation. Apparently when I said that no one was left in the room to room service they interpreted that as I had checked out. I was promised my clothes back, and sure enough they arrived if not thoroughly wrinkled and in a plastic bag. To add insult to injury it came with a list of my bagged belongings:
blue jeans, underwear,
socks, t-shirts, blouse
I’m pretty sure that was in reference to my v-neck t-shirt, but I guess that’s moot. What’s important here is that in passing a message to the staff, I had introduced some ambiguity that came back to bite me.
In designing and implementing software, we strive to build and maintain clarity of purpose and meaning throughout our code. Although most of the types of connascence are pretty straightforward to understand and fairly familiar to anyone who’s had to work with code, being able to put a name to a smell and a direction from it is an excellent step in maintaining internal consistency without sacrificing clarity.
Next up: Programming is Not Like Music, As Much As I’d Like It To Be