Upload
flash-conference
View
1.077
Download
0
Embed Size (px)
Citation preview
Построение гибкой архитектуры приложения с использованием
фреймворка
Robotlegs 2
Чего мы хотим?
Фреймворк или библиотека это всего лишь инструмент...
override public function prepare() : void {registerCompleteCallback(onComplete);
add(InitSocialConnectionCommand);add(InitServerConnectionCommand);add(GetOwnProfileCommand);
add(GetFriendsProfilesCommand).withPayloads(userModel.gpUserID);add(GetBalanceCommand);
add(LoadAssetsCommand); ...}
private function onComplete(success : Boolean) : void {…
}
...Простое оформление сложной логики
...Простое и понятное API[Inject]public var сommandMap : IEventCommandMap;[Inject]public var mediatorMap : IMediatorMap;[Inject(name=”privateInjector”)]public var injector : IInjector;…commandMap.map(CoreEvent.BUY_ITEM).toCommand(BuyItemCommand).withGuards(EnoghMoneyGuard);commandMap.map(CoreEvent.BUY_ITEM).toCommand(ShowBuyCoinsPopupCommand).withGuards(NotEnoghMoneyGuard);...injector.map(Model).asSingleton();injector.map(Model).toSingleton(ConcreteModel);injector.map(Model).toValue(new Model());injector.map(IModel).toType(ConcreteModel).seal();…mediatorMap.map(IBottomBar).toMediator(BottomBarMediator);mediatorMap.map(SettingsView).toMediator(SettingsMediator).autoRemove(false);
...Легкое расширение функционала
● модульность
● внедрение зависимостей
● низкая связанность компонентов
● переиспользование кода
Основные плюсы и возможности:
● модульность
● гибкий и понятный синтаксис
● удобная и простая система внедрения зависимостей
● удобная система расширений
● нет привязки к конкретной реализации сущностей
● унифицирующий стиль разработкиНебольшой минус:
● фреймворк не быстрый
[Inject(name=”...”, optional=”true”)]public var myInstance:MyInstanceClass
илиIInjector#getInstance(class, name=””);
Когда доступно:
public class MyInstanceClass { [Inject] public var variable:Number;
public function MyInstanceClass() { // not ready }
[PostConstruct] public function initialize():void { // ready }}
[PreDestroy]при анмаппинге или же при вызове
IInjector#destroyInstance()
Создание правил внедрения зависимостей (Mapping)
...Примеры маппинга
commandMap.map(CoreEvent.BUY_ITEM).toCommand(BuyItemCommand).withGuards(EnoghMoneyGuard).once();commandMap.map(CoreEvent.BUY_ITEM).toCommand(ShowBuyCoinsPopupCommand).withGuards(NotEnoghMoneyGuard);...injector.map(Model).asSingleton();injector.map(Model).toSingleton(ConcreteModel);injector.map(Model).toValue(new Model());injector.map(IModel).toType(ConcreteModel).seal();…mediatorMap.map(IBottomBar).toMediator(BottomBarMediator);mediatorMap.map(SettingsView).toMediator(SettingsMediator).autoRemove(false);
...Список основных сущностей
● context● config / extension / bundle● view● mediator● command● model● service● guard
Context
● инициализация фреймворка
● удаление фреймворка
● предоставление общей шины
_context = new Context().install(MVCSBundle).configure(MainConfig, NativeConfig, StarlingConfig).configure(
new robotlegs.starling.extensions.contextView.ContextView(Starling.current),new robotlegs.bender.extensions.contextView.ContextView(this))
Configs
● место для маппинга
Extensions
● предоставляет расширение функционала фреймворка
- поддержка старлинга, сигналов, модульности и т.д.
Bundles● Набор расширений, описанных в одном файле.
public class MVCSBundle implements IBundle{ public function extend(context:IContext):void { context.logLevel = LogLevel.DEBUG;
context.install( ContextViewExtension, EventDispatcherExtension, ModularityExtension, DirectCommandMapExtension, EventCommandMapExtension, LocalEventMapExtension, ViewManagerExtension, StageCrawlerExtension, StageSyncExtension);
context.configure(ContextViewListenerConfig); }}
Views
● нет конкретной реализации
● рендеринг на основе входящих данных
● предоставляет API
● ничего не знает об устройстве приложения, все данные получает из медиатора
● может только отправлять события-оповещения для медиатора
● ссылки на вью имеют только другие вью или медиатор
● может иметь несколько медиаторов за раз
Mediators
● работает только с одним экземпляром вью за раз
● можно мапить на интерфейс или на несколько классов вью
● создается автоматически при добавлении вью в дисплей лист
● удаляется при удалении вью из дисплей листа (можно отключить)
● служит для связи вью и остальных компонентов приложения
● не имееет никакой постронней логики
● может дергать модели и сервисы напрямую
● может слушать и посылать события от\в приложение
● нельзя получить прямую ссылку на медиатор
Commands
● нет привязки к конкретной реализации
● запускаются в ответ на события из общей шины
● предназначены для выполнения какого то одного действия
● создаются, выполняют действие, удаляются
● нельзя получить ссылку на команду
● содержат бизнес логику
● могут дергать модели и сервисы, запускать другие событие
● не могут слушать события приложения
Models
● инкапсуляция данных и предоставление API для доступа к ним
● могут диспатчить события в приложение
● не могут слушать события от приложения
● не должны содержать лишней логики
Services
● сущности для работы с внешними сервисами
● не хранят данные
● могут парсить данные
● могут диспатчить события в приложение
● не могут слушать события от приложения
Guards
● используются для предотвращения создания или выполнения чего либо
● нет привязки к конкретной реализации
● нельзя получить ссылку на гуард
● применяются те же инджекты что и для основной цели
● выполняется непосредственно перед созданием основной цели
● если гаурд не одобряет то основная цель не создается
● мгновенны, асинхронных гуардов пока что нет
● на момент запуска гуарда, все данные должны быть доступны в приложении
А теперь все вместе!
делите свой код на более мелкие части по зонам ответственности
Что почитать:
● http://knowledge.robotlegs.org/
● https://github.com/robotlegs/robotlegs-framework
● https://github.com/robotlegs/swiftsuspenders
● https://github.com/alebianco/robotlegs-utilities-macrobot
● https://github.com/robotlegs
● ActionScript Developer's Guide to Robotlegs
Спасибо!
Вопросы?