2

Structure:

Server - Desktop Application

I would like to have an auto update mechanism on the desktop application. This can be achieved with stuff like Squirel.Windows, and is outside the scope of this question. Just a side note the DesktopApp has multiple variants for different OS (Mac and Windows).

The problem is, that the server is not always the latest version. For instance:

Server.v1 - DesktopApp.v1
Server.v2 - DesktopApp.v1

Server.v1 and Server.v2 has different behavior and breaking changes. How do I structure the auto update on DesktopApp in a managable way?

Server version can also suddenly go to a different version, for instance from Server.v2 to Server.v1. It is outside our control.

NOTE: The server does not comply with semver, so minor version numbers can have breaking changes

Suggestion 1)

Make DesktopApp backwards compatible like this

if(serverVersion == Server.v1) {
    MetodOfLogicThatWorksOnV1();
}; 
if(serverVersion >= Server.v2) {
    MetodOfLogicThatWorksOnV2();
};

Now I can freely update DesktopApp.v1 as much as I want and it will be completely backwards compatible. Users of the Desktop application all use the latest version.

Worries: Could cause very complex logic after a while, making it prone to error

Suggestion 2)

Make DesktopApp update mechanic know when it should downgrade

if(serverVersion == Server.v1) {
    DesktopApp.SelfUpdater.Update(v1);
};
if(serverVersion >= Server.v2) {
    DesktopApp.SelfUpdater.Update(latest);
};

Now users will get different DesktopApp version depending on what version of the server they are connected to.

Worries: Users will have to update/downgrade depending on version. Will become complex to maintain this update logic. A bug fix will now have to be made on both DesktopApp.v1 and DesktopApp.v2

Suggestion 3)

Create 1 DesktopApp per Server version

if(serverVersion != clientVersion) {
    DesktopApp.SelfUpdater.Update(serverVersion);
};

This means I know that the version of the Server will always be designed for the exact version of the DesktopApp I use

Worries: Extremely many version of DesktopApp need to be made, and bug fixes need to be deployed to many versions.

Question:

How can I structure auto updating a desktop application when you have multiple server versions, with breaking changes between each server version?

Community
  • 1
  • 1
M Andersen
  • 23
  • 3

2 Answers2

1

If your organization controls both the server and desktop application, the best answer is to be disciplined around the server development. You should make it clear that frequent incompatible changes to the server protocol are adding work for the application team. One tool I've (lightly) used that can help here is Pact, which will let you "record" a client's requests and expected responses, and then run those as test cases against a server, without needing a complete end-to-end test setup.

If you control the server, another better option is to have the server support older protocol versions. I don't use the API directly much, but its API reference lists all past versions and has a list of changes, and older and newer clients and servers can interoperate. Docker also implements your "option 1", where the client code can downgrade to an older protocol version if needed.

Otherwise, from the point of view of a user, your option 1 is the only good one. An application that routinely wants to break your workflow and reinstall itself (option 2) gets annoying quickly, but it's worse if the application just randomly stops working when the server upgrades (option 3). There are also common deployment patterns like "canary builds" that can result in both older and newer servers running at the same time, and to support these the client application needs to be able to work with both.

David Maze
  • 130,717
  • 29
  • 175
  • 215
1

Instead of the switch you could have an interface that define your operations, and a "traditional" factory method to instantiate the correct implementation:

IMyOperations GetMyOperationsFactory(){
  var version = Server.GetVersion()
  if (version == 1) return new MyOperationsV1();
  if (version == 2) return new MyOperationsV2();
  throw new InvalidOperationException("Server version " + version + " not supported");
}

Then you at least isolate version-specific behavior. Add traditional object-orientation (inheritance and whatnot) if beneficial.

Steinar Herland
  • 1,134
  • 1
  • 9
  • 15