Skip to main content
logging in the middle added
Source Link
Frank
  • 14.4k
  • 3
  • 43
  • 68

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.

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.

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.

Source Link
Frank
  • 14.4k
  • 3
  • 43
  • 68

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.