Silverlight 4 is now available in beta form. I decided to take it for a test drive by implementing some calendars for amateur astronomy. Specifically, I wanted to use Silverlight to calculate and graph the positions of the four Galilean moons of Jupiter, including interesting events like occultations, shadow transits and the position of the Great Red Spot.
The task highlights the advanced display model of WPF/XAML, with a combination of standard controls for setting the date and time parameters, dynamically repositioned and scaled lines for scaling the calendar, and totally dynamic paths for the satellite’s positions. Visual Studio 2010 (now in Beta 2) includes a complete visual design surface for Silverlight, allowing me to rough out a design declaratively (including visual prototypes for the curves I wanted to draw).
The Model-View-ViewModel pattern has come to be the de facto standard design for WPF applications. In this pattern, the “Model” retains its standard meaning as those elements relating to the domain. The “View” is also quite familiar as the user interface, but is more passive than the view in the traditional “Model-View-Controller” triad; in MVVM, the View typically relies heavily on the data-binding facilities of the .NET Framework to attach to the “ViewModel,” which houses the UI’s interaction logic. In this way, the View is almost like a concrete implementation of the ViewModel’s abstraction (“almost” because the ViewModel is not a pure abstraction, and the two are not related by class inheritance but by data-binding).
Because the View is so loosely coupled to the ViewModel (at least visibly; the infrastructure for data-binding is complex but hardly ever requires attention), view “stuff” is easy to test. This was especially useful in my application, where one view is animated, and another boils down to a bunch of sine waves superimposed on a ruler-like calendar that needs to be accurate when fully zoomed in.
Just to make things interesting, my Model initially disagreed with other calculators. I cannot deny jumping to the conclusion that I had a time zone problem (in any application that references time in any way, there will at some point be bugs relating to time zones), but tests saved me from countless hours trying to find the problem by judging, “OK, it looks like Io and Ganymede cross on the 17th around 10 UTC. Is that right?” (It turned out that the orbital constants I used were based upon a non-standard epoch. Live by the easy Internet search, die by the easy Internet search.)
I eventually got the basics down and happily spent a few minutes moving the scale slider up and down and watching the orbits compress and expand. But dissatisfaction quickly set in, as the recalculations were not smooth, but had a noticeable jerkiness to them. Time to get those other seven cores off their lazy butts…
In Silverlight, one uses a BackgroundWorker for concurrency. This is a straightforward class that exposes a “DoWork” event whose handler executes on a background thread and events such as “ProgressChanged” and “RunWorkerCompleted” that execute in the thread in which the BackgroundWorker was started.
The reason that recalculation was taking a noticeable amount of time is because my calendar calculates the location of four moons, their shadows, and the Great Red Spot for each row in the calendar’s 1000-pixel height. The obvious tactic in terms of processing would be to parallelize the outer loop, which was spinning through all the rows in the calendar. Obvious, but ill advised. On an 8-core machine, a BackgroundWorker for each of the four Galilean moons and another for the Great Red Spot map is likely to be more efficient, as there’s much less thread-management overhead and greater coherence. On the other hand, one can imagine recasting the calculations into a form appropriate for implementing in a shader, which could potentially be lightning fast.
As with Windows programs, one can only manipulate the UI within the main thread, exchanging data solely by parameters passed in and out of the “DoWork” handler. This was expected, but I was taken aback that I could not even create unattached UIElement objects in the background. While I could calculate all the points in the moon’s orbit in the background thread, I had to pass back all that data, and the instantiation of the corresponding Polyline was done in the main UI thread. It all worked out well enough, but was yet another instance where the current concurrency model is distinctly unsatisfying.
Other than the design surface in VS 2010, I did not use Silverlight 4’s new capabilities, such as printing or hosting HTML elements. I was simply having too much fun working with my domain and making a creative interface for it. Isn’t that what programming’s all about?
Larry O’Brien is a technology consultant, analyst and writer. Read his blog at www.knowing.net.