Edit my points
The refactoring project rumbles on but my time with it is drawing to a close. This week the currency traders decided that they wanted to be able to manually override the live data in some circumstances. They wanted to be able to edit a live data point, set its value to a fixed amount and have all dependant displays take this new value into account.
Like most things in computing an extra level of indirection saved the day…
The FX display that forms part of the refactoring project allows live data to feed into a display where traders can display standard terms; like 1 month, or 1 week, and also specify custom terms; like 12/12/03 to 14/01/03 for the purpose of quoting and making currency swaps.
Sometimes they’d like to be able to override the live data to adjust their spreads. They wanted to be able to say ’this particular value from this particular supplier should actually be X rather than the live value’ and have all of the displays and dependant points accept the fact…
Due to the work that had been done to make the FX engine easy to test we’d already decoupled things quite nicely. Live data “tickers” are kept in a pool and the displays pull items out of the pool to make up display points; a 1 month display point might require a SPOT and 1M ticker. A one month and a day point might also require the 2M ticker so that it can interpolate the required point. Pools are stored by contributor; reuters, prebon, internal, etc and by currency. The requirement boiled down to being able to freeze the ticker, let display points work from the frozen value yet let trades still access the real values.
Our tickers live in a live data library; this knows all about how to connect a live data item that’s specific to one of the client’s service providers to an object that implements our abstract ILiveData
interface. The rest of the application works with the data via the interface. It seemed that the easiest way to provide this editable functionality was to slip another object in between the live data object and the application. This new object would also implement ILiveData
and would be able to decide when to pass requests through to the underlying live data item and when to stand in for that item and provide its own, user supplied, data values.
Step one was to write a test for the new functionality. We wanted to be able to edit a point and then, later on, cancel that edit and allow the point to continue to tick with live updates. When the new object was in ’edited’ mode it dealt with client requests itself, when in live mode it passed most requests on to the real live data. Some stuff was slightly more complex; the live data objects are subjects in the observer pattern and so can have observers. The new object needed to intercept these observation registrations and register itself with the real object, effectively chaining the observations and adjusting the observed state where needed.
The testing went well. The new object was developed and tested in a couple of hours. Then came integration with the great untested mass of code that still makes up the bulk of the refactoring project. The main part of the integration was putting a pretty GUI on the underlying complexity. This took longer than it should have; rather than just being able to run a test to ensure that new functionality worked as expected I needed to run up the entire application and navigate to the appropriate point. This slower code/test cycle meant that I started to move in larger steps and make larger mistakes. This was frustrating compared to the smooth, fast, progress that I’d made when working within the test framework… Ho hum. Eventually it was done and it pretty much just works as expected, which is good… It works well enough to show the traders so that we can get some feedback about the GUI. There’s some low level details to be finished off but that shouldn’t take too long and should be stuff that can be done in the relative safety of the tests.