post sharp presentation

Post on 25-Jun-2015

514 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

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

Produce Cleaner Code with Aspect-Oriented Programming

Christophe Geersgeersch@gmail.comhttp://www.cgeers.com/

AOP Facts

•AOP is 15 years oldMature

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

Industry-Adopted

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

Agenda• The Problem with Conventional Programming

• What is AOP?

• Why AOP?

• PostSharp Features

• Comparing AOP Frameworks

The Problem with Conventional Programming

Part 1

In the beginning there was nothing.

public class RentalService{}

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.

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

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

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.

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.

• 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?

• Security

• Exception Handling

• Tracing

• Monitoring

• Transaction

• Data Binding

• Thread Sync

• Caching

• Validation

Non-Functional Requirements

Cross-Cutting Concerns

Encapsulating Infrastructure Concerns?

Aspects!

Strengthen Applications With Aspects

Show Me!

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

Show Me!2. Write an aspect {Demo}

Show Me!3. Apply the aspect {Demo}

Show Me!How does it work?

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

The Idea Behind AOPPart 2

Cross-Cutting Concerns

Separation of Concerns

Problem Domain

Solution Domain

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

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

Why You Should Care

The benefits of aspect-oriented programming

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

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

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

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

Features

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

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

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

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

• Naming conventions

FeaturesAttribute Inheritance• Interfaces

• Classes

• Virtual Methods

• Assemblies (!)

Object

Entity

Customer

Order

Message

Update Message

Create Message

- or -

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

Comparing Aspect FrameworksPart 4

Comparing Aspect FrameworksStatic vs Dynamic AOP

Build-Time:Very ExpressiveRobust ModelNot InvasiveStatic

Run-Time:Less ExpressiveBrittle ModelInvasiveDynamic

Hybrid

PostSharp

Spring.NETCastleMS Unity/PIAB

LinFu

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?

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?

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

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?

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

http://www.sharpcrafters.com/geersch@gmail.com

top related