views:

189

answers:

5

The initialization code of our Flex application is doing a series of asynchronous calls to check user credentials, load external data, connecting to a JMS topic, etc. Depending on the context the application runs in, some of these calls are not executed or executed with different parameters.

Since all of these calls happen asynchronously, the code controlling them is hard to read, understand, maintain and test. For each call, we need to have some callback mechanism in which we decide what call to execute next.

I was wondering if anyone had experimented with wrapping these calls in executable units and having a Fluent Interface (FI) that would connect and control them.

From the top of my head, the code might look something like:

var asyncChain:AsyncChain = execute(LoadSystemSettings)
.execute(LoadAppContext)
.if(IsAutologin)
  .execute(AutoLogin)
.else()
  .execute(ShowLoginScreen)
.etc;
asyncChain.execute();

The AsyncChain would be an execution tree, build with the FI (and we could of course also build one without a FI).

This might be an interesting idea for environments that run in a single threaded model like the Flash Player, Silverlight, JavaFX?, ...

Before I dive into the code to try things out, I was hoping to get some feedback.


Update 19/03/2010: We have created an experimental Task API in the Spring ActionScript project that provides control over async processes. We'd be happy to get feedback. http://www.springactionscript.org/docs/reference/html/the_operation_api.html#tasks

A: 

since your functions must be asynchronous, you can't make them block to wait for the next action, so all they do is stash some codes in a structure that will be executed later.

sounds familiar? in short, you're compiling a language and executing a VM.

nothing wrong with that, but thinking in the right terms will let you search for the right literature. for example, instead of fighting with your internal structure so the .else() part knows which .if() it pairs, just write a full parser and send it a string with your program.

also there are lots of examples on writing simple VMs

Javier
A: 

Definitely you can do this. You can pass action and continuation functions and threat them to be async call and callback. This is called Continuation passing style. This will require to convert you conventional logic to sequence of function calls.

Straightforward way will be to introduce some monadic framework (like in Haskell) that will encapsulate your asynchronous calls. But you still have to create multiple functions (callbacks) while converting your program logic to CPS. See: CPS in Haskell. But the syntax is ugly. Good syntax is in Scheme, but this is tightly related to Scheme computational model: macros and library code available for macro processing.

With some language support you can simplify the syntax: example is computation expressions in F#, exactly async one. Under the hood is close relative to the Monad concept.

Another interesting idea of high level event driven programming is implemented in Reactive Extensions for .NET (Rx). The idea is pretty simple: events are very simiplar to lists. The difference is that you don't construct them (push based collection), but rather you get next element from them (pull based collection). Invert an interface correspondingly: instead of MoveNext and Current in IEnumerator you will get OnNext, OnDone and OnError in IObservable. An then, combining existing observables you can get something close to code you suggested.

vpolozov
A: 

Much of this is very interesting discussion on this type of programming. It's also the weakest part of our most common languages, and it's very painful to express asynchronous logic within a synchronous language. I believe continuations are the answer here because we can think synchronous and program synchronous, but model asynchronous program control flow easily. Synchronous programming is very well understood and reuse is very easy. Async not at all. But, until the world catches up...alas.

What you're suggesting looks interesting but I've done this type of thing now at least twice, and never been happy with it. I think you're going to have a difficult time to evaluate your if blocks at runtime. The problem I've always had was getting the data from one step to the next in a clean manner. How are you going to write a if statement against values that might not be present until after a step has run.

If I were you I'd consider looking at the State pattern. State pattern models this type of behavior in objects and the transitions can be performed asynchronously. YOu might be able to create a Fluent interface for creating States like you have above.

I'd be very interested in hearing how it goes as I'm doing this exact thing in my AIR app now, and I'm only sorta happy with it.

chubbard
A: 

I've done something similar, specifically for the initialization of applications. However, I wrote it with MXML usage in mind since we develop most of our flash applications using Flex.

The syntax looks just like declaring an array (I'm just making up the tags, but you get the idea):

<Initialize>
    <DisplayPreloader />
    <LoadConfiguration id="configurationLoader" source="foo.xml" />
    <ParseConfiguration source="{configurationLoader.result}" />

    <!-- ... --->
</Initialize>

Using interfaces such as IMXMLObject it works quite well to just slap this into an application and hey presto, there's your initialization code. Of course, this doesn't have to be for initialization, it could apply anywhere.

Notable pros:

  • Order of execution is intuitive, and easy to change (just move a tag up or down)
  • Steps in the list doesn't really care about other steps
  • Data can be passed between steps by using binding syntax, promotes dependancy injection
  • Properly encapsulated single-task steps can very easily be re-used

Notable cons:

  • MXML == angle bracket tax
  • Using bindings for passing data could lead to unexpected results if triggered multiple times
  • Care should be taken that steps adhere to the Single Responsibility Principle, otherwise it can easily become much too complex
macke
+1  A: 

If it comes to using Flex and having insight in the flow of asynchronous calls I would use the archectural framework Mate. As the Api states: 'A fundamental part of Mate is the EventMap tag which allows you define mappings for the events that your application creates. It is basically a list of IActionList blocks, where each block matches an event type[..]" Now in each EventMap you can have several asynchronous server calls that are logically connected to each other. The whole thing is mxml tag based, so also very easy to read.

Olivier de Jonge