vendredi 9 septembre 2016

Handling conditional statements while designing a logger class?

How do you handle the conditional statements while designing a class like log4j?

Taking log4j example, a class can have different levels(Info, Warning, Error, others...). Now to print for the different levels you would need different methods for each level. So there could be a basic design as follows:

public class CustomLogger {

    enum Level{
        INFO, WARNING, ERROR;
    }

    private Level level;

    public CustomLogger(Level level) {
        this.level = level;
    }

    public void info(String s){
        if(level == Level.INFO || level == Level.WARNING || level == Level.ERROR){
            System.out.println(s);
        }
    }

    public void warning(String s){
        if(level == Level.WARNING || level == Level.ERROR){
            System.out.println(s);
        }
    }

    public void error(String s){
        if(level == Level.ERROR){
            System.out.println(s);
        }
    }
}

The problem with this design I guess is that it has way too many if conditions and in case I need to add a new state I would have to modify all the if cases. So what I think could be a better design is as follows:

There is a State super class which is extended by class Info, class Warning and class Error. The State class has methods printInfo(), printWarning() and printError(). All the subclasses implement these methods and leave blank the once they need. As an example class Warning would look like:

class Warning extends State{

    public void printInfo(String s){
        //don't print
    }

    public void printWarning(String s){
        System.out.println(s);
    }

    public void printError(String s){
        System.out.println(s);
    }
}

Now the CustomLogger will have an association with State which will be injected to it at some moment and all the methods in CustomLogger will call methods of State class implementation. Something like:

public class CustomLogger {

    private State state;

    public CustomLogger(State state) {
        this.state = state;
    }

    public void info(String s){
        state.printInfo(s);
    }

    public void warning(String s){
        state.printWarning(s);
    }

    public void error(String s){
        state.printError(s);
    }

}

Even though this eliminates the conditional cases, but it induces a dependency of the methods call. If I add a new State then that states printState() method would have to added to every subclass which I guess is not a good practice. What else cab be done in such cases?

Aucun commentaire:

Enregistrer un commentaire