aspect-oriented programming (aop) in .net

23
Yuriy Guts Software Architect @ ELEKS

Upload: yuriy-guts

Post on 15-Jul-2015

1.604 views

Category:

Software


3 download

TRANSCRIPT

Page 1: Aspect-Oriented Programming (AOP) in .NET

Yuriy GutsSoftware Architect @ ELEKS

Page 2: Aspect-Oriented Programming (AOP) in .NET

Clients

Application Services

Infrastructure Services

Desktop Browser

Desktop Application

Native Mobile App. . .

API Business Components Reporting. . .ORM

RDBMS Cache SearchIndex. . .Filesystem

Page 3: Aspect-Oriented Programming (AOP) in .NET

Clients

Application Services

Infrastructure Services

Desktop Browser

Desktop Application

Native Mobile App. . .

API Business Components Search. . .ORM

RDBMS Cache SearchIndex. . .Filesystem

Cross-Cutting Concerns

Identity & Access Mgmt.

Audit

Logging

. . .

Import & Export

Page 4: Aspect-Oriented Programming (AOP) in .NET

public class ReputationService : IReputationService...private readonly IUserDataService _userDataService;

public ReputationService(IUserDataService userDataService){

_userDataService = userDataService;}

public int AddReputationForQuestion(Question question){

int pointsToAdd = question.UpVotes * 5 - question.DownVotes * 2;int newReputation = _userDataService.AddReputationForUser(question.Author, pointsToAdd);return newReputation;

}

public int AddReputationForAnswer(Answer answer){

int pointsToAdd = answer.UpVotes * 10 - answer.DownVotes * 3;int newReputation = _userDataService.AddReputationForUser(answer.Author, pointsToAdd);return newReputation;

}...

Page 5: Aspect-Oriented Programming (AOP) in .NET

public int AddReputationForQuestion(Question question){

int pointsToAdd = question.UpVotes * 5 - question.DownVotes * 2;int newReputation = _userDataService.AddReputationForUser(question.Author, pointsToAdd);return newReputation;

}

Page 6: Aspect-Oriented Programming (AOP) in .NET

public int AddReputationForQuestion(Question question){

Console.WriteLine("{0:HH:mm:ss.fff}: AddReputationForQuestion started.", DateTime.Now);

int pointsToAdd = question.UpVotes * 5 - question.DownVotes * 2;int newReputation = _userDataService.AddReputationForUser(question.Author, pointsToAdd);

Console.WriteLine("{0:HH:mm:ss.fff}: AddReputationForQuestion completed.", DateTime.Now);return newReputation;

}

Page 7: Aspect-Oriented Programming (AOP) in .NET

public int AddReputationForQuestion(Question question){

Console.WriteLine("{0:HH:mm:ss.fff}: AddReputationForQuestion started.", DateTime.Now);

if (question == null){

throw new ArgumentNullException("question");}if (question.Author == null){

throw new ArgumentNullException("question", "Author cannot be null.");}if (question.UpVotes < 0 || question.DownVotes < 0){

throw new ArgumentException("A question cannot have a negative number of votes");}

int pointsToAdd = question.UpVotes * 5 - question.DownVotes * 2;int newReputation = _userDataService.AddReputationForUser(question.Author, pointsToAdd);

Console.WriteLine("{0:HH:mm:ss.fff}: AddReputationForQuestion completed.", DateTime.Now);return newReputation;

}

Page 8: Aspect-Oriented Programming (AOP) in .NET

public int AddReputationForQuestion(Question question){

Console.WriteLine("{0:HH:mm:ss.fff}: AddReputationForQuestion started.", DateTime.Now);

if (question == null) throw new ArgumentNullException("question");if (question.Author == null) throw new ArgumentNullException("question", "Author cannot be null.");if (question.UpVotes < 0 || question.DownVotes < 0) throw new ArgumentException("A question cannot have a negative number of votes");

var attemptsLeft = 3;try{

while (attemptsLeft > 0){

try{

int pointsToAdd = question.UpVotes * 5 - question.DownVotes * 2;int newReputation = _userDataService.AddReputationForUser(question.Author, pointsToAdd);

Console.WriteLine("{0:HH:mm:ss.fff}: AddReputationForQuestion completed.", DateTime.Now);return newReputation;

}catch{

attemptsLeft--;if (attemptsLeft == 0){

throw;}

}}

}catch (Exception ex){

Console.WriteLine("{0:HH:mm:ss.fff}: AddReputationForQuestion failed with exception: {1}.", DateTime.Now, ex);}throw new Exception();

}

Page 9: Aspect-Oriented Programming (AOP) in .NET

public int AddReputationForQuestion(Question question){

QuestionValidator.ValidateQuestion(question);return BoundaryLogging<int>.Run("AddReputationForQuestion", () =>{

return MultipleAttemptExecutor<int>.Run(3, () =>{

int pointsToAdd = question.UpVotes * 5 - question.DownVotes * 2;int newReputation = _userDataService.AddReputationForUser(question.Author, pointsToAdd);return newReputation;

});});

}

Page 10: Aspect-Oriented Programming (AOP) in .NET

[DomainValidation][BoundaryLogging][MultipleAttemptExecution(3)]public int AddReputationForQuestion(Question question){

int pointsToAdd = question.UpVotes * 5 - question.DownVotes * 2;int newReputation = _userDataService.AddReputationForUser(question.Author, pointsToAdd);return newReputation;

}

Page 11: Aspect-Oriented Programming (AOP) in .NET
Page 12: Aspect-Oriented Programming (AOP) in .NET

Language Compiler

AOP Post-Compiler

Source Code

IL Code

IL Code withgenerated aspects

Page 13: Aspect-Oriented Programming (AOP) in .NET

IoC ContainerCalling Code

Dynamic Proxy

Original class

1

2

34

5

Page 14: Aspect-Oriented Programming (AOP) in .NET

return this;

return F(this);

Page 15: Aspect-Oriented Programming (AOP) in .NET

• PostSharp (IL weaving)

• Castle.DynamicProxy (call interception)

(just to name a few)

Page 16: Aspect-Oriented Programming (AOP) in .NET

[Serializable]public class BoundaryLogging : OnMethodBoundaryAspect{

public override void OnEntry(MethodExecutionArgs args){

Console.WriteLine("{0:HH:mm:ss.fff}: {1} started.", DateTime.Now, args.Method.Name);}

public override void OnExit(MethodExecutionArgs args){

Console.WriteLine("{0:HH:mm:ss.fff}: {1} completed.", DateTime.Now, args.Method.Name);}

public override void OnException(MethodExecutionArgs args){

Console.WriteLine("{0:HH:mm:ss.fff}: {1} failed with exception: {2}.",DateTime.Now, args.Method.Name, args.Exception);

}}

Page 17: Aspect-Oriented Programming (AOP) in .NET

[Serializable]public class MultipleAttemptExecution : MethodInterceptionAspect{

private readonly int _maxAttempts;public MultipleAttemptExecution(int maxAttempts){

_maxAttempts = maxAttempts;}

public override void OnInvoke(MethodInterceptionArgs args){

var attemptsLeft = _maxAttempts;while (attemptsLeft > 0){

try{

args.Proceed();return;

}catch{

attemptsLeft--;if (attemptsLeft == 0) throw;

}}throw new Exception("Maximum attempts reached.");

}}

Page 18: Aspect-Oriented Programming (AOP) in .NET

[DomainValidation][BoundaryLogging][MultipleAttemptExecution(3)]public int AddReputationForQuestion(Question question){

int pointsToAdd = question.UpVotes * 5 - question.DownVotes * 2;int newReputation = _userDataService.AddReputationForUser(question.Author, pointsToAdd);return newReputation;

}

Page 19: Aspect-Oriented Programming (AOP) in .NET
Page 20: Aspect-Oriented Programming (AOP) in .NET

• [Authorize] attribute in ASP.NET MVC

• HttpModules in ASP.NET lifecycle

• Anything else?

Page 21: Aspect-Oriented Programming (AOP) in .NET

• Logging & Audit

• Transactions

• Security

• Caching

• Exception Management

• Generating and validating code

Page 22: Aspect-Oriented Programming (AOP) in .NET

1. Introduces “magic”, can reduce understanding of the big picture (*).

2. Requires special tools or code decorations.

3. Even mature frameworks have bugs.

(*) Greg Young:www.infoq.com/presentations/8-lines-code-refactoring

Page 23: Aspect-Oriented Programming (AOP) in .NET

yuriy.guts @ eleks.com

https://github.com/YuriyGuts/refactoring-with-aop