Post sharp presentation

  • 462 views
Uploaded on

 

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
462
On Slideshare
0
From Embeds
0
Number of Embeds
1

Actions

Shares
Downloads
18
Comments
0
Likes
1

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. An Introduction to Aspect-Oriented Programming in Microsoft .NET.
    Produce Cleaner Code with Aspect-Oriented Programming
    Christophe Geers
    geersch@gmail.com
    http://www.cgeers.com/
  • 2. AOP Facts
  • 3. Agenda
    The Problem with Conventional Programming
    What is AOP?
    Why AOP?
    PostSharp Features
    Comparing AOP Frameworks
  • 4. The Problem with Conventional Programming
    Part 1
  • 5. In the beginning there was nothing.
    public class RentalService
    {
    }
  • 6. Customer said: let there be business value.
    publicclassRentalService
    {
    publicvoid RentMovie(Guid movieId, Guid customerId)
    {
    Moviemovie = Movie.GetById(movieId);
    Customercustomer = Customer.GetById(customerId);
     
    var history = newRentalHistory();
    history.MovieId = movieId;
    history.CustomerId = customerId;
    history.RentedOn = DateTime.Now;
    customer.History.Add(history);
     
    customer.Balance -= movie.RentalPrice;
    }
    }
    And there was business code.
  • 7. publicclassRentalService
    {
    privatestaticreadonlyTraceSource Trace =
    newTraceSource(typeof (RentalService).FullName);
     
    publicvoid 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 = newRentalHistory();
    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;
    }
    }
    }
     
    Testers said: Letthere be logging
    And there was logging code.
  • 8. publicclassRentalService
    {
    privatestaticreadonlyTraceSource Trace =
    newTraceSource(typeof (RentalService).FullName);
     
    publicvoid RentMovie(Guid movieId, Guid customerId)
    {
    if (movieId == Guid.Empty) thrownewArgumentException("movieId");
    if (customerId == Guid.Empty) thrownewArgumentException("customerId");
     
    Trace.TraceInformation(
    "Entering RentalService.RentMovie(movieId = {0},_customerId = {1})",
    movieId, customerId);
     
    try
    {
     
    Moviemovie = Movie.GetById(movieId);
    Customercustomer = Customer.GetById(customerId);
     
    var history = newRentalHistory();
    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;
    }
    }
    }
     
    Devssaid: Letthere be defensive programming
    Thenthere was precondition checking code.
  • 9. publicclassRentalService
    {
    privatestaticreadonlyTraceSource Trace =
    newTraceSource(typeof (RentalService).FullName);
     
    publicvoid RentMovie(Guid movieId, Guid customerId)
    {
    if (movieId == Guid.Empty) thrownewArgumentException("movieId");
    if (customerId == Guid.Empty) thrownew
    ArgumentException("customerId");
     
    Trace.TraceInformation(
    "Entering RentalService.RentMovie(movieId = {0},_customerId =
    {1})“, movieId, customerId); 
    try
    {
    using (var scope = newTransactionScope())
    {
    Moviemovie = Movie.GetById(movieId);
    Customercustomer = Customer.GetById(customerId);
     
    var history = newRentalHistory();
    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;
    }
    }
    }
     
    Let there be transactions.
    And there was transaction handling code.
  • 10. publicclassRentalService
    {
    privatestaticreadonlyTraceSource Trace =
    newTraceSource(typeof (RentalService).FullName);
     
    publicvoid RentMovie(Guid movieId, Guid customerId)
    {
    if (movieId == Guid.Empty) thrownewArgumentException("movieId");
    if (customerId == Guid.Empty) thrownew
    ArgumentException("customerId");
     
    try
    {
    Trace.TraceInformation(
    "Entering RentalService.RentMovie(movieId = {0},_customerId =
    {1})“, movieId, customerId); 
    try
    {
    using (var scope = newTransactionScope())
    {
    Moviemovie = Movie.GetById(movieId);
    Customercustomer = Customer.GetById(customerId);
     
    var history = newRentalHistory();
    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;
    }
    }
    }
     
     
    Let there be user-friendly error messages.
    And there was exception handling code.
  • 11. 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?
  • 12. Security
    Exception Handling
    Tracing
    Monitoring
    Transaction
    Data Binding
    Thread Sync
    Caching
    Validation
    Non-Functional Requirements
    Cross-Cutting Concerns
  • 13. Encapsulating Infrastructure Concerns?
  • 14. Aspects!
  • 15. Strengthen Applications With Aspects
    Show Me!
  • 16. Show Me!
    1. Add a reference to PostSharp.dll
  • 17. Show Me!
    2. Write an aspect {Demo}
  • 18. Show Me!
    3. Apply the aspect {Demo}
  • 19. Show Me!
    How does it work?
    1. Source
    2. Compiler
    3. PostSharp
    4. Run Time
  • 20. The Idea Behind AOP
    Part 2
  • 21. Problem Domain
    Cross-Cutting Concerns
    Solution Domain
    Separation of Concerns
  • 22. 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
    Applyaspects to elements of code
  • 23. 15 Years of AOP History
    Hype Years
    Productivity Years
    Research Years
  • 24. Why You Should Care
    The benefits of aspect-oriented programming
  • 25. The benefits of aspect-oriented programming
    Decrease Development Costs
    WriteFewer lines of code
    ReadFewer lines of code
    Concise, clear, understandable code
    Size-Cost relationship is superlinear
  • 26. The benefits of aspect-oriented programming
    Improve Quality
    Fewer lines of code -> Fewer Defects
    More automation -> Fewer Defects
    Less boiler-plate code -> More interesting work -> Increased attention -> Fewer Defects
  • 27. The benefits of aspect-oriented programming
    Decrease 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
  • 28. The benefits of aspect-oriented programming
    Decrease Maintenance Costs
  • 29. Features
  • 30. Features
    Code Transformation Primitives
    Modifications
    Introductions
    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
  • 31. Features
    Composite 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
  • 32. Features
    Aspect Multicasting
    Using a single line of code, apply an aspects to multiple elements of code based on:
    Attributes (public/private, virtual/sealed, …)
    Naming conventions
  • 33. Features
    Attribute Inheritance
    Interfaces
    Classes
    Virtual Methods
    Assemblies (!)
    - or -
  • 34. Robust Aspect Composition
    Multiple aspects on the same element of code
    Aspect dependency framework
    Ordering
    Requirement
    Conflict
    Strong ordering and commutativity
     Deterministic Behavior
    D
    C
    B
    A
  • 35. Comparing Aspect Frameworks
    Part 4
  • 36. Comparing Aspect Frameworks
    Static vs Dynamic AOP
    Spring.NET
    Castle
    MS Unity/PIAB
    PostSharp
    LinFu
    Build-Time:
    Very Expressive
    Robust Model
    Not InvasiveStatic
    Run-Time:Less ExpressiveBrittle Model
    InvasiveDynamic
    Hybrid
  • 37. Comparing Aspect Frameworks
    Expressiveness (1/2)
    What can you do with the framework?
  • 38. Comparing Aspect Frameworks
    Expressiveness (2/2)
    How do you apply aspects to code?
  • 39. Comparing Aspect Frameworks
    Non-Invasiveness
    Can you use aspects without deep refactoring?
    Require the use of factory methods
  • 40. Comparing Aspect Frameworks
    Robustness
    Can you prevent aspects from being improperly used?
  • 41. Comparing Aspect Frameworks
    Misc.
    Other points that matter
  • 42. http://www.sharpcrafters.com/geersch@gmail.com