If you get the rare luxury to start a new project from scratch, there's something deep down inside you that makes you want to do it right. You pick the right people, equipment and tools so that you have the best chance of success. Unfortunately, sometimes incorrect decisions are innocently made and a technical time bomb is placed in the code.

About 20 years ago at Big Money Inc., such a project was started and such a mistake was made. In this case, the mistake revolved around choosing a messaging platform that failed miserably when asked to pump more messages than was intended. The original developers knew not of this otherwise widely-known limitation.

Compounding things was the choice of implementation. Usually, when you build a transport layer, you do something like this:

  public interface ICallback {
    void callback(Record rec);
  }

  public class Handler implements ICallback {
    public void callback(Record rec) {
      // do something with it
    }
  }

  public interface ITransport {
    void connect();
    void disconnect();
    void retryConnectionWithDegradingFrequencyAndAlerts();
    void publish(Record rec);
    void registerCallback(ICallback callback, String subject);
    // ...
  }

  public class ConcreteTransport implements ITransport {
    // Implementation here
  }

You instantiate it with relevant parameters for each transport instance you need, and inject or pass the concrete object - by the interface - wherever it's needed. This way, when a new transport comes along tomorrow, you only need to implement a new concrete interface, once, instantiate the new wrapper and inject or pass it in lieu of the previous one.

This is not a new way of doing things. Encapsulation is not a new concept. Many souls far wiser than us documented this in great detail a very long time ago.

But the original developers were unaware of such sorcery as encapsulation, interfaces or (Spring) injection, so the system was built with all of the code to connect, publish and subscribe hard wired into every single class that needed to send or receive messages. Literally more than 800 of them. Decapsulation at its finest!

Fast forward more than a decade and there's an economic event that caused the volume being pushed through the messaging system to spike; the messaging system collapsed and brought everything that depended on it to a screeching halt. In the middle of business. World wide. Naturally, high level managers suddenly pushed this issue to the top of their priorities: This MUST be fixed IMMEDIATELY!

Of course, when the current developers on the team looked into it, they had to report unpleasant news regarding 800+ places where code needed to be changed. Rather than attempt to factor it out into encapsulated classes and merely use it where required, management decided that they could not afford to risk introducing bugs by rearranging code, and that they should keep things as they are and fix it everywhere it's used. The available staff of two people reported that this would take a while. Management roared: Unacceptable! Start coding post-haste! Type, young minions - TYPE!

And type they did. Until one of them gave up on IT and left to pursue a career as a florist. The lone remaining developer assigned to the task slogged forward, but at the pace of a single developer. When management queried why the pace of progress was now 50% of what it was, he reported: You KNOW that the other guy is no longer here, right?

Management realized they had to do something, so they did what they do best; they ignored reality and barked orders, leading to many conversations along the lines of...

  Manager: We MUST maintain the planned rate of fixes or we won't meet the schedule!

  Developer:: The schedule assumes two folks, already up to speed, working on it full
  time - if you maintain the scheduled level of resources, we can maintain
  the expected throughput

  M: But we don't have time to find and train someone new

  D:...but you have time to miss your deliverable?
...and downhill it went from there.

To complicate matters, there was a new corporate-wide directive to move off of the messaging system (to which they were moving) onto yet another corporate-mandated tool, implying that all of the in-line rework would need to be re-reworked.

Management insisted that development had no choice but to proceed as they had been instructed.

The lone developer realized that he was being assigned full responsibility for numerous earlier management failures, that he was in a corner and had no choice but to go for broke. He pointed out that this was an unreasonable approach that was guaranteed to fail. If he had been allowed to refactor the code into an encapsulated/injected model, it would be relatively trivial to change messaging systems. Until a sane direction was to be adopted, he was through being set up to pay for technical debt that the project had amassed while he was still in high school.

They ordered him to do as they said, and that he needed to own this problem and do whatever it took to get it fixed.

He pointed out that before he would take ownership of a problem, it had to be reasonably fixable, and that he needed to get some say in how the solution would be implemented. While there are many ways to succeed, some paths are guaranteed to fail, and he would not accept responsibility for 12 years of someone else's bad decisions and accumulated technical debt.

M: You don't have a choice!

D: Yes I do. I resign effective 2 weeks from today!

They really couldn't argue with that, so over the next 2 weeks, he wrote down everything he knew about it, mostly in an attempt to warn the next poor soul inflicted with this mess. Then he halted the remaining 50% of the development effort on the project by saying goodbye and walking out.

[Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!