What are the different methods for injecting cross-cutting concerns into a class so that I can minimize the coupling of the classes involved while keeping the code testable (TDD or otherwise)?
For example, consider if I have a class that requires both logging functionality and centralized exception management. Should I use DIP and inject both required concerns via an interface into the class that requires them? Should I use a service locater that I pass to each class that will require some cross cutting functionality? Is there a different solution altogether? Am I asking the wrong question entirely?
The Publish-subscribe pattern is another event based pattern that allows you to address cross cutting concerns.
For example, logging, security and data transfer are the concerns needed in almost every module of an application, thus they are the cross-cutting concerns.
The Decorator design pattern is an excellent starting point for implementing cross-cutting concerns.
First you need to define an interface that models the service in question. Then you implement the real functionality of that service without thinking about your cross-cutting concern at all.
Then you can subsequently implement decorating classes that wrap around other instances and implement the desired cross-cutting concern.
This approach can be implemented entirely with Plain Old C# Objects (POCOs) and requires no extra frameworks.
However, if you get tired of writing all the extra decorators, you may want to use a framework. I have no experience with explicit AOP frameworks, but most DI Containers such as Castle Windsor offer AOP-like features.
Here's an example of using Decorators. Let's say that you have the following interface:
public interface IMyInterface { void DoStuff(string s); }
Your concrete implementation may do something very interesting, such as writing the string to the Console:
public class ConsoleThing : IMyInterface { public void DoStuff(string s) { Console.WriteLine(s); } }
If you wish to log the DoStuff operation, you can now implement a logging Decorator:
public class LoggingThing : IMyInterface { private readonly IMyInterface innerThing; public LoggingThing(IMyInterface innerThing) { this.innerThing = innerThing; } public void DoStuff(string s) { this.innerThing.DoStuff(s); Log.Write("DoStuff", s); } }
You can keep writing new Decorators, like a caching Decorator or one that implements security and so on, and just wrap them around each other.
Note: I rarely recommend static interfaces, so the Log.Write interface is not a recommendation, but merely mean as a placeholder. In a real implemetation, I'd inject some kind of ILogger interface into LoggingThing.
You can use the Observer pattern.
The Subject holds a collection of Observers. When the Subject performs an action, it notifies the Observers of the change. The Observers can then perform an action without the Subject caring what that action is.
Here's an example:
public interface IThingObserver { void Notify(); // can also pass in a parameter with event information } public class Thing { private readonly ICollection<IThingObserver> observers; public Thing() { observers = new List<IThingObserver>(); } public void RegisterObserver(IThingObserver observer) { observers.Add(observer); } public void UnregisterObserver(IThingObserver observer) { observers.Remove(observer); } private void NotifyObservers() { foreach (IThingObserver observer in observers) { observer.Notify(); } } public void DoIt() { Console.WriteLine("Doing it..."); NotifyObservers(); } } public class LoggingThingObserver : IThingObserver { public void Notify() { Log.Write("It is done."); } }
I'm used to Java, so please forgive any syntax errors.
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