Parsley                        &                       framework for Flex/Flash/AIRAlexander BudjakovFlex Developerprideco...
Parsley is all about decoupling
OverviewParsley is Open Source, licensed under the Apache License 2.0Written by Jens HalmFirst version 1.0.RC1 (2007-12-09...
Features           Parsley                           SpicelibFlexible IOC Container              Command FrameworkDependen...
Inversion of Control (IoC)
Inversion of Control (IoC) Hollywood Principle: Dont call us, well call you.                           Program logic runs ...
IoC ExampleHere is the simplest possible                          Here are a common smells that should leadIoC component  ...
IOC Container We may ask for the object from the container and the container creates the object and its dependencies      ...
Dependency Injection (DI)
Dependency Injection (DI)[Inject]       The core feature of any IOC Container                             How objects obta...
Dependency Injection (DI)       You may have these different tools
Dependency Injection (DI)        You may have these different tools       OR just one tool with attachments
Dependency Injection (DI)        You may have these different tools       OR just one tool with attachments             Th...
Dependency Injection (DI)    Three ways of classic DI
Dependency Injection (DI)                        public class Controller {                           private var model:Mod...
Dependency Injection (DI)                        public class Controller {                           private var model:Mod...
Dependency Injection (DI)                        public class Controller {                           private var model:Mod...
NOT Dependency Injection           public class Controller {              private var model:Model;              public fun...
IoC and DI Benefits•   Dependency management•   Simplify the reuse of classes or components•   Offers configuration flexib...
Configuration and Initialization
Configuration and Initialization       • Telling the IOC Container which classes it         should manage   1   • MXML, XM...
<?xml version="1.0" encoding="utf-8"?>UserConfig.mxml   <parsley:Objects xmlns:fx="http://ns.adobe.com/mxml/2009"         ...
Configuration and Initialization       • Telling the IOC Container which classes it         should manage   1   • MXML, XM...
public class GetUsersCommand {GetUsersCommand.as                         [Inject]                         public var servi...
Configuration and Initialization       • Telling the IOC Container which classes it         should manage.   1   • MXML, X...
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"You can use one big          xmlns:s="library://ns.adobe.com/flex/s...
Decoupled Bindings[Publish][Subscribe][PublishSubscribe]• This feature is much more dynamic than Dependency Injection.• It...
Decoupled BindingsActionScript Examples[Bindable][Publish(objectId="selectedUser")]public var selectedUser:User;[Subscribe...
Messaging[ManagedEvents][MessageDispatcher][MessageHandler][MessageBinding][MessageError]• The exchange messages between o...
ActionScript Examples[Event(name="userSelected",type="com.xyz.UserSelectedEvent")]        UserSelectedEvent.as[ManagedEven...
Object Lifecycle[Init][Destroy]                        Lifecycle phases      preConfigure   preInit   postInit    preDestr...
Object Lifecycle[Init][Destroy]                                   Lifecycle phases        preConfigure            preInit ...
Managed Commands•   Dynamically add a command to a Context only for the time it executes•   Declarative way to configure C...
Managed Commands[CommandResult]                   <parsley:MapCommand type="{GetUserProfileCommand}"/>[CommandError]      ...
Managed Commands Declaring Groups in MXML<parsley:MapCommand messageType="{FindUserMessage}">   <parsley:CommandSequence> ...
Building MVC Architectures
Custom Scopes
Custom ScopesDefault scope is global<parsley:ContextBuilder>                                     Add new “window” scope   ...
LocalizationUsual using with flex binding<s:Label text="{resourceManager.getString(resources, ‘user.profile)}"/>It is usef...
Configuration Properties       project.properties       dev_url = http://www.dev.xyz.com       prod_url = http://www.prod....
Conclusion
Questions?Understanding                             Information
Upcoming SlideShare
Loading in …5
×

Parsley & Flex

2,710 views

Published on

Published in: Technology, Education
1 Comment
6 Likes
Statistics
Notes
  • not bad
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total views
2,710
On SlideShare
0
From Embeds
0
Number of Embeds
15
Actions
Shares
0
Downloads
69
Comments
1
Likes
6
Embeds 0
No embeds

No notes for slide

Parsley & Flex

  1. 1. Parsley & framework for Flex/Flash/AIRAlexander BudjakovFlex Developerprideconan@gmail.com
  2. 2. Parsley is all about decoupling
  3. 3. OverviewParsley is Open Source, licensed under the Apache License 2.0Written by Jens HalmFirst version 1.0.RC1 (2007-12-09)Last version 3.0.0 (2012-02-06) > 4 yearsParsley is an Application Framework for Flex and Flash Applications built upon an IOCContainer and Messaging Framework that can be used to create highly decoupledarchitectures.
  4. 4. Features Parsley SpicelibFlexible IOC Container Command FrameworkDependency Injection XML-MapperDecoupled Bindings Reflection APIMessaging Framework LoggingManaged CommandsDynamic View WiringAdvanced ModularityObject LifecycleLocalizationExtensibility
  5. 5. Inversion of Control (IoC)
  6. 6. Inversion of Control (IoC) Hollywood Principle: Dont call us, well call you. Program logic runs against abstractions such as callbacks
  7. 7. IoC ExampleHere is the simplest possible Here are a common smells that should leadIoC component you to refactor to IoCpackage com { package com { public interface IMap { public class GPSNavigator implements INavigator { //methods private var map:IMap; } public function GPSNavigator() {} this.map = new UkraineMapImpl(); }package com { //other methods public class GPSNavigator implements INavigator { } private var map:IMap; } public function GPSNavigator(map:IMap) { } this.map = map; Some other smells. //other methods package com { } public class GPSNavigator implements INavigator {} private static var map:IMap = MapFactory.getMap(); public function GPSNavigator() { } //other methods } } It is hard coded Not reusable.
  8. 8. IOC Container We may ask for the object from the container and the container creates the object and its dependencies <interface> EBookReader File inject creates PDFFileImpl TXTFileImpl IoC ContainerParsley is a classic IOC Container. It provides support for Dependency Injection,Object Lifecycle Management and Messaging
  9. 9. Dependency Injection (DI)
  10. 10. Dependency Injection (DI)[Inject] The core feature of any IOC Container How objects obtain references to each other
  11. 11. Dependency Injection (DI) You may have these different tools
  12. 12. Dependency Injection (DI) You may have these different tools OR just one tool with attachments
  13. 13. Dependency Injection (DI) You may have these different tools OR just one tool with attachments This brings us to the Design Principles - Program to an interface, not an implementation
  14. 14. Dependency Injection (DI) Three ways of classic DI
  15. 15. Dependency Injection (DI) public class Controller { private var model:Model; public function Controller(model:Model) {Constructor Injection this.model = model; } }
  16. 16. Dependency Injection (DI) public class Controller { private var model:Model; public function Controller(model:Model) {Constructor Injection this.model = model; } } public class Controller { private var _model:Model; public function set model(value:Model):void { Setter Injection _model = value; } }
  17. 17. Dependency Injection (DI) public class Controller { private var model:Model; public function Controller(model:Model) {Constructor Injection this.model = model; } } public class Controller { private var _model:Model; public function set model(value:Model):void { Setter Injection _model = value; } } public interface IController { function injectModel(model:Model):void } Interface Injection public class Controller implements IController { private var model:Model; public function injectModel(model:Model):void { this.model = model; } }
  18. 18. NOT Dependency Injection public class Controller { private var model:Model; public function Controller() { model = new Model(); } } public class Controller { private var model:Model; public function Controller() { model = ModelFactory.create(Model); } } public class Controller { private var model:Model; public function Controller() { model = Model.getInstance(); } }
  19. 19. IoC and DI Benefits• Dependency management• Simplify the reuse of classes or components• Offers configuration flexibility• Simplify unit-testing• The "cleaner" code
  20. 20. Configuration and Initialization
  21. 21. Configuration and Initialization • Telling the IOC Container which classes it should manage 1 • MXML, XML, AS
  22. 22. <?xml version="1.0" encoding="utf-8"?>UserConfig.mxml <parsley:Objects xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:parsley="http://www.spicefactory.org/parsley"> // *hidden imports <fx:Declarations> <parsley:Object id="userModel" type="{Model}" lazy="true"/> <parsley:DynamicObject type="{Counter}"> <parsley:Property name="maxCount" value="100" /> </parsley:DynamicObject> <parsley:View type="{UsersView}"/> <service:MockUsersService /> <parsley:MapCommand type="{GetUsersCommand}" messageType="{GetUsersMessage}"/> </fx:Declarations> </parsley:Objects>
  23. 23. Configuration and Initialization • Telling the IOC Container which classes it should manage 1 • MXML, XML, AS. • Configure DI or Messaging for each individual class 2 • MXML, XML, Metadata tags
  24. 24. public class GetUsersCommand {GetUsersCommand.as [Inject] public var service:IUsersService; [Inject(id="userModel")] public var model:Model; public function execute():AsyncToken { return service.getUsers(); } public function result(users:ArrayCollection):void { model.users = users; } } public class UsersView extends SkinnableComponent {UserView.as [Inject] public var model:Model; [Publish(objectId="selectedUser")] [Bindable] public var seletedUser:User; [MessageHandler(selector="user")] public function externalUserSelection(msg:SelectMessage):void { //do something } }
  25. 25. Configuration and Initialization • Telling the IOC Container which classes it should manage. 1 • MXML, XML, AS. • Configure DI or Messaging for each individual class 2 • MXML, XML, Metadata tags • Initialize IOC Container 3
  26. 26. <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"You can use one big xmlns:s="library://ns.adobe.com/flex/spark"configuration file xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:parsley="http://www.spicefactory.org/parsley" <fx:Declarations> <parsley:ContextBuilder config="{UserConfig}"/> </fx:Declarations> </s:Application> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"Or several files with xmlns:s="library://ns.adobe.com/flex/spark"separated configuration xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:parsley="http://www.spicefactory.org/parsley" <fx:Declarations> <parsley:ContextBuilder> <parsley:FlexConfig type="{UserConfig}"/> <parsley:FlexConfig type="{ServiceConfig}"/> <parsley:FlexConfig type="{MockServiceConfig}"/> </parsley:ContextBuilder </fx:Declarations> </s:Application> ContextBuilder.newBuilder()Configuration DSL .config(FlexConfig.forClass(UserConfig)) .config(FlexConfig.forClass(ServiceConfig)) .config(XmlConfig.forFile("logging.xml")) .build();
  27. 27. Decoupled Bindings[Publish][Subscribe][PublishSubscribe]• This feature is much more dynamic than Dependency Injection.• It is really more the decoupled equivalent of the typical usage of Flex Bindings.• The published object does not even have to be a container managed object.
  28. 28. Decoupled BindingsActionScript Examples[Bindable][Publish(objectId="selectedUser")]public var selectedUser:User;[Subscribe(scope="window")]public var selectedUser:User; uses Local[Bindable] SharedObjects[PublishSubscribe(persistent="true", objectId="selectedUserId")]public var selectedUserId:int;MXML Example<parsley:View type="{UsersView}"> <parsley:Publish property="selectedUser“ objectId="selectedUser"/></parsley:View>
  29. 29. Messaging[ManagedEvents][MessageDispatcher][MessageHandler][MessageBinding][MessageError]• The exchange messages between objects in a fully decoupled manner (sender and the receiver do not have to know each other)• Messaging Framework is generic, it does not impose a particular usage style
  30. 30. ActionScript Examples[Event(name="userSelected",type="com.xyz.UserSelectedEvent")] UserSelectedEvent.as[ManagedEvents("userSelected, somethingSelected")]public class UsersView extends SkinnableComponent { Event based class private function handleUserSelect(user:User):void { dispatchEvent(new UserSelectedEvent("userSelected", user)); }}public class UsersView extends SkinnableComponent { UserSeletedMessage.as [MessageDispatcher] Simple class public var dispatcher:Function; private function handleUserSelect(user:User):void { dispatcher(new UserSeletedMessage(user)); }}[MessageHandler(type="com.xyz.UserSelectedEvent", messageProperties="user, role“)]public function handleUserSelect(user:User, role:String):void {}[MessageBinding(messageProperty="user", type="com.xyz.UserSelectedEvent")]public var user:User;
  31. 31. Object Lifecycle[Init][Destroy] Lifecycle phases preConfigure preInit postInit preDestroy postDestroy
  32. 32. Object Lifecycle[Init][Destroy] Lifecycle phases preConfigure preInit postInit preDestroy postDestroyThe methods marked with [Init] get invoked after the object has been instantiated and allinjections have been processed.[Init]public function init():void { //}The methods marked with [Destroy] get invoked after the Context instance they belongto has been destroyed with Context.destroy() or when the object was removed fromthe Context.[Destroy]public function destroy():void { //}
  33. 33. Managed Commands• Dynamically add a command to a Context only for the time it executes• Declarative way to configure Commands• Grouping commands (parallel, sequence, flow)• Map command to message
  34. 34. Managed Commands[CommandResult] <parsley:MapCommand type="{GetUserProfileCommand}"/>[CommandError] public class GetUserProfileCommand {[CommandComplete][CommandStatus] [Inject("userService")] public var service:RemoteObject; public function execute(msg:GetUserMessage):AsyncToken { return service.getUserProfile(msg.userId); } public function result(profile:Profile):void { // } } [CommandResult] public function profileResult(profile:Profile, message:GetUserMessage):void { [CommandError] public function handleResult(fault:FaultEvent, trigger:GetUserMessage):void {[Bindable][CommandStatus(type="com.xyz.GetUserMessage")]public var isGettingProfile:Boolean;<s:Button label="GetProfile" enabled="{isGettingProfile}" click="..." />
  35. 35. Managed Commands Declaring Groups in MXML<parsley:MapCommand messageType="{FindUserMessage}"> <parsley:CommandSequence> <parsley:Command type="{GetUsersCommand}"/> <parsley:Command type="{FindUserCommand}"/> </parsley:CommandSequence></parsley:MapCommand><parsley:MapCommand messageType="{FindUserMessage}"> <parsley:ParallelCommands> <parsley:Command type="{FindUserCommand}"/> <parsley:Command type="{OutputDataComand}"/> </parsley:ParallelCommands></parsley:MapCommand>
  36. 36. Building MVC Architectures
  37. 37. Custom Scopes
  38. 38. Custom ScopesDefault scope is global<parsley:ContextBuilder> Add new “window” scope <parsley:FlexConfig type="{UserConfig}"/> <parsley:FlexConfig type="{ServiceConfig}"/> <parsley:Scope name="window" inherited="true"/> Change default scope to local. <parsley:MessageSettings defaultReceiverScope="local"/></parsley:ContextBuilder>Actionscript Examples[ManagedEvents("add, remove", scope=“global")][MessageDispatcher(scope="local")]public var dispatcher:Function;[MessageHandler(selector="add", scope="local")]public function save (event:UdpateUser):void {[Subscribe(objectId="selectedUser", scope="window")]public var selectedUser:User;
  39. 39. LocalizationUsual using with flex binding<s:Label text="{resourceManager.getString(resources, ‘user.profile)}"/>It is useful for properties of objects managed by the IOC Container[ResourceBinding(bundle="resources", key="user.profile")]public var message:String;MXML Example<parsley:View type="{ProfileView}"> <parsley:ResourceBinding property="header" bundle="resources" key="user.profile" /></parsley:View>
  40. 40. Configuration Properties project.properties dev_url = http://www.dev.xyz.com prod_url = http://www.prod.xyx.com version = 1.0.0Property File compiled into the Application<fx:Declarations> <fx:String id="properties" source="project.properties" /></fx:Declarations><parsley:ContextBuilder <parsley:PropertiesString source="{properties}"/></parsley:ContextBuilder>External Property File<parsley:ContextBuilder <parsley:PropertiesFile file="project.properties" /></parsley:ContextBuilder> Using Properties in MXML Configuration<parsley:Object type="{Config}"> <parsley:Property name="dev" value="{properties.dev_url}" /> <parsley:Property name="prod" value="{properties.prod_url}" /> <parsley:Property name="version" value="{properties.version}" /></parsley:Object>
  41. 41. Conclusion
  42. 42. Questions?Understanding Information

×