Saturday, April 2, 2016

Reinvigorating a large Android code-base



The problem

We faced a classic problem on a recent project. Stop me if you've heard this one before. We are supporting a well established product with millions of users, running on a large underlying code base, but the code base has been building technical debt for years, slowly turning into a Frankenstein, causing support problems. The types of problems we were facing include:

  • Separation of concerns violations making unit test maintenance and creation more challenging, with lower than ideal coverage
  • Threading complexity in places leading to defects that are difficult to find and repair
  • Numerous special-case customizations distributed throughout the code, each addressing specific customer needs that only activate for that customer
  • Reduction in team velocity due to code complexity and the other issues listed above

Challenges of Addressing Technical Debt

In one of my first posts I touched on the challenges of balancing time spent paying back technical debt vs time spent adding new features. It is always difficult to find opportunities to address these types of concerns in a code base because the investment of a large refactoring effort is very high and the direct customer value can be perceived as low (especially outside of engineering) and difficult to quantify when compared to ongoing targeted feature enhancements and defect fixes.

I find the best approach is usually to address refactoring in an iterative approach rather than tackling an entire code base all at once. In this fashion you can balance new feature development with the need to keep your foundation stable.

Solution Overview

On this recent project, however, we were given a task to refresh the entire UI. This was an unusual opportunity to re-evaluate the code base holistically and introduce new concepts and techniques.
We targeted three primary technologies to aid in this effort:

  • Dependency injection using Dagger2
  • Decomposition of Android activities into Model/View/Controllers
  • Usage of RxJava and retrolambda for component communication and thread management

Over the next several posts I will delve into the approach we took, how each contributed to solving the problems identified above, and some of the challenges we faced. 

No comments:

Post a Comment