Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the different methods for injecting cross-cutting concerns?

Tags:

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?

like image 446
Stacy Vicknair Avatar asked Nov 10 '09 15:11

Stacy Vicknair


People also ask

Which pattern helps with cross-cutting concerns like transactions?

The Publish-subscribe pattern is another event based pattern that allows you to address cross cutting concerns.

Which are considered to be typical common crosscutting concerns that would be a good fit for a AOP?

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.


2 Answers

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.

like image 126
Mark Seemann Avatar answered Sep 24 '22 01:09

Mark Seemann


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.

like image 38
Eva Avatar answered Sep 25 '22 01:09

Eva