0

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.

2
  • Where does the task name and ID come from? Are they magic strings or do they come from an object you already have? If they are both properties of an object you have, then your LogFormatter could take that object as it's first parameter, and make the intent behind your logging more clear. Jan 23, 2018 at 14:40
  • There does exist a task object but I was not making it available it to all classes/methods. Maybe during bean creation itself, I can do that.
    – comiventor
    Jan 23, 2018 at 21:07

1 Answer 1

0

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.

1
  • I didn't know one can import static methods like that. Uber cool
    – comiventor
    Jan 23, 2018 at 21:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.