Title: Phx.Morph Can Aspect-Oriented Programming solve Microsoft
1Phx.MorphCan Aspect-OrientedProgramming solve
Microsofts growing software problem?
- Marc Eaddy
- Columbia University
2Background
- The Phoenix Project
- Microsofts production-grade compiler,
analysis,and tools infrastructure - Will become backend for all Microsoft compilers
- Massive software project
- Currently 1.8M LOC (318K hand-written)
3Problem
- Many Phoenix requirements cannot be cleanly
separated using traditional OO techniques
(inheritance and aggregation) - Unanticipated requirements
- Requirements to satisfy multiple clients and
scenarios - Operational (orthogonal) requirements
- Traditional OO solutions resulted in increased
software complexity - Designs are complex and highly coupled
- Code is cluttered and difficult to write and
maintain - Many other groups at Microsoft are also
struggling with this problem
4Our goal
Phx.Morph
- Determine if Aspect-Oriented Programming (AOP)
can improve Phoenix development
Our approach
- Use Phoenix to develop an AOP solution
- Then turn around and use the AOP solution to help
develop Phoenix
5Aspect-Oriented Programming
- Promise of greater separation of concerns
- AOP Open Classes Advice
- Open Classes (type changes)
- Advice (code changes)
- AspectJ is the canonical AOP specification and
implementation
6AOP buzzwords
- joinpoint an execution event
- function call, function execution, field access,
exception, etc. - advice code that the programmer wants to be
called before, after, or instead of (around),
some joinpoint - pointcut a pattern for matching joinpoints
- e.g., System.Output.
- weaving transforming a program to call advice
code
7Weaving using Phx.Morph
Post-Link Step
Normal assemblies containing custom AOP attributes
Aspect Assemblies
Source Files
Original Program
WeavedProgram
Phx.Morph
Compiler
Original developer can be oblivious
8Open Classes (OC)
- Ability to split a class definition into separate
modules
- Similar to Partial Classes in C except
- post-link time can extend a class at any time
- works on assemblies no source reqd
- language agnostic
- We support adding fields, properties, methods,
base interfaces, and base classes
9Original class
10Demo Adding foreach sugar
- using System.Collections
- using Phx.Morph.Attributes
- Extends("Node")
- class NodeEnumeratorAspect Node, IEnumerable
-
- Add
- public IEnumerator GetEnumerator()
-
- return new NodeEnumerator(this)
-
-
Class to extend
Add this iface
Add this method
11NodeEnumerator
- public class NodeEnumerator IEnumerator
-
- Node node
- int index -1
- public NodeEnumerator(Node node)
- this.node node
-
- public object Current
- get return node.GetChild(index)
-
- public bool MoveNext()
- return index lt node.ChildCount
-
- public void Reset() index -1
12foreach client
static void DumpNode(Node root, string indent)
if (root null) return
System.Console.WriteLine(indent root)
foreach (Node child in root)
DumpNode(child, indent " ")
New capability!
13Adding the Visitor patternTraditional OO
OO design is tightly coupled and hard to maintain
14Adding the Visitor patternOpen Classes
Open Classes design breaks the circular
dependency and centralizes the code
Depends On
15Phoenix client extensibilityTraditional OO
- Client wants to attach custom data to an object
- Example IR-Longevity plug-in tracks compiler
phase when an instruction is created
Clients extension object
16Phoenix client extensibilityOpen Classes
- Weave Phx.dll
- To add BirthPhase field directly to Instr
Clients extension object
- Empowers clients
- High performance
- Type safe
- Dont have to wait for RDK drop
- Dont require help from Phoenix team
17Advice
- Ability to inject code at specific points in a
program - profiling
- logging/tracing
- log field get/set
- dirty bit (persistence, synchronization)
- change notification (undo/redo/rollback)
- enforce invariants (non-null, const, data flow,
Design by Contract) - error checking/handling
- fault injection
- caching/memoization
- proxies/delegation
- etc. etc.
18Demo Logging reflection usage
- Want to log a message whenever we use the
Reflection API - Self-weave Phx.Morph.dll
19Logging advice
- using Phx.Morph.Aop
- using Phx.Morph.Attributes
- public class LogReflectionAspect
-
- Advice(AdviceType.before, "call(System.Reflec
tion..)") - static public void LogReflection(Signature
string signature, - SourceLocation.WithinSignature string
withinSignature, - SourceLocation.FilePath string
filePath, - SourceLocation.Line uint line)
-
- System.Console.WriteLine()
- System.Console.WriteLine("Called 0()",
signature) - System.Console.WriteLine(" inside
0()", withinSignature) - System.Console.WriteLine(" File 0,
Line 1", - System.IO.Path.GetFileName(filePath),
line) -
20Weaved result
- IL_0065 ldarg.0
- IL_0066 call class System.Reflection.Assembly
System.Reflection.AssemblyLoad(string)
21Weaved result
- IL_0065 ldarg.0
- IL_0066 ldstr "System.Reflection.Assembly.Load"
- IL_006b ldstr "Phx.Morph.ReflectionHelpers.Load
Assembly" - IL_0070 ldstr "c\\phx\\rdk\\samples\\Morpher\\
Phx.Morph\\ReflectionHelpers.cs" - IL_0075 ldc.i4 0xfb
- IL_007a call void LogReflectionExtLogReflecti
on( string, -
string, -
string, -
uint32) - IL_007f call class System.Reflection.Assembly
System.Reflection.AssemblyLoad(string)
22Logging output
- Called System.Reflection.Assembly.Load()
- inside Phx.Morph.ReflectionHelpers.LoadAssembly
() - File ReflectionHelpers.cs, Line 251
- Called System.Reflection.Emit.AssemblyBuilder.Defi
neDynamicModule() - inside Phx.Morph.Attributes.AttributeHelper.Cre
ateTypeBuilder() - File AttributeHelper.cs, Line 499
- Called System.Reflection.Emit.ModuleBuilder.Define
Type() - inside Phx.Morph.Attributes.AttributeHelper.Cre
ateTypeBuilder() - File AttributeHelper.cs, Line 504
- etc
23Demo Enforcing invariants
- Supporting const-ness at runtime
- Person teacher new Person()
- teacher.Salary 25000
- teacher.IsConst true
- teacher.Salary 1000000
- Caveat Must weave all clients
New!
Invariant violated!
24Invariant aspect
- Extends("Person")
- class InvariantAspect
-
- Add
- public bool IsConst
- Advice(AdviceType.before, "set(Person.)")
- void CheckIsConst(
- SourceLocation.WithinSignature string
withinSignature, - This object This)
-
- if (IsConst)
-
- System.Console.WriteLine(
- "Person '0' violated IsConst constraint
inside 1", - This, withinSignature)
-
-
25Phx.Morph implementation
- Built using Phoenix
- MorphPlugin plugs into PEREW and uses Phx.Morph
to perform weaving
Phx.Morph
Editors Open Classes, weaving
AOP Joinpoints, pointcuts,
PEREW Assembly Re-Writer
Attributes Custom AOP attributes
MorphPlugin
Phoenix Core API
26Current limitations
- Managed-code only
- Cannot access private members
- Limited aspect instantiation model
- Instance advice methods are imported
- Static advice methods are referenced
- Not yet implemented
- Cant import a method with multiple return
statements - Around advice
- Many pointcuts not implemented (including cflow)
- Aspect composition and precedence
- Access to some joinpoint context (Args, Target,
thisJoinPoint)
27Related work
Real (shipped) products
IBM WebSphere HyperProbes
AspectJ
BEA JRockit JVM
JAsCo
PROSE
IBM Eclipse
JBoss (J2EE)
JMangler
DynAOP
Products
EAOP
Steamloom
Spring (J2EE)
CeaserJ
Jakarta Hivemind
JAML
Java
.NET
Phx.Morph
AspectC
Rapier.NET
Aspect
C
No real products
Loom.NET
AspectC
AspectDNG
FeatureC
Weave.NET
Meta.NET
Wool
Other
XWeaver
Eos
Aspect.NET
Aspects
PostSharp
AspectS
SetPoint
CLAW
AOPHP
ComposeStar
Apostle
Hyper/J
SourceWeave.NET
PHPaspect
Pythius
DemeterJ
AopDotNetAddin
PEAK
AOP.NET
Encase
Composition Filters
AspectScheme
AspectL
AOP-Engine
AspectCocoa
Concern Manipulation Environment
AspectR
Italics Microsoft-sponsored (although none are
shipped)
28Why our work is interesting
- Built using Phoenix Microsofts
production-grade compiler, analysis and tools
infrastructure - Capable of weaving very large programs (e.g.,
Phoenix itself, which is 1.8M LOC) - Evolves in parallel with Phoenix and the Common
Language Runtime (performance improvements, bug
fixes, API evolution, etc.) - Used by Phoenix to solve real business
requirements - Phoenix is real software
- Hampered by traditional OO techniques
- Weve started using AOP to develop Phoenix
29Conclusions
- Our goal was to determine if AOP would improve
Phoenix development - Re-implemented a Phoenix plug-in to use Open
Classes instead of the OO extension API - Began prototyping grafting adapter interfaces
onto Phoenix classes to integrate with another
library - We validated the feasibility of using Phx.Morph
on Phoenix itself
30Future work
- Work on Microsofts key blocking issues
- Debugability
- Maintainability
- Performance
- Versioning
- Serviceability
- Explore more AOP scenarios
- compile-time (ala Partial Classes for C)
- Makes it easier for Phoenix to use their own
extensions - Easily separate hand-written code from generated
code (code behind) - load-time
- Needed to fully support compile-time weaving
- runtime (dynamic weaving)
- Useful for on-the-fly debugging and rapid
prototyping - Improve ease-of-use
- IDE integration, projecting aspects into source
code
31Acks
- Many thanks to the Phoenix team!
- Mentor Weiping Hu
- Andy Ayers
- Julian Burger
- Jan Gray
- John Lefor
- Paddy McDonald
- Chuck Mitchell
32Contact
- Marc Eaddy me133_at_columbia.edu
33CLR wish list
- New partial metadata keyword
- Extends the C Partial Classes concept beyond
compile time and makes it language neutral - Compiler support Class definition class source
files partial class source files partial
classes defined in referenced assemblies - Runtime support Combines partial classes at
load-time - Complete CodeDOM API
- Express all C and C/CLI language constructs
- Express complete syntax tree (including comments
and whitespace) - Parsers for C and C/CLI
- Weaving at runtime
- Ability to add fields, methods, etc. after
load-time (ModuleLoadFinished) - Fix ICorProfiler.SetFunctionReJIT (dont want to
use out-of-process debugger API solution) - Support for JIT deoptimization
34More future work
- Next step is a proof-of-concept
- Determine small piece of Phoenix to aspectualize
- Design aspect solution
- Implement remaining required AOP functionality
- Modify Phoenix build process to perform post-link
weaving step - Explore more AOP scenarios
- compile-time (ala Partial Classes for C)
- Makes it easier for Phoenix to use their own
extensions - Easily separate hand-written code from generated
code (code behind) - load-time
- Needed to fully support compile-time weaving
- runtime (dynamic weaving)
- Useful for on-the-fly debugging and rapid
prototyping - Improve ease-of-use
- IDE integration, projecting aspects into source
code