post sharp presentation

42
An Introduction to Aspect-Oriented Programming in Microsoft .NET. Produce Cleaner Code with Aspect-Oriented Programming Christophe Geers [email protected] http://www.cgeers.com/

Upload: christophe-geers

Post on 25-Jun-2015

514 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: Post sharp presentation

An Introduction to Aspect-Oriented Programming in Microsoft .NET.

Produce Cleaner Code with Aspect-Oriented Programming

Christophe [email protected]://www.cgeers.com/

Page 2: Post sharp presentation

AOP Facts

•AOP is 15 years oldMature

•Siemens, Hitachi, SAP, ASML•WebSphere, JBoss, WebLogic

Industry-Adopted

•-15% Lines of Code•-20% CouplingReal Benefits

Page 3: Post sharp presentation

Agenda• The Problem with Conventional Programming

• What is AOP?

• Why AOP?

• PostSharp Features

• Comparing AOP Frameworks

Page 4: Post sharp presentation

The Problem with Conventional Programming

Part 1

Page 5: Post sharp presentation

In the beginning there was nothing.

public class RentalService{}

Page 6: Post sharp presentation

public class RentalService{ public void RentMovie(Guid movieId, Guid customerId) { Movie movie = Movie.GetById(movieId); Customer customer = Customer.GetById(customerId);  var history = new RentalHistory(); history.MovieId = movieId; history.CustomerId = customerId; history.RentedOn = DateTime.Now; customer.History.Add(history);  customer.Balance -= movie.RentalPrice; }}

Customer said: let there be business value.

And there was business code.

Page 7: Post sharp presentation

Testers said: Let there be

logging

And there was logging code.

public class RentalService{ private static readonly TraceSource Trace = new TraceSource(typeof (RentalService).FullName);  public void RentMovie(Guid movieId, Guid customerId) { Trace.TraceInformation( "Entering RentalService.RentMovie(movieId = {0},_customerId = {1})", movieId, customerId);  try {  Movie movie = Movie.GetById(movieId); Customer customer = Customer.GetById(customerId);  var history = new RentalHistory(); history.MovieId = movieId; history.CustomerId = customerId; history.RentedOn = DateTime.Now; customer.History.Add(history);  customer.Balance -= movie.RentalPrice;  Trace.TraceInformation( "Leaving RentalService.RentMovie(movieId = {0}, customerId = {1})", movieId, customerId); } catch (Exception ex) { Trace.TraceEvent(TraceEventType.Error, 0, "Exception: RentalService.RentMovie(movieId = {0}, customerId = {1}) failed: {2}", movieId, customerId, ex.Message); throw; } }}

Page 8: Post sharp presentation

Thenthere was

precondition checking code.

public class RentalService{ private static readonly TraceSource Trace = new TraceSource(typeof (RentalService).FullName);  public void RentMovie(Guid movieId, Guid customerId) { if (movieId == Guid.Empty) throw new ArgumentException("movieId"); if (customerId == Guid.Empty) throw new ArgumentException("customerId");  Trace.TraceInformation( "Entering RentalService.RentMovie(movieId = {0},_customerId = {1})", movieId, customerId);  try {  Movie movie = Movie.GetById(movieId); Customer customer = Customer.GetById(customerId);  var history = new RentalHistory(); history.MovieId = movieId; history.CustomerId = customerId; history.RentedOn = DateTime.Now; customer.History.Add(history);  customer.Balance -= movie.RentalPrice;  Trace.TraceInformation( "Leaving RentalService.RentMovie(movieId = {0}, customerId = {1})", movieId, customerId); } catch (Exception ex) { Trace.TraceEvent(TraceEventType.Error, 0, "Exception: RentalService.RentMovie(movieId = {0}, customerId = {1}) failed : {2}", movieId, customerId, ex.Message); throw; } }}

Devs said: Let there be

defensive programming

Page 9: Post sharp presentation

public class RentalService{ private static readonly TraceSource Trace = new TraceSource(typeof (RentalService).FullName);  public void RentMovie(Guid movieId, Guid customerId) { if (movieId == Guid.Empty) throw new ArgumentException("movieId"); if (customerId == Guid.Empty) throw new ArgumentException("customerId");  Trace.TraceInformation( "Entering RentalService.RentMovie(movieId = {0},_customerId = {1})“, movieId, customerId);  try {

using (var scope = new TransactionScope()) { Movie movie = Movie.GetById(movieId); Customer customer = Customer.GetById(customerId);  var history = new RentalHistory(); history.MovieId = movieId; history.CustomerId = customerId; history.RentedOn = DateTime.Now; customer.History.Add(history);  customer.Balance -= movie.RentalPrice;  ContextManager.Context.SaveChanges(); scope.Complete();

  Trace.TraceInformation( "Leaving RentalService.RentMovie(movieId = {0}, customerId = {1})“, movieId, customerId); } } catch (Exception ex) { Trace.TraceEvent(TraceEventType.Error, 0, "Exception: RentalService.RentMovie(movieId = {0}, customerId = {1}) failed : {2}", movieId, customerId, ex.Message); throw; } }}

And there was transaction handling code.Let there be transactions.

Page 10: Post sharp presentation

public class RentalService{ private static readonly TraceSource Trace = new TraceSource(typeof (RentalService).FullName);  public void RentMovie(Guid movieId, Guid customerId) { if (movieId == Guid.Empty) throw new ArgumentException("movieId"); if (customerId == Guid.Empty) throw new ArgumentException("customerId");  try { Trace.TraceInformation( "Entering RentalService.RentMovie(movieId = {0},_customerId = {1})“, movieId, customerId);  try { using (var scope = new TransactionScope()) { Movie movie = Movie.GetById(movieId); Customer customer = Customer.GetById(customerId);  var history = new RentalHistory(); history.MovieId = movieId; history.CustomerId = customerId; history.RentedOn = DateTime.Now; customer.History.Add(history);  customer.Balance -= movie.RentalPrice;  ContextManager.Context.SaveChanges(); scope.Complete();  Trace.TraceInformation( "Leaving RentalService.RentMovie(movieId = {0}, customerId = {1})“, movieId, customerId);

} } catch (Exception ex) { Trace.TraceEvent(TraceEventType.Error, 0, "Exception: RentalService.RentMovie(movieId = {0}, customerId = {1}) failed : {2}", movieId, customerId, ex.Message); throw; } } catch (Exception ex) { if (ExceptionManager.Handle(ex)) throw; } }} 

And there was exception handling code.Let there be user-friendly error messages.

Page 11: Post sharp presentation

• We want a nice separation of concerns (assembly > namespace > class > method)

• OOP forces us to write crap!

• Code Scattering

• Code Tangling

• Code Coupling

Layer 1

Layer 2

Why do we write ugly code?

Page 12: Post sharp presentation

• Security

• Exception Handling

• Tracing

• Monitoring

• Transaction

• Data Binding

• Thread Sync

• Caching

• Validation

Non-Functional Requirements

Cross-Cutting Concerns

Page 13: Post sharp presentation

Encapsulating Infrastructure Concerns?

Page 14: Post sharp presentation

Aspects!

Page 15: Post sharp presentation

Strengthen Applications With Aspects

Show Me!

Page 16: Post sharp presentation

Show Me!1. Add a reference to PostSharp.dll

Page 17: Post sharp presentation

Show Me!2. Write an aspect {Demo}

Page 18: Post sharp presentation

Show Me!3. Apply the aspect {Demo}

Page 19: Post sharp presentation

Show Me!How does it work?

1. Source 2. Compiler 3. PostSharp 4. Run Time

Page 20: Post sharp presentation

The Idea Behind AOPPart 2

Page 21: Post sharp presentation

Cross-Cutting Concerns

Separation of Concerns

Problem Domain

Solution Domain

Page 22: Post sharp presentation

What is AOP?An extension of (not an alternative to) OOP that addresses the issue of cross-cutting concerns by providing a mean to:

• Encapsulate cross-cutting concerns

into Aspects = collection of transformations of code

• Apply aspects to elements of code

Page 23: Post sharp presentation

15 Years of AOP History

1994-1996

• First efforts on program transformation

1997

•AOP coined by Gregor Kiczales (Xerox PARC)

2001

•AspectJ published;• First AOSD

Conference

2003

•AspectJ released to the Eclise OSS community

• Spring Framework 1.0

• .NET 1.0

2004

•Build up of Interface21, later SpringSource, around IoC and AOP

•Works Begins on PostSharp

• JBoss AOP•WebSphere AOP•AJDT• SAP Enhancement

Framework

2007-2008

• PostSharp 1.0• PostSharp 1.5•ALCOB (AOP for

COBOL)

2009

• SpringSource acquired by VMWare, $400M

2010

• PostSharp 2.0

Research Years Hype Years Productivity Years

Page 24: Post sharp presentation

Why You Should Care

The benefits of aspect-oriented programming

Page 25: Post sharp presentation

The benefits of aspect-oriented programmingDecrease Development Costs• Write Fewer lines of code

• Read Fewer lines of code

• Concise, clear, understandable code

• Size-Cost relationship is superlinear

Page 26: Post sharp presentation

The benefits of aspect-oriented programmingImprove Quality• Fewer lines of code

→ Fewer Defects• More automation

→ Fewer Defects• Less boiler-plate code

→ More interesting work → Increased attention

→ Fewer Defects

Page 27: Post sharp presentation

The benefits of aspect-oriented programmingDecrease Maintenance Costs• Remember:

• Fewer Defects• Maintenance = 75% Reading Code

• How do you change a pattern once it’s implemented?

• Better architecture metrics:

• Decreased component coupling

• Increased component cohesion

Page 28: Post sharp presentation

The benefits of aspect-oriented programmingDecrease Maintenance Costs

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 160

5

10

15

20

25

30

RedesignRedesign

Redesign

Redesign

Redesign

Conventional AOP Redesign

Time

Com

plex

ity

Page 29: Post sharp presentation

Features

Page 30: Post sharp presentation

FeaturesCode Transformation Primitives

• Around Methods

• Method Interception

• Property Interception

• Field Interception

• Event Interception

• Interface Introduction

• Method Introduction

• Property Introduction

• Event Introduction

• Member Import

• Custom Attribute Intro

• Managed Resource Intro

IntroductionsModifications

Page 31: Post sharp presentation

FeaturesComposite Aspects• Aspects composed of multiple primitive transformations

• Advice = Additional Behavior ≈ Transformation

• Pointcut = Expression selecting target elements of code

• Declarative

• LINQ over System.Reflection

• Adding aspects dynamically: IAspectProvider

Page 32: Post sharp presentation

FeaturesAspect MulticastingUsing a single line of code, apply an aspects to multiple elements of code based on:

• Attributes (public/private, virtual/sealed, …)

• Naming conventions

Page 33: Post sharp presentation

FeaturesAttribute Inheritance• Interfaces

• Classes

• Virtual Methods

• Assemblies (!)

Object

Entity

Customer

Order

Message

Update Message

Create Message

- or -

Page 34: Post sharp presentation

Robust Aspect Composition• Multiple aspects on the same element of code

• Aspect dependency framework

• Ordering

• Requirement

• Conflict

• Strong ordering and commutativity

Deterministic Behavior

D

CB

A

Page 35: Post sharp presentation

Comparing Aspect FrameworksPart 4

Page 36: Post sharp presentation

Comparing Aspect FrameworksStatic vs Dynamic AOP

Build-Time:Very ExpressiveRobust ModelNot InvasiveStatic

Run-Time:Less ExpressiveBrittle ModelInvasiveDynamic

Hybrid

PostSharp

Spring.NETCastleMS Unity/PIAB

LinFu

Page 37: Post sharp presentation

Comparing Aspect FrameworksExpressiveness (1/2)

PostSharp Linfu Spring.NET Castle Unity/PIAB

Method Interception Yes Yes Yes YesInterface Introduction Yes Yes Yes YesPrivate/Sealed Member Interception Yes Yes

Event Interception YesMember Introduction YesComposite Aspects Yes

What can you do with the framework?

Page 38: Post sharp presentation

Comparing Aspect FrameworksExpressiveness (2/2)

PostSharp Linfu Spring.NET Castle Unity/PIAB

Custom Attributes Yes Yes Yes YesCustom C# Code Yes Yes Yes FeasibleAspect Inheritance YesXML Config. Yes Yes

How do you apply aspects to code?

Page 39: Post sharp presentation

Comparing Aspect FrameworksNon-Invasiveness

PostSharp Linfu Spring.NET Castle Unity/PIAB

No change required in base source code Yes Yes

Use on any object (e.g. WPF control) Yes Yes

Can you use aspects without deep refactoring?

Require the use of factory methods

Page 40: Post sharp presentation

Comparing Aspect FrameworksRobustness

PostSharp Linfu Spring.NET Castle Unity/PIAB

Aspect Validation Yes FeasibleAspect Dependency Framework Yes

Can you prevent aspects from being improperly used?

Page 41: Post sharp presentation

Comparing Aspect FrameworksMisc.

PostSharp Linfu Spring.NET Castle Unity/PIAB

Dynamic: change aspects without recompiling

Yes Yes Yes

Productive: Visual Studio tooling Yes

No Impact on Build Time Yes Yes

Support: Extensive Documentation, Commercially Supported

Yes Yes Yes

Other points that matter

Page 42: Post sharp presentation

http://www.sharpcrafters.com/[email protected]