8

Introduction

I am implementing a abstract Java class of a processing framework*. By implementing the function execute, I am able to add business logical functionality. I would like to add logging at the start and end of every implementation of every of my execute functions. Also in between some logging, if specific things are done. However, I would like to make this in a uniform manner. My thought was to inherit the framework class to an own new class which implements the logging and provides some new executeWithLogging functions, which are wrapping the logging around the specific parts. I am not sure if that is the best idea and whether I am able to use a design pattern that would make the whole endeavor elegant. How would I go on about the whole thing?

Challenges (please consider these!)

  1. One challenge in my case is that the original class has only one execute function, however, I'd need logging around multiple parts.
  2. The second thing is: Using a decorator pattern (was my first idea as well) does not quite work, if I am using also a execute, because the super.execute()-function would have to be called in the first line of my new execute(), isn't it?
  3. There would be at least 4 classes involved: BaseFunction from the framework, LoggingFunction extends BaseFunction from me, MyBusinessFunction extends LoggingFunction from me, MyBusinessClass which instanciates MyBusinessFunction.
  4. Not only do I need logging at the beginning and end of execute, but also in the middle.
  5. The "logging" is not just simple Java logging, but actually logging to a database. This does not change anything about the principles, but demonstrates that the logging might be more than just one line of code.

Maybe an example how I'd do the whole thing would be nice, to get me going.

|* A Storm Trident Function, similar to a Storm bolt, but this is not particularly important.

  • 1
    super.execute is called by the decorator, not the decoratee. Your main class shouldn't even realize it is being decorated and you only need to be careful with this-calls, as they cannot include the decorator (as opposed to an approach with mixins or traits). – Frank Oct 1 '15 at 12:51
  • Is execute in BaseFunction abstract ? – Spotted Oct 1 '15 at 20:08
  • @Spotted: Yes, execute is abstract in BaseFunction. – Make42 Oct 2 '15 at 12:18
10

There are generally several possible ways to perform logging around a certain execution. First of all, it is good that you want to separate this, as logging is a typical example for Separation of Concerns. It truly doesn't make much sense to add logging directly into your business logic.

As for possible design patterns, here is a (non-conclusive) list from the top of my head:

  • Decorator pattern: A well-known design pattern, whereby you basically wrap the non-logging class into another class of the same interface and the wrapper does the logging before and/or after calling the wrapped class.

  • Function composition: In a functional programming language, you can simply compose your function with a logging function. This is similar to the decorator pattern in OO languages, but not a preferred way really, since the composed logging function would be based on a side-effecting implementation.

  • Monads: Monads are also from the functional programming world and allow you to decouple your execution and logging. This basically means you aggregate necessary logging messages and executions methods, but do not yet execute either. You can then process the monad in order to perform log-writing and/or actual execution of the business logic.

  • Aspect-oriented programming: More sophisticated approach, which achieves complete separation, as the class that does the non-logging behavior never directly interacts with the logging.

  • Relaying: Other standard design patterns may be suitable as well, for example, a Facade could serve as the logged entrypoint, before forwarding the call to another class which performs the business logic part. This can be applied to different abstraction levels as well. For example, you could log requests made to an externally reachable service URL, before relaying to an internal URL for actual non-logged processing of requests.

As for your added requirement that you need to perform logging "in the middle" - that's probably pointing to a strange design. Why is it, that your execute is doing so much, that something like a "middle" of its execution is even remotely of interest? If there is indeed such a lot of stuff going on, then why not bunch it up into stages/phases/what-have-you? You could in theory achieve logging in the middle with AOP I guess, but I'd still argue that a design change seems to be much more appropriate.

3

I have the feeling that you absolutly want to use a pattern. Remember that a bad usage of design patterns may result in a code less maintainable/readable.

That beeing said...

Your case is tricky as it seems you want to do 2 kinds of logging:

  1. Logging some steps of your logical functionality (inside execute)
  2. Logging around function calls (entering/exiting a function) (outside execute)

For the first case, at the moment you want to log some things inside a function, you have to do it... inside the function. You could use the template method pattern to make things a bit prettier but I think it's overkill in this case.

public final class MyBusinessFunction extends BaseFunction {
    @Override
    public final void execute() {
        log.info("Initializing some variables");
        int i = 0;
        double d = 1.0;

        log.info("Starting algorithm");
        for(...) {
            ...
            log.info("One step forward");
            ...
        }
        log.info("Ending algorithm");

        ...
        log.info("Cleaning some mess");
        ...
    }
}

For the second case, the decorator pattern is the way to go:

public final class LoggingFunction extends BaseFunction {
    private final BaseFunction origin;

    public LoggingFunction(BaseFunction origin) {
        this.origin = origin;
    }

    @Override
    public final void execute() {
        log.info("Entering execute");
        origin.execute();
        log.info("Exiting execute");
    }
}

And you could use it like this in BusinessClass:

public final BusinessClass {
    private final BaseFunction f1;

    public BusinessClass() {
        this.f1 = new LoggingFunction(new MyBusinessFunction());
    }

    public final void doFunction() {
        f1.execute();
    }
}

A call to doFunction will log this:

Entering execute
Initializing some variables
Starting algorithm
One step forward
One step forward
...
Ending algorithm
Cleaning some mess
Exiting execute
  • Would it work to omit the origin attribute and write super.execute(); instead of origin.execute();? – Make42 Oct 1 '15 at 16:19
  • Your solution is not complete - maybe due to my bad explaining. I'll add information in the question. – Make42 Oct 1 '15 at 16:21
  • @user49283 Why do you want to call super.execute() as this method is abstract ? – Spotted Oct 2 '15 at 13:27
  • @user49283 I also have updated my answer – Spotted Oct 2 '15 at 13:29
  • I have not quite understood the template pattern, but I'll give it another go soon. In the meantime: How about using the Command Pattern? I gave an answer using a Command Pattern - please comment! – Make42 Oct 3 '15 at 12:10
1

Your approach seems valid and is actually an implementation of the Decorator Pattern. There are other ways you could do this I suppose, but Decorator is a very elegant and easy to understand pattern that is very suited to solving your problem.

0

How about using the Command Pattern?

abstract class MyLoggingCommandPart {

  MyLoggingCommandPart() {
    log.info("Entering execute part");
    executeWithoutLogging();
    log.info("Exiting execute part");
  }

  abstract void executeWithoutLogging();

}

abstract class MyLoggingCommandWhole {

  MyLoggingCommandWhole() {
    log.info("Entering execute whole");
    executeWithoutLogging();
    log.info("Exiting execute whole");
  }

  abstract void executeWithoutLogging();

}

public final class MyBusinessFunction extends BaseFunction {

    @Override
    public final void execute() {

        new MyLoggingCommandWhole(){

            @Override
            executeWithoutLogging(){

                new MyLoggingCommandPart(){
                    @Override
                    executeWithoutLogging(){
                    // ... what I actually wanne do
                    }
                }

                new MyLoggingCommandPart(){
                    @Override
                    executeWithoutLogging(){
                    // ... some more stuff I actually wanne do
                    }
                }
            }
        }
    }
}
  • I don't have a lot of experience with the command pattern. The only obvious negativ point I see is that it's hardly readable (note the level of indentation), so I won't use it because I like to care of the people who will read my code in the future. – Spotted Oct 7 '15 at 9:50
  • Also execute() do nothing at the moment as you're just instanciating MyLoggingCommandWhole. – Spotted Oct 7 '15 at 9:51
  • @Spotted: I thought that instaciating MyLoggingCommandWhole, executes executeWithoutLogging(); from MyLoggingCommandWhole. Is that not the case? – Make42 Oct 10 '15 at 12:07
  • No it's not the case. You would have to write something like: MyLoggingCommandWhole cmd = new MyLoggingCommandWhole() { ... }; cmd.executeWithoutLogging(); – Spotted Oct 12 '15 at 7:42
  • @Spotted: That would hardly make any sense. If it is as you say, I'd rather have to put the code from the constructor into a function like executeWithLogging() and cmd.executeWithLogging(). Afterall, that is what should be executed. – Make42 Oct 12 '15 at 9:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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