I've got some really expensive business logic inside my domain layer where the data must be tracked in order to get a picture of what happened if something fails. Because of this, I want to declare a simple logging interface:
public interface ILogger {
void Log(LogEntry entry);
}
Now my question is - where does this interface belongs to? Of course logging might be a infrastructure concern (and a little bit of cross layer concern), but if I place it in the infrastructure layer, my domain services don't get access to it. If I place it into the domain layer, I introduce the concept of logging into my domain, which feels awkward.
I'm already using certain concepts from CQRS & EventSourcing inside my application, however throwing a event for like everything that happens with the data inside a domain service seems like an overkill (especially if the data falls into a state that doesn't get returned by a domain service until further transformations have been made.)
There are some options here.
Use decorators. You say you are already using CQRS, so add decorators to the commands/queries which you want to log. The downside is that you can only log before and after the execution of the command/query, not during the execution. And I'm not sure if it will be easy to log for your events as well this way.
Use your interface. If you choose this path, than indeed your ILogger
interface should be in the domain layer, because the domain will require a component that implements your logger requirements, so the domain layer is the one to define this interface. The implementation of it must be elsewhere, and in an infrastructure layer sounds fine to me.
[...] my domain services don't get access to it
Why not? ILogger
should live in the infrastucture layer, but who said that domain layer has no access to infrastructure members?
As far as I know, infrastructure is an unrelated non-domain specific code which solves common problems like I/O, networking, database-access and so on. And logging is an infrastructure concern.
Infrastructure code should implement or provide cross-layer software pieces, and it might provide a infrastructure-based ILogger
implementation. If your domain requires some kind of specific code for logging, you'll provide a SomeDomainLogger
implemented in the domain layer.
I don't know if you're already using inversion of control, since this is the best way to load such kind of implementations of infrastructure code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With