After writing the Alert Aggregator sample for the Tuscany Native runtime I thought it would be worthwhile documenting my experiences. I've titled this "Best Practices" but perhaps "Hints & Tips" or "Andy's Observations" would be more appropriate! Anyway, below is a suggested list of things to do/think about when writing your own SCA based applications. A few of the points below are from general software development, but they apply equally to SCA development.
Start by drawing your SCA diagram (example here) - this helps with the componentization of your app. SCA diagrams aren't code path diagrams (such as a BPEL visualization): they simply show what blocks of function you have and which blocks are used by other blocks. Separating components into composites also helps you think about componentization and deployment, as (currently) the smallest deployable block is a composite. Similarly, an SCA diagram is not a class diagram - the smallest SCA unit is the component which could consist of multiple classes or scripts or similar. You may have a requirement for a "Utilities" class providing some basic function that is used by lots of other classes - SCA wires involve a certain amount of overhead, so it may not be worth creating a "Utilities" component that all other components reference. Instead, it can be valid to have multiple instances of the same class embedded as part of multiple components.
Think about the services and references that your components and composites provide/require, so you can draw the wiring on the diagram and work out which components and composites you need, but don't worry too much about bindings (REST, WS, etc) - SCA/Tuscany makes it so easy to switch bindings that this can be decided at a later time.
I didn't worry too much about interfaces at this point - I planned to do most of my components in scripting languages (which don't need defined interfaces in Tuscany Native). In other languages (Java, C++) it may be worth defining the public interfaces that your component implements, so you can see how and where functions are implemented within your composites.
When coding the component implementations, it's easiest to start with the 'least-dependent' components - those that don't need lots of other infrastructure or other components or composites in place. For the Alert Aggregator sample (see here), my order of component development was as follows:
RSSChecker
AlertConfig
AlertChecker
HTMLFormatter
POPChecker
Of course, as in normal software development, this was an iterative process where each component got revisited as necessary.
Component implementations were developed in a standard test-driven manner, but deploying within an SCA runtime adds extra layers of required testing (think unit vs. system tests). I began by testing my component implementations in a standalone, unit-testing-style fashion, then tested under Tuscany via local clients, then via remote clients using whichever service bindings I had chosen and finally via full system tests (in the Alert Aggregator case, through clicking on a web page). The power of SCA meant that I could use the same client code for both local and remote testing , just by adding in a local SCA reference that called the remote service (see the PythonCalculator sample for an example of this - the sample.calculator.client/client.py code is almost exactly the same as the sample.calculator.wsclient/client.py code).
I found I needed to programme somewhat defensively - Tuscany SCA Native (or at least the extensions I used) is not yet particularly good at handling exceptions or errors that get thrown, but not caught, in component code. Instead, I tried to check for bad data and catch exception cases within the component implementation. The handling of errors is something that definately needs more work in Tuscany SCA Native - should errors get propagated back to the original client, or should they be caught and logged? A problem that exacerbates this issue is that some of our logging messages don't provide much (or any!) useful information!
The XML story with Tuscany SCA Native is pretty good - I found using SDO/XML/Python ElementTree objects easy and very useful. I would probably go as far as suggesting that developers use XML complex types and SDO rather than trying to flow multiple method parameters, as this can mean less changes required in code and interfaces throughout the development cycle. |