Hi,

On 24 Mar 2006, at 18:11, Richard Gaskin wrote:

Right. While your specific setup did manage to discover a bug, perhaps the reason no one's reported this before is that they prefer to write less code.

Replicated code not only takes more time to write, but as you note it takes more time to revise. Even if you were using something that worked perfectly, there may come a time when you want to enhance it. Replicated code means replicating the enhancement effort.

Well it definitely does if it's wrong!!!! lol

By replicate I mean that whenever I wanted to store something in a field, I used put <something> into me form rather than the long id form. Which meant that now I have implemented the ISM I had revise all usages to use the long id form. But it's done now and well worth it.


In common practice "me" is rarely used, as it only affects one object. In the example shown above, a more generalized approach might be this card script:

  on preOpenCard
      repeat with i = 1 to the number of flds
        if the lockText of fld i is false then
           put empty into fld i
        end if
      end repeat
      pass preOpenCard
  end preOpenCard

Yes, but this only works for fields and it only works on *all* fields, what if you wanted to leave the field untouched from the last time it was used. By putting the logic in the field/object in question you can initialize it or not initialize depending on what is needed and you only need to change the object in question which stops potential bugs from affecting ALL objects. You only have to worry about bugs in the object you have changed.

That simple handler accomodates any number of fields without modification to the code or the objects. You can add or delete fields at any time, and the form still clears itself before being displayed.

Now suppose we later decide we want to have some fields to display default values, while still leaving others blank. We could add a simple property to any field that needs it, and we only make a small change in that one card handler:

  on preOpenCard
      repeat with i = 1 to the number of flds
        if the lockText of fld i is false then
           put the uDefaultValue of fld i into fld i
        end if
      end repeat
      pass preOpenCard
  end preOpenCard

See above, but also, what if the default value is is not a constant, but can be changed by the user? Using this method you are stuck with the single "uDefaultValue" value, whereas using the ISM approach you are free to obtain the value anyway you like and it's specific for the object in question.

I read your outline at <http://lists.runrev.com/pipermail/use- revolution/2006-March/079065.html>, and although after two readings I can't figure out what its goal is my hunch is that it could be satisfied with a single backScript or library and property settings in affected objects.

Maybe a better example is this. I have a preferences stack, one of the items on it is the unit of measurement, it can be set to MM, CM or Inches. I have a couple of groups in my Group Library to do with measure. One of them has the following fields:

[] = a field
<> = variable value

[Width:]   [ <value_in_units>]   [<Units>]
[Height:]  [ <value_in_units>]  [<Units>]

If the units were set to CM and the values were 100.

Now the user opens the preferences stack and changes the units to MM. I want all <Units> values to change from CM to MM and I want 100 CM's to now be 1000 MM's.

Using ISM, I would do this in the script for the Value and Units fields:

ListenForMessage("PrefsMeasureUnits",kMeasureUnits)

and define the following handlers for the <Units> fields:

on PrefsMeasureUnits theMessageID, theSubClass, theUnitValue
set the text of the long id of me to theUnitValue
end

and on the <value_in_units> fields:

on PrefsMeasureUnits theMessageID, theSubClass, theUnitValue
put CalcualteNewValue(the text of the long id of me, theUnitValue) into myNewValue
set the text of the long id of me to myNewValue
end

And in the script of the popup menu in the preferences stack, I'd write:
get ISMPutMessage("PrefsMeasureUnits", kMeasureUnits,theNewUnitsValue)

And any object in any card on any stack can "listen" for the message, so they all initialize to the correct value. I therefore only need to change the value once, not once for each object.

For instance:

No other stacks are open/running.

The user runs Preference Stack and changes the measure units to MM.
The user closes the Preference Stack.
The last time Stack A was run the measure units was set to CM.
The User runs Stack A, the "measure" fields call ISMListenForMessage, since there is now a message pending they automatically change to "MM". If there was not a message pending then a message would not be sent and no code would be executed. The way you are proposing I would have to re-initialize the object every time whether the value has changed or not!

Such an approach keeps the code centralized, making it easier to write, maintain, and enhance. Objects could be added or removed from the behavioral management by just changing a property, never needing to even open a script editor.

I don't need to open the script editor either! And if I delete an object then messages just stop being sent to it!

There's also a performance benefit to using the natural message path whenever practical. Consider these benchmarks from a simple test case* (times shown are per call):

Native:  0.007ms
Send:    0.011ms
Do:      0.013ms

In a single call, the difference between native message inheritance and "send" is only 0.004ms, certainly not worth worrying about. But if one were building a system in which "send" is being used throughout as the primary means of driving things, the aggregate cost of that 50% peformance difference may make the system noticeably less responsive. Those clock cycles could probably be put to better use; even if performance appears fine for now, future enhancements may require additional load elsewhere, so it's often a good idea to keep performance in mind even when it doesn't initially seem important.

I see your point, but in practice, using the ISM approach only the objects that need to act are called whereas using the other methods all fields need to be visited. I have found that the performance is about the same and it's just as responsive. This is just driving a basic GUI, if I needed to do something really fast, I would use an external command and deal in microseconds not milliseconds.

For instance the Experimental stack I did has 274 objects, 94 of them can be called via ISM, but in practice the most objects I have that are affected by a user GUI action is 6. The overhead is minimal. I have to get a stack working by Monday, but after that I will do the extra work needed in ISM, do a first draft of the documentation and post it to RevOnline. You can then take a look at how it works, but I am willing to bet you will not think that it's any slower than other Rev Apps I have seen.

There are of course times when "send" and "do" are the only way to solve a problem, but with the flexibility of frontScripts, libraries, and backScripts such cases are few.

ISM is a library so I am using this technique.I really don't know anything about front or back scripts, and to be honest the lack of good documentation has put me off looking at them. What I have works for me and allows me to create apps must more quickly than using the methods you describe.

Have a Great Weekend and thanks again for all the help.
All the Best
Dave
_______________________________________________
use-revolution mailing list
use-revolution@lists.runrev.com
Please visit this url to subscribe, unsubscribe and manage your subscription 
preferences:
http://lists.runrev.com/mailman/listinfo/use-revolution

Reply via email to