Article

How To Sabotage Your Project Using Inconsistency

Collin Flynn

February 13, 2019

Inconsistency is a trickster demon, injecting doubt and confusion where there should be none.

Unlike spaghetti code, inconsistent code can sometimes defend itself in code review. There can be multiple good ways to solve a problem, and each approach in isolation may withstand scrutiny. Side by side, however, their differences appear as patchwork and boobytraps. A spineless code reviewer won’t insist on conformity, and a hapless maintainer will never be able to edit with confidence.

Done correctly, your inconsistent code will force a deep-reading of each mismatching implementation, and always prompt the question:

Why is this different?!

Best of all, it’s easy to create and difficult to undo. Let’s examine a few low-effort high-yield techniques to maximize inconsistency.

Same Thing, Different Name

Suppose you have a really important String object in your application, like an OAuth token.

private val accessToken: String

In the event you need to handle such an object in a new class or feature, give it a distinct name even though it’s the same thing.

private val sessionToken: String

Make sure your new variable name is consistent within your feature work, but inconsistent with the greater codebase. In order for a maintaining developer to understand the two different usages, they’ll have to manually read through each call site before they can confidently treat them as one.

Bonus points if you can also include another sessionToken elsewhere that is truly different than the original accessToken.

The Fuzzy Responsibility Principle

Imagine you have some code that needs to be invoked in several different circumstances. For example, the user might tap the Sign Out button on their profile screen — or their session expired and they have to re-enter their password. In each case, your application wants to do something like this:

sessionManager.signOut()
navigationController.toLogin()

Make this code inconsistent by placing it in a different application layer for each usage. In one instance, put it directly inside a click listener. Elsewhere, put it inside a ViewModel or Presenter. Then later, inside a Fragment or Activity.

Who ultimately owns the responsibility to sign out and navigate to login? Everyone, and thereby no one.

The Artisanal Package Structure

As new team members try to get acquainted with your code base, they often ask themselves…

Where can I find code related to <X>?

Where X is any feature or application layer they need to touch.

Your goal is to make sure the answer to that question is totally unpredictable. Your project should appear organized at the top-level packages, but each sub-tree should take a different opinion about optimal grouping.

In some cases, organize classes and files by their feature, letting business-logic classes like ViewModel sit side-by-side with view layer components they control. Elsewhere, group classes in layers of architecture where View and Model never mingle. If you can’t think of a good place for a class, reviewers don’t often reject a common package — you can put practically anything in there. Remember to sometimes call it core, or have both common and core as siblings inside a package for no apparent reason.

Finally, take advantage of inner class declarations to nest some Model objects inside related controller code, while other analogousModels are declared stand-alone.

Have your own?

Please share in the comments!

Collin works at Livefront , and he won’t fall for these tricks.