tag:robotlegs.tenderapp.com,2009-10-18:/discussions/robotlegs-2/13125-data-from-many-modelsRobotlegs: Discussion 2015-09-08T18:28:07Ztag:robotlegs.tenderapp.com,2009-10-18:Comment/376517412015-08-14T10:05:17Z2015-08-14T10:05:17ZData from many models<div><blockquote>
<p>And once you start injecting a number of models into a command,
more references and logic is performed in the command, which could
affect the commands lifecycle and garbage collection</p>
</blockquote>
<p>Normally, commands are available for garbage collection
immediately after execution. If a command doesn't get away after it
has been executed, it is because something ( a long-living object
or class) is keeping a reference to the command. It's your
responsibility, as a developer, to avoid such situations. Do you
have a concrete use case where a command is kept in memory, or are
you talking theoretically? When you say that it could affect
command's lifecycle, what do you mean by that?</p>
<blockquote>
<p>I would guess these are both viable, but I am a little wary, as
once you start injecting models wherever you need them, it is
tempting to do so in mediators/services.</p>
</blockquote>
<p>Yes, they are viable scenarios.</p>
<p>Well, you should be able to resist the temptation :)</p>
<p>Robotlegs 2 and Swiftsuspenders make it possible to inject
anything wherever you want. But, that doesn't mean you should. The
MVCS meta-design pattern gives you some guidance on the roles of
the tiers and on how to design your classes. You know already that
you can either follow the recommended practices stricto modo, or
that you can adapt them to your needs. Or, that you can use another
pattern.</p>
<p>Regarding the amount of logic you put into a command, you are
right if you think that a command shouldn't become bloated with
logic. Maybe you just need to split it into several commands, each
being responsible for just a part of the business logic. Macrobot
is a utility/extension that provides two ways (sequence, parallel)
to batch commands.</p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/376517412015-08-14T14:25:24Z2015-08-19T21:05:56ZData from many models<div><p>Occasionally an async action is performed by a command, which is
why I am worried about proper garbage collection. What is exactly
is the disposal process for a command?</p>
<p>I know that if you give an asynchronous service process a
callback that resides in a command, this will maintain a reference
to it. What about local variables created in a commands execute
method? Sometimes I find myself performing a few manipulations on a
command, or in a command, taking data from one model, manipulating
it in another model, and then running it off to a service. I am
guessing this is a sign it needs to be split up into multiple
commands, because we start violating the SRP. I will look into
macrobot.</p></div>dkartentag:robotlegs.tenderapp.com,2009-10-18:Comment/376517412015-08-14T15:53:29Z2015-08-19T21:05:56ZData from many models<div><p>The use case is looking up data imported from an external file.
Data from the file needs to be matched/merged with data kept in
several models. Occasionally, if the data cannot be found in memory
(aka the models), a database lookup needs to be performed. My
current solution is a sort of aggregate model (or perhaps its more
of a service?) that has injections for the necessary models and the
db service (this is dirty I know but for right now I cannot see a
way to separate this service dependency). This aggregate model
takes the parsed file data and manipulates it, querying the other
models when necessary. While I am pretty happy with it, the data is
short lived and not stateful, which makes me think it should be
processed in a command. I guess the aggregate model can be
instantiated on the fly with the injector?</p></div>dkartentag:robotlegs.tenderapp.com,2009-10-18:Comment/376517412015-08-14T16:10:26Z2015-08-14T16:10:26ZData from many models<div><blockquote>
<p>What is exactly is the disposal process for a command?</p>
</blockquote>
<p>Inside of CommandExecutor.executeCommand() the command object
has a local scope.<br>
The command is instantiated and its execute method is called.<br>
The "execute" method to invoke on the Command instance is set to
the default 'execute'. (Btw., You can set it to another method of
your choice, when you map the event to the command).<br>
If there is none keeping a reference to that locally instantiated
command, it will get gc-ed:</p>
<p><a href="https://github.com/robotlegs/robotlegs-framework/blob/master/src/robotlegs/bender/extensions/commandCenter/impl/CommandExecutor.as#L72">
https://github.com/robotlegs/robotlegs-framework/blob/master/src/ro...</a></p>
<blockquote>
<p>I know that if you give an asynchronous service process a
callback that resides in a command, this will maintain a reference
to it.</p>
</blockquote>
<p>Exactly. But, only until the async process is complete. After
that the command goes away.<br>
This is actually what we expect to happen when working with async
calls in a command.</p>
<blockquote>
<p>What about local variables created in a commands execute
method?</p>
</blockquote>
<p>What do you mean?</p>
<blockquote>
<p>Sometimes I find myself performing a few manipulations on a
command, or in a command, taking data from one model, manipulating
it in another model, and then running it off to a service. I am
guessing this is a sign it needs to be split up into multiple
commands, because we start violating the SRP.</p>
</blockquote>
<p>Sometimes it makes sense to have a group of actions inside a
single command, if those actions are somehow related.
Theoretically, I'd prefer to have a single command accessing 2
models and a service instead of 4 commands doing the same job. But,
as always, there are many factors influencing such a decision in a
concrete use case. You'll have to find out for yourself how
granular you want to go.</p>
<p>Here the macrobot that works with robotlegs 2 :</p>
<p><a href="https://github.com/alebianco/robotlegs-utilities-macrobot">https://github.com/alebianco/robotlegs-utilities-macrobot</a></p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/376517412015-08-15T12:50:55Z2015-08-15T12:50:55ZData from many models<div><p>I didn't see your last message when I responded yesterday.</p>
<blockquote>
<p>While I am pretty happy with it, the data is short lived and not
stateful, which makes me think it should be processed in a
command.</p>
</blockquote>
<p>YES!! This is much better than using the hybrid class you've
mentioned.</p>
<blockquote>
<p>The use case is looking up data imported from an external
file.</p>
</blockquote>
<p>The loading of data from an external file would be a job for a
Service class-FileSystemService</p>
<blockquote>
<p>Data from the file needs to be matched/merged with data kept in
several models.</p>
</blockquote>
<p>DataComparator could be a class that compares the data from the
file with existing models' data.</p>
<blockquote>
<p>Occasionally, if the data cannot be found in memory (aka the
models), a database lookup needs to be performed.</p>
</blockquote>
<p>That'd be a job of a DBService.</p>
<p>File System Service------> DataComparator Model<------DB
Service</p>
<p>A command could orchestrate the entire process, if it had the 2
Services and the DataComparator class injected into it.<br>
Or, if you wanted to use a sequence of commands (macrobot), you
could use a command to encapsulate the loading of the file data ,
another command to perform the data comparison, and a third command
to make a db request. 3 tasks, 3 commands.</p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/376517412015-08-19T21:06:46Z2015-08-19T21:06:47ZData from many models<div><p>Macrobot is great, thank you for recommending it. That is
exactly what I've done. I made an IFileReaderService and
implemented it with a DelimitedFileService (it happens that all
files that we are reading are delimited with commas, semicolons,
etc). The DelimitedFileService simply reads the delimited data and
returns it in an array of row arrays. This data gets passed to a
model which parses the raw data into a more logical form (for now
just Objects, but could be typed later). Our parsed data is passed
to a command which calls the DataComparator model, performs its
model lookups, performs whatever db lookups necessary, and returns
the matched data.</p>
<p>I know that it is breaking principles to combine the
DataComparator model with the db service, but I need to keep the
data being matched together. For now I have not figured out a way
to do so, but I've thought of maybe storing the data being matched
in the DataComparator model, returning a list of conflicts that
need to be looked up in the database, and then returning to the
DataComparator model with db data, but I've left out doing this for
now, I have other things more important to work on.</p>
<p>If you have any suggestions, great, but if this seems good
enough, you can close this!</p></div>dkartentag:robotlegs.tenderapp.com,2009-10-18:Comment/376517412015-08-20T10:48:37Z2015-08-20T10:48:37ZData from many models<div><blockquote>
<p>Macrobot is great, thank you for recommending it.</p>
</blockquote>
<p>My pleasure.</p>
<blockquote>
<p>but I've thought of maybe storing the data being matched in the
DataComparator model, returning a list of conflicts that need to be
looked up in the database, and then returning to the DataComparator
model with db data</p>
</blockquote>
<p>Yes, that is the better way of doing it. The Model shouldn't
have to care about how or from where the data is received. You
could go a step further and encapsulate the logic for data
comparison in another class, especially if you think that this kind
of data comparison will be needed in more places. The Model would
call methods on the comparator class (injected into the Model), and
would just keep the data in memory as long as needed and/or prepare
it for further use.</p>
<p>Instead of calling a Service directly from a Model:</p>
<ul>
<li>
<p>the Model can dispatch events to trigger Command(s) that would
call a Service</p>
</li>
<li>
<p>a Command, having the Model injected, can take the result from
Model's operations on the data and pass it to a Service, also
injected into the Command</p>
</li>
</ul>
<p>The result from a Service call can be received in a call-back
function inside a Command, or the Service dispatches events to
trigger Commands.</p>
<p>When using Macrobot, commands can be executed directly from
within your batch command. This might come in handy every now and
then, so I thought I mention it.</p>
<p>Also, Direct Command Map is a robotlegs extension that does a
similar job as the Macrobot:<br>
<a href="https://github.com/robotlegs/robotlegs-framework/tree/master/src/robotlegs/bender/extensions/directCommandMap">
https://github.com/robotlegs/robotlegs-framework/tree/master/src/ro...</a></p>
<blockquote>
<p>but I've left out doing this for now, I have other things more
important to work on.</p>
</blockquote>
<p>Right. Go with what works for now, and since you are aware of
the deficiencies in the code/design, I'm sure you'll come back to
it later to improve and refine it.</p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/376517412015-09-02T15:29:34Z2015-09-02T15:29:34ZData from many models<div><p>Another question about centralizing data into one model. I am
finding I have a bunch of models that are basically lists. The only
functionality I have added to them is to add and remove items from
the list they manage. This got me thinking perhaps it would be
better to write them as list classes, and have one model that deals
with all the lists. I constantly find myself needing to reference
more than one list in a single method or procedure.</p>
<p>Is it poor practice to have one model manage multiple lists?</p></div>dkartentag:robotlegs.tenderapp.com,2009-10-18:Comment/376517412015-09-02T16:56:45Z2015-09-02T16:56:45ZData from many models<div><blockquote>
<p>Is it poor practice to have one model manage multiple lists?</p>
</blockquote>
<p>It depends on the number of lists and on their roles, or on the
role of that model or on the type or level of its cohesion.<br>
Having a single Model managing <em>all</em> lists of an application
is going to be a problem in case the application grows in size and
complexity over time and you have a lot of logic inside of this
<strong>global</strong> Model or if tight coupling is one of the
side effects of this approach.<br>
But, maybe in the context of your application it makes sense to
centralize the adding and removing of list items like you said. I
don't know. You have to know this:)</p></div>Ondina D.F.