Technical debt, while over two decades old, is a term very much of the essence in this age of Agile development, Lean startups, Minimum Viable Products and DevOps practices. Technical debt has been a phenomenon since the first mainframe punchcard but with a much broader swath of our economy being dominated by businesses viewing themselves as “software companies” and “product development” referring to software more often than any durable good, an increasingly broad set of stakeholders feel the effects of technical debt.

What Is Technical Debt?

Ward Cunningham, hugely influential computer scientist and co-creator of Extreme Programming, is generally credited with coining the term “technical debt” in 1992 as follows:

“Shipping first-time code is like going into debt. A little debt speeds development so long as it is paid back promptly with a rewrite… The danger occurs when the debt is not repaid. Every minute spent on not-quite-right code counts as interest on that debt. Entire engineering organizations can be brought to a stand-still under the debt load of an unconsolidated implementation…”

I love Ward’s definition and find it painfully accurate. I find the following to be a more pragmatic definition and one that is most intuitive to product managers (who happen to be those being called on to drive remediation of technical debt):

“Quick, dirty or otherwise inadvisable development that leads to more work later so that the shortcuts taken won’t lead to bugs or make future changes hard to implement.”

Technical Debt Smells

As a technical manager, product manager or Agile Product Owner, how can you get a feel for the level of technical debt in your digital products? How can you gauge whether technical debt is increasing or decreasing? Once we’ve covered more characteristics about technical debt we will cover some good tools for a quantitative assessment of your code bases but for now we will talk about quantitative assessments – use of intuitive “code smells”.

Kent Beck coined the term “Code Smell” as a surface-level indication (in other words, you’re likely to notice it if you’re near it) that usually corresponds to a deeper problem with the code. Just as food that smells a little funny might not guarantee that it is spoiled, you should probably check the food out before you eat it. In software, code smells are usually not as obvious as outright bugs but if you’re tuned in you’ll definitely notice them. The following are some classic technical debt smells:

Simple Functional Changes or Additions Take a Long Time

For instance, you have determined that you need to add a “salutation” and “suffix” field to your CRM application and your development team greets you with pained looks and/or racks several days of work to make the change. The amount of work to unpack and remediate debt-ridden logic while building out your additions is adding major unexpected cost to your project.

Bug Fixes Take a Long Time

A problem comes in from the field that your web application is rendering a key page in poor form on smartphones. The bug takes three days, senior development staff is called in and extensive late hours are put in.

Bug Found

Code Changes for Small Additions Frequently Lead to Bugs

In the course of the addition the “salutation” and “suffix” fields to your CRM application, three reports break and the data update feature breaks. Seemingly unrelated features regress to broken states for no apparent reason.

Developers Actively Avoid Being Assigned to the Code

Your development team actively avoids being assigned to the team working on your apps. Word spreads quickly among the corps when an app’s technical debt has grown out of control and soon it will be difficult to get your developers of choice to voluntarily work on your app.

The Application Operates Slower Than You’d Expect or Slower Than It Used To

You use your app for day-to-day work and the slowdown from how it worked a year ago is palpable. Technical debt has a way of gumming up the works in an application. Workarounds mount and inefficient legacy code dominates the application, bringing it to a crawl.

Any of the above sound familiar? If so that is not a guarantee that you have mounting technical debt but it would be wise to dig deeper and involve technical staff to evaluate your software for the presence of technical debt.

Consequences of Technical Debt

Other than for academic reasons, why should you worry about technical debt? Putting an end to the smells above is alone probably reason enough. However, let’s dig a little deeper to see things you will need to deal with if you leave technical debt unattended.

Interest Payments

Every time developers work with your app, every time a support request comes in and each time you make small adjustments your developers will need to make a hard choice: add to technical debt (making the situation worse) or re-write portions of the software to unwind the technical debt and make progress. This is completely analogous to financial debt: either make interest payments on your loan or sink further into debt.

Unpredictable Tipping Point

Technical debt often takes the form of sub-optimal and often rough workarounds within code that developers have used either out of necessity to meet a deadline or out of a lack of skill. As these aspects of the code base build up there can come a time far enough into the application’s life in which the application is built up of more workaround code than advisably-built professional code. At this point developers will spend more time understanding and working around the various jury rigs than they will contributing to rigorous solutions. Once this happens you are at a tipping point in which more time is spent keeping the software operating and it will become completely unpredictable how long code changes and functional additions are likely to take.

Increased Time to Delivery

Predominant technical debt and code rot leads to developer and architect discussions and in-depth planning to make changes to the code and still deliver quality product. There will be times when, despite this planning, developers run into pockets of the code base that are more entrenched in outdated technologies or unsustainable implementations that side-tracks to shore up the hidden technical debt is greater than projected. Thus, despite the longer prediction than you expected (see above) the actual timeframe can stretch out even further.

Significant Number of Defects

In modern software development, developers and engineers rely on extensive unit, integration and functional tests to run during each commit and catch any instances of regression – times when working on a new feature breaks an old feature. Code bases with a large extent of technical debt are often absent these kinds of automated tests – as a result regressions do occur at a higher rate than normally expected.

Rising Development and Support Costs

Because of the many ways in which high technical debt applications result in lengthier planning, existing code re-writes and sub-optimal coding approaches the time (and associated cost) for in-house staff to work with the application goes up along with the cost of frequent out-of-house consulting required at times to remediated particularly thorny code bases.

Money Bag

Product Atrophy

Because of the above product owners are not as interested in working with a software application – when they do so they are often rewarded with buggy releases, budget overages and delayed timelines. As such they avoid activating teams to work with the application and thus rot continues to build.

Decreased Predictability

Just as developers, engineers and product owners receive constant surprises from technical debt-ridden software the business receives less precise signals as to timeline and cost for maintenance and incremental development. Upper management and product benefactors begin to lose faith in the application and the team as predictability and their ability to make proper business decisions goes out the window.

Underperformance

While we have spent a great bit of time covering the ways in which working with technical debt-ridden applications makes developer and engineer lives difficult, costly and drawn-out there are also very real consequences to the users of applications with high levels of technical debt. Due to the presence of antiquated technologies, algorithmic workarounds and rushed work the actual response time, availability and server/cloud resources of the application will suffer.

Decreased Customer Satisfaction

Rolling together all of the things above about technical and business impacts of technical debt you’re going to see customer satisfaction slip. As such you will soon hear from your end users that they have felt the bite of technical debt.

Not All Technical Debt Is Bad

There are indeed strategically and practically sounds reasons to plan for the creation of technical debt. That may sound very counter-intuitive and granted there aren’t many reasons. But the few reasons that do exist are very good reasons. First, let’s talk about why you need to be careful about this.

Strategically allowing or even encouraging the creation of technical debt is a very valid strategy in certain circumstances. One specific example is a product that is planned to have a short life. Since it’s not going to live long it does not have to be built to withstand a strong legacy; we’ll only need to make debt payments for a very short period of time – and then the app will be shut down. In this case it makes sense to build the product quickly, just good enough to last the short time and then retire it, along with the debt, as soon as possible. It does not make economic sense to gold-plate a short-term solution.

The same can be said for a product nearing its end of life. Eric Ries contends that in a Lean world the value prototypes bring are to validate theories, give learning and stir interest/establish the proof of concept. Since prototypes are intended to be thrown away, this approach is a special case of the “don’t worry about technical debt for products with a short life”.

One very defensible rationale for intentional technical debt is for a “throwaway prototype”. You may have significant interest in a big new application but not quite achieved full budgetary support to build it in full. You may be asked to put together a proof of concept for a very reduced budget to determine viability of the application to solve business problems and to get feedback from potential users. As such a quick prototype with non-production tooling, lower-cost staff and non-enterprise approaches can be taken to provide the appearance of near-complete application such that it can be put in front of customers.

This approach gives the opportunity for very realistic feedback on needed features, the things that have the most value, pointers on what the usability should be like and then a better decision on scope and project sponsorship can be made. Then this prototype can be thrown in the trash and a fully-funded enterprise solution can be developed with these learnings – what you have learned in this process will greatly exceed the cost of the thrown-away prototype. Whatever you do, do not build upon your rough prototype for the real solution! If you do so you will enter an entirely unprecedented world of technical pain.

Check out part II in this series to learn about identifying technical debt and part III about dealing with technical debt.

As a fairly new user story writer, I have been reading a couple of books and working through the learning curve of writing good user stories (and the acceptance criteria that goes along with them). It’s becoming more and more evident that having well written user stories, with acceptance criteria, is directly correlated to a project running smoothly.

What are user stories?

This one question could probably be debated for a whole blog, but we’ll go with a simple definition from User Stories Applied by Mike Cohn:

“A user story describes functionality that will be valuable to either a user or purchaser of a system or software.”

Within Scrum, user stories are one of the key artifacts development teams use. The idea is to provide enough high level information and detail of a requirement that developers can produce a reasonable estimate to implement the solution. Cohn also suggests writing them with a more formal approach using this formula:

User Story Formula

This approach allows you to think about how the feature is built and why. There are many approaches you can try and trial and error can help you determine the best approach for your team. Make sure your user stories are always written so that they are understandable by both business and technical individuals.

Who writes the user stories?

Many different roles within an organization can be responsible for writing user stories, but the key is the person writing the user stories is representing someone important to the end solution, like the stakeholder, customer, or an end user. Ultimately, Product Owners own the user stories and are responsible for writing, gathering and prioritizing them.

Guidelines for Writing User Stories

Have a meaningful goal

When writing your user stories identify the user roles and their goals. This will help you create high level stories. Which in turn, you can begin to break into smaller stories. Just remember the stories need to have some sort of functional meaning, there needs to be a way to “test” that the story has been completed. The story should have a meaningful goal, allowing the user to feel that something has been accomplished. One thing I keep forgetting is that the story should not include a solution. Really, as the Product Owner, I don’t necessarily care how they get to the end goal as long as the goal is met and testable. I have to continue to keep in mind that I just need to right the user role and goal, not how to accomplish the goal. It really only adds confusion for the team. The team can look at the goal and the acceptance criteria and then task out the solution.

Ensure the work can be completed in the sprint

You can also focus on more short term stories, making the story a size that would allow the team to complete it within the next sprint or iteration. For stories that are a little further out, you can still create them, they can also be a little larger and less precise. Then as you get closer to working on those stories being worked on, go in and re-write them to make them smaller and more precise. And, of course, always communicate with the appropriate parties and add detailed acceptance criteria. At the end of the day, each story/iteration should deliver business value to the stakeholder(s). If it doesn’t, it’s considered incomplete and should not be included in the sprint.vector-illustration-of-scrum

Think about the End User

Adding to the idea of user roles, most people find it helpful to write stories with users in mind so that as the project begins to get developed everyone is thinking about the actual end-user. Such as a Marketing Manager or IT Manager, they can imagine an actual person vs. a “user”. Also, if you can focus on one user, that may make things easier to read, but there will be times when you have multiple roles and it makes sense to write for multiple roles. You can also focus on the problem that needs to be solved. Either way, using a persona or a fictional character as your end user will help visualize the functionality needed to meet the goals of that persona. Another common mistake (or 2) is to write a user story as the Product Owner or as a Developer. These types of stories aren’t actually helpful. They don’t represent value to the customer as the story, which may be relevant and needed, doesn’t deliver business value at the end of the story. You can include these stories, just make sure they are written from a persona’s view.

Use an Active Voice

Also, using an active voice makes the user story easier to read and understand. This also goes back to using the “As a (role) I want (something) so that (benefit)” approach. It allows you to understand what the active user wants to do and what the outcome should be. Keep the stories simple and concise. Try to leave out non-essential information, which isn’t always easy, but sometimes less is more! Another key thing to remember, don’t speculate. If you don’t know what the user is trying to do with the product or how they will use it, you should take a stop a back and observe (if possible) and/or interview the appropriate users/customers. The user stories need to be based on relevant knowledge.

The End Result

The bottom line is that the team needs to understand the story, conversations should happen around the story and a test to confirm the story has been successfully completed. User Stories evolve by interviewing users, observing users, questionnaires and conversation. Usually, you can achieve the best results when you combine a couple of these methods rather than focusing or over relying on one. The interaction will really help solidify the goal of the user, therefore providing a better understanding to the user story writer. Also, as you move through the project, User Stories may change. You may find you don’t need one or you add 2 more, or re-write a handful based on what you have built and what you now know. That’s the great thing about being Agile, it doesn’t bottle neck you. The team can make adjustments on the fly, be flexible, be agile. You can re-order stories if needed too. There is no single recipe for User Stories, but I hope I provided some background on how to write good user stories for your team. As a final reminder, the story should be independent, valuable, estimatable, fit in one iteration and testable. Save the detail for the acceptance criteria and the tasks associated with the story. Hope you found this post helpful!