Fail Fast

 class​ CruiseControl {
 static​ ​final​ ​double​ SPEED_OF_LIGHT_KMH = 1079252850;
 static​ ​final​ ​double​ SPEED_LIMIT = SPEED_OF_LIGHT_KMH;
 
 private​ ​double​ targetSpeedKmh;
 
 void​ setTargetSpeedKmh(​double​ speedKmh) {
»if​ (speedKmh < 0) {
 throw​ ​new​ IllegalArgumentException();
  } ​else​ ​if​ (speedKmh <= SPEED_LIMIT) {
  targetSpeedKmh = speedKmh;
» } ​else​ {
 throw​ ​new​ IllegalArgumentException();
  }
  }
 }

Let’s take a look at the method setTargetSpeedKmh(). The if conditional with its three branches surely does some exception handling. But do you immediately understand why it’s structured that way? Probably not.

The normal path in this method is a little bit concealed. It’s the second of the three branches surrounded by (or hidden in between) two branches of error handling. We’re primarily interested in this normal path, because there lies the actual functionality, and this one will be executed most of the time. The code above wastes precious developer time just for spotting that path between the parameter validation.

When you read those branches sequentially, the last one is troublesome. The first branch is a validation, and the second the normal path. At that point, you might think you know how the method works and what parameters it accepts. But then the last branch comes along with another validation condition. You have to do a mental rollback and update your understanding of the parameter validation. This is a waste of mental energy that’s just not necessary.

There’s another unnecessary complication in the code. All branches of the conditional are connected so you have to understand all conditions together. This is easy for the first branch with the condition speedKmh <= 0, but it becomes more complicated for the other two. Which condition applies exactly for the second and third branches? It’s !(speedKmh <= 0) && speedKmh <= SPEED_LIMIT and !(!(speedKmh <= 0) && speedKmh <= SPEED_LIMIT). No problem for the JVM, but it’s not that easy for us humans.

So, how can we make this code more understandable? By failing fast:

 class​ CruiseControl {
 static​ ​final​ ​double​ SPEED_OF_LIGHT_KMH = 1079252850;
 static​ ​final​ ​double​ SPEED_LIMIT = SPEED_OF_LIGHT_KMH;
 
 private​ ​double​ targetSpeedKmh;
 
 void​ setTargetSpeedKmh(​double​ speedKmh) {
»if​ (speedKmh < 0 || speedKmh > SPEED_LIMIT) {
 throw​ ​new​ IllegalArgumentException();
  }
 
  targetSpeedKmh = speedKmh;
  }
 }

We separated the normal path from parameter validations and placed the two combined conditions at the top of the method. If one of them holds, the method returns immediately and throws an IllegalArgumentException. In other words, the method fails fast.

Failing fast makes the whole method more readable and understandable! But not only that, we even got rid of one level of indentation for the normal path.

Think of the validation block as the bouncer of your club and the normal path block as the dance area. The bouncer ensures that no underaged party people can enter your club. We trust the bouncer that she’s doing her job, so we know we don’t need to check again on the dance floor. That means we can concentrate on the normal path without having to recall all validation conditions.

And with that solution, you can immediately spot the two-part structure separated by an empty line. First comes the parameter validation, then the normal path of the method. This means that you can jump right into the most important part of the method—the normal path—and you don’t need to read the whole validation logic upfront.

The structure of the method is quite good now, but we can improve this solution even more: we should apply Explain Cause in Message and Simplify Boolean Expressions. Go ahead and try it for yourself!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
13.58.5.57