1 of 34

Tackling Technical Debt:

An Analytical Approach

Chelsea Troy

@HeyChelseaTroy

chelseatroy.com

2 of 34

An Online Guide to this Workshop

  • We’re going to cover a lot!�
  • If I don’t get to a question that you have, please post it to the channel.
  • There’s an extended version of this workshop and a ~1 year plan to turn it into a full-length course.

SOCIAL STUFF

  • If you’re a Tweeter, please feel free to include in the tweet:
    • @HeyChelseaTroy
    • @strangeloop_stl
    • ###strangeloop2022
  • The tweets are really helpful to me for get support to build longer and more detailed educational materials!

3 of 34

Chelsea Troy (she/her)

  • Staff Eng, Search Data Use @mozilla
  • Teaching, Python & Mobile @UChicagoMPCS
  • Workshops, Tech Debt & System Risk @Oreilly
  • Cussing, Useless @HeyChelseaTroy on Twitter
  • Cussing, Informative @ chelseatroy.com
  • Volunteer @ Ruby for Good
  • Mentoring & Curriculum @ Emergent Works

My specialty is systems with data that carries a lot of critical risk: giant datasets with a lot of PII in them, NASA Landsat data, cancer recovery application data, health insurance data, etc.

Happy to tell happy ending and horror stories about any of the above projects in the Strangeloop hallway track :)

4 of 34

What is “technical debt?”

Two Misconceptions:

  1. Tech Debt == Bad Code
  2. Once you build a feature, it’s “free”

5 of 34

Critical Concept: Maintenance Load

The proportion of total developer effort spent on maintaining the existing feature set.

  • Updating, up-versioning, or investigating existing code
  • Determining whether a given feature ever worked
  • Adjusting deployment so that existing functionality will scale to new scales

Heuristic: Any developer activity that isn’t adding a feature or removing a feature.

6 of 34

Critical Concept: Context Loss

Missing information about how, whether, or why a piece of the code base existed or worked.

It can come from:

  • Something wasn’t documented and the team forgot
  • Only one person ever knew and that person left
  • The code is so complicated that even the original author isn’t sure what’s going on anymore

7 of 34

Critical Concept: Technical Debt

Maintenance load in the existing codebase that comes from context loss.

How do you know if your maintenance load is under control right now?

8 of 34

Signs that your maintenance load is not, in fact, under control:

  • Agreements with product to “take on” tech debt to deliver a feature
  • The team has accepted that some features just don’t work
  • There are repositories or features that the whole team avoids (abandoned houses)

9 of 34

Individual Question

What’s your worst maintenance load horror story?

How about the opposite?

(you can type your answers here):

10 of 34

What practices distinguish YOUR maintenance load horror stories from good stories?

Individual Question (5 min):

(Type these somewhere for yourself...we’ll use them later)

11 of 34

Why does maintenance load rise?

12 of 34

Critical Concept: Code Stewardship

The skill set of reducing—though we can’t eliminate—maintenance load.

It includes:

  • Writing discoverable code

13 of 34

Critical Concept: Code Stewardship

The skill set of reducing—though we can’t eliminate—maintenance load.

It includes:

  • Writing discoverable code
  • Writing code with the malleability/rigidity in the right places

14 of 34

Critical Concept: Code Stewardship

The skill set of reducing—though we can’t eliminate—maintenance load.

It includes:

  • Writing discoverable code
  • Writing code with the malleability/rigidity in the right places
  • Documenting code with detail in the right places

15 of 34

Critical Concept: Code Stewardship

The skill set of reducing—though we can’t eliminate—maintenance load.

It includes:

16 of 34

Critical Concept: Code Stewardship

The skill set of reducing—though we can’t eliminate—maintenance load.

It includes:

  • Writing discoverable code
  • Writing code with the malleability/rigidity in the right places
  • Documenting code with detail in the right places
  • Writing tests that convey code functionality and boundaries
  • Transferring context to other members of the team

17 of 34

Individual Exercise:

Earlier, you considered what practices distinguished high and low maintenance load accumulations on teams over time.

Do your practices fall under one of these five examples? Type your post-its on the relevant column of this easyretro.

Which ones expand our list of examples of code stewardship?

18 of 34

5 minute break

19 of 34

Identifying the Causes of Maintenance Load

Step 1: Identify culprits in the code.

Step 2: Prioritize high-leverage changes.

20 of 34

Step 1: Identify Culprits in the Code

Setting aside time to “pay back technical debt” is too vague and leads to renovations that don’t really reduce maintenance load.

21 of 34

Watch out for code renovations.

These are changes that developers make to working, maintainable code because it doesn’t match their personal architectural preferences. Pet refactors often fall under this.

These changes do not reduce maintenance load, and they often erase context that the team already shares about how the code works.

22 of 34

Have you performed something you now suspect of being a code renovation?

23 of 34

1-2 Individual Stories

24 of 34

Step 2: Prioritize High-Leverage Changes

High-leverage change: Largest reduction in maintenance load for up-front effort

25 of 34

Prioritize:

  1. Removing feature bloat, whenever possible.
    • Make features earn their keep.

26 of 34

Prioritize:

  • Removing feature bloat, whenever possible.
  • Addressing documented holdups that repeatedly blow up time estimates.
    • You’ll get this information from your retrospective notes and from the document where you recorded the reasons that things took longer than expected.

27 of 34

Prioritize:

  • Removing feature bloat, whenever possible
  • Addressing documented holdups that repeatedly blow up time estimates.
  • Addressing abandoned houses at the point where a change is needed.
    • Addressing the whole thing right away is probably not realistic
    • Reward devs for forensic software analysis—recovering lost context—and context transfer—sharing what they learned with others

28 of 34

Prioritize:

  • Removing feature bloat, whenever possible
  • Address documented holdups that repeatedly blow up time estimates.
  • Addressing abandoned houses at the point where a change is needed.
  • Looking for places where the code flexibility doesn’t match how often that code actually changes

29 of 34

Prioritize:

  • Removing feature bloat, whenever possible
  • Addressing documented holdups that repeatedly blow up time estimates.
  • Addressing abandoned houses at the point where a change is needed.
  • Looking for places where the code flexibility doesn’t match how often that code actually changes
  • Equipping engineers to suggest streamlining options.
    • Example: “Delete” buttons on image annotation rectangles

30 of 34

Individual Exercise

In an app for making restaurant reservations…

  1. Which of these items would you address?
  2. How would you address them?
  3. How would you prioritize those projects relative to one another?�

Ticket Priority Poll

31 of 34

Time zone adjustment—92% of our members live in the same time zone as our database hosting, so the adjustment code does not even run for those 92% of people. For some reason it consistently mishandles time zones that are behind the database time zone, so it shows all reservation slots as earlier than the restaurant intended. It adjusts to time zones ahead of the database time zone properly.

Send Restaurant Recommendation to a Friend—

Our servers crashed 3 times last year from accounts signing up and spamming people restaurant recommendations. Besides those incidents, the only account that sends restaurant recommendations is the CEO’s.

Functional NavigationOur new senior software engineer came from writing Clojure, and he would like to experiment with a new, functional approach to navigating between screens on our mobile apps (Swift for iOS, Kotlin for Android). At present, screen navigation is not broken and is not a source of problems.

Object-Oriented Restaurant Code—The code for restaurant behavior is written in an object-oriented fashion, with each restaurant type in its own class. Last year we added one new type of restaurant (takeout only/no tables to reserve), and to do it, we subclassed ‘Restaurant’ and no-opped the reservation methods. We also added six new functionalities to restaurants—ordering by phone, tipping, donating a meal, changing the number of people on the reservation, advertising the COVID suppression policy, and progressive pricing.

Social Auth is handle-dependentanyone who has changed their handle on the account they use social auth with cannot sign into our service anymore without changing their social auth handle back to the old one. We get probably a dozen emails a month about this from our members. The authentication code is in the API repo, which is an old Django app. No one currently employed here knows much about it. The documentation consists of how to get it running on a machine, but there is no endpoint documentation, no Swagger, no troubleshooting guide. There are unit tests, but no integration tests or functional tests. The commit messages are things like “bugfix” and most of them are from a developer who stopped working here two years ago.

Case sensitive API endpoints—Example: to fetch reservations, from our API the endpoint is a GET request to an endpoint ending in /Reservations. Requesting from /reservations gives a 404. This is annoying and unconventional. Our frontend and our mobile apps are the only three clients of this API. Third-party services using our API are not on the roadmap. Currently, all three clients have functioning integrations, though the frontend developers and mobile developers all roll their eyes anytime they have to use the integration code or explain to a new developer that the server endpoints are all case-sensitive.

32 of 34

Reviewing Our Priorities

33 of 34

Q+A

34 of 34

Feedback Form (all fields optional)