Category Archives: Java

Why I think in Python is not a good idea to raise exceptions inside your methods

Last update: 2022-05-18 10:48 Irish Time

Recently a colleague was asking me for advice on their design of error handling in a Python application.

They were catching an error and raising an Exception, inside the except part of a method, to be catch outside the method.

And at some point a simple logic got really messy and unnecessarily complicated. Also troubleshooting and debugging an error was painful because they were only getting a Custom Exception and not context.

I explained to my colleague that I believed that the person that created that Exception chain of catch came from Java background and why I think they choose that path, and why I think in Python it’s a bad idea.

In Java, functions and methods can only return one object.

I programmed a lot in Java in my career, and it was a pain having to create value objects, and having to create all kind of objects for the return. Is it a good thing that types are strongly verified by the language? Yes. It worked? Yes. It made me invest much more time than necessary? Also yes.

Having the possibility to return only one object makes it mandatory having a way to return when there was an error. Otherwise you would need to encapsulate an error code and error description fields in each object, which is contrary to the nature of the object.

For example, a class Persona. Doesn’t make any sense having an attribute inside the class Persona to register if an operation related to this object went wrong.

For example, if we are in a class Spaceship that has a method GetPersonaInCommand() and there is a problem in that method, doesn’t make any sense to return an empty Persona object with attributes idError, errorDescription. Probably the Constructor or Persona will require at least a name or Id to build the object…. so in this case, makes sense that the method raises an Exception so the calling code catches it and knows that something went wrong or when there is no data to return.

This will force to write Custom Exceptions, but it’s a solution.

Another solution is creating a generic response object which could be an Object with these attributes:

  • idError
  • errorDescription
  • an Object which is the response, in our example Persona or null

I created this kind of approach for my Cassandra libraries to easily work with Cassandra from Java and from PHP, and for Cassandra Universal Driver (a http/s gateway created in year 2014).

Why this in not necessary in Python

Python allows you to return multiple values, so I encourage you tor return a boolean for indicating the success of the operation, and the object/value you’re interested.

You can see it easily if you take a look to FileUtils class from my OpenSource libraries carleslibs.

The method get_file_size_in_bytes(self, s_file) for example:

    def get_file_size_in_bytes(self, s_file):

        b_success = False
        i_file_size = 0

        try:
            # This will help with Unit Testing by raisin IOError Exception
            self.test_helper()

            i_file_size = os.path.getsize(s_file)
            b_success = True
        except IOError:
            b_success = False

        return b_success, i_file_size

It will always return a boolean value to indicate success or failure of the operation and an integer for the size of the file.

The calling code will do something like this:

o_fileutils = FileUtils()
b_success, i_bytes = o_fileutils.get_file_size_in_bytes("profile.png")
if b_succes is False:
    print("Error! The file does not exist or cannot be accessed!")
    exit(1)

if i_bytes < 1024:
    print("The profile picture should be at least 1KB")
    exit(1)

print("Profile picture exists and is", i_bytes, " bytes in length!")

The fact that Python can return multiple variables makes super easy dealing with error handling without having to take the road of Custom Exceptions.

And it is Ok if you want to follow this path, but in my opinion, for most of the developers up to Senior levels, it only over complicates the logic of your code and the amount of try/excepts you have to have everywhere.

If you use PHP you can mix different types in an Array, so you can always return an Array with a boolean, or an i_id_error, and your object or data of whatever type it’s.

Getting back to my carleslibs Open Source package, it is super easy to Unit Test these methods.

In my opinion, this level of simplicity, brings only advantages. Including Software Development speed, which is good for the business.

I’m not advocating for not using Custom Exceptions or to not develop a Exceptions Raising strategy if you need it and you know what you’re doing. I’m just suggesting why I think most of the developments in Python do not really need this and only over complicates the development. There are situations where raising exceptions will be a perfectly useful or even the best approach, there are many scenarios, but I think that in most of cases, using raise inside except will only multiply the time of the development and slow down the speed of bringing new features to the business, over complicating Unit Test as well, and be a real pain for the Junior and Intermediate developers.

The Constructor

Obviously, as the Constructor doesn’t return any value, it is perfectly fine to raise an exception in there, or just to use try/except in the code that is instancing the objects.

News from the blog 2021-01-11

Happy New Year to all.

Is something very simple, but will help my student friends to validate Input from Keyboard without losing too many hours.

The Input Validation Classes I create in PHP for Privalia or in my PHP Catalonia Framework, are much, much, more powerful, allowing the validation of complete forms, rendering errors, etc… although they were created for Web, and not for Keyboard input.

It recursively goes to all the subdirectories looking for .py files, and then it counts the lines.

  • I updated the price of my books to be the minimum allowed by LeanPub, to $5 USD, and created a bundle of two of them for $7 USD.

So people can benefit from this during the lock down.

  • I’ve updated the Python Combat Guide book with a sample of using Paramiko Libraries for SSH, and increased the Object Oriented Programing and Unit Testing, sections. I also added some books to the Bibliography.
  • I’ve read the postmortem initial analysis from Slack’s incident. It’s really interesting.

I cannot share it, but I guess that at some point they will publish it on their blog:

https://slack.engineering/

  • As I’m giving more Python Classes I decided to write a book to teach to code in Python for non-programmers.

Java validation Classes for Keyboard

I share with you a very lightweight, stand alone, Java validation Class for Input Keyboard, that I created for a university project.

The first thing to mention is an advice about using the Scanner with nextInt(), nextDouble(), next()…

My recommendation is to avoid using these. Work only with Strings and convert to the right Datatype. So use only nextLine(). You will save hours of frustration.

Those are the methods that I’ve implemented:

  • int askQuestion(String question, int minValue, int maxValue)
    Ask a Question expecting to get a number, like “What year was you born: “, and set a minimum value and a maximum value. The method will not allow to continue until the user enters a valid integer between the ranges.
  • float askQuestion(String question, float minValue, float maxValue)
    Same idea with Floats.
  • double askQuestion(String question, double minValue, double maxValue)
    Same with Double, so for example question = “Enter the price: “.
  • String askQuestion(String question)
    Ask a question and get a String. Simple, no validation. Not even if it’s empty String.
  • askQuestionLength(String question, int minLength, int maxLength)
    Here I changed the name of the method. Same mechanics as askQuestion, but will validate that the String entered is between minimum length and maxlength. For example, to ask a password between 8 and 12 characters.
  • String askQuestion(String question, String[] allowedValues)
    This one accepts a question, and an Array of Strings with the values that are acceptable. Is case sensitive.
    So, using MT Notation, you call it with:

String[] a_s_acceptedValues = new String[4];
a_s_acceptedValues[0] = “Barcelona”;
a_s_acceptedValues[1] = “Cork”;
a_s_acceptedValues[2] = “Irvine”;
a_s_acceptedValues[3] = “Edinburgh”;
String s_answer = o_inputFromKeyboard.askQuestion(“What is your favorite city?”, a_s_acceptedValues);

Here is the code for the Class InputFromKeyboard.

package com.carlesmateo;

import java.util.Scanner;

public class InputFromKeyboard {

    private static Scanner keyboard = new Scanner(System.in);

    public static int askQuestion(String question, int minValue, int maxValue) {
        // Make sure we enter in the loop
        int value = minValue -1;

        while (value < minValue || value > maxValue) {
            try {
                String valueString = askQuestion(question);
                value = Integer.parseInt(valueString);

            } catch (Exception e) {
                System.out.println("Invalid number!");
            }
        }

        return value;
    }

    public static float askQuestion(String question, float minValue, float maxValue) {
        // Make sure we enter in the loop
        float value = minValue -1;

        while (value < minValue || value > maxValue) {
            try {
                String valueString = askQuestion(question);
                value = Float.parseFloat(valueString);

            } catch (Exception e) {
                System.out.println("Invalid number!");
            }
        }

        return value;
    }

    public static double askQuestion(String question, double minValue, double maxValue) {
        // Make sure we enter in the loop
        double value = minValue -1;

        while (value < minValue || value > maxValue) {
            try {
                String valueString = askQuestion(question);
                value = Double.parseDouble(valueString);

            } catch (Exception e) {
                System.out.println("Invalid number!");
            }
        }

        return value;
    }


    public static String askQuestion(String question) {
        // Make sure we enter in the loop
        String answer = "";

        while (answer.equals("")) {

            try {
                System.out.print(question);
                answer = keyboard.nextLine();

            } catch (Exception e) {
                System.out.println("Invalid value!");
                // System.out.println(e.getMessage());
            }
        }

        return answer;
    }

    public static String askQuestionLength(String question, int minLength, int maxLength) {
        // Make sure we enter in the loop
        String answer = "";

        while (answer.equals("")) {

            try {
                System.out.print(question);
                answer = keyboard.nextLine();

                int length = answer.length();
                if (length < minLength || length > maxLength) {
                    answer = "";
                    System.out.println("Answer should be between " + minLength + " and " + maxLength + " characters.");
                }

            } catch (Exception e) {
                System.out.println("Invalid value!");
                // System.out.println(e.getMessage());
            }
        }

        return answer;
    }

    public static String askQuestion(String question, String[] allowedValues) {
        // Make sure we enter in the loop
        String answer = "";

        while (answer.equals("")) {

            try {
                System.out.print(question);
                answer = keyboard.nextLine();

                boolean found = false;
                for (int counter=0; counter < allowedValues.length; counter++) {
                    if (answer.equals(allowedValues[counter])) {
                        found = true;
                    }
                }

                if (found == false) {
                    System.out.println("Please enter any of the allowed values:");
                    for (int counter=0; counter < allowedValues.length; counter++) {
                        System.out.println(allowedValues[counter]);
                    }
                    answer = "";
                }

            } catch (Exception e) {
                System.out.println("Invalid value!");
                // System.out.println(e.getMessage());
            }
        }

        return answer;
    }

}

Is a reduced subset of functionality respect what I created in my Web PHP Framework Catalonia Framework, or the Input Data Validation that my friend Joim created in Privalia and later I extended and maintained.

All the Frameworks have similar Input Data functionalities, some much more complex, supporting RegExp, or several rules, multiselection (typical for web), accepting only a subset of characters, but this is the typical 80% functionality that everybody needs when writing a console program.