Internal APIs

March 3, 2008

I had this unpleasant situation a few days ago: a colleague, in process of making a fix, decided to rename some utility methods to better reflect their behavior. An admirable intention, but in the process, he had to modify around thirty different classes to reflect the naming change and broke every branch and local checkout that existed. He believes he did nothing wrong. I disagree. His mistake, as I consider it, is indicative of a tempting but fallacious notion of “our code” or “internal code”.

Look at it this way: If you were making a public API, say an XML parser, that was used by multiple third parties, would you make non-backward compatible changes to it and expect your users to accomodate? Would you rename public methods/fields/properties? Would you substantially alter their purpose or behavior?

Within just about any non-trivial code base, especially an object-oriented one, similar pieces of code soon emerge, even if they are not visible to third parties. Common data structures, utilities, even plain old beans that store configuration information - all of these things are examples of “Internal APIs”. An internal API is any piece of code that gets used in more than one nugget of functionality. Like their public counterparts, internal APIs require thorough design and dillidgent change management. If a member needs to be renamed, it is not enough to change the name - the deprecated name (clearly marked and documented as such) still has to be supported.

Changing behavior of members is tricker still… if a change introduces materially new behavior (rather than fixing bugs/quirks on existing behavior), the new behavior needs to come under a new name that clearly describes it… I would argue that even when all references to old behavior now merit the use of the new behavior, the new behavior needs to be a separate member unto itself - the act of updating all the code and tests that exercise the old behavior becomes the act of explicit confirmation that no assumptions of old behavior are present. Any invocation of an API member (internal or external) introduces coupling by assumption where the calling code makes an assumption of what the API call will provide. If the API behavior changes, the name has to change too, so that these old assumptions are forcibly and explicitly disclaimed.

Entry Filed under: programming practices, real-life story. .

Leave a Comment

Required

Required, hidden

Some HTML allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Trackback this post  |  Subscribe to the comments via RSS Feed


Welcome!

My name is Yev Bronshteyn, and you have reached the online repository of my tirades on the world of software engineering and perhaps that other world as well (I've never seen it, but heard it exists). Please leave comments - they make me feel warm and fuzzy inside... Peace!


Add to Technorati Favorites

Categories

Recent Posts

Feeds

Links