« July 2004 | Main | September 2004 »
August 27, 2004
iteration::two Sharing the Love
Ali over at iteration::two has been a madman of late posting a number of samples on their blog over the last few days. Recommended reading for all.
Note: Author receives no benefit from promoting this site. It just gives him something he can post quickly while heads down working on the next Flex release.
Posted by mchotin at 05:48 PM | Comments (0)
August 10, 2004
RemoteObject Stateful vs. Stateless Classes
Hans asked a while back if I'd discuss stateful vs. stateless classes for the RemoteObject tag. I don't think I have anything definitive or official to say, but I'll go through my own thought process as to how I decide what kind of class I'm going to use. First, the default is stateless, so I try to err on using a stateless class unless something compelling comes along to make the class stateful. With that in mind, some reasons to consider stateful classes (not in any order).
- How long does it take to instantiate an instance of your class? A new stateless class will be instantiated every time you call any method, so instantiation should be cheap. Now we all know that instantiation is never cheap, so in the future I could see us supporting some sort of pooling mechanism where classes would need to be obtained and released. Anyway, if it takes a long time to instantiate your class, it might be worth keeping it stateful assuming it doesn't also hog massive memory.
- How many users will be logged in at once? If the number isn't too high, perhaps you can save some instantiation time by making the class stateful. Too many users at once and you'll be taking up memory, especially if your class is holding references to other classes and preventing garbage collection.
- Are you load-balancing your server? This would strike me as a reason to try to avoid stateful classes as you'd then need to transfer this class across to another server as well. However, as long as your class can be load balanced by your app server if stored in a session variable you can set it as stateful.
- How much information is needed across operations? For example, does some sort of token need to be passed to every operation that your RemoteObject will then pass to a commerce server? Are there multiple tokens to pass? A stateful class would allow you to set a token once, then not have to pass it through each method (which saves a little space and time on the wire). However, you then pay the expenses mentioned above of space on the server (memory). What if you stored that information in a 3rd place, like a database or regular file and accessed using a shorter token? If you were passing a lot of information a stateless approach means a lot of network traffic and a stateful approach means a lot of server memory . The database approach might be a reasonable compromise, however the cost here is the database access for every operation (and any network costs between the database and your app server).
I think I could probably keep building on this list, but you are hopefully seeing a pattern. Like most optimizations, you are making a choice between time and space. You generally save time by having a stateful class which means potentially less network traffic between Flash client and app server and fewer instantiations. However the expense is that you end up using more memory on the server as every RemoteObject and relevant data is stored for each session. Sometimes the choice will be obvious, and sometimes you'll need to run tools like profilers and heap analysts to give you more data to reach a decision.
If anyone has stories of how you've made your own decisions feel free to share. And maybe some other folks who've done more work with the RemoteObject at Macromedia will jump in as well.
Posted by mchotin at 01:15 PM | Comments (2)
Notes on Data Validation
I've been answering some questions for folks internally and externally about validation and thought I'd try to post it here for anyone who's interested. This is a combination of personal opinion as to how validation can work as well as notes on how it does work now...
Validation in Flex is a mechanism for determining if data is valid. That data can be any field of any object, anywhere. The Flex system tries to build on this simple concept and add in the ability for certain data to be automatically validated. And we then take it a step further and if possible display errors at the source of their problem (the red border around a UI component).
Before getting into a few more details I want to share some of the thoughts that went behind the design of our validation framework. First, we always want to encourage a separation of Model and View. The view onto data might look different than the raw representation of data itself (think formatting). Therefore, we built around the principle that it is data that is valid or invalid, not the view onto that data. This is why you validate a Model's field, not the TextInput's text.
The second principle we followed is that validation should not affect data flow. In Flex, data is often passed around using data binding which therefore implies that the source and destination should always be in sync. In fact, there is no way to determine if the source and destination are in sync because it is assumed they always will be (with the notable exception of not syncing an initially undefined/null/empty-string value). Given that binding implies synchronization, it seemed that it'd be wrong for a binding to not take place if the data it was trying to pass was invalid. We decided the data should go to its destination and other parts of the system should prevent further application execution if there is a problem. I've seen differences of opinion on this approach and am open to incorporating other ideas into the system in the future if they make sense.
OK, now some more details on automatic and manual validation. A field is automatically validated if it is the destination of a binding expression. This generally implies that you will validate Models as opposed to UI controls, as it's often safe to assume that data already in Models will be correct while user input may be incorrect. If the field you want to validate is not the destination of a binding (or you want to re-execute validation on something already bound) you need to use the Validator.isValid method (or Validator.isStructureValid). See the ASDoc and chapters for more info.
Now what about making the red borders and error tooltips appear. When a binding is created the compiler looks at the source expression and sees if it can find a UIComponent as part of it. If it does, that becomes the automatic listener for a Validator using the destination as its field. So when we see a binding expression like this:
<mx:Model id="foo">
<bar>{someInput.text}</bar>
</mx:Model>
we see that the source expression is "someInput.text" and the destination is "foo.bar". A Validator with field="foo.bar" will thus have a default listener of "someInput" (the UIComponent). So there we go, automatic validation listeners. Now if the compiler didn't make the connection correctly or if you want a different component to be your listener, simply reassign the listener on the Validator tag (the docs discuss how to be a validation listener).
Extra notes:
A Validator can be assigned to validate objects not in your document. You can validate components that live in other documents no problem:
<mx:Validator field="someComponent.someOtherComponent.someObject.someField" listener="someComponentOnMyDocument" />
If the Validator is defined in another document but you want to call isValid from another location, the isValid call is ready for that as well.
The method signature for isValid is this: Validator.isValid(document, field), document is the reference to the document where you defined the Validator. field is the string that should exactly match the field declaration on the Validator tag.
So if you're willing to call isValid yourself you don't need to worry about setting up binding for validation to work (and it doesn't need to validate against an mx:Model). And if you want the red borders to appear and you're not using binding, you set up the listener. And if all of that needs to happen in another document, no problem.
Hope this sheds some light on validation. Feel free to make comments on the docs or here if you'd like more info on something.
Posted by mchotin at 01:11 PM | Comments (5)