tag:robotlegs.tenderapp.com,2009-10-18:/discussions/robotlegs-2/13189-keeping-things-dryRobotlegs: Discussion 2018-10-18T16:35:58Ztag:robotlegs.tenderapp.com,2009-10-18:Comment/378887032015-09-10T12:36:25Z2015-09-10T12:36:25ZKeeping things DRY<div><p>I don't know how you set the mode (state) of your view, when you
add the view to the stage through view's API or on user
interactions from within the view?</p>
<blockquote>
<p>Right now I have given my view a public mode property, and
adding event listeners in the mediator based on the mode but this
seems like its violating the idea of a mediator.</p>
</blockquote>
<p>Does this mean that you are asking the view about its state in
mediator's initialize method?<br>
Like, if( view.mode=="editing" ) addContextListener for some
event...?</p>
<ul>
<li>If you don't like this approach, you can let the view dispatch
an event when its state changes, and the mediator can remove/add
event listeners like this:</li>
</ul>
<pre>
<code>private function onViewStateChanged(event:ViewStateEvent):void
{
removeContextListener(SomeContextEvent.SOME_TYPE, onSomeType, SomeContextEvent);
if(event.message=="editing")
addContextListener(SomeContextEvent.SOME_TYPE, onSomeType, SomeContextEvent);
}</code>
</pre>
<ul>
<li>
<p>or, the view can send a ViewStateEvent with 2 different types,
ADD_LISTENERS, REMOVE_LISTENERS and the mediator would add or
remove events in the corresponding handlers</p>
</li>
<li>
<p>another possibility is to let the view itself decide if it is
interested in the data coming from the mediator depending on its
state.</p>
</li>
<li>
<p>another option (for the case of adding views to the stage that
have a predefined role):</p>
</li>
</ul>
<p>Create interfaces for your view, say, IAddThings, IEditThings
and let the view implement both 'behaviours'. When you need an
editing view you add it to the stage as IEditThings, and as
IAddThings when you need it for other purposes...<br>
Create 2 mediators, one for the IAddThings and another for the
IEditThings and inject IAddThings into AddThingsMediator and
IEditThings into EditThingsMediator.<br>
Create 2 guards for the 2 mediators. The EditThingsMediator should
be created if the view's state is "editing" (the view can be
injected into the guard, which can interogate view's state).<br>
The AddThingsMediator should be created only if view's state is
"adding" or is not "editing" or whatever condition you need to
check.<br>
The mediators should add event listeners only for the events of
interest to them.<br>
This solution might be the cleanest, but it is a bit more
convoluted. Let me know if you need more clarification on this.</p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/378887032015-09-10T15:42:07Z2015-09-10T15:42:07ZKeeping things DRY<div><p>For the use case you've presented I'd use a ReportSettingsModel
holding a property 'report' of type ReportSettingsVO, as shown in
the example below. The view is setting the values on a new
ReportSettingsVO and is dispatching an event with a payload of type
ReportSettingsVO.<br>
ReportSettingsCommand passes the event's payload to the model. When
the GenerateReportCommand is triggered, it reads the model's
properties and passes them onto the ReportFileService.<br>
So, ReportSettingsModel has a property report: ReportSettingsVO and
it could contain other properties as well, as VOs or other types,
but the 2 properties carried by the ReportSettingsVO are not part
of the ReportSettingsModel.<br>
Tell me why this wouldn't work for you?</p>
<pre>
<code>public class ReportSettingsVO
{
protected var _reportType:String;
protected var _rowsPerPage:Number;
public function ReportSettingsVO(reportType:String, rowsPerPage:Number)
{
_reportType = reportType;
_rowsPerPage = rowsPerPage;
}
public function get reportType():String
{
return _reportType;
}
public function get rowsPerPage():Number
{
return _rowsPerPage;
}
}</code>
</pre>
<p>ReportSettingsModel::</p>
<pre>
<code>public class ReportSettingsModel
{
private var _report:ReportSettingsVO;
//private var _someOtherVO:SomeOtherVO;
//private var anotherThing:String;
public function ReportSettingsModel()
{
}
public function get report():ReportSettingsVO
{
return _report;
}
public function set report(value:ReportSettingsVO):void
{
_report = value;
}
}</code>
</pre>
<p>ReportView - editing the report settings::</p>
<pre>
<code>var reportType:String = someComponent.value;//PDF/TXT
var report:ReportSettingsVO = new ReportSettingsVO(reportType , 5);
....
dispatchEvent(new ReportSettingsEvent(ReportSettingsEvent.REPORT_SETTINGS_CHANGED, report));</code>
</pre>
<p>ReportSettingsCommand::</p>
<pre>
<code>[Inject]
public var event: ReportSettingsEvent;
[Inject]
public var model:ReportSettingsModel;
public function execute():void
{
model.report = event.report;
}</code>
</pre>
<p>GenerateReportCommand, needing the report settings::</p>
<pre>
<code>[Inject]
public var model:ReportSettingsModel;
[Inject]
public var service: ReportFileService;
public function execute():void
{
service.doYourThing(model.report.reportType);
//or just
service.doYourThing(model.report);
}</code>
</pre>
<blockquote>
<p>Should settings be tracked in value objects and injected into
the models that need them?</p>
</blockquote>
<p>Are you referring to the same scenario as the one above? If the
answer is yes, then I'd say no, you shouldn't inject the vos into
the models.</p>
<p>If you're setting the VO's values once at the app start and
you're not going to edit them later, then you could inject them
wherever you needed them.</p>
<blockquote>
<p>Could we create these VOs on the fly in commands, and the use
injector.mapValue to apply it to all injection points?</p>
</blockquote>
<p>Yes, you can create classes on the fly like this:</p>
<pre>
<code>var someVO:SomeVO = injector.getOrCreateNewInstance(SomeVO);
if (!injector.hasMapping(SomeVO))
injector.map(SomeVO).toValue(someVO);
someVO.someProperty = "new value";</code>
</pre>
<p>but you have to decide whether it makes sense to use vos like
this.<br>
You should know by now that injecting everything everywhere comes
at a price!</p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/378887032015-09-11T19:10:40Z2015-09-11T19:10:40ZKeeping things DRY<div><p>Once I had written out my question, the answer became more
obvious. Thanks for confirming with your wisdom!</p></div>dkarten