Skip to content

Instantly share code, notes, and snippets.

@rbirkby
Created May 17, 2013 08:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rbirkby/5597813 to your computer and use it in GitHub Desktop.
Save rbirkby/5597813 to your computer and use it in GitHub Desktop.
Adding a Logger to an authorization system using a Decorator and abiding by SOLID. Please note that this solution isn't thread safe.
using System;
using System.Diagnostics;
using System.Threading;
using Xunit;
namespace CodingChallenge
{
class Program
{
static void Main()
{
// In a real application, these dependencies would be injected in via an IoC container.
var logger = new InMemoryLogger();
var service = new AuthorisationService();
var instrumentingService = new InstrumentedAuthorisationService(logger, service);
for (int i = 0; i < 50; i++)
{
instrumentingService.Authorise(new AuthorisationRequest());
}
Console.WriteLine("Execution count: {0}", logger.ExecutionCount);
Console.WriteLine("Average execution time: {0}", logger.AverageExecutionTime);
}
}
class WhenInstrumentingAuthorisationService {
[Fact]
public void ShouldRecordCorrectExecutionCount()
{
// InMemoryLogger should be injected in as a singleton.
var logger = new InMemoryLogger();
for (int i = 0; i < 50; i++)
{
var instrumentingService = new InstrumentedAuthorisationService(logger, new AuthorisationService());
instrumentingService.Authorise(new AuthorisationRequest());
}
Assert.Equal(50, logger.ExecutionCount);
}
}
public interface ILogger
{
void IncrementExecutionCount();
void RecordExecutionTime(TimeSpan elapsed);
TimeSpan AverageExecutionTime { get; }
int ExecutionCount { get; }
}
public interface IAuthorisationService
{
void Authorise(AuthorisationRequest request);
}
public class InMemoryLogger : ILogger
{
private int _executionCount;
private TimeSpan _totalExecutionTime;
public void IncrementExecutionCount()
{
_executionCount++;
}
public void RecordExecutionTime(TimeSpan elapsed)
{
_totalExecutionTime += elapsed;
}
public TimeSpan AverageExecutionTime
{
get { return new TimeSpan(_totalExecutionTime.Ticks / _executionCount); }
}
public int ExecutionCount
{
get { return _executionCount; }
}
}
public class InstrumentedAuthorisationService : IAuthorisationService
{
private readonly ILogger _logger;
private readonly IAuthorisationService _target;
public InstrumentedAuthorisationService(ILogger logger, IAuthorisationService target)
{
_logger = logger;
_target = target;
}
public void Authorise(AuthorisationRequest request)
{
var timer = Stopwatch.StartNew();
_target.Authorise(request);
_logger.RecordExecutionTime(timer.Elapsed);
_logger.IncrementExecutionCount();
}
}
public class AuthorisationService : IAuthorisationService
{
public void Authorise(AuthorisationRequest request)
{
//Authorisation code
Thread.Sleep(new Random().Next(10, 100)); // For demonstration purposes *only*.
}
}
public class AuthorisationRequest
{
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment