Working with Microsoft’s composite application block framework (CAB) has made me think about application design in a SOA (Service Oriented Architecture) environment. This article is a few thoughts on how we might use the CAB to solve some of the problems associated with creating composite user interfaces in such a service oriented environment.
I am responsible for a trading and risk management application at an investment bank. The application deals with credit derivatives. Our application is currently a pretty typical layered monolith, designed as below:
As you can see we have:
- A database management component that does connection management to our database
- A data access layer that contains the SQL for connection to our database
- A model layer that contains all the business logic
- A presentation layer that is intended to be a lightweight set of screens
- Some vertical components that give us common error handling and utilities etc.
- A set of ‘business entities’ that are data classes that are used to pass data around between the tiers
We have service interface layers (sets of interfaces) separating the layers. You can’t use the data access or model components without going through these service interface layers.
Limitations of the Current Design: Monolithic and not Service-Oriented
This design isn’t very service-oriented. This is largely because when we wrote it we didn’t have many services available that we could plug in to. Most of our interaction with other systems is via flat files FTP’d to or from us overnight. This isn’t ideal, and we’re going to change it.
The application is also a monolith because each of these components covers the whole gamut of system functionality. So we have written, for example, trade entry screens for our products, curve management logic for products, and pricing code for our products. This is inefficient because it duplicates what other development teams are doing.
Business Functionality in the Examples
To simplify these examples I’ve assumed the system only has system functionality in three categories: static/market data management, trade management, and pricing/risk. In the real world things are a little more complex than that.
For those of you that don’t work in banking:
- ‘Static data’ in credit derivatives is things like details of companies, details of the bonds they have issued, and other underlying data to the business, such as lists of currencies, industry sectors, credit ratings, countries etc.
- ‘Market data management’ is interest rates and credit spreads (‘curves’), and correlations, and associated mathematics
- ‘Trade management’ deals with details of our trades executed in the market, and handling of booking and associated workflow
- ‘Pricing/risk’ takes the trades and market data and works out values associated with the trades
Approach to Changing the Design
We are currently considering the possibility of turning the above design into a vertically layered application with each component the responsibility of a separate team of developers. Each team will be responsible for the entire vertical stream. So for example the static/market data team would provide the data access, the business logic AND the GUI components for all static and market data management.
The user interface components will then sit in a composite application smart client alongside the other teams’ user interface components. Functionality that is needed by other teams will be exposed as CAB services on the client via interface components. We will use the basic SCSF design, with interface components for each vertical stream being the only thing that needs to be referenced if you want to access the functionality.
The end result would look something like this:
This can be further clarified with an example. There will be some curve screens in the GUI. These will be the responsibility of the static and market data management team. This team will also be responsible for the entire infrastructure in getting these curves to display (the business and data access logic). Similarly there will be some pricing screens in the same GUI. These will be the responsibility of the pricing and risk team in the same way.
Because of the way composite applications are structured in the composite application block it should be possible, for example, to release curve enhancements separately from pricing enhancements (and still have the user interface work).
Interfaces in the CAB/SCSF
I should probably make it clear here what I mean by ‘interfaces’ here. I do mean C# interfaces as a starting point: that is, lists of method signatures that can be called. But the CAB also expects you to declare events and commands in the interface components. These allow for looser coupling between components. One advantage of this design is that you can as tightly or loosely couple components as you want. You can even tightly couple some interactions and loosely couple others within a component. For example, if you are requesting and then manipulating a set of complex business objects through the interface you’d probably want a full C# interface. If you’re just telling another component to perform a simple action (say price a trade with current market data) you might do that with a command.
Interaction Between Vertical Layers: Integrated Front-End
In our example above, the pricing component will need to use the curves when it actually does some pricing. It will clearly do this through the interfaces defined by the static and market data team, usually server-side. However, one advantage of this design could be to have the pricing component actually get the data the user is looking at on the client and submit it with a pricing request.
The example I’m going to use here is what happens if a user has changed a curve locally to some extreme values and wants to reprice their book using it. However, the user doesn’t want to actually save that curve so other people can see it.
Clearly what we ideally want is the ability for our user to change the data and then just hit a ‘reprice’ button. A composite smart client application of the kind described here gives us the chance to do that, since we can handle the interaction client-side. The pricing component could have a ‘price using local data’ button that would request the data from the client-side market data component via the service interface and could then submit it with it’s pricing request.
Non-Integrated Front Ends
Most n- tier SOA designs really struggle with these ‘what-if’ scenarios, and consequently the problem of giving our users an integrated experience. More often than not you simply can’t change a curve and reprice your book. Sometimes you can do this but you have to go to another application, change the curve and save it some temporary state, and then go to the risk application and tell it to use that curve. Sometimes you can do it, but only via a spreadsheet download that you’ve had to write yourself.
The reason for this is that it’s traditionally been quite difficult to build integrated front-ends to a series of services, and often we haven’t tried too hard. It’s far easier for the curve team to write their own standalone curve GUI and let the pricing team worry about the pricing problems.
We could almost go as far as having ALL interaction for the smart client components happening on the client via these interfaces. Suppose, for example, the trade management component needs to use a list of currencies. It could make a request to the static data service via the CAB interface on the client. The static data service can then go to its store via a web service or EMS or any other means. It can also cache the results for future calls. The trade management component no longer has to worry about connectivity to the static data component’s web service or servers; it’s all handled for it.
This would mean our SOA would be about client-side interfaces and services, rather than web service interfaces (or some server-side equivalent). The programming model in the client would be hugely simplified. To get and use static or market data all the pricing team have to do is reference the appropriate interface and call it using standard C#. There’s no need for web service plumbing and handling the return types.
Interactivity on the client would be improved too: for example the static data service could maintain a client-side cache of static data, responding to requests for data from it from the other components as necessary. We’ve reduced server trips for our client code substantially. Our interfaces can in theory be ‘chattier’ without too much penalty.
There are a couple of issues I can think of with this:
- Clearly the more interaction we have between our client-side components the more tightly coupled they become. Versioning of the interfaces will become a problem, though possibly less of a problem than web service versioning, since these interfaces are only being used directly by a limited number of clients.
- We’re writing an interface that can only be consumed in one specific way (in the smart client framework), and may well want web service interfaces on our components anyway to allow server-side calls, calls from other platforms etc. So we may be making support of our components more difficult rather than easier.
However, in many ways where I work we already have this model in place: many of our analytics components run client-side but will also handle connecting to back-end services and getting curve and static data for you.
At the moment these are just ideas that we are considering. Obviously smart clients are deeply unfashionable in a world where Ajax is the current GUI silver bullet. But we’ve repeatedly seen teams struggle to create even half-decent trading applications in browsers, and we don’t see that changing in the immediate future. Possibly something like this may be a more practical way to proceed.