It's not about code reuse, it's about maintenance

Uli Kusterer has an article on his blog about what he calls “Cocoa ground rules.”

Since I’ve seen many people violate two ground rules of object-oriented programming (OOP), I thought I’d list them here, in the hopes it’ll help some beginners not fight the frameworks but rather go with the flow in Cocoa:

Uli then lists encapsulation and designing for code reuse as the ground rules. Now Uli is giving some good advice here, but I’d like to nit pick him here a bit for my own personal agenda… I mean, for the good of the people. Yeah, that’s it, the good of the people.

I propose that designing for code reuse, in most cases, is not the best thing to do. Allow me to explain.

Think about the times that you actually reuse code, in real, live applications. Its usually data structures, generic algorithms (like sorts and searches), and standard controls. Now think about where you find such code. That’s right, the basic data structures, algorithms, and UI widgets that you reuse in different applications are provided by the operating system or language for you. You don’t need to implement them, and, in general, shouldn’t try to. Apple is smart and realizes that applications get developed faster when developers don’t have implement basic data structures etc, that the operating system could provide for them.

Since the operating system and programming language provide most, if not all reusable classes, what’s left in your application is the application-specific classes. By definition application-specific code doesn’t typically have reuses in other applications, unless you’re writing competition for yourself. For example, if you have a class that reads in a SVG document, then you are probably drooling on yourself from having to read that insane specification. Plus, its unlikely you’ll need that SVG reader class in another application unless its also a SVG editor.

Now some of you think you have just spotted a hole in my logic. What if you have an application that is a lightweight SVG viewer and then a full-featured vector editing application? Both are plausible products that would need a class to read SVG documents. But they will have very different uses of the SVG reader class. The lightweight viewer will want to quickly build up the graphics state and draw, while the editor will want to keep the SVG DOM around so it can be edited later. Not a problem, you can abstract the SVG reader class to simply use callbacks on the delegate and let the delegate build up a DOM or whatever it needs to do to be efficient. That fixes the problem.

Right?

Except that the whole “abstracting” part is real hard. Very hard, especially if you haven’t implemented all the possible users of the class yet. As any API designer will tell you, it’s difficult to anticipate how a class is going to be used. That can lead to one of two situations: a class that isn’t abstracted enough to be used by multiple client classes, or a class that’s over engineered and very hard to use. Neither is ideal, but I will argue that being over engineered is worse.

Over engineered code is often bug riddled because of its complexity. It also runs the risk of having untested code in it, where the implementor said, “I don’t need this method now, but someone might need it later.” This introduces code that may or may not work, but creates the illusion, by being in the codebase, of being tested. That’s very bad. Over engineered code, as a result of being complex, also has a higher rate of being abandoned by potential users. If another programmer can’t figure out a class, they’re much more likely to create a new class to do what they want. On the other hand, if they see a simpler class that they understand, but doesn’t quite do what they need, they are more likely to enhance it to meet the original need and theirs as well.

I’m not saying code reuse is bad, I’m saying code reuse as a goal can be bad. In the stead of code reuse, I propose a new goal (or old, depending on how long you’ve been around).

As I so convincingly showed above, achieving code reuse is quite often not an attainable or realistic goal, because it so rarely happens. But what does happen a lot, and is in fact inevitable, is code maintenance. No matter what you write, you will have to maintain it at some point, unless you write really crappy code that no one in their right mind wants to use. There are several reasons why maintenance is more important than reuse:

  • Money. More money is generated from product upgrades (maintenance) than the initial release.
  • Time. Maintenance is where the product spends most of its life cycle.
  • Code reuse itself. As I said above, most code reuse is achieved by modifying simple classes to meet the needs of additional clients.

Now that everyone knows that code maintenance is where developers spend their time, and make their money, we should optimize for it. How do we do that? Well, we need some new ground rules for that.

The ground rules of any programming, whether object-oriented or otherwise, lies in two terms: cohesion and coupling. Hopefully you remember these terms from your computer science classes, but in case you were getting a bikini wax that day, I’ll define them.

Cohesion describes the internal relationship of a module, or in OOP terms, a class. High cohesion means that everything in the class is tightly related (e.g. the x and y member variables in a point class), where low cohesion means that everything inside is only loosely related, if at all (e.g. the Windows Registry).

Coupling describes the external relationships of a module or class. High coupling means that a class is very dependent on other classes, such as deriving from them or declaring them as friends. Coupling can also be the use of other classes or aggregating instances of other classes. Low coupling means that a class or module pretty much stands on its own. i.e. It doesn’t need other classes to compile or run.

Ideally, you want high cohesion and low coupling.

High cohesion and low coupling improve code maintenance in some simple ways. High cohesion means you don’t have to go searching everywhere in the codebase to find everything about, say, vectors. Its all in one place. Which means the code is easier to understand, and also modify. Low coupling also means that code is easier to understand, because you don’t have to understand how several classes work (such as a class and its parents and friends), but just a minimal set. More importantly, low coupling means the code is easier to modify. Since code isn’t tightly coupled, then you can modify code in one class and not have to worry about it effecting a class its not coupled to. This extremely important in large software systems, like when you’re trying to figure out why moving a button in a dialog changes how your preferences are written out.

“Fine”, you say, “I want high cohesion and low coupling, but it sounds like proper encapsulation will get me that, which in turn will lead to code reuse, easier maintenance, and incredible abs. How is that any different from what Uli said?”

The goal is different. You’re goal is not code reuse, although it might be a welcomed side effect. Your goal is easy code maintenance. Focusing on how to make things easier to maintain, as opposed to reusable, changes how you code your classes. Instead of spending time trying to guess all the possible uses of a class and making them generic as possible, you code it to satisfy the needs of its current clients efficiently. As different clients require its use, then you modify the class to accommodate them.

In all fairness, reusability for Uli is really important. But its not because of programming ground rules, its because of product requirements. Uli has lots of sample code, and the primary feature of sample code is reuse. That said, I would still argue that it is more important that the sample code be maintainable than outright reusable by everyone. Its impossible to guess all the possible ways a Cocoa view could be used, so its more pressing that it can be understood and modified by the user to do what’s needed.

In computer science you should always optimize for the common case. Which is code maintenance, not code reuse.

(P.S. My apologies to Uli if I have misrepresented anything you said. Your comment on code reuse got me thinking about the people who rant and rave about code reuse as if it were the Holy Grail.)

Objective-C 2.0

Andy Matuschak has a great write up on what to expect in Objective-C 2.0. As someone who didn’t make it to WWDC this year (one of my business partners got to go this year), I found the article very informative.

What’s more, he managed to describe the changes to Objective-C using only publicly available sources (i.e. no NDA violations). Very impressive.

Xcode scavenger hunt

I’ve always enjoyed a good scavenger hunt for the way it can get rid of unwanted people without hurting their feelings. This is why they’re particularly effective at the end of a party, when you’re busy, or when you need a reason to have random people arbitrarily obey your whims and enjoy it.

Organizer: Here, go look for these random objects I just thought up!

Participant: OK! Where do you think I can find one of these “cow catchers”?

Organizer: Just stand on these tracks and it’ll come right to you.

Participant: Wow, thanks! I love scavenger hunts, they’re so fun!

But I digress.

Surprisingly, there are ways to have a scavenger hunt without committing a felony. I’d like to try one now. See if you can find the following things in Xcode:

  • Your dignity, when the Xcode’s linker locks up the entire machine, except for iTunes, and your business partner calls and you have to explain why The Breakfast Club soundtrack is blaring in the background.
  • Which symbol you haven’t defined, but your linker won’t tell you about, because Xcode turns on ZeroLink (motto: We eliminate the most important job of a linker so you don’t have to!) by default in hopes that you’ll give up on your product idea, and just email it to Apple directly thereby cutting out the middleman.
  • The file you just had opened, but accidently closed, but can’t access from the Open Recent menu because source files aren’t project files, and nobody ever needed to quickly access anything but project files, you big jerk.
  • A button in the Find in Files dialog that says, “No thanks, I don’t want a Find Set, I’d just like to search this folder.” Bonus points if it doesn’t require creating a Find Set to enable it.
  • Any way to make Open Quickly slower or more inconvenient. Requiring three or more keys to invoke it or ensuring it searches the smallest set of files possible do not count, because Apple has already thought of those. (Hint: it should include Find Sets in some way.)
  • A clue of what might should happen when you double click on a function in the debugger’s call stack. (Hint: Look at CodeWarrior.) If you find this, don’t give it to me, email it to the Xcode team. They need it.
  • The state of the program when a call to DebugStr() or Debugger() happens and Xcode quickly, efficiently, and without error doesn’t stop for them.
  • Code demonstrating the technical reasons for why Xcode can’t save the window locations of a project when the files they are stored in are not locked, although the file next to them is. (Hint: the code should invoke the Heisenberg Uncertainty Principle, or involve a lot of illegal narcotics.)
  • A flowchart that explains the optimal way in which to obtain the new developer documentation that Xcode insists on telling me about every five minutes, in an application modal dialog. Bonus points for why its not in the Software Update or why you need an NDA to read about how Quickdraw is deprecated in four different languages.
  • The cure for Xcode’s Alzheimer’s, who cannot remember between runs that I selected “Show Types” in the debugger, despite the fact that I yell at it each time to remind it.
  • Your brain, after attempting to determine what correlation or relationship there is between what you selected for Go To Symbol (command-double click), and what Xcode actually retrieved.

How many were you able to find? Entries can be submitted via Apple’s Blackhole of no Return, which, for some reason, they insist on calling “Bug Reporter.”