Dawn - Actionscript Library

Preview:

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

Questions etc?

Recommended