The Neglected Interface

Those engineers (un)fortunate enough to work with me know my stance on interfaces: they’re the software, everything else is implementation detail. Software engineers spend a great time of time and energy on designing, developing and refining interfaces. From URI structures of RESTful web services, to versioned payloads, to in-code interfaces, to naming conventions, and so on.

Some less obvious interfaces are often given little to no attention. I’m sure the Martin Fowlers of the world have given this set some clever name like Implicit Interfaces or Accidental Interfaces1, but the concept is pretty simple: as soon as someone or some process starts depending on some side effect of your application, you now have an interface you must abide by. This could be a particular log format, or some structure of the DOM, or some javascript event. Either way, you didn’t give it much thought, but you’re stuck with it now, and you’ll build shims and adapters to support it until the end of time, because you’re a good engineer and your software solves problems.

But there is another interface which tends to receive still less forethought: the interface between Engineering and the rest of the Business.  You, the engineer, have a deep, obvious understanding of engineering problems: the crushing technical debt, why this incoming ticket is “just a hack”, which scalability nightmare is hiding under the bed. But that’s your job; you’re supposed to know these. This puts the burden on Engineering to effectively communicate these concerns with the Business in a way that not only makes sense, but can be appropriately prioritized. This is the Business Interface.

The best way to go about this is obvious: it depends. It will necessarily vary by company, by people and personalities, by budget, by any number of other things. Sorry, no silver bullets. But there are several interfaces that almost universally do not work2.

The No-Op

I see this more often than I should, especially (and embarrassingly) among some more talented engineers. Here’s an abbreviated version:

Product Manager: “I need you to [do something unpleasant]”
Engineer: “I’m not doing that”

Let’s imagine this as a software interface and implementation for a moment. Consider the save() operation on a DAO. This is the equivalent of the one-line implementation:

public void save(MyObject obj) {
    throw new GoScrewYourselfException("No");
}

Doesn’t take a brilliant engineer to see that this implementation isn’t going to work for them. Objects aren’t being persisted. An unpleasant exchange or phrase may inadvertently end up displayed to a client. When v2 of this library comes out, it will be too late. The implementers have violated our trust, and we’ll go back to using something we trust from The Big Guys (Spring, JBoss, Apache, etc.).

The same is true of Engineering and the Business. This engineer has cost not only himself, but also his team and his larger engineering organization the good faith of the Business. The next time the Business needs something done, they won’t go to you.

“Great” you say. “I didn’t want to do this in the first place. Weren’t you reading?” Sure, but I won’t be the next time. Perhaps you aren’t doing this unpleasant work, but someone on your team knows they’re doing this because of your refusal. You’ve alienated Business (bad), but you’ve also alienated your team (very bad). And you’ve lost the seat at the table where you might have had an opportunity to prevent this type of request the next time it came around. You may have Failed Fast, but make no mistake: you failed.

 Just a Hack

The Business has a great opportunity to make a ton of money on this week’s sale of Foo3. Let’s eavesdrop:

Product Manager: “Quick, when someone clicks on ‘Foo’ show them our exciting offer!”
Engineer: “That’s just a hack. It’s only ‘Foo’ this week.”

How much context is simply missing from both sides of this conversation? It’s possible, perhaps probable, that this is a one-time, time-limited revenue opportunity for the business. Perhaps if this hack (or “exceptional use case”) goes live in the next day the business stands to benefit greatly from an external contract, or has a chance of netting a great number of new subscribers. It is entirely within the Business’ best interest to get whatever hack out the door is necessary to make this deal happen this week. Why shouldn’t they want this, and what do they care if it’s “just a hack”?

So what is the engineer trying, but failing, to convey? Most likely the concern is one of the following:

  1. If we keep coding up these exceptions for each deal, we will have unmaintainable, buggy code that will be difficult to use for delivering new, important features later
  2. This will break feature X you asked for N months ago
  3. This is short-sighted, and it would be better for everyone if we built out a more general-purpose means of associating deals with special offers

First, any one of these is a dramatically better response to the initial request than what was given. They at the least offer some context as to the engineering reservations about the request, and at best offer some alternatives and talking points for a productive conversation.

When a dialogue is started, there is a possibility of things working out for both parties. A reasonable Business might still request the ‘hack‘ ‘exceptional use case’ get done immediately, but opt for #3 to replace the hack as soon as the current deal is over. Or it might recognize this a unique situation and agree to have the custom code ripped out of the code base as soon as the deal ends. Perhaps they had forgotten about #2 and decide this use case isn’t as important as feature X. Engineering does no additional work and the Business, while not completely satisfied, at least was able to make an informed decision.

#1 tends to be the sticky point. A less understanding business may return with a demand the use case be shipped regardless, and it’s Engineering’s job to deal with these exceptions. It can be a slow process from there, and it will likely involve tracking lost time or lost opportunities over time due to this one-off existing in the code base. Or it may not be a matter of the Business being shortsighted. It may have genuinely believed this was a one-time thing but some more of these opportunities presented themselves over time. This is not an “I told you so” moment. This is a new opportunity to propose #3. At the very least, it’s a chance to restart the dialogue with the benefit of more context.

The Busy Wait

This one is insidious. Consider the same scenario as before: the Business asks for a quick feature this week, but the Engineer unilaterally decides on #3. The expectation from the Business is the feature is going out quickly (after all, it’s a simple use case), but Engineering knows best and builds out a flexible means of associating deals with special offers.

Product Managers start getting anxious. They bug your manager daily about why this small feature isn’t live yet. He or she starts wondering themselves. When asked, you reply with something like “it’s almost done” or “probably tomorrow”. The day of the deadline arrives, and this simple request still isn’t live. The deal is blown. A short while later, you deliver a very well engineered solution that gives the Business all the power they need to perform this request without Engineering’s involvement the next time. You expect some praise, but you’re met with anger or disappointment. Both parties are confused and unhappy. What happened?

To strain our DAO simile from earlier, the implementation now looks something like this:

public void save(MyObject obj) {
    SomeOtherObject obj2 = new SomeOtherObject(obj);
    obj2.setProp1(normalize(obj.getProp1())); // this isn't ideal, let's change some data
    obj2.setProp2(null); // meh, don't really want to do prop2
    obj2.setCreatedAt(ZonedDateTime.now().minusHours(1)); // it's daylight savings time, right?
    Thread.sleep(2000);
    betterSave(obj2);
}

You’d probably still be pretty livid with this implementation. This was supposed to save your object, but instead it ‘did something even better’. It saved a ‘better’ object by fixing some potentially incorrect dates and cleaning some of the input. But it also took a long time, and performed actions not expected from an implementation of this interface. Don’t be surprised when the Business feels equally livid at your implementation of the Neglected Interface.

The Infinite Sleep/Wake Loop

Much like the Busy Wait, only instead of taking much too long to implement a larger feature set, a long time is taken to deliver nothing. Back to spying:

Product Manager: “I need feature X this week”
Engineer: “Sure, no problem”
[the next day]
Product Manager: “How’s it going?”
Engineer: “I’m starting on it today”
[the next day]
Product Manager: “Anything you need me to look at?”
Engineer: “Oh, no, sorry I got side-tracked yesterday, I’ll get to it this afternoon”
[the next day]
Product Manager: “I have a chat with the client today, is there a test link I can show them?”
Engineer: “The spec doesn’t say what to do when Y or Z happens. I’m a bit stuck until then.”

And so on. The deadline comes and goes and no progress was made. To finish beating our DAO simile to death, here’s the implementation:

public void save(MyObject obj) {
    try {
        while (true) {
            Thread.sleep(1000*60*60*24); // wait a day
        }
    } catch (InterruptedException e) {
        save(obj);
    }
}

As an engineer concerned with the performance of your application, you’d much prefer this implementation to immediately abort and give you an opportunity to take another action rather than silently do nothing in a loop. The Business feels the same. Your peers and managers will similarly start losing confidence in your ability to get things done.

Hallmarks of a Good Business Interface

  1. Constant dialogue – When both parties understand why something is happening, or not happening, they can adjust. They can use their expertise to plan alternative courses of action. Or, as demonstrated earlier, can work together to find mutually beneficial compromises. When dialogue stops, it can not only hurt internal relationships but may damage external relationships when the Business fails to deliver on commitments
  2. Articulation of concerns and alternatives – “No” is never a productive statement. Instead, express your concerns about the proposal. Even better, couple this with some alternative ideas.
  3. Use a common language – Engineers speak in terms of technical debt, ease of maintenance, and general “ugh” factor. Product managers speak in user experiences, partner relationships, and the top- and bottom- lines. When forming proposals, or voicing concerns, attempt to translate your worries into Product Manager worries.
  4. Recognize that you’re trying to solve the same problems – Both parties are trying to grow the business. You by streamlining your ability to deliver features quickly and safely. They be prioritizing features most beneficial to the business. You’re both right, and if you can both move your agendas forward, everyone wins.
  5. Respect their expertise – You’ve worked hard to be a good engineer. You’ve read a lot, you’ve done a lot, you’ve made some mistakes and grown. Leaders in the Business in other areas have done the same. Treat them as your peers. Defer to their expertise on the subject and they are likely to do the same.
  6. When all else fails, find help – There may be other people in the Business who are better equipped to handle conflict than you. If you cannot seem to get your point across, consider talking to your manager. If the matter seems to have become personal, talk to HR. The earlier you can break the cycle of a bad relationship, the better off you’ll be. Chances are, both of you plan on sticking around a while, and it’s difficult for either of you to get things done while there’s personal tension.
  1. Law of Unintended Interfaces?
  2. If I were a successful writer of the engineering disciplines, these would be labeled “Business Interface Anti-Patterns”. But I’m not, and you’re just as tired of reading about ‘patterns’ as I am. Besides, a pattern is just another interface, right?
  3. Foo: Great for Parties!

Leave a Reply

Your email address will not be published. Required fields are marked *