2. About Me
â Consultant (southofshasta.com)
â Software Development, Training, Design
â Using ColdFusion since 1999 (4.x)
â Other stuff: C++, Java, jQuery, PHP, .NET, etc.
â Manager of SacInteractive (formerly Sacramento CFUG)
â Reformed Video Game Developer.
â Stuff I've Done: CycleGear.com, CastImages.com,
Fusion Events Staffing, Grim Fandango, Star Wars
Rogue Squadron, SimPark, SimSafari.
3. Today's Agenda
â What is Dependency Injection?
â When/why do I want it in my projects?
â Intro to Bean Management.
â Intro to Aspect Oriented Programming (AOP).
â Intro to Inversion of Control (IOC).
â Other info.
â Questions.
â Lunch!
4. Prerequisites
â Have some experience building classes and
objects.
â Don't need to be an expert at it.
â Don't need to have used an MVC framework.
â DI frameworks can be totally separate.
â And 1 more thing you need to know...
5. Prerequisites
â Know that Object Oriented Programming is
hard.
â And some of it is confusing at first.
â And that's NORMAL.
7. What is Dependency Injection?
â A âdesign patternâ
â $6 phrase for âa way to organize your classes so
they work together in a flexible wayâ.
â Sort of like a for() loop, if() statement or array[].
â Reusable technique, but based around objects.
â There are lots of design patterns
â Dependency Injection is 1 design pattern
â Inversion of Control (IOC), Aspect Oriented Programming
(AOP) and Bean Management are all âvariations on that
themeâ.
â There are lots of others too.
â Book: âHead First Design Patternsâ
8. What is Dependency Injection?
â It's not platform specific.
â D/I libraries available for ColdFusion, Java,
.NET, JavaScript, etc.
â For today's presentation, I'm using a mix of
pseudocode and condensed examples from
various languages.
â Some of the keywords will change, all the
concepts work the same across the libraries
and languages.
9. Why / When Do I Want
D/I In My Projects?
â Short answer:
When you have lots of classes that talk to each
other, want to keep code organized, and make it
easy to swap different âtypesâ of objects in/out of
your application.
10. Why / When Do I Want
D/I In My Projects?
â Short answer:
When you have lots of classes that talk to each
other, want to keep code organized, and make it
easy to swap different âtypesâ of objects in/out of
your application.
â Longer answer:
That's what the rest of the slides are for...
11. Does this mean...
â I have to rebuild my entire app to use D/I?
â No. But you might get more benefits if you make a
few changes to legacy code along the way.
â I have to learn a new way to code all my classes?
â No. You can leave everything as-is.
â The nice thing about D/I is you can use it or not
use it. If you want to write code the âold wayâ in
part of your app, there's nothing stopping you
from doing so. It will all still work as-is.
â Neat huh? Let's learn a bit more, shall we?
13. What's a Bean?
A âthingâ your D/I framework knows about.
class User{ ⊠}
class DateUtils {âŠ}
In your DI framework:
bean id=âmyUserâ class=âUserâ
bean id=âmyDateUtilsâ class=âDateUtilsâ
(Exact syntax varies between DI libraries.)
14. Bean Management
class A {
public class A() {...}
}
class B{
public class B( A a )
{ ⊠}
}
class C {
public class C( B b )
{ ⊠}
}
class D{
public class D( C c )
{...}
}
So if I -JUST- want a D object made...
15. Bean Management
I have to do all this...
A a = new A();
B b = new B( a );
C c = new C( b );
D d = new D( c );
4 lines of code. The first 3 of which are just âboilerplateâ to
create the variables I need to make a D.
Multiply that out over all the objects in your app...
= a LOT of boilerplate code!
Another way to say it:
âD depends on A, B and C being made firstâ.
16. Bean Management
With a D/I library that does Bean Management, you'd write
something like this instead...
D d = ColdSpring.getBean( âDâ );
4 lines of code just became 1. And no more boilerplate stuff!
You tell your D/I framework âI need a D. Please go find out what
classes D depends on, make those as needed, and hand me
back the final D when you're done.â
(âColdSpringâ is kind of a placeholder here for any D/I
framework. They all work about the same.)
17. Bean Management
â Quasi Real World Example
â Mailing department wide messages.
â Mail Service CFC
â Needs a Department CFC to know which
Department is being emailed
â Department needs a Department DAO for it's SQL
stuff.
â And a SecurityLogin CFC to make sure it's
validated/logged in/whatever.
20. Bean Management
â New Way
ColdSpring.getBean( âmailServiceâ ).sendMail();
Yes, 1 line of code.
Yes, it is THAT easy.
(I'm over simplifying a little, for effect.)
21. Bean Management
â So how does the D/I framework âknowâ that I need an A, B and
C to make a D object?
â Varies a little from framework to framework.
â Configuration based: XML file that âdescribesâ the relationship
between the objects.
â (ColdSpring, Spring)
â Nice for, say, white-box testing w/ hands-on QA team.
â Convention based:
â Works automatically by which folders you store classes in,
and how the classes are named.
â DI/1, WireBox
â Just pick one and try it out, they all do the same core âthingsâ.
23. Inversion of Control (IOC)
â Fancy term for âflippingâ some code around
from the âtraditionalâ or ânormalâ way you'd build
objects.
â Instead of building an Employee object, then a
Department object, then putting the Employee
IN the Department.
â You say âget me a fully populated/constructed
Departmentâ.
â Magic happens, automatically building the
Employee object for you.
24. Inversion Of Control (IOC)
class RockGroup
{
private String groupName;
public String getGroupName(){
return groupName;
}
public void setGroupName( String name ) {
this.groupName = name;
}
}
No Constructor.
And groupName is
private.
So we have to call the
setter to initialize the
variable with something.
25. Inversion Of Control (IOC)
With regular code, we'd do this:
String myBandName = âdepeche modeâ;
RockGroup rg = new RockGroup();
rg.setGroupName( myBandName );
That works but...
Every time I want to provide a different default
value, I have to change code, and recompile.
26. Inversion Of Control (IOC)
What if we could provide that default value in a
âconfig fileâ, outside of code?
And whenever we create a RockGroup object, it
automatically gets a default value for
groupName passed in at that instant?
You can!
27. Inversion Of Control (IOC)
Using a D/I framework, you can have a âconfigâ that notes
default values for your classes:
<class name=âRockGroupâ>
<property name=âgroupNameâ value=âDepeche Modeâ />
</class>
rg = ColdSpring.getBean( âRockGroupâ )
...any time I make a RockGroup, it will automatically initialize
the âgroupNameâ variable to the default value I provided. No
extra lines of code. And changing this default is now done in a
config file. No recompiling code to change it!
28. Inversion Of Control (IOC)
What about classes inside of other classes
â AKA âCompositionâ or the âhas aâ relationship.
â Kind of the same thing...
29. Inversion Of Control (IOC)
class RockGroup{
private String groupName;
public String getGroupName()
{ ⊠}
public void
setGroupName( String name )
{âŠ}
private Musician singer;
public Musician getSinger()
{ ⊠}
public void setSinger( Musician
m ) {âŠ}
}
class Musician{
private String name;
private int yearsSober;
private int age;
public String getName()
{ return name; }
public void setName( String n )
{ this.name = n; }
public int getYearsSober() { ⊠}
public void setYearsSober(int y)
{ ⊠}
public void setAge( int a ){...}
public int getAge(){ return age; }
}
30. Inversion of Control (IOC)
With straight code...
Musician m = new Musician();
m.name = âDavid Lee Rothâ;
m.age = 50;
m.yearsSober = 10;
RockGroup rg = new RockGroup();
rg.setGroupName( âVan Halenâ );
rg.setSinger( m );
31. Inversion Of Control (IOC)
The Musician class has a String property, that
gets initialized just like the String property in
RockGroup. Ditto for the âintâ properties, etc:
Spring.getBean( âMusicianâ );
â ânameâ will always be whatever is in my config for the
Musician class.
<class name=âMusicianâ>
<property name=ânameâ value=âDavid Lee Rothâ />
<property name=âageâ value=â50â />
<property name=âyearsSoberâ value=â10â />
</class>
32. Inversion Of Control (IOC)
You can also refer to other classes in the config, and âinjectâ them
into each other, just like we âinjectedâ the String and int into
Musician:
<class name=âSingerâ id=âsingerBeanâ>
<property name=ânameâ value=âDavid Lee Rothâ />
<property name=âyearsSoberâ value=â10â />
<property name=âageâ value=â50â />
</class>
<class name=âRockGroupâ>
<property name=âgroupNameâ value=âVan Halenâ />
<property name=âsingerâ ref=âsingerBeanâ />
</class>
33. Inversion Of Control (IOC)
So now when I do this...
rg = DIFramework.getBean( âRockGroupâ );
â rg will be fully constructed...
â It will have a âgroupNameâ property set to âVan
Halenâ
â It will have a âsingerâ property set to âDavid Lee
Rothâ, he'll be 50 years old and 10 years sober.
â I did that all with 1 line of code, no boilerplate stuff.
â If I want to change those defaults, I don't have to
recompile, I just change a âconfigâ setting.
34. Inversion Of Control (IOC)
Swapping out one type of Musician for another doesn't require
recompiling code, just change a config
<class name=âSingerâ id=âsingerBean2â>
<property name=ânameâ value=âSammy Hagarâ />
<property name=âyearsSoberâ value=â15â />
<property name=âageâ value=â51â />
</class>
<class name=âRockGroupâ>
<property name=âgroupNameâ value=âVan Halenâ />
<property name=âsingerâ ref=âsingerBean2â />
</class>
35. Inversion Of Control (IOC)
Swapping out one type of Musician for another doesn't require
recompiling code, just change a config
<class name=âSingerâ id=âsingerBean2â>
<property name=ânameâ value=âSammy Hagarâ />
<property name=âyearsSoberâ value=â15â />
<property name=âageâ value=â51â />
</class>
<class name=âRockGroupâ>
<property name=âgroupNameâ value=âVan Halenâ />
<property name=âsingerâ ref=âsingerBean2â />
</class>
Off topic: discussing if Dave is better/worse than Sammy.
37. Aspect Oriented Programming (AOP)
â AKA âCross Cuttingâ
â Change the âaspectâ of how a function is called.
â Say I have a foo() method.
â Any time foo() is called...
â Automatically...
â Call code before or after foo()
â Wrap some sort of code âaroundâ foo()
â e.g. try/catch blocks
â It no longer just does âfoo()â
â Also does whatever you define as an aspect of
calling foo().
38. Aspect Oriented Programming (AOP)
â Example: drawSalesReport()
â In your AOP library:
<func name=âdrawSalesReportâ>
<aspect before run=âcheckIfLoggedInâ />
<aspect after run=âsaveToDebugLogFileâ />
</func>
39. Aspect Oriented Programming (AOP)
â In your code, it USED to look like this:
checkIfLoggedIn();
drawSalesReport( UserID=555, dtCreated=#now()# );
SaveToDebugLogFile();
â What happens NOW is...
DIFramework.runWithAdvice( âdrawSalesReportâ,
{ UserID=555, dtCreated=#now()# } );
and that does all 3 things, in correct order.
40. Aspect Oriented Programming (AOP)
â But wait, there's more!
â Can also wrap âblocksâ of code around each
other, not just function calls before/after each
other.
â e.g. try/catch blocks.
41. Aspect Oriented Programming (AOP)
Say I have a query like so:
<cfquery name=âqryGetUsersâ>
SELECT * FROM Users
</cfquery>
In Production, I want that wrapped in a
try/catch, but in QA/Development, I don't. (So I
can see the debug output, etc.)
42. Aspect Oriented Programming (AOP)
I'd have to set some kind of âflagâ:
<cfif isProduction>
<cftry>
<cfquery name=âqryGetUsersâ>
SELECT * FROM Users
</cfquery>
<cfcatch> <cflog ⊠/> </cfcatch>
</cftry>
<cfelse>
<cfquery name=âqryGetUsersâ>
SELECT * FROM Users
</cfquery>
</cfif>
Duplicate Code!
Remember the DRY rule!
43. Aspect Oriented Programming (AOP)
â Instead of calling a getUsers() method directly:
â GetUsers();
â In your AOP library:
<advice around functionName=âgetUsersWithAdviceâ>
<method name=âgetUsersâ />
</advice>
44. Aspect Oriented Programming (AOP)
<advice around functionName=âgetUsersWithAdviceâ>
â <method name=âgetUsersâ />
</advice>
function getUsersWithAdvice( funcToRun ) {
if( isProduction ) {
try{ #funcToRun#(); }
catch{ ⊠}
}
else{ #funcToRun#(); }
â In your code: DIFramework.runWithAdvice( âgetUsersâ );
â The if() statement is still there but our duplicate SQL is gone!
45. So what's the catch?
â This is maybe a new way of thinking about how
you build your classes.
â Takes some getting used to.
â Debugging errors can be slower at first.
...but it does make your code more flexible.
46. Remember...
â You don't have to do this all at once.
â Start with (for example) Bean Management.
â Add other bits as you get comfortable.
â It's not like an MVC framework where the
WHOLE app has to be considered.
â Find 1 tiny spot in your app, add a little DI there.
â Add more in increments, go as you learn.
47. Also Remember...
â OO Programming is hard.
â It's different than Procedural code.
â Takes getting used to.
â That's NORMAL.
â Nobody learns all this stuff instantly.
â It takes some time.
â (But it is the way most languages are going these
days.)
48. Other Resources
â Book: Spring In Action (Java)
â Book: Head First Design Patterns
â Framework/1, DI/1 and AOP/1
â ColdSpring documentation
â Good examples, not overwhelming.
â SpringByExample.org
â Java code, but explanation of the general concepts
is pretty good.
â I'm guessing the ColdBox docs are also great
for this too. Those guys like to write!