Question

I have a LogFormatter class which looks like below

@Sl4j    
class LogFormatter {
        public static String format(String taskType, String taskId, String message) {
            return String.format("TaskType: %s, TaskId: %s, Message: %s",
                    taskType, taskId, message);
    }

Mostly there are 4 types of tasks but can grow to more in future. Most classes are dedicated to one of the four task types.

Now every time, I have to get a log line out, I need to call this logFormatter and a typical log line looks like below -

log.info(LogFormatter.format(
                    "StackOverflowTask",
                    "StackOverflowId",
                    "A long long message exceeding 50 characters"));

Each such log line breaks the code readability for the reader. At the least, I would like to keep this log line short enough to a single line.

One of the ways is to somehow let LogFormatter method call understand the task type to save repetition in every line.

I have two paths to follow -

One is to create separate classes for each task type like

class StackOverflowTaskLogFormatter extends LogFormatter

OR

create separate methods like

public void formatStackOverflowTaskLog()

First solution to me looks better because I can introduce more such classes without modifying existing ones (Open-Closed Principle) and the signature of method format will remain same. But I am still not content to write so many classes and then many more @Autowireds in each class, creating class bloatware. Also, I can clearly see that such kind of specialisation also increases class/method length and beats the original intended purpose behind their creation.

I am keen to understand if there are better ways to maintain code readability in above situation.

Was it helpful?

Solution

Let's say you have an interface that represents a task, and every task in your system implements that interface:

public interface Task {
    String getId();
    String getType();
}

Now your LogFormatter can be simplified into taking 2 parameters:

@Sl4j
class LogFormatter {
    public static String format(Task task, String message) {
         return String.format("Task type: %s, Task Id: %s, Message: %s",
             task.getType(), task.getId(), message);
    }
}

Your log entry should be a bit more readable since you can simply reference your task object.

Logging from inside the object:

log.info(LogFormatter.format(this, "A long long message exceeding 50 characters"));

Logging from outside the object:

log.info(LogFormatter.format(taskObject, "A long long message exceeding 50 characters"));

Another option is to import your formatting functions statically:

import static LogFormatter.*;

// code follows inside the object...
log.info(format(this, "A long long message exceeding 50 characters"));

Neither of those deviate too far from your current design and work with just about any logging framework.

Licensed under: CC-BY-SA with attribution
scroll top