Friday, October 16, 2015

Dot-Programming your Object Oriented Code

I was once told to "exalt the obvious."

There is a power in it, because sometimes we overlook obvious things that are blessings to us and can reshape our world. This, I think, is one such.


'Way back in the 80s and 90s we were trying to get people to practice Object-Oriented Design and Object-Oriented Languages were gaining a bit of ground. Heck, in '86 or so C++ started to be a big deal, because it mixed some OO with our beloved C. Soon we saw semi-OO BASIC and even a version of Object-Oriented COBOL. Wow.

We tried to codify principles and practices that helped people to do good design. You probably followed all the great stuff we did at Object Mentor, led by Uncle Bob Martin (who I still appreciate and respect, though we don't see each other very often).

We expounded on coupling and cohesion, as well we should, but we lacked the mechanism in our programming environments to help us really seat the idea of OO in the minds of our fellows.

Serendipity

Well, in the meantime, the IDE manufacturers (and plugin writers, God bless them) created something that solves 1/2 of the problem. They created smart code completion.

Yes, it was a long time ago. And yes,  it's everywhere, from IntelliJ and Eclipse to Pycharm and Idle, from Vim's to Emacs. Nothing new in the mechanism here.

Heck, most of us wouldn't want to consider using an editor that couldn't give us some kind of smart completion. It would be like working in edlin.



And, dolts that we are, we said "oh, that's kind of nice" and we went about our business as usual, and didn't react to the amazing manna from heaven that this innovation represents.

We snatched defeat from the jaws of victory!

What were we thinking?



See, what this really gives us is..... ....
DOT PROGRAMMING


So, basically, you type the name of a thing and then a dot, and you're given a list of actions that the thing can perform.

Big deal, you're still saying?

Okay. Let me slow this down for you.

When you write a program, you will not read the documentation. You don't have time and inclination for that.

You don't memorize the class hierarchy or the class interface. There are far too many classes and you are far too smart and mobile and frankly short on time to spend a bunch of time memorizing stuff. You are no fool.

You won't read all the code. Nobody reads all the code. The days when you wanted to write long methods so that people can read them from top-to-bottom are over. That's dead. Dead like .bat scripts and CP/M. It's over.

So now, you're working in a class and you type the name of some object and you press the dot. The list that pops up is your guide to the world of the object whose name lives on the left side of the dot you just pressed.

And you know everyone else is doing the same thing.

THEREFORE:

When you write a method that does anything remotely interesting, you have one VERY important question to answer:

When someone needs this method, where will they look for it?

Or, slightly rephrased:
What object should be on the left of the dot? 

Let's say the object is a "Playlist." Don't worry about what that means, just stay with me here. And assume you're writing a report to say which playlists are used by which accounts in the system, and how long each one is. Just imagine that's valuable.

Failure Is Always An Option

You could, of course, write a method that takes a Playlist object and returns the number of items contained in the playlist. That's useful. Before you really understood the universality of DOT PROGRAMMING you might have written it as a local function to avoid "mucking with the design."

But now you're enlightened.

Now you realize that most people who need a playlist's length probably won't go looking for it in your crummy little report class out in the jerkwater corners of the application.

Their cool new code should have nothing to do with your report class. This is especially true if their code is in the UI or Web Page or deep in the business logic.

Your current code will not be the object on the left of that dot.

You can leave it where it is, but that doesn't sound like such a great idea now.

Cohesion: The Single Responsibility Purpose

Where did you look for the length function? Why, you looked for it as a method on the Playlist.

When you saw it didn't exist, you wrote your method into the report.

It would have saved you time if the method already existed on the class where it operates.

And then it hits you. When the next programmer doesn't see it pop up as a choice on the Playlist object, they're going to write it too. And the next one. And the next.

Everyone will duplicate this method unless they find it in the one place that it really belongs (ie that it is expected) in the code base.

And they might mess it up. And then you're going to think your method is at fault and go debugging in the wrong place, possibly. That's going to suck.

This waste will continue until someone decides to move the method to someplace where their coworkers can find it ... and then they'll have to find and delete all the duplicates that have popped up or else there will be bloat everywhere.

Oh, no. There probably already is.

Feature Envy

But the method is all about the Playlist, and only touches methods and variables of the Playlist. It really has almost nothing to do with your report. It's in the wrong place.

And sure enough, it's in four or five other places.

Refactoring

So you resolve to move the method to the only reasonable place where it won't cause duplication and frustration and wasted effort -- to the Playlist class.

And you'll get rid of the duplicates.

Quality

But if you're going to put it on the Playlist class where everyone is going to be able to call it, then it had darned well better work. You don't want to be the fault of future failures.

So you pick the best (most comprehensive or performant) of the existing methods. Maybe we combine the strengths of two or more of those methods together.

Then we methodically replace the calls to some local getPlaylistLength and getPlayListSize and countOfItemsInPlaylist with Playlist.getLength(). So far everything seems  to still work.

So I guess we'd better write some automated tests that put this thing through its paces and are wise to its subtleties, like recursive containment and non-unique contents, and .... wait, are we using the right data structure for this?

Now we've got testing (though it's post-facto) and design thinking, because if we put it in the right place, then its quality matters.

Embrace Dot Programming

An object-oriented system is really a system organized like a big filing cabinet. Things (data, methods) are located where you expect them to be.

Dot Programming is just Object Oriented Programming, if we decide to listen to what our code is telling us about the social context of our work.

No comments:

Post a Comment