Structured Programming in the Apama EPL
Posted by Louis Lovas
This
is my second installment on a series devoted to the Apama
Event Processing Language, MonitorScript. In my introduction
to the Apama EPL I described the basic structure of the language, some
concepts and terminology. I also included the obligatory Hello World sample.
In this entry I'll continue that basic tutorial delving
into the elemental structure of
the EPL. I've decided to do this to highlight the very simple fact that
the language adheres to the principles of structured programming.
Just so we're all on the same page, here's a definition I
found
on the web:
That's a definition that is clearly irrefutable. In order for a
language to live up to that definition it must have a number
fundamentals. Code
modularity, or developing code as
separate modules. This allows for parallel
development, improves
maintainability and allows modules to be plug replaceable. Encapsulation
is a means of hiding an implementation or
inner workings of a calculation or algorithm. Lastly there
are Interfaces
and
instances.
This architectural pattern may be applied to the design and
implementation of applications which transmit events between loosely
coupled software components. These are just a few of those
fundamentals. These
essential elements of languages have been part of the scene for
decades. They are present in the procedural programming languages like C and
in object oriented languages like C++ and java.
Lest we forget our roots as software engineers, with all the hype surrounding CEP and their constituent domain-specific languages, it's important to do a reality-check and not get swept up and forget the basic principles necessary for creating long-standing maintainable code. Last year I wrote a piece on readability as a criteria for a successful language this is primarily based on a development language having these basic fundamentals: modularity, encapsulation, interfaces and instances.
Apama's EPL, MonitorScript has all these capabilities, as I will describe below. It's what allows us to build reusable framework components, and solutions. Which we've done so with our Capital Markets Framework and Solution Accelerators for FX Aggregation, Smart Order Routing, Surveillance, Bond Pricing, etc. These are components written in our EPL that have the plug'n'play modularity to be redeployed in multiple customers.
To illustrate this idea of structure - modularity, encapsulation and interfaces I'll use a short example of a producer and consumer. This is a common design pattern or idiom we use extensively. The Apama EPL's event paradigm extends not only to the type of CEP applications we enable but also to the nature of the language itself. If you're familiar with message passing languages such as Erlang this will be a familiar concept. Different modules that make up an application communicate with one another by passing messages (or events as is the case).
In this example I have a service or producer monitor that generates and sends Item events, a client or consumer monitor that consumes Item events and an interface for the interaction between the two. If the term Monitor seems strange, I've defined a set of terms and concepts in my introduction, I suggest a quick review of that get up to speed.
The interface to the monitor, defined below is the set of events it receives and transmits. The event definitions for these events are declared within a package name (i.e. com.apamax.sample). Apama's EPL supports java-like package names for name-space isolation to strengthen that modularity notion.
package com.apamax.sample; event SubscribeToItems { string item_name; } event UnsubscribeFromItems { string item_name; } event Item { string item_name; integer item_count; float item_price; } |
The Item Interface is simply a set of prescribed events. Two are to instruct the
consumer to start/stop receiving Items and the Item definition itself. As I
mentioned it uses a subscription
idiom. We use this notion extensively where a Monitor is a layer over some subscription-based service such as a
market data
adapter. A real market data interface would be much more extensive. Here, I've
scaled it back for the sake of simplicity, but you can imagine a more
robust interface
including error handling and status events.
The Item Consumer.
package com.apamax.sample; monitor ItemClient { SubscribeToItems subscribeToItems; Item item; action onload { subscribeToItems.item_name := "sample"; route subscribeToItems; on all Item():item { log "Got an item: " + item.toString(); if (item.item_count > 10) then { route UnsubscribeFromItems("sample"); log "All done."; } } } } |
The Item consumer is also a Monitor in the com.apamax.sample
namespace. It is a user of our event interface to the Item service and as such is
interested
in receiving events of type Item.
The interface defines the
means
to do this by subscribing. The consumer simply has to create a SubscribeToItems
event and forward it to producer service.
As I mentioned earlier, the Apama EPL adheres to an event paradigm as a fundamental characteristic of the language. The route statement is a means by which Monitors communicate. This is another precept and underlines the fundamentals of modularity and encapsulation.
Once a subscription request has been sent (route subscribeToItems), the consumer listens for Items events, (on all Item()). In this simple example, we're just looking to receive them all without any filtering or pattern matching. I will explore event pattern matching - both the simple and complex in a follow-up blog.
To complete the picture, the sample tests a field in the Item event and terminates the subscription if it exceeds a constant value, (item_count > 10).
package com.apamax.sample; monitor ItemService { SubscribeToItems subItems; UnsubscribeFromItems unsubItems; integer cnt := 0; float price := 0.0; listener l; action onload { on all SubscribeToItems():subItems { startItems(subItems.item_name); } on all UnsubscribeFromItems():unsubItems { stopItems(unsubItems.item_name); } } action startItems(string name) { l := on all wait(0.1) { route Item(name, cnt, price); cnt := cnt + 1; price := price + 0.1; } } action stopItems(string name) { // do something to stop routing events l.quit(); } } |
The Item producer is also in the
com.apamax.sample
namespace. It defines listeners for SubscribeToItems and UnsubscribeFromItems.Two
events from our interface. Typically, subscriptions would
be managed
on a per-user basis, thus allowing multiple consumers to
subscribe to our Item service. This is a detail I will outline in a
subsequent installment along with a few other related
features such as instance management.
Once a subscription request has been received, the startItems action (i.e. a method) is invoked to continuously route Item events to the consumer every 0.1 seconds (on all wait(0.1) ...) . Again, in a real world scenario, this particular portion of a service would be more involved, such as possibly managing the interaction to an external adapter for example.
For terminating a subscription on behalf of the client (on all unSubscribeItems()), we simply terminate the wait listener (a looping construct) set up in startItems.
- To stress that the fundamentals of structured programming are ever present: modularity, encapsulation and interfaces. Two benefits of Apama's modularity that are noteworthy relate to the plug'n'play idea I mentioned earlier. a) As typical with modular programming, revised modules can be introduced with little or no impact as long as interfaces are left intact. This is also a truism with the Apama EPL. b) Those revised modules (Monitors) can be replaced in a running system, a shutdown is not required. Furthermore, the modularity also extends beyond the boundary of a single CEP engine to multiple CEP engines in an Event Process Network (EPN) with no actual code change.
- The event paradigm is inherent in the language not just for application events but for the entire application design center.
In future installments on the Apama EPL, I'll delve into a few more of the language constructs that extend this basic idiom (multiple consumers, spawning, and parallelism).
Once again thanks for reading,
Louie
Good post, your post could really help me in my work. Hopefully this will help increase my traffic more. Thanks for sharing.
Posted by: Simonn | Saturday, March 21, 2009 at 10:51 PM