Say you have a .Net application. From a deployment perspective, your application is a relatively normal application. A primary executable, probably Windows Forms or WPF based, a class library or two, and a few third party controls. The application has reached a shipping point and now it’s time to distribute it to more than a few workstations. You’ve chosen to distribute your application using the Windows Installer. You’re now faced with determining the strategy for maintaining the workstations that have installed your application. Whatever strategy you choose to pursue, you will be confronted with this question:
When I update my application, do I replace all of my assemblies, making updating simple, or do I replace only what I just changed, making updates smaller, but more complicated?
This question is going to arise whether you create Windows Installer upgrades and patches, use a third party updating solution, or even consider rolling your own updater. Regardless of the tool you use, at some point you will find yourself pondering the topic. The physically small update is the apparent no-brainer. The uninitiated may say, “of course we want our updates small. Nobody wants to wait on updates, and we don’t want to waste bandwidth. Net neutrality isn’t here yet!” This is all true, and can be a compelling argument. So you march forward on the task… until the details emerge. To keep updates small, versioning rears its ugly head. An incremental update can only target specific previous versions. For manually distributed software updates, as is often the case with Windows Installer deployments, knowing what version you have, and which patch, or patches, you need to apply becomes as big a deterrent to end-user updating as a larger update.
After considering the challenges of implementation, the simplicity of larger, but version agnostic updates will cause you to reconsider your seemingly obvious initial plan. This is a big reason why so many organizations start out attempting to distribute patches and incremental upgrades, but then revert to the far more common version agnostic approach of uninstall/re-install. (There are plenty of technical challenges involved in actually producing working Windows Installer upgrades and patches, which also plays a role here as well).
So which path do you choose? Consider the following.
-
Frequency of updates
If you are creating updates frequently, you want the update process creation to be as automated as possible. Decreasing the manual involvement increases efficiency as well as lowers the opportunity for mistakes. If you have the infrastructure to automate the creation of small, incremental updates then you should do so. If not, your update process will be simpler and less prone to error if you build larger, version agnostic updates. Even if you are doing this frequently.
-
Frequency of application use
For applications that are launched and updated infrequently, accumulating incremental updates can create an undesirable user experience. Try to avoid forcing your users to regularly discover and apply multiple updates, one right after another. You should build larger updates that apply to more versions, or ensure your update process can apply multiple individual updates in a single update session.
-
Physical size of the application files
Physically large application assemblies make for large updates. File patching can significantly reduce this size of an update, but requires strict control of which previous versions can apply the update.
-
Number of deployed clients
For applications with many thousands of deployed clients, the network burden of larger updates is much more significant than applications with tens or hundreds of deployed clients. As your installed user base grows, minimizing the physical size of each update becomes far more important in order to manage your server bandwidth utilization without resorting to throttled update deployment.
-
Network Environment
The network speed between the update server and deployed clients can dictate your decisions, especially when slow links are known to exist. When your application lives within slow networks, smaller updates are more desirable.
-
Background Download to Reduce the Burden
Downloading updates in the background and informing the user when an update is ready to apply removes much of the burden the user experiences with larger updates. It doesn’t remove the burden from the network though.
-
Infrequent Exceptions to the Norm
Targeting multiple versions, and making exceptions when you need to update infrequently modified files, such as third-party tools and help documentation keeps the initial update implementation effort low, ongoing update creation simple, and minimizes the burden that updating places on the end-user.
A commonly pursued solution to this updating dilemma
is not to consider application updating as an in incremental progression, but rather a “synchronization” process. A process where deployed workstation application files are kept in-sync with a master version located on a server. This approach works well if the updating process only updates files. It doesn’t work so well when application maintenance also requires performing other updating activities, such as registry and data store maintenance. Security and licensing concerns also make the “sync” approach more challenging and less desirable than version migration approaches.
Our updating solution, AppLife Update, is an incremental updating solution. Each update is self-contained, and includes all of the updating logic and new files/assemblies needed to migrate a deployed application from a previous version to a new version. When an update is created, you get to choose which previous versions can successfully apply the new update. You can target all previous versions, a list of discrete versions, or all greater than a previous version. How you’ve defined the update obviously determines which previous versions you can target. When defining an update, you have a lot of latitude in your decisions. You can package and deploy Windows Installer databases, you can replace whole files, you can individually patch existing files, you can use update actions that automate the determination of which files need to be updated. With an update system like AppLife Update, there is little difference in the effort needed to create updates that target all previous versions, or just the most recent version, however the bandwidth and user experience factors still need to be considered.
The flexibility is there to create the application updating strategy that best fits your application and your organization. If the size of the update package necessary to replace all of the assemblies built in a standard upgrade of your application is acceptable, your update process will be far simpler to create and maintain if you target all previous versions with each update. If the factors involved with your application dictate smaller updates, you can easily extend your updating process to seamlessly discover and download multiple updates, as well as display to the user a unified updating experience.