Title: Phx.Morph Why hasnt Microsoft adopted AspectOriented Programming
1Phx.MorphWhy hasnt Microsoft adopted
Aspect-Oriented Programming?
- 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 (non-functional) 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/behavior 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
WovenProgram
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
10Adding the Visitor patternTraditional OO
OO design is tightly coupled and hard to maintain
11Adding the Visitor patternOpen Classes
Open Classes design breaks the circular
dependency and centralizes the code
Depends On
12Phoenix 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
13Phoenix 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
14Advice
- 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
- asynchronous methods
- design patterns (visitor, adaptor, factory, )
- Quality of Service
- etc. etc.
15Demo Logging reflection usage
- Want to log a message whenever we use the
Reflection API - Self-weave Phx.Morph.dll
16Logging 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) -
17Weaved result
- IL_0065 ldarg.0
- IL_0066 call class System.Reflection.Assembly
System.Reflection.AssemblyLoad(string)
18Weaved 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)
19Logging 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
20Phx.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
21Current limitations
- Managed-code only
- Cannot access private members
- Problems weaving inlined code
- Cannot weave signed code
- 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)
22Related work
Real (shipped) products
IBM WebSphere HyperProbes
AspectJ
BEA JRockit JVM
PROSE
Axon
JAsCo
Nanning
IBM Eclipse
JBoss (J2EE)
JMangler
Products
DynAOP
EAOP
Steamloom
SiteVision
Jakarta Hivemind
CeaserJ
JAML
Spring (J2EE)
Jiazzi
Java
JAC
Arachne
.NET
Phx.Morph
AspectC
TinyC2
Rapier.NET
Aspect
C
AspectC
No real products
Loom.NET
AspectDNG
FeatureC
Weave.NET
Meta.NET
Wool
XWeaver
Other
JAsCo.NET
Eos
Aspect.NET
Aspects
AspectS
PostSharp
SetPoint
CLAW
AOPHP
Compose
Apostle
Poly
Hyper/J
SourceWeave.NET
AspectCOOL
PHPaspect
DemeterJ
AopDotNetAddin
Pythius
AOP.NET
PEAK
Encase
Composition Filters
AspectScheme
AspectL
AOP-Engine
AspectCocoa
Concern Manipulation Environment
AspectR
Italics Microsoft-sponsored (although none are
shipped)
23AOP support in .NET
- Static weaving
- CodeDOM
- Parsing not implemented
- AST cant represent C/CLI or all of C
- Limited byte code instrumentation tools
- Debug information gets out of sync
- Dynamic weaving
- Discouraged in general
- Cant specify custom class loader
- Profiler API
- Limited interception capabilities
- Not able to force a method to be re-JITd
- No support for Open Classes
- Edit-and-Continue API
- Debug only
- Inefficient
- Hard to specify patches
24Why is Microsoft waiting?
- Comprehension
- Must be able to predict behavior
- Must be easy to understand
- Integration into existing tools and software
processes - Aspects in-the-large
- Debuggability
- Source-level debugging is critical
- Phx.Morph keeps debug information in sync
- Wicca allows full source-level debugging
- Testing
- AOP introduces new fault models
- Serviceability
- EXE/DLL boundary no longer signifies ownership
- Version currently linked to size/date
- Origin tracking needed to isolate faults
(repudiation) - Evolution
- Performance
25Conclusion
- Our goal was to determine if AOP would improve
Phoenix development - Re-implemented a Phoenix plug-in to use Open
Classes - Began prototyping grafting adapter interfaces
onto Phoenix classes - Validated the feasibility of using Phx.Morph on
Phoenix itself - Learned why Microsoft is timid about using AOP
26Future work
- Address barriers to entry
- Debuggability, Testing, Comprehension,
Serviceability, Performance - Lobby for AOP support in .NET
- Infect Microsoft with AOP
27Acks
- Many thanks to the Phoenix team!
- Mentor Weiping Hu
- Andy Ayers
- Julian Burger
- Jan Gray
- John Lefor
- Paddy McDonald
- Chuck Mitchell
28Contact
- Marc Eaddy eaddy_at_cs.columbia.edu
29Extra slides
30Demo 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
31NodeEnumerator
- 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
-
- public void Reset() index -1
32foreach 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!
33Demo 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!
34Invariant 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)
-
-
35Why 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
36CLR 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
- Metadata embedded in IL
- Ability to explicitly specify joinpoints (expands
joinpoint model) - Ability to pass extra information to the aspect
(specific message to log)
37Future work
- Work on Microsofts key blocking issues
- Debuggability
- 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
38More 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
39Conclusions
- 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