I'm having trouble coming up with a good way to structure the interfaces for two modules that are logically independent but whose implementations may be combined for the purposes of performance or efficiency.
My specific situation is the replacement of the separate queuing and logging modules in a message routing application with a combined database-backed implementation (let's call it
DbQueueLog). It's easy enough for
DbQueueLog to implement both the
ILogger interfaces so clients of the old queuing and logging modules can use it seamlessly. The challenge is that the most efficient and performant implementation of
DbQueueLog involves combining the
EnqueueMessage(Message m) and
LogMessage(Message m, List<LogParams> p) methods into an
EnqueueAndLogMessage(Message m, List<LogParams> p) method that minimizes the number of cross-process database calls and the amount of data written to disk. I could create a new
IQueueLog interface with these new methods, but I'm uncomfortable with what that would mean if a future iteration of the application moved back to separate queuing and logging modules.
Are there any design approaches to this situation that would allow me to build the efficient, performant
DbQueueLog implementation now without permanently coupling together the application's queuing and logging modules?
Edit: The application is built on Windows using C# in case any there are any platform-specific techniques that might be available.