Risk of Misplaced Arguments in Java

By Tanin | 30 June 2019

Lilit recently added support for showing parameter names in a method call, so I want to write about how misplaced arguments in Java can lead to subtle bugs, and how Lilit helps avoid them altogether.

Have you ever had a constructor (or a method) with many parameters of identical type like below?

class Filter {
  Filter(
    double qualityThreshold,
    double abuseThreshold,
    double relationshipThreshold,
    double favoriteThreshold
  ) {
    // do something here
  }
}

The above constructor is at risk at being invoked with misplaced arguments. It's easy to make this mistake but difficult to spot one. You can imagine:

double qualityThreshold = 0.7;
double abuseThreshold = 0.3;
double relationshipThreshold = 0.2;
double favoriteThreshold = 0.1;

new Filter(
  qualityThreshold,
  relationshipThreshold, // oops, misplaced argument here
  abuseThreshold, // oops, misplaced argument here
  favoriteThreshold
);

Reviewing code like this in a pull request on your browser becomes a nightmare.

Story time

Back in 2014, when I was working on notification filtering at Twitter, we had this exact bug.

On Twitter, an influential user with millions of followers would get a lot of @-mentions. Mention filtering was one way to help them cope with the huge amount of incoming information.

At the time, Marc Andreessen was one of our most influential users, and he emailed Dick Costolo, who was our CEO back then. Dick forwarded the email to my manager.

While I don't remember the exact words, I do remember that the email was distinctly short. Maybe that's how extremely successful people write their emails. If I recall correctly, it looked something like:

Why is it filtered out? [Tweet link]

That was it. That was the whole email.

After digging in for quite some time, we've finally spotted that the order of the arguments in one of the constructor calls was wrong. Two threshold values were swapped when instantiating the filtering class.

Back then, we heavily used Twitter's code search, which was an internal code viewer website. But, in hindsight, we might have discovered the root cause faster if we cloned the repo and looked at the code on our IntelliJs.

This bug has stuck with me for years. It is one of the experiences that inspired me to build better tooling to read code on browser like Lilit.

Introducing Lilit

In Java, having multiple parameters of identical type is essentially a usability issue. While we can refactor code to address this issue, Lilit is a decent risk mitigation with no code change.

Lilit is a "true" Java code intelligence in the sense that it understands Java semantically. Therefore, Lilit can show the parameter names next to the arguments as shown below:

double qualityThreshold = 0.7;
double abuseThreshold = 0.3;
double relationshipThreshold = 0.2;
double favoriteThreshold = 0.1;

new Filter(
  qualityThreshold = qualityThreshold,
  abuseThreshold = relationshipThreshold,
  relationshipThreshold = abuseThreshold,
  favoriteThreshold = favoriteThreshold
)

With the annotated parameter names directly on your browser, it becomes easier to spot that relationshipThreshold and abuseThreshold are misplaced.

Review code painlessly on your browser. Avoid misplaced arguments. Use Lilit for your team today.

Join the discussion on Reddit and Hacker news.