Java Design – Should You Throw Exception or Do Nothing When Breaking a Contract?

designjava

Let's say we have a list of players in our Event class. And we have a dictionary with the score of each player. We can add a score to a player using the addScore method:

public class Event {
    private List<Player> players;
    private Map<Player, Integer> score;

    public void addScore(Player p, int playerScore) { /* ... */ }
}

Now say we cannot allow the player to be either null or not to be contained of the player list defined in the event.

I just asked about null values and it seems the best approach would be to throw an exception. But trying to add a score to a player that doesn't belong to that event is another story:

public void addScore(Player p, int playerScore) {
    if (p == null) throw new IllegalArgumentException("The player cannot be null");

    if (!players.contains(p))
       // ???

    // the rest of the method
}

What should I do? What's the best approach? Should I throw a similar exception? Should I just do nothing? Or should I do something else?

Best Answer

The best idea to follow here is known as "fail fast". The basic philosophy goes as follows:

  • When the program's data is in an invalid state, errors occur which cause the program to not do what it's intended to do.
  • Depending on how widely different the invalid data is from the expected data, it's possible for the incorrect data to propagate for quite a long time, causing more and more errors, before it's detected.
  • The sooner an error is detected and execution is halted, the less damage it can do.
  • The closer an error is detected to the point of its underlying cause, the simpler it is to track down and fix the underlying cause.
  • Therefore, you want to fail fast: raise an exception, crash the whole program if necessary, as soon as possible, rather than allow data corruption to propagate.