Upload
sammyt
View
1.929
Download
0
Tags:
Embed Size (px)
DESCRIPTION
dependency injection, notifications, type safe commands and actionscript gripes
Citation preview
Dawnstanding on the shoulders of giants
What is Dawn
• Dependency Injection library inspired by Google Guice
• Notification system based on types
• Simple type safe command pattern
Why?
• Unhappy with my options
• Small issues that have large consequences
• Flash and Flex
• Small (~12K)
• A new breed of project
What its not
• MVC, MVP ... you structure your app
• Plugin architecture
• Aiming to take over the world
Some Design Principles
• Testing is vital
• Play to language strengths
• Type safety is winfull
• Configuration is no fun (keep it DRY)
• Static state is bad
• Types are better than strings
Dependency Injectiona lot of fuss about nothing
TheDoctor
Tardis
TheDoctor
TardisAssistant
TheDoctor
Tardis MissionAssistant
TheDoctor
IAssistant IMissionTardis
TheDoctor
IAssistant IMissionTardis
TheDoctor
RoseTyler
DonnaNoble
IAssistant IMissionTardis
TheDoctor
RoseTyler
DonnaNoble Daleks
Cybermen
IAssistant IMissionTardis
TheDoctor
RoseTyler
DonnaNoble Daleks
Cybermen
Object graph ofTheDoctor
Creating The Doctor• Construct dependencies within the class
• Service locator
• Factories
• DI By hand
Doing it by handclass TheDoctor{ public var mission:IMission; public var assistant:IAssistant; public var tardis:Tardis;}
Doing it by handvar doctor:TheDoctor = new TheDoctor();
Doing it by handvar tardis:Tardis = new Tardis();var doctor:TheDoctor = new TheDoctor();doctor.tardis = tardis;
Doing it by handvar assistant:IAssistant = new RoseTyler();var tardis:Tardis = new Tardis();var doctor:TheDoctor = new TheDoctor();doctor.tardis = tardis;doctor.assistant = assistant;
Doing it by handvar mission:IMission = new Daleks();var assistant:IAssistant = new RoseTyler();var tardis:Tardis = new Tardis();var doctor:TheDoctor = new TheDoctor();doctor.tardis = tardis;doctor.assistant = assistant;doctor.mission = mission;
Doing it by hand• Thats a lot of code to create a Doctor
• More code to maintain
• Fragile to change
• Client of TheDoctor must know inner workings (encapsulation fail)
• Construction followed simple patterns
Dependency Injection is all about creating
object graphs!
Dawn DI• How can object creation be automated and easy?
• Meets design principles
• Thank you Google Guice!
Configure the Doctor
Configure the Doctor1. Indicate the dependencies
Configure the Doctor1. Indicate the dependencies
2. Chose an assistant
Configure the Doctor1. Indicate the dependencies
2. Chose an assistant
3. Chose a mission
Configure the Doctorclass TheDoctor{ public var mission:IMission; public var assistant:IAssistant; public var tardis:Tardis;}
Configure the Doctorclass TheDoctor{ [Inject] public var mission:IMission; [Inject] public var assistant:IAssistant; [Inject] public var tardis:Tardis;}
Configure the Doctorclass Config implements IConfig{ public function create(mapper:IMapper):void{
mapper.map(IAssistant).toClass(RoseTyler);
mapper.map(IMission).toClass(Daleks);
}}
Create the Docvar mission:IMission = new Daleks();var assistant:IAssistant = new RoseTyler();var tardis:Tardis = new Tardis();var doctor:TheDoctor = new TheDoctor();doctor.tardis = tardis;doctor.assistant = assistant;doctor.mission = mission;
Create the Doc
Create the Doc
builder.getObject(TheDoctor)
Create the Doc
var doctor:TheDoctor;var builder:IBuilder = new Builder(new Config());
doctor = builder.getObject(TheDoctor) as TheDoctor;
Dawn DI• You write less code (no XML)
• Configuration is ActionScript (and small)
• Classes are compiled into final swf
• Agile code, refactor structure fast and easily
• Testing is easy, second nature
• DI helps you write better code!
• Dawn makes DI easy!
Dawn DI• Scopes - Singleton or Transient
• Map toFactory/toInstance for construction control
• Modular configuration
• Name injections
• Inject properties like strings or arrays
• Optional injections
• Inject via mutators or properties
FP-183
[Inject] Dawn DI• Simple
• Light
• Type safe
• Test friendly
• Terse
Notificationsdecoupling without the compromise
Dawn Notifications
• Type based
• Closure friendly
• Static free
The Problem
The Problem
View
View
View
View
The Problem
View
View
View
View
Data
The Problem
View
View
View
View
DataData
The Problem
View
View
View
View
DataDataData
The Problem
View
View
View
View
DataDataDataData
The Problem
View
View
View
View
DataDataDataData
The Problem
View
View
View
View
DataDataDataData
The Problem
View
View
View
View
DataDataDataData
The Problem
View
View
View
View
DataDataDataData
The Problem
View
View
View
View
DataDataDataData
The Problem
View
View
View
View
DataDataDataData
The Problem
View
View
View
View
DataDataDataData
The Problem
View
View
View
View
DataDataDataData
The Problem
View
View
View
View
DataDataDataData
The Problem
View
View
View
View
DataDataDataData
Gets a little confusing?
Decouple and Scale
Decouple and Scale
View
View
View
View
Decouple and Scale
View
View
View
View
DataDataDataData
Decouple and ScaleNotification System
View
View
View
View
DataDataDataData
Decouple and ScaleNotification System
View
View
View
View
DataDataDataData
Decouple and ScaleNotification System
View
View
View
View
DataDataDataData
Type based
Type based
addEventListener(type:String,closure:Function...)
Type based
addEventListener(type:String,closure:Function...)
addCallback(type:Class,closure:Function);
Why Types
Why Types• Make full use of polymorphism
IEventType, BaseRpcEvent, com.wibble.Woo
Why Types• Make full use of polymorphism
IEventType, BaseRpcEvent, com.wibble.Woo
• Avoids meaningless staticsFinishedBaconEvent.FINISHED_BACON
Why Types• Make full use of polymorphism
IEventType, BaseRpcEvent, com.wibble.Woo
• Avoids meaningless staticsFinishedBaconEvent.FINISHED_BACON
• No hidden collisions MyEvent.CLOSE == Event.CLOSE == FAIL
Why Types• Make full use of polymorphism
IEventType, BaseRpcEvent, com.wibble.Woo
• Avoids meaningless staticsFinishedBaconEvent.FINISHED_BACON
• No hidden collisions MyEvent.CLOSE == Event.CLOSE == FAIL
• No switch statementsswitch( notification.getName() )
Closure unfriendly
addEventListener(Event.ADDED, function(event:Event):void{ trace(“haha, Try removing me”) });
Closure friendly!
Closure friendly!
var listener:IListenerRegistration = bus.addCallback(ILogAction, function(note:ILogAction):void{ } );
Closure friendly!
var listener:IListenerRegistration = bus.addCallback(ILogAction, function(note:ILogAction):void{ } );
listener.remove();
Triggering
class TadPole{[Inject] public var bus:INotificationBus;
[DependenciesInjected]public function init():void{
bus.trigger(new TadPoleCreated());
}}
Dawn Notifications• Simple API
• Use the language, closures are good!
• Types are smarter then strings (Duh!)
• Reduce the complexity of application structure
Commandssimple tools are easy to build with
Commands
• easy to maintain stateless goodies
• central point for lots of easy wins
• queueing
• cacheing
• handle errors
• etc etc.
Commands
• ICommand interfaces force casting
• execute(param:Object):void
• How to access other application objects
• Model.getInstance();
• Mapping Strings to Commands is fiddly (more developer discipline)
• registerCommand(Notify.GET_THING, GetThingCommand);
Dawn Commands
• Injectable
• Type safe
• Type based DRY configuration
Dawn Commandsclass MakeHayCommand{
[Inject] public var barn:Barn;
[Execute] public function execute(note:MakeHay):void{
barn.makeHay(note.howMuchHay);
}
}
Dawn Commandsclass MakeHayCommand{
[Inject] public var barn:Barn;
[Execute] public function execute(note:MakeHay):void{
barn.makeHay(note.howMuchHay);
}
}
Dawn Commandsclass MakeHayCommand{
[Inject] public var barn:Barn;
[Execute] public function execute(note:MakeHay):void{
barn.makeHay(note.howMuchHay);
}
}
Dawn Commandsclass MakeHayCommand{
[Inject] public var barn:Barn;
[Execute] public function execute(note:MakeHay):void{
barn.makeHay(note.howMuchHay);
}
}
Dawn Commands
addCommand(MakeHayCommand);
Dawn
• Dependency Injection
• Notifications
• Commands
http://github.com/sammyt/dawn
Questions etc?