3

I have a bit of “legacy” Scala code (Java-like), which does a bit of data access. There’s a decorator which tracks usage of the DAO methods (collecting metrics), like this:

class TrackingDao(tracker: Tracker) extends Dao {
    def fetchById(id: UUID, source: String): Option[String] = {
        tracker.track("fetchById", source) {
            actualFetchLogic(...)
        }
    }
    ...
}

I'm trying to model this as a Free monad. I've defined the following algebra for the DAO operations:

sealed trait DBOp[A]
case class FetchById(id: UUID) extends DBOp[Option[String]]
...

I see two options:

a) I can either make two interpreters that take DBOp, one performs the actual data access, the other does the tracking, and compose them together OR
b) I make Tracking an explicit algebra, and use a Coproduct to use them both in the same for composition OR
c) Something completely different!

The first option looks more like a "decorator" approach, which is tied to DBOp, the second is more generic solution, but would require calling the 'tracking' algebra explicitly.

In addition, notice the source parameter on the original fetchById call: it's only used for tracking. I much rather remove it from the API.

Here's the actual question: how do I model the tracking?

4

2 に答える 2