Creating high quality Android code – History

I recently started working on a legacy Android code base. This is a massive project with slightly more than 250 000 lines of code, zero tests, lots of code duplication and in general, massive issues.

There’s no consistent formatting, naming or even package structure. I’ve seen classes and activities with 8500 lines of code.

The code is peppered with things like:

The app often crashes with OutOfMemoryError’s, which has led the developers to just catch those as well.

This raises a few issues.

How do you get an objective measure of how bad the code quality is?

This is necessary for a couple of reasons, but the most important in my opinion is to start getting an indication of whether the code is getting better or worse over time.

The simplest solution here is probably tools like static analysis which can give you a standardised metric and maybe test coverage.

All of these numbers are at least somewhat useless, ambiguous and possibly misleading, but tracking them over time in some kind of sensible manner can at least give you an indication of whether your code is improving.

How do you explain to an inexperienced developer why these practices are wrong?

In a recent code review, I called a developer out on catching a NullPointerException. His argument was that he would need to do 3 null checks, so why can’t he rather just catch it once?

My first thought was: “Because it’s wrong”. Everybody knows you never catch unchecked exceptions. My second though was that catching an NPE gives me an instant indication that you don’t know better, so I can’t trust your code and need to be much more careful with anything else you do.

But why? What reasons do I give this developer? Saying “Because it’s wrong” doesn’t help anybody.

How do you start fixing this project?

There are lots of big problems:

  • We are still developing new features. We can’t stop dev to refactor.
  • Which parts of the codebase would most benefit from improvement? This is not necessarily purely a matter of quality. If I have a really bad module, but nobody has touched it for two years, it might not need to be improved.
  • There are less experienced developers on the project. How do you stop them (or the more experienced devs for that matter) from adding more bad code.
  • The lack of tests means that we have to be very careful about how we refactor.
  • The code is not testable at the moment:
    • There is no inversion of control, so most things cannot be mocked out.
    • The app relies on heaps of global state which makes testing harder (It also leads to the aforementioned OutOfMemoryError’s).
  • Where do you start? There are so many major problems, which do you tackle first?

Where to go from here?

I’ll tackle these in upcoming blog posts. I expect this will turn into a fairly big series of posts… I’ll add links to the relevant posts here as I create them.

While I’m specifically referring to Android development, most of what I discuss will make perfect sense to Java developers and I suspect the practices will apply to any development.

This is what I think is necessary at the moment. This list may change as I work on these:

  1. Starting to fix legacy code
  2. Style guides
  3. Identifying problem areas
  4. Best practices
  5. Sensible refactoring
  6. Starting testing?