Silverlight is a powerful tool for writing line of business applications. With the rich features of Silverlight comes great responsibility because the bulk of the processing takes place on the client machine rather than the server. At the recent Silverlight Firestarter event, one company announced that their customers run the new application at 1/30th the original cost after the switch to Silverlight from a server-driven model. Reaping these benefits requires a new approach to building applications. Silverlight developers must keep the memory footprint and processing power of the client in mind when architecting solutions.
Enterprise Silverlight applications follow the client/server paradigm. Scaling the application is about understanding where you can scale and providing a flexible architecture to accommodate this.
Taking a modular approach
Taking a modular approach to building Silverlight applications will help them scale. Instead of downloading an entire application to the client machine, which would take not only significant time to cross the wire but also utilize a larger memory footprint, the application can be divided into modules. Modules are logical segments of the application that can be developed, tested, and loaded independently from each other.
In a hypothetical Scrum management application, one module addresses the release level, another module focuses on sprints and a third module handles individual backlog items.
Silverlight provides a built-in facility for loading dynamic modules using the Managed Extensibility Framework (MEF). MEF provides a special catalog called a DeploymentCatalog, that is able to dynamically load other XAP files. An XAP file can be dynamically loaded with two lines of code:
var deployment = new DeploymentCatalog("DynamicModule.xap");
By doing this, you ensure that the initial application only contains the basic core functionality that the user needs. You only download and execute the additional modules when they are requested. This helps minimize the memory footprint for the client by only bringing down the features the user needs and requests. You can also hook into a progress event to track the download and a completed event to kick off other processes once the module has been loaded.
The network is another scale point for applications. “Chatty” applications may suffer from slow performance due to their reliance of network response time. There are several ways you can conserve network bandwidth and only send data across the wire when absolutely needed. Two common places to handle this are validation and cache.
What does validation have to do with network bandwidth? It is common for “CRUD” applications (create, read, update, and delete) to transmit data to the server and provide updates to the client. While it is important that the server contain validation logic to ensure the integrity of the data, depending solely on the server creates what are known as “round-trips.” A round-trip occurs when the client posts some data, the server validates the data and a message is sent back to the server with the result.
Because Silverlight is based on the core Common Language Runtime (CLR), it is possible to both share and link code between the Silverlight client and the server. The CLR team blog has an excellent article on sharing assemblies between Silverlight and .NET applications:
You can also link files to share them between the Silverlight and .NET projects. Linking files allows you to take advantage of existing server validation routines and run them on the client. You can reduce round-trips to the server by validating the data on the client before sending it. Not only will this help conserve bandwidth, but it will also reduce the load on the server, allowing it to scale better across more Silverlight clients.
Another common method to reduce bandwidth is to utilize a cache. It is a common misconception that caches automatically improve performance or speed. While this may be true in certain cases, sometimes it is just as fast to retrieve data from the server as it is to read from a cache. There are many factors involved, but one thing a cache will do for certain is help conserve bandwidth by eliminating the need to transfer additional data over the wire. It is important you test the application before implementing the cache to provide a baseline to compare against so you can determine the validity of using the cache.
Silverlight provides a robust isolated storage mechanism. It is possible to serialize and de-serialize data to isolated storage as the cache for your application. The best candidate for cached data is data that rarely changes. In the hypothetical scrum management application, items like status codes and enumerations are an example of cached data.
There are several approaches to caching. Preemptive caching involves downloading the necessary data items up front and storing them in the cache so they are available when needed. Lazy caching is the practice of fetching data the first time it is needed, then storing it to the cache and referencing it later. More complicated caching scenarios involve policies that determine how long data may remain in the cache and the rules and mechanisms that invalidate cached data and trigger a trip to the server.
Business logic refers to the more complex algorithms and routines that are run against the data in the application. Decisions and workflows are examples of business logic. Many developers fail to take advantage of the fact that Silverlight provides a full-blown CLR and treat it simply as a user interface (UI) layer. Silverlight readily accommodates complex logic that runs right on the client.
The advantage to this is that the client machine acts as a “node” for processing. Consider the scenario of 1 million users accessing an application. When the application is written to process all business logic on the server, the server requires tremendous processing power to handle all of the requests. The data center must scale out by placing a load balancer in front of multiple servers to divide the work.
Each of those users has their own machine with processing power. Moving the business logic to the user offloads the computations from the server. Instead of requiring several powerful servers, you can distribute the work across 1 million lightweight nodes each applying the business logic.
There are many ways to scale a Silverlight application and these tips should provide a decent foundation to start from. By breaking the application into logical modules, distributing logic between the client and server and sharing business logic across nodes you should be able to scale your application to support from hundreds to millions of concurrent users. Silverlight is the ideal technology to provide line of business software in the enterprise.