Skip to content

Instantly share code, notes, and snippets.

@Mercandj
Last active October 5, 2022 21:41
Show Gist options
  • Save Mercandj/ffa819ed49ba91133a740dd26a2865cd to your computer and use it in GitHub Desktop.
Save Mercandj/ffa819ed49ba91133a740dd26a2865cd to your computer and use it in GitHub Desktop.

Fail fast

One goal of mobile apps or any dev project, is to not have crash or wrong behavior.

I. Example and "safe" implementation

Imagine a car with a car.setAccelerationPercent(Float).

For example, the client using the car can

  • shut off the acceleration with car.setAccelerationPercent(0f)
  • put half of the max power car.setAccelerationPercent(0.5f)
  • put max pressure on the engine with car.setAccelerationPercent(1f)
interface Car {
  
   fun setAccelerationPercent(@FloatRange(from = 0.0, to 1.0) percent: Float) 
}

The car does not support negative percent or percent bigger than 1f. Percent must be between [0f; 1f].

A dummy implementation could be:

class CarDummy: Car {
  
   override fun setAccelerationPercent(@FloatRange(from = 0.0, to 1.0) percent: Float) {
      // Use percent directly
   }
}

The problem is that client can still call car.setAccelerationPercent(-42f).

To avoid crash or wrong behaviour, one way is to consider < 0f percent as 0f and > 1f as 1f percent.

class CarSafe: Car {
  
   override fun setAccelerationPercent(@FloatRange(from = 0.0, to 1.0) percent: Float) {
      val percentSafe = when {
         percent < 0f -> 0f
         percent > 1f -> 1f
         else -> percent
      }
      // Use percentSafe
   }
}

Like that, you are safe, the percent use internally will always be between [0f; 1f] even if client are using "non sens" percent. The CarSafe will work perfectly.

II. What we miss with a "safe" implementation

With the CarSafe implementation, sure you are "fixing" the crash. But you are only fixing consequence of the crash and not the reason. With the CarSafe implementation, you will not fix what the caller is doing. And there could be a "bigger" and "deeper" issue behind the fact that caller are calling your setter with "non sens" values.

So, one non intuitive approach is by failing fast. By making your app crash, that will allow you make the fix at the root of the issue and understand the why?.

class CarFailFast: Car {
  
   override fun setAccelerationPercent(@FloatRange(from = 0.0, to 1.0) percent: Float) {
      check (0f <= percent && percent <= 1f) {
         "Percent must be [0; 1]. percent: $percent" // In kotlin, will crash with explicit error message
      }
      // Use percent
   }
}

With this implementation, sure you app will crash, but you will be aware of it (on mobile for example, we have firebase or play store crash reports). Your crash free rate will means something.

What's worse than a crash is a miss behavor you are not aware of.

Conclusion

To conclude,

  • Try to find the why? and fix the why? before fixing the what?
  • Be carefull with silent return. A crash / report will let you aware of the issue and able to fix the reason

Links:

To go further, here are other Developer Pinciples.


Other articles and projects on Mercandj.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment