Last week we reviewed using Neat Architecture for Showpitch‘s Domain Services. This week we’re going to go in to Neat and Logging on Showpitch.
At Showpitch we’ve built on the Logging Interceptor that’s offered in Neat. But it’s a fantastic starting point! Using this we get a lot of functionality right out of the box for each new piece of code we add to Showpitch. So let’s talk about Logging and how Neat Logging solves some pretty common problems!
Logging, A Necessary Evil
As app developers, we all eventually reach the same conclusion, one famously posited by Murphy –
If something can go wrong, it eventually will go wrong.
In the face of the inevitable we then have to acknowledge that we will need to understand what’s going wrong, when, and how. And so we start adding Logging code to our app.
So why do I call Logging a “Necessary Evil”?
This is because, as app developers, we are not writing apps for Logging. We’re not designing, coding, and hacking for the sake of Logging. We build apps to solve problems. If we didn’t need to write code, reserve systems resources, and spend database and disk space for Logging we wouldn’t. And yet time and again we spend hours of our time, countless CPU cycles, and endless bytes of storage on Logging.
So great is the tax that is levied by Logging that it could easily be framed as an app’s equivalent of that dastardly Sheriff of Nottingham. We hate to pay its tax, but there’s no getting out of it.
And without Logging we can’t know what’s going wrong, when, and how. It’s Evil, but it’s Necessary, hence a “Necessary Evil”.
Logging, A Cross Cutting Concern
Once we accept the need for Logging, the next step is to add it to our app. And this is where, for many app developers, the pain begins. How familiar does this code block look to you?
public class AThingDoingClass : IAThingDoingClass
{
public void DoesOneThingAndOneThingOnly()
{
try
{
DoSomethingThatCouldThrowAnError();
}
catch(Exception ex)
{
Logger.Log(ex);
}
}
}
What can we learn from this example?
First, we’re using 8 lines of code, for something that should only require 1. That’s a lot of extra code, just to accommodate Logging.
Second, we can probably expect to see this code duplicated about 500 times in our application. Not very DRY, is it? We need Logging all over the place, but we’re reproducing the same code over and over!
Finally, let’s talk SOLID, specifically Single Responsibility. Where does our method say it’s a Logging method? It “Does One Thing And One Thing Only” from what we can see. It would seem this method doesn’t live up to its Single Responsibility.
This is where such a Cross Cutting Concern comes from. All over the app we’re going to need Logging, but this concern isn’t specific to any given method, nor is it the responsibility of any of those methods. And yet it shows up all over!
Logging, A Decorator Approach
So could we at least address the Single Responsibility issue?
Yes, by introducing a Decorator we can separate these responsibilities. For example:
public class AThingDoingClass : IAThingDoingClass
{
public void DoesOneThingAndOneThingOnly()
{
DoSomethingThatCouldThrowAnError();
}
}
public class AThingDoingClassLoggingDecorator : IAThingDoingClass
{
private read only IAThingDoingClass _aThingDoingClass;
public AThingDoingClassLoggingDecorator(IAThingDoingClass aThingDoingClass)
{
_aThingDoingClass = aThingDoingClass;
}
public void DoesOneThingAndOneThingOnly()
{
try
{
_aThingDoingClass.DoesOneThingAndOneThingOnly();
}
catch(Exception ex)
{
Logger.Log(ex);
}
}
}
Ok, now we only have one responsibility per method. Great, but this is still a lot of code to write! And it’s still not DRY! So is there an even better way?
Logging, An Aspect and Neat
What if there were a way to wrap every class and every method in your application with one of these Decorators, automatically, without having to repeat the same code all over?
That’s what Neat does! Using Interceptors built in to Microsoft Practices Unity 3 we’ve built a Logging Interceptor in Neat, which does exactly this.
This is evocative of Aspect-Oriented Programming (AOP). .Net doesn’t lend itself well to AOP, but using Interceptors we can achieve something very close to it! And this is exciting, because it means we can now assign behavior in our app simply by ascribing an Aspect to our code! And once we have that, we can make these Aspects a convention of our code. This gets us a lot of behavior for a much smaller investment!
We even built a Decorator around the Microsoft Practices Unity 3 container that automatically registers this Interceptor with every class registration. This makes the Logging Aspect of our app a convention that every class and every method uses. We’ve also included a Mongo Logging Provider, built on top of nLog, that’s already wired up in the Neat example solution. This way you get Logging right away, no muss, no fuss!
So what does this mean for a developer? It means you can simplify and reduce code, like the example code, to only what it does, and let the Architecture take care of Logging for you. For example:
public class AThingDoingClass : IAThingDoingClass
{
public void DoesOneThingAndOneThingOnly()
{
DoSomethingThatCouldThrowAnError();
}
}
That’s it! The Logging is there, but it’s intrinsic to the app now.
If you want to explore how this has been done, take a look under the hood in the Neat example solution. Get started at the GitHub Page for Neat.
The following objects comprise this Logging solution in Neat and will be interesting to look at:
- Neat.Infrastructure.Unity.Interceptor.LoggingInterceptor
- Neat.Infrastructure.Unity.LoggingUnityContainer
- Neat.Infrastructure.Logging.ILogProvider
- Neat.Infrastructure.Logging.NLogProvider
If you want to build a new LogProvider to use a different Logging system, or even a custom Logging system, then just build a new class that implements Neat.Infrastructure.Logging.ILogProvider and register it with the container. Your Logging system will now be used!
That’s Logging in Neat! Showpitch started with this solution and with it and its evolution, we’ve saved our team literally hundreds of hours of Production troubleshooting and writing and maintaining Logging code for our platform!
Is there something you want to see me cover in the next post? Is there a part of Neat or Showpitch you want to see more on, or something you want to see added to Neat? Please add a comment below! And keep checking back to learn more!
<< Back to Showpitch Advanced Part 1
On to Showpitch Advanced Part 3 >>