Business of Software

10 Tips for Managing Technical Debt

Throughout my career in software, I have learned that technical debt is not just an unavoidable consequence of software development, but a necessary part of it. To innovate and grow, sometimes we need to make strategic decisions that trade what I often term “the practical for the perfect”. However, if you never pay it down, technical debt can accumulate and become a barrier to progress. Here are some effective strategies that I’ve found in order to manage technical debt.

Tech Debt

1. Acknowledge and Track Technical Debt

The first step in managing technical debt is acknowledging its existence. It’s crucial to keep an open dialog about it within your team and make it part of the development process. Technical debt needs to be tracked work items in whatever system you work from (Jira, Trello, etc). Whatever you do, these decisions cannot just become “tribal knowledge” that can get lost with time. It should be documented what debt you incurred – and why – as well as what changes are needed when time is allotted.

2. Prioritize Debt Payment

All debts are not created equal. Some can cripple your progress and make your system impossible to change, while others are just a little annoying. Therefore, prioritizing which debts to pay first is essential. Just like paying of credit card debt usually involves some classification of interest rate, balance, etc, you should create a classification to rate and prioritize your technical debt across metrics that are valuable to you and your organization.

3. Regular Refactoring

Code refactoring is a critical practice in controlling technical debt. I encourage my developers to refactor as they go, which can often eliminate stray technical debt. For example, we may have created an inflexible “hack” method to get something done in the moment that was supposed to be a “one-time-only” deal. But, you know how those things go. Soon, there is a “second time only” and instead of making another “hack” method, we encourage a refactoring to make the first method more flexible and allow it to solve both scenarios (as well as future ones).

4. Dedicated Time for Debt Reduction

We’ve found it helpful to allocate dedicated time for addressing technical debt. Depending on the organization and the amount of debt, we have literally limited the amount of “new” work we would allow to be added to a sprint and included time for developers to work on tech debt work items. This not only helps in debt reduction but also encourages developers to take ownership of their code.

5. Continuous Integration

CI (Continuous Integration) can help prevent the accumulation of technical debt by catching problems early. Including an automated test suite that runs whenever changes are made gives developers immediate feedback if they’ve introduced an issue.

6. Code Reviews

Peer code reviews are an excellent practice to prevent the introduction of new technical debt. A second pair of eyes often catches potential issues that the original developer might have missed.

7. Invest in Training

Piggy-backing a little off of number 6… A well-trained development team is less likely to create technical debt in the first place. Continued training and learning is an investment to reduce future technical debt, as well as a great way to keep your team engaged and let them know that you’re interested and invested in their careers.

8. Quality over Speed

While it’s important to deliver quickly in a competitive environment, sacrificing code quality for speed is a recipe for technical debt. I tend to emphasize the importance of good coding practices, and remind our teams that “quick hacks” can and will cause problems down the line. It doesn’t mean that we can’t ever take a tradeoff, but we need to know the rules so that we can bend/break them strategically.

9. Documentation and Knowledge Sharing

Good documentation is another good way to control technical debt. Clear, concise, and up-to-date documentation of systems, architecture, and codebases reduces the chances of duplicating efforts or making uninformed decisions that can add to technical debt. Consider having knowledge sharing sessions within your team to ensure everyone understands the system and its quirks.

10. Tech Debt Retrospectives

Periodically, it is a good idea to have a Tech Debt Retrospective to consider the kinds of things that repeatedly add to tech debt and how the team is progressing on paying it down. This can be a useful way to see harmful patterns and create ways to prevent them.

(Bonus) Balancing Business Needs and Tech Needs

Lastly, it’s essential to remember that while technical debt should be managed, business needs often require making trade-offs. By maintaining an open dialog with the product team, we can strike a balance between delivering new features and keeping technical debt in check. We are paid to help the business, not just “build cool stuff” and “pad our resumes”. Falling too far to one side or the other can be a disaster. Too tech-focused and you can build something that is of no use to anyone (or worse… something that never gets finished due to IT Navel Gazing). Too business-focused and you build something that lacks utility for anything other than yesterday’s problems. Find the balance, learn to “speak business”, and find the compromises.

Technical debt management is ongoing and is about developing a mindset and behaviors that consider long-term implications while making short-term decisions. Remember, the goal is not to completely eliminate technical debt, but to keep it under control so it doesn’t hinder your team’s progress and your company’s growth.

Business of Software

Micromanagers

MicroscopeOne of the things that we – as workers – hate the most is the micromanager. What is funny is that most people who micromanage others don’t like to be micromanaged themselves. So, why do they do it? Is it effective, despite the backlash? Is it just poor management? Is it a fallback tactic? I can’t claim to have the definitive answers, but here are my thoughts.

Micromanaging is when someone in a supervisory capacity has to know what you’re doing at all times. Often, they may even want to dictate those steps that you take to complete your work. Those two don’t always go together and it is important to realize what you’re dealing with if you’re being micromanaged and what issues you are facing if you’re the micromanager.

I’ll start with the second one first. The supervisor who wants to dictate the steps that you do take to do your work likely does not trust you to do the work properly. I’m not talking about workplaces where you need to follow 95 precise steps to brew Coca-Cola, transport radioactive material, or some other precise job. I’m talking about jobs where you are coding a project, preparing a report, writing a paper, documenting incidents, etc. If someone constantly has to shoulder surf or have updates in order to ensure that you are doing things correctly, then they don’t trust you to do the work.

The other kind of supervisor who has to know what you are doing at all times also doesn’t trust you, but it isn’t because they don’t think you can do your job when you’re doing it. It is because they fear that you’re “slacking off” or “cheating the system”. Their idea of Managementâ„¢ is to make sure that no one gets paid for 1 minute of time more than they are supposed to and that the department is achieving maximum throughput. Now, having the department run efficiently and with great throughput is good management, but squeezing blood from a turnip is not.

I’m going to deal with the unpopular part of this first. First, you should make sure that you – as the worker – are not a problem. Maybe you’re 100% of the problem, maybe you’re 0.01% of the problem, but a mature person will seek to correct what they can in themselves whenever possible. You know the truth, are you slacking off? Do you do the absolute minimum and take long lunches and stand around and talk every time you can? Do you never communicate status so your manager always has to ask you? If so, you might be the cause of your boss’ behavior. Fix it. If you can’t fix it because you hate your job and this is how you cope? Look for another job. Harsh? Sure, but you’ll be happier if you go somewhere that you want to be and enjoy being.

For those micromanagers who are reading this… your turn. You need to fix yourselves. Even if you do have employees slacking off or doing things incorrectly… you’re not helping. In fact, you’re annoying your employees and running yourself ragged with trying to keep track of their minute-by-minute whereabouts. In second fact, you aren’t really managing anything, you’re babysitting it at best. Who have you grown in a position, mentored up? I don’t mean someone who got promoted entirely on their own merits. I mean someone who was average or below average and you mentored and trained them up into a rising star in the company. If you’re honest, you can probably count that number on one hand or maybe no hands. People don’t rise and thrive under a dictator. However, you possibly have legitimate concerns. Let’s take a look at how you could possibly deal with them in a better way.

Slackers

Maybe people are slacking. Depending on the office culture or your collection of humans, people might be trying to get away with as little as possible. The slacking is on them, but if you micromanage, you’re training people to only work when you’re around and to master the art of looking busy when you aren’t. So, how do you manage your way out of this? This is probably your fault as well. You need to set goals for the results that you want achieved. If you’ve asked for 30 widgets and 30 widgets are getting done, then why are you bearing down on people? On the other hand, if you’ve asked for 30 widgets and only 5 have gotten done, then there is a real issue. At that point, you’ve got to speak to the low performers, coach/train them up, and possibly pursue discipline. Not everyone is a fit with every company.

However, if you’ve asked for 30 widgets and are getting 30 widgets, but you feel like more could be done, then increase the “quota”. If you’ve been measuring all along, you will be able to see if your team is becoming more efficient, less efficient, or stagnating. By being involved at the proper level, you’ll also get a real sense for whether or not your employees are “sandbagging”. But, measuring does not mean demanding or accounting for every second of an employee’s day. People work differently and you need to account for that, but if you’re looking to increase productivity, you’re not doing much more than steadily decreasing your own.

I know that there are people who would bristle at the suggestion that employees aren’t doing their best for the entire day or that there are readers who would believe that I’m advocating for a poor work-life balance. I am a proponent that people should work hard while they are on the clock. If you do that, work-life balance shouldn’t be a problem. If you work hard, taking time off won’t matter because you won’t constantly be behind. If you (and your team) are all doing your best and you’re still behind and there isn’t an obvious point-in-time reason, then you’re understaffed or mismanaged and that’s the manager’s problem. However, I’m not against people who do work more or even work over from time to time to get things done, as I describe in this post from over 9 years ago.

You have to understand, though, that the freedom you are asking for requires that you accept accountability for your work and your work output. It is possible that your department is churning out their 30 widgets, but that is because a handful of people on the team are killing themselves to make it happen. Burning them out so that you can hide in the bathroom and watch TikToks isn’t sustainable and could definitely cause a manager to dig deeper. You will have brought that on yourself.

Any of the environments I’ve described will result in higher than normal turnover, burnout, and lack of innovation. If someone is being dictated to, they’ll never find creative efficiency gains. If a group is being hounded for every second of their time, they’ll never feel safe enough to try and fail some creative new ideas.

Often, though, the consequences of micromanagement are that the manager loses the big picture. The manager’s job is to lead, grow, develop, and put their team in position to be a strategic asset for the company. If the manager is worried about whether Suzy’s bathroom breaks are 5 minutes or less or if Ken starts his knots right-over-left instead of left-over-right, they will not be in the right mindset to think strategically for the mid-to-long term like they should. Honestly, this could be intentional. If the manager was over-promoted and feels more comfortable in their old job, they might easily fall back into habits of dogging the minute-to-minute instead of planning the week-to-week or month-to-month.

So, what do we do about micromanagement? Summing it all up, the TL;DR; is that if you’re a worker being micromanaged, first check your own house. Take a solid look and make sure that you aren’t giving people a good reason to look closer at what you do all day. Once that’s clean, talk to the supervisor or manager. Help them out… manage up. Have the tough talk that you’d prefer not to be micromanaged and see if you can agree to productivity goals and then work hard to meet them. If that goes poorly, deal with it or get a new job.

If you’re in management and someone comes to you, listen. Take an honest look at yourself and see what you can fix or apply. If no one has come to you, but you see yourself in this post, then take a step back. Find some mentors who can give you advice. If you don’t have management mentors, get some. But start with figuring out what productivity that you need and set goals for the department and then step back.

Whether worker or manager, if you work to eliminate micromanagement, stress levels will go down and job satisfaction will go up on both sides of the line.

Business of Software

Survivorship Bias

XKCD Survivorship Bias CartoonThis week, I was listening to a business podcast and the guest was describing the “techniques for success” that they had used and how they now teach those techniques to others. As I began to wonder how much of this (and all such advice) was attributable to Survivorship Bias and planning this post in my mind, I started to think about what image should go with it. Of course there is a relevant XKCD comic, Randall Munroe thinks of everything first.

I’ve been accused of some Survivorship Bias in the past, too. My ideas around how individuals can become successful programmers through individual learning and not through college is how I got started, but am I establishing too much personal credibility on the fact that I made it through a minefield without stepping on a mine? I didn’t give it too much thought until this week.

If you aren’t sure what Survivorship Bias is, the XKCD above does a great job of explaining it. But, the short “word only” explanation is that Survivorship Bias is a kind of selection bias. In this case, the bias places a great deal of attention and credence on things that made it past some gate or obstacle and ignores the less visible things that didn’t make it past.

One example that I used this week is with “Guaranteed Winners for Monday Night Football”. I don’t know how prevalent this is any more, but it used to be advertised everywhere there was sports content. The basic idea is that you call in and they give you the winner of an upcoming football game, ostensibly so you can bet on it and win. The scam is that they give some portion of the callers one team and one portion of the callers the other team.

One of those teams will win and then those callers, bolstered by their win, will call back. The next time, they pay for a “Guaranteed Pick”. Again, the callers are given both teams fairly evenly. This goes on and on until you have people who have won 10 games in a row thinking that this phone line is worth its weight in gold. They might crow loudly about the powers of prognostication that the picker has. The problem is that this entire scenario forgets about the ever-growing portion of callers who have received a losing pick along the way. That’s Survivorship Bias.

So, is all advice bad? Is all advice a by-product of Survivorship?

As in all things, I think the answer is Yes and No.

In my opinion, the way around this is twofold. First, be very wary of a “lone survivor”. If there is only one voice crying out about a path, look for the 90+% who might have followed the same advice to a bad end. Secondly, if people who follow particular advice seem to always improve and you diligently look and you can’t find a significant population of people that failed with the advice, then it is likely good advice.

The problem is that advice can’t be too specific. Now, I believe that through hard work anyone can improve their circumstances. However, what does that even mean? Not everyone starts on a level playing field, with the same advantages or disadvantages, and from the same starting place. You have to know what success looks like for you.

For example: Yes, you are following the email list building advice, but your email list is 1/1000th the size of the person who sold you that course. Consider the advice and consider the circumstances. First, their market is huge. They are selling business products to wannabe entrepreneurs nationwide (or even worldwide). If you are selling backgammon supplies to the greater Sheboygan, Wisconsin area (nothing against Sheboygan), you aren’t going to be able to reach the same number of people.

As for my personal bias about becoming a self-taught programmer, this also has a caveat. You can only do it if you are the kind of person who will dedicate hours to learning and also to practice. You have to be able to learn from just watching videos or reading rather than interaction. You have to create so many side projects and put so much sample code on GitHub. You have to be diligent to study and work even when you get home from your full-time job and your family is fighting for your time. You have to promise to work after people have gone to bed or before they wake up… something. It is hard to know what to do when no one is telling you what to do.

That leads to the other bias secretly at play. There are the concepts of Self-Serving Bias and Attribution Theory. They are related and the relevant part I want to pick out is that people often attribute positive events to their own character but attribute negative events to external factors (Psychology Today). Likewise, if someone else messes up, it is common to ignore external factors and blame the person’s character or drive or something internal to them. We don’t cut them any slack, but we can cut ourselves all kinds of slack.

What can we do? Just be aware. For certain, tell your story. If you see someone successful, listen to their story. Then, in all things, listen critically. Think critically. Take advice generally and apply it to your specific situation where it fits, throw out what doesn’t. If that doesn’t work, try something else. Rapid iteration and prototyping isn’t just for software, it works for approaches to life’s problems and obstacles, too.

Code Tips

Async Void Cannot Access a Disposed Object

A SinkRecently, I was trying to throw a quick method on a controller to create a user on the fly. I was pretty new into a .Net Core Web API project and I just needed to add a quick user to start to test some of the authenticated API calls that I was creating. So, I wrote code that was very similar to this:

[HttpGet("~/peteonsoftware")]
public async void CreateUser()
{
    var user = new ApplicationUser()
    {
        Email = "me@myserver.com",
        UserName = "me@myserver.com"
    };
    var result = await _userManager.CreateAsync(user, "SomePasswordThatIUsed,YouKnowHowItIs...");
}

When I started it up and made a call to http://localhost:56617/peteonsoftware, I got an error that read:

System.ObjectDisposedException occurred
  HResult=0x80131622
  Message=Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling Dispose() on the context, or wrapping the context in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.

I could not figure this out. I would debug and stop on the line. My dependency injection was working and my _userManager was populated via dependency injection and I reviewed documentation and what I was calling should work. I lost a lot of time to this. It turns out that I was the victim of some optimization that .Net is doing for me. Notice that my method is async. Notice also that my method returns void. So, as far as .Net is concerned, it can go ahead and return from my method as soon as it fires off that CreateAsync() call because it doesn’t care about the result and it isn’t returning anything anyway.

I naively thought that my await would keep everything holding on until the method returned. NOPE! I found through research that my method was returning before it was done and everything started cleaning up and disposing. Therefore, when the method went to work, everything was disposed, resulting in my error. When I made the small change of no longer returning void, everything worked.

[HttpGet("~/peteonsoftware")]
public async Task CreateUser()
{
    var user = new ApplicationUser()
    {
        Email = "me@myserver.com",
        UserName = "me@myserver.com"
    };
    var result = await _userManager.CreateAsync(user, "SomePasswordThatIUsed,YouKnowHowItIs...");

    // Yes, I know I could just return above, but I like it to be separate sometimes, don't judge me!
    return result;
}

Now when I call, I get back

{"succeeded":true,"errors":[]}

So, lesson to learn… async void is BAD! Lots of unexpected consequences. Always return something from an async method to ensure that nothing gets cleaned up early.

Podcasts

Podcast Episode 51 – Matthew Groves on Couchbase

Matthew D. GrovesIn Episode 51, we go back to our interview roots and have our first returning guest (who was also our first guest, period), Matthew Groves. Matthew is a Developer Evangelist for Couchbase, Inc. I’ve been following what he’s been doing with Couchbase since joining the company and I was interested to find more about the product. It turns out that Couchbase has some pretty nice features and you’ll want to listen to this episode and find out what’s new.

Links Mentioned in this Show:

Couchbase

Cross Cutting Concerns

Couchbase Blogs

The CouchCase

CodeMash

Matthew Groves’ Original Pete on Software Episode

You can also subscribe to the podcast at any of these places:
iTunes Link RSS Feed

Thanks to all the people who listen, and a special thanks to those who have rated me. I really appreciate it.

The episodes have been archived. Click Here to see the archive page.