CSC/ECE 517 Fall 2012/ch1 1w27 ms: Difference between revisions
Line 66: | Line 66: | ||
===The Problem=== | ===The Problem=== | ||
* | |||
**But the code that uses it isn’t! | * Persistence itself is already modular | ||
**Persistence invocation code is scattered | ** But the code that uses it isn’t! | ||
**BankAccount code is tangled with code from other concerns. | ** Persistence invocation code is scattered | ||
** BankAccount code is tangled with code from other concerns | |||
** BankAccount’s modularity is compromised | |||
* Also, similar persistence code is added to other components | |||
** Redundancy: | |||
*** Hard to change all occurrences consistently. | |||
*** Hard to replace the Persistence solution. | |||
*** Breaks Don’t Repeat Yourself! (DRY) | |||
** Reuse is hard. | |||
*** The persistence solution may be different in another context. | |||
==AOP Concepts== | ==AOP Concepts== |
Revision as of 00:36, 13 September 2012
Aspect Oriented Programming (AOP)
Aspect Oriented Programming (AOP) refers to a new way of designing software. It aims to increase modularity by allowing the separation of cross-cutting concerns. AOP includes programming methods and tools that support the modularization of concerns at the level of the source code. It is not a replacement to popular Object Oriented Programming (OOP), but is complimentary to it.
Overview
Aspect-oriented programming entails breaking down program logic into distinct parts, called concerns. Nearly all programming paradigms support some level of grouping and encapsulation of concerns into separate, independent entities by providing abstractions (e.g., procedures, modules, classes, methods) that can be used for implementing, abstracting and composing these concerns. But some concerns defy these forms of implementation and are called crosscutting concerns because they "cut across" multiple abstractions in a program. An example to this is logging. In an normal object oriented language program we might need to invoke a logger function from everywhere we this functionality.
Why do we need AOP? The banking example
Consider a simple banking application written in Ruby.
require 'insufficient_funds' class BankAccount
attr_accessor :balance
def initialize @balance = 0.0 end
def deposit(amount) @balance += amount end
def withdraw(amount) if @balance < amount raise InsufficientFunds end @balance -= amount end
end
This is simple enough. But is not very useful. What if we need persistence too?
require 'insufficient_funds_error'
class BankAccount attr_reader :balance # 1
def balance=(amount) @balance = amount persist_balance # 2 end
def initialize @balance = retrieve_balance # 3 end
def deposit(amount) @balance += amount persist_balance # 2 end
def withdraw(amount) if @balance < amount raise InsufficientFundsError end @balance -= amount persist_balance # 2 end
def retrieve_balance # 3 # Get from database end
def persist_balance # 2 # Save to database end
end
We can see that now other interests have become tangled with the basic functionality (sometimes called the business logic concern). Now add:
- Transactional behavior
- Authentication and authorization
- “Observers”, like a UI
Also this code will be repeated across other domain objects which need the same behavior. Finally, attempt to reuse this code in a new application with a different persistence store, transaction engine, security model etc.
The Problem
- Persistence itself is already modular
- But the code that uses it isn’t!
- Persistence invocation code is scattered
- BankAccount code is tangled with code from other concerns
- BankAccount’s modularity is compromised
- Also, similar persistence code is added to other components
- Redundancy:
- Hard to change all occurrences consistently.
- Hard to replace the Persistence solution.
- Breaks Don’t Repeat Yourself! (DRY)
- Reuse is hard.
- The persistence solution may be different in another context.
- Redundancy: