Is it possible to cover all scenarios ? - Part I

Should we hide our errors under the carpet ?

Lets say that a developer code a cool new class in a rainy monday:

public class IntrovertedClass {

        public int calculateSomethingImportant(Object input) {
                try {
                     return doSomeComplicatedMathWithOnlyPositiveNumbers(input);
                }
                catch (Exception e) {
                     System.out.println("This should never happen !");  
                }   
                return 0;
        }

}

So whats wrong with this class someone may ask ?

So the developer now write the class that use IntrovertedClass:

public class UsageClass {

       // do some init stuff

       public void showReportToUser(Object input) {
              // ... do some pre work
             total = total + total * introvertedClassInstance.calculateSomethingImportant(input);
             // ... show to user
       }

}

Ok. Lets say in demo to our team we do the following scenario:

image.png

Everybody is happy and we deploy to production directly as we have our new Continuos Delivery pipeline and all tests passed gracefully.

Two weeks passed and the developer comes back from vacations. And then 10 Priority 1 JIRA tickets assigned to him and also a meeting with his boss at 11am.

So he logs-in quickly and download the logs from the past 10 days:

And for his surprise he found a familiar log message:

06/03 User:A This should never happen ! 06/04 User:A This should never happen ! 06/05 User:B This should never happen ! ......

So in the meeting with his boss. His boss explains to him that customers are getting in their reports same total amount despite that they have entered the "right" amount in the UI.

image.png

So the developer goes back to his desk and after checking his logs. He has no clue about it. So he calls quickly to his front-end friend and ask her if she has some logs that she can share so he can knows what the user has sent to the UI.

So she sends her logs to the now worried developer:

06/03 User:A {input: "1%"} 06/04 User:A {input: -10} 06/05 User:B {input: "10$"}

So after scratching his head for an hour as there is no way someone human can enter these inputs and then cursing the user for not entering the right values. He goes back to the code and change it:

public class IntrovertedClass {

        public int calculateSomethingImportant(Object input) {
                try {
                     if valid(input) {
                            return doSomeComplicatedMathWithOnlyPositiveNumbers(input);
                     }
                }
                catch (Exception e) {
                     System.out.println("Yes error can happen ! " + e);  
                }   
                return 0;
        }

        public boolean valid(Object input) {
               if isANumber(input) { 
                    if (input > 0) {
                         return True;
                    }
               }
               return False;
         }

}

So he adds some tests and all of them pass. And then on Friday code goes live again.

Monday the developer arrives early to the office and check the logs:

06/09 User A: Yes error can happen ! - NumberFormatException 2.455 cannot be converted to Integer. 06/09 User A: Yes error can happen ! - NumberFormatException 8.315 cannot be converted to Integer. 06/09 User E: Yes error can happen ! - NumberFormatException 12'5.00 cannot be converted to Integer.

So the developer thinks what is wrong with User A. And in that moment a UX engineer ask him if everything is ok. The developer explains to him the problem and the UX comes up with a user-friendly solution that according to his research will make everyone happy.

Just show a message to the user. Let him/her know that something happened.

So the developer fix the code again:

public class IntrovertedClass {

        public int calculateSomethingImportant(Object input) {
                try {
                     if valid(input) {
                            return doSomeComplicatedMathWithOnlyPositiveNumbers(input);
                     }
                }
                catch (Exception e) {
                     System.out.println("Error will happen ! " + e);  
                     throw new WrapperException(e, "The system has crashed. Please contact the administrator");
                }   
                return 0;
        }

        public boolean valid(Object input) {
               if isANumber(input) { 
                    if (input > 0) {
                         return True;
                    }
               }
               return False;
         }

}

So in the meantime in the UI:

image.png

Now my thoughts:

So i think as a golden rule we should not hide exceptions as these ones will become difficult to track and debug. Also will produce some "weird" or "random" errors.

Not really sure if it is ok to show a generic error message to the user but it is better than showing wrong data or calculations.

Solution ?

In my personal experience a better solution is to do the right validations as soon as possible so no wrong or invalid data goes deeper in our call stack. And if there is no way to prevent invalid inputs; throwing an exception is better than just capturing the exception and hide it into oblivion.

About this i've found very interesting the "let it crash" philosophy from Elixir/Erlang:

isaacjarquin.github.io/software/2017/07/01/..

In summary is to the code happy path first and just let the system fail, capture the error and restart the process again. So the user never knows that the system has crashed. Then fix code and so on.

Maybe i would write a post about it soon ;).

But the question in the title remains: is it possible to cover all scenarios ?

....Coming Soon Part II....