שקופית 1 - Forum 2

Download Report

Transcript שקופית 1 - Forum 2

Applying Aspect-Oriented
Software Development to
Middleware Frameworks
Tal Cohen
Joint work with Yossi
Gil
Research Overview
More Results
– Applicable to almost any software development
domain.
development
domain.
Solution
• The research outcome: a set of
programming language constructs.
Problem
– Huge software programs for banks, government
agencies, etc.
government
agencies, etc.
Overview
• The problem: simplifying the design,
development and modularity of enterprise
applications.
Contributions
• Shakeins – aspect-like mechanism
combining AOP with OOP.
Problem
Solution
More Results
• Factories – a language-level mechanism
for managing object instantiation.
• JTL –a language for Query-by-Example
searches in a program source.
• Object Evolution – objects can change
type at runtime in type-safe systems.
Overview
– AspectJ2EE – a proof-of-concept design for
shakeins in Enterprise Java.
Outline
• The Problem: Enterprise Application
Development.
• Additional Contributions
More Results
– From better static pointcuts to dynamic shakeins
Solution
– How to integrate AOP with middleware frameworks
Problem
• The Solution: Shakeins
Overview
– "The unbelievable complexity of simple chores"
– Overview of existing solutions: middleware
frameworks, aspects…
– … and why they aren't good enough
Shakeins
Overview
class
Secure<Car
class Car
>
Now with anti-theft
mechanism!
Problem
Solution
More Results
Interface
Implementation:
Interface:
Engineremains
and
other visible
externally
unchanged
internals
features
Shakeins
Now with
recording blackbox!
class
We also
Logging<Secure<Car>>
do buses!
Overview
Problem
Solution
More Results
Interface is still
unchanged
Shakeins in Brief
• Intelligently modify the original class:
C++
More Results
• Similar to but less chaotic than
aspects.
Solution
Account accnt = new Secure<Account>()
Problem
• Can be used to create objects, but not
to declare variables (not a new type):
Overview
shakein Secure { // Secure<T> re-implements T
before execution of any public method (in T) {
… perform security test …
Mixins, Java generics, and
}
}
templates cannot do this!
The Problem
Why Programming a Banking
Application is Easy
Overview
Problem
class Account {
void transferTo(Account other, int amount) {
if (balance < amount)
throw new OverdraftException();
this.balance -= amount;
other.balance += amount;
}
…
Solution
More Results
Why Programming a Banking
Application is Not Easy
Problem
Solution
More Results
Non-functional concerns yield tangled and scattered code.
Overview
class Account {
void transferTo(Account other, int amount) {
Log.log("Attempting transfer");
LOGGING
User user = Security.getContext().getCurrentUser();
if (!user.canTransferFrom(this))
SECURITY
Log.securityError(); throw new SecurityException();
Transaction tx = Db.getConnection().beginTransaction();
this.refreshFields(); other.refreshFields();
if (balance < amount)
tx.rollback(); throw new OverdraftException();
this.balance -= amount;
other.balance += amount; BUSINESS LOGIC
this.updateDb(); other.updateDb();
PERSISTENCE
tx.commit();
TRANSACTION MANAGEMENT
Log.log("Transfer completed");
}
…
Making Enterprise
Development Easier
• Past
Past: Work hard
• Present
Present: Middleware Frameworks
Solution
• Future:
Future Aspect-Oriented
Middleware Frameworks
Problem
–CORBA, DCOM, Enterprise Java
Overview
–Bonus: You get to use COBOL
More Results
Middleware Frameworks
and Services
More Results
– e.g., by XML files.
Solution
• Services are configurable.
Problem
– You write the business logic,
– The framework handles everything else.
Overview
• Enable large-scale, multi-tier application
development.
• Provide services attachable to business
logic.
• The (unreached) ideal:
Programming a Banking
Set of services is pre-defined and not
Application
in J2EE
extensible.
Overview
Problem
Solution
More Results
class AccountBean {•So (e.g.) logging remains tangled and scattered.
void transferTo(Account other, int amount) {
Log.log("Attempting transfer");
LOGGING
if (getBalance() < amount)
BUSINESS
throw new OverdraftException();
LOGIC
setBalance(getBalance()
–
amount);
Not trivial to use.
other.setBalance(other.getBalance()
+ amount);
•e.g., can't simply access the field balance.
Log.log("Transfer
•Several supportcompleted");
class required (not shown) –
}
home, interface, etc.
<ejb-jar>
…
•Somewhat easier withPersistence,
v5.
transactions, security:
<enterprise-beans>
services, configured using XML files.
<entity>
Services are<ejb-name>Account</ejb-name>
not programmable.
<home>come.acme.AccountHome</home>
•Need a different security model? No can do.
<remote>com.acme.Account</remote>
•Can't control how persistence logs operations.
<ejb-class>com.acme.AccountBean</ejb-class>
<persistence-type>Container</persistence-type>
…
Aspect-Oriented Programming
To The Rescue!
Problem
Solution
More Results
– Decompose the system into distinct
aspects (code modules).
– Develop each aspect independently.
– The aspects are then woven into
a complete system.
– Chief example: AspectJ
Overview
• The new kid in town: a buzzword and a
panacea solution to tangled and
scattered code:
Decomposition and Weaving
Problem
Program
requirements
Executable
Overview
Clearly distinct
concerns
(conceptual process)
Aspect
Weaving
(mechanical process)
Solution
Aspectual
Decomposition
More Results
Programming a Banking
Application
with AOP
Very extensible.
}
Solution
}
More Results
throw
new SecurityException();
Log.log("Began
" + methodName);
}
after successful execution of same {
Log.log(methodName + " ended successfully");
}
Reusable
configurable.
after
failed and
execution
of same {
Log.log(methodName
+ " caused
exception:
+ e);
•e.g.,
the same logging aspect
can be used
for many "classes.
…
Problem
Everything else:
User user
= Security.getContext().getCurrentUser();
aspect
Logging
{
defined as Aspects
ifbefore
(!user.canAccessAccount(this))
execution of public methods in Account {
Overview
•Define new aspects as you deem fitting.
class Account {
void transferTo(Account other, int amount) {
if (balance < amount)
BUSINESS
throw
new
OverdraftException();
Highly programmable.
LOGIC
this.balance
amount;
•Not just
a pre-defined –=
set of
code transformations.
other.balance += amount;
} aspect Security {
…
before execution of any public method in Account {
The Problem with Aspects
More Results
– Can't handle large enterprise applications.
Solution
• Worse, aspects do not scale.
Problem
– A "paradigm mismatch" between AOP and
OOP.
Overview
• Aspects are very similar to inheritance in
that they create variations on existing
code.
• However, there is a schism between
aspects and inheritance.
Aspects as Class Modifiers
• Unclear: How may an aspect modify the type?
– Can it remove members?
– Can it change method signatures?
• Unclear: Does an aspect modify subclasses,
too?
Solution
More Results
– Does a subclass inherit from the modified version of
the class, or from the original one?
– Does an advice applied to "before execution of method
m()" apply to execution of overridden versions of m,
too?
Problem
– Can it require additional constructor parameters?
– Insert code before super()?
Overview
• Unclear: How may an aspect modify the instance
creation mechanisms?
Scalability?
• Versatility
• Configurability
Solution
More Results
– AOP: Precedence problems with multiple
aspects.
– Enterprise apps: Order matters – and should
not be set globally.
Problem
• Plus, different modifications of same base class
required by different parts of the program.
Overview
– AOP: Aspect application is destructive.
– Enterprise apps: Legacy code must not be
broken.
Manageability?
• Granularity
Solution
More Results
– AOP: Class is oblivious to aspects that
modify it
– Enterprise apps: Need to know what aspects
apply to a given class
Problem
• Seeing the Big Picture
Overview
– AOP: An aspect may apply to any class!
– Enterprise apps: Selective application
required.
Aspects Do Not Scale
• The AspectJ philosophy:
Overview
– Throw in all program modules (classes, aspects).
– Let the compiler do the mixing.
Problem
Solution
More Results
The Solution
Shakeins
Problem
Solution
– No paradigm mismatch…
Overview
• The basic principle: Use OOP to
implement AOP.
• Use the existing inheritance
mechanism to implement class
modifications.
• Suddenly, all the problems disappear.
More Results
What is a Shakein?
Solution
• A parameterized, generic-like structure.
Problem
– We get a new implementation of an existing
type.
– The old implementation continues to exist!
Overview
• A Shakein makes a re-implementation of
a class.
• It does not change the type.
More Results
Shakeins as “Reimplements” Operators
A class in OOP is:
Simple subclassing:
1. A type declaration
C p;
2. Template for object creation
(constructor, field layout etc.)
p = new C();
3. An implementation
p.m();
1. Creates a subtype by adding
more functions to the protocol.
2. Extends the structure definition
by adding more fields.
– Cannot declare variables of type C’
More Results
2. May have additional fields.
3. May have a modified behavior.
Solution
1. C’ has the same type as C.
Problem
Given a class C, shakein S, the application
C’=S[p1,…,pn]<C> is a new class such that
Overview
3. Modifies the behavior by
replacement and refinement
Aren't These Just Mixins?
• A mixin takes a class parameter and
generates a subclass.
– Unparameterized (except for the superclass).
More Results
• Can't include instructions to "add security tests to
every public method".
Solution
– Create a new type.
– Must be highly aware of the superclass.
Problem
• However, unlike shakeins, mixins:
Overview
– M<C> extends C.
– Encapsulates the "delta" between layers of
inheritance.
Shakein Example
Note: not "public methods in Account"
Implicit type parameter ("<T>")
Solution
More Results
after failed execution of same {
Log.log(methodName + " caused exception: " + e); …
Problem
after successful execution of same {
Log.log(methodName + " ended successfully");
}
Overview
shakein Logging {
before execution of public methods {
Log.log("Began " + methodName);
}
Using a Shakein
• Account accnt =
new Logging<Account>();
Problem
Solution
– Shakeins do not define new types, only new
implementations!
Overview
• The shakein application is explicit.
• The variable type is the (original) type.
More Results
Applying a Shakein to
a Class Hierarchy
Type C1
C1’
C1
Type C3
C4’
No inheritance relationship between
the re-implementations
Since no new types are defined, this
does not disturb polymorphism!
More Results
C4
C3’
Solution
Type C4
C3
Problem
C2’
C2
Overview
Type C2
Shakeins Do Scale
Solution
More Results
• Explicit and flexible ordering – you can
have Logging<Secure<Account>>, or
Secure<Logging<Account>>, or both.
Problem
– If the changes are desired in existing code,
only instance creation points have to be
changed.
– See our work on factories…
Overview
• Explicit application – no undesired
classes are matched, ever.
• Original class still exists – existing code
is not broken.
Parameterization
Solution
More Results
…
Account a = new Logging["a.log"]<Account>();
Account b = new Logging["b.log"]<Account>();
Problem
shakein Logging[String filename] {
before execution of public methods {
Log.log(filename, "Began " + methodName);
}
after successful execution of same {
Log.log(filename, methodName + " ended");
}
Overview
• What if we want different instances of
Account to log into different log files?
• With aspects – though luck.
• With shakeins – just add a parameter to the
shakein:
Repeated Applications
• We can even apply the same shakein more
than once to the same class.
• Example:
Problem
Log of operations after
security tests.
Overview
– Possibly with different parameters.
Log["pre"]<Secure<Log["post"]<Account>>>()
Solution
More Results
Log of operations before
security tests.
Pointcut Parameters
– Examples: "execution of public methods",
"read access of field f", etc.
Solution
More Results
shakein Secure[pointcut p, String role] {
before p {
SecurityContext().requireRole(role);
}
}
Problem
• Shakeins support pointcut parameters.
Overview
• A "pointcut" is the expression that specifies
where the aspect/shakein code ("advice")
should be injected.
Pointcut Parameters +
Repeated Application
Secure[Pt, "teller"]<
Secure[Pc, "client"]<Account>>
More Results
– (client operations)
Solution
• Pc = execution of transferTo || withdraw
Problem
– (teller-only operations)
Overview
• Pt = execution of createNew ||
changeOwner
Shakein Composition
shakein StdPersistence =
Transactional ○ Persistent;
Overview
Problem
Solution
shakein MySecure =
Secure[Pt, "teller"] ○
Secure[Pc, "client"];
More Results
Other Middleware AOP Solutions
• JBoss AOP: Extension to the JBoss opensource J2EE server.
Solution
More Results
– Works using interceptors.
– Pointcuts evaluated at runtime.
Problem
• Spring AOP: Open-source "lightweight"
middleware framework.
Overview
– Works by bytecode manipulation.
– Supports runtime application/removal of
aspects.
– Susceptible to runtime failure if not configured
properly.
Feature Comparison



Pointcut
parameters



Untouched
Patched
Untouched
Class/type
separation



Join points
supported
Most of
AspectJ's
All of AspectJ's
Method
execution only
Weaving
mechanism
Ahead-of-time
Subclassing
Patching classes
at load-time
Runtime proxy
generation
Repeated
application
Original class
More Results
Explicit, local
ordering
Parameterization
Solution
Spring


Problem
JBoss AOP


Overview
Shakeins


Performance Comparison
Problem
Solution
More Results
– Classic example of
repeated,
parameterized
application.
– Code in all 3 versions
optimized for repeated
application (no code
duplication) rather than
performance.
Overview
• Given a class Point,
apply aspects
(shakeins) to confine
the valid range of
values for x and y.
How Do You Take Your Aspects?
Shaken, not stirred.
Overview
Problem
Solution
More Results
Additional Results
AspectJ2EE
Secure[Pt, "teller"]<Secure[Pc, "client"]<Account>>
Problem
– No expressions like
Overview
• An integration of the shakein concept into
existing J2EE frameworks and applications.
• Each service defined as a shakein.
• Shakein application managed by XML
configuration files.
appear in the code.
Solution
More Results
• J2EE Home objects ensure that all instances
are created with shakeins applied.
• Deploy-time weaving.
JTL: The Java Tools Language
• Joint research with Itay Maman and Evelina Zarivach.
Overview
Problem
Solution
More Results
• The AspectJ pointcut-specification
sublanguage is generally viewed as
insufficient.
• JTL is a Datalog-like language for code
queries that can (among other things)
replace AspectJ's pointcut sublanguage.
• Based on Query-by-Example.
• No need for looping constructs.
• Rich predefined predicate library.
JTL Examples
• Search for float-typed static method:
– Regular exp.: static.*float.*\(.*\)
– AspectJ: static float *.*(..)
Overview
• Inaccurate.
• OK, for this specific use.
• Insane.
More Results
– JTL: static float method
Solution
.//returns/@type="float"
and @modifiers="static" ]
Problem
– XQuery: /class/method[
JTL Examples
• Another query: "any public field in a class that
contains no setter or getter methods".
void 'set[A-Z]?*'(_);
-- Given:=
the standard
getter
public library:
!void 'get[A-Z]?*'();
Solution
More Results
field_in_plain_class := public field,
declared_in[C], C
{
C.members:
{
no getter;
no setter;
};
Problem
Regular exp.: impossible.
AspectJ: impossible.
XQuery: Possible, but…
JTL:
setter := public
Overview
–
–
–
–
Factories
• Remove the need for the Abstract Factory and
Factory Method design patterns.
Solution
More Results
– Including: which actual class to instantiate, or if we
should use an existing instance.
Problem
• Ensure all instances are created with shakeins
applied – without touching client code.
• Constructors only deal with initialization; factories
deal with object creation.
Overview
– Used extensively in middleware frameworks (e.g.,
home objects in J2EE, Bean Factory in Spring, etc.)
Factories
Overview
• With existing patterns: if class S is changed to
become a singleton, all existing code that calls
new S() must be changed to call
S.getInstance().
• With factories, the change is local to S.
– The factory S() will manage a single instance.
Problem
Solution
More Results
• With existing patterns: if B extends A, and A has
controlled instantiation via a getInstance
method, what will B.getInstance() return?
• With factories: such static methods are not
needed.
Object Evolution
• Dynamic reclassification: allowing an object to change
its type at runtime.
• e.g., State design pattern.
Overview
– e.g., prince → frog.
– Supported by Smalltalk, several others.
– Many real-world uses
• Type safety problems…
Prince p = new Prince();
if (…) p → Frog();
p.drawSword(); // potential runtime type error
Problem
• Our solution: limit to monotonic changes only.
Solution
More Results
– "Object evolution" -- moving down the inheritance tree.
– Prince → king is okay!
Object Evolution Flavors
• I-Evolution: Movement down the inheritance
tree.
– Might fail if runtime type differs from static type.
More Results
– Type not changed at all (only the class), so…
– Changes can be undone – still monotonic!
– Result: shakeins as "dynamic aspects".
Solution
• S-Evolution: Move by applying a shakein to the
runtime type of the object.
Problem
– No "type mismatch" possible.
– Failure even less likely with idempotent mixins.
Overview
• M-Evolution: Move by applying a mixin to the
runtime type of the object.