|
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 |
|
{ |
|
} |
|
} |