Search code examples
scalaaopscala-2.10cross-cutting-concerns

How to handle cross cutting concerns the Scala way


I am reading online about cross cutting concerns since I just implemented Log4j into my code. Some people are saying using AspectJ is okay, while others point out that it breaks functional programming. That mixins are Scala's solution for cross cutting concerns.

However, I cringe when I think I will extend a trait to an object/ class that is not related itself.

e.g. new Database with Logger

Here Logger has nothing to do with Database, but its how to mixing to provide logging. I would prefer to do it the Scala way, so I want to find out this is what people mean by mixins.

Can someone please show me a quick example of how to go about this in Scala?


Solution

  • This is a big topic with lots of potential "correct" answers. My personal favourite would be using either "by name parameters" or higher order functions.

    A a very simple example of this:

    object Logging {
      def logCall[T](name: String)(block: => T): T = {
        log.info(s"Invoking: $name")
        block
      }
    }
    

    Which would allow you to apply it both in an object that itself knows about the cross cutting concern (something like annotating wrapping a method call with something in java):

    class DB {
      import Logging._
      def insert(item: Something) = logCall("insert") {
        ???
      }
    }
    

    Or at the call site:

    import Logging._
    def businessLogic() {
      val user = ???
      val result = logCall("insert user")(DB.insert(user))
      println(result)
    }
    

    The nice thing with this is that it is very explicit and self explanatory (which, again, are things you might value high or not).