Vladimir Prus


vladimirprus.com

Tuesday, May 31, 2016

Desktops and Startups

I spent a good part of 2015 working on a desktop app for a startup, not a typical combination these days. If you're building a mobile app, there are multiple companies offering platforms for every task you need, and a of recommendations which platform to choose. On desktop, you have to build or pick everything yourself. In this post, I'll share some advice.

UI framework

What does one use to create cross-platform desktop applications these days? Let’s first look at standard options at each platform.

On Windows, there are two modern technologies:

  • XAML, .NET and C#. Good stack if you like C#. In our case, we have a shell extention too, which per Microsoft guidelines should not be written with managed code, but doing that one part in C++ is not very hard.

  • XAML, Windows Runtime and C++/CX. This is newer technology, apparently coming from the part of Microsoft that prefers C++. The C++/CX language is native, with no CLR runtime involved, and is pretty close to standard C++, and is therefore attractive if you're a mostly C++ engineer. On the downside, you're limited to Windows 8.1 and later. Also, the application will be a Metro-style one—while there we announcements that desktop apps will be possible soon, that did not happen yet. Shell extension or tray icon will likely be a big problem.

On OSX, there’s only one native stack, although you have the choice between Objective C (not a language I want to write core logic in, ever) and Swift (not a language I want to write core logic in, yet).

Two technologies attempt to be fully cross-platform:

  • Qt and C++ (using either Qt Widgets or Qt Quick for UI). Works, in theory, on all Windows versions and OSX versions in existence, with Qt Widgets extemely stable and Qt Quick maturing.

  • Xamarin and C# (using Xamarin.Forms and XAML). Also a nice stack, and compiles to native code, but requires Windows 8.1 or later.

Given the above, what do you do if you definitely want to reuse core logic level? Since we wanted to support Windows version prior to 8.1, this rules out C#, and we actually already had ths level written in C++ with Qt. And while putting XAML UI on Windows and Objective-C UI on OSX on top of C++ core would be possible, that would add fair number of incidental complexity. Therefore, I went with the Qt option, and since the UI was not going to be extremly complicated, decided to give Qt Quick a try.

Of course, this was a tradeoff between development speed and native look. I have originally produced Windows version, and then creating first OSX version took about a day—clearly good at a startup. On top of that, any interface changes were immediately available for both platforms, just a rebuild away. The UI did not look exactly native on OSX, but close enough for most people, and on Windows, there’s already enough of style variety that nobody had any concerns.

On the negative side, it turned that Qt Quick is not as mature as I’ve hoped. I have covered this in detail in the previous post.

Conclusion: Qt with Qt Quick is fine if you have little UI and is already using C++. Xamarin might be a viable option as well

Installer

We wanted the installation and update to be as transparent as possible, with no questions asked. On OSX, using DMG for initial installation is the standard solution, and autoupdate can be handled by a library called Sparkle.

On Windows, Microsoft documents two options. Windows Installer (MSI) is the standard technology, but does not support autoupdate, and any custom solutions has to display prompt dialogs. ClickOnce is a newer technology for .NET applications, supporting installing into per-user location without touching any system directory and transparent updates. Sadly, it does not appear to support native C++ applications, only C++ applications built for CLR. I’ve ended up writing a custom installer from scratch.

The installer downloads an update manifest (in the Sparkle format), then downloads an archive for the most recent version, checks signature, unpacks to a subdirectory of users AppData folder, and run the binary from there. Auto-update works much the same—detect that update manifest has changed, and start the installer again. When the new version of the application starts, it uses IPC to ask any previous version to shut down.

This approach works suprisingly well—most installation attempts succeed, and most auto-update attempts do indeed update. It is interesting to note how diverse environments are over the world. For example, downloading 20 megabytes is almost instance for me, but it takes minutes, and sometimes several tries, for users in other locations. Adopting binary deltas, like Chrome does, sounds a good idea.

Conclusion: on Windows, custom installer is a viable option for a native binary that does not modify system, and on OSX, Sparkle works out of the box.

Signing

I first run into Windows binary signing at Mentor, when we were building our P2 installer, and at one point, the IT-mandated anti-virus software started deleting our own binaries. It would only stop when we got a code signing certificate. This time, couple years later, we had as much as three obstacles. First, Chrome would flag our installer as risky on download. Second, Windows SafeFilter would refuse to run it. Finallay, finally the antivirus software would randomly wake up and break things. Naturally, we had to get code signing certificate too.

The code signing certificate involves organization validation. Not much of a problem for a large company whose address can be validated by Google maps. But a small startup with no landline, no office number on the door, and no utility bills is deemed suspect by the registars. It took a while for our CEO to build appropriate chain of trust.

I would say the whole system is quite pointless. Surely, organization validation makes it possible to pass an address and a phone number to police, in case good guys become bad overnight. However, it does absolutely nothing to protect against good-willing but incompetent guys — for example who leak signing keys, build on virus-infected machines or do not secure auto-update. And it does nothing to protect against really-bad guys, who surely can fake addresses and phone numbers.

Conclusion: if you plan to publish windows applications, get a code signing certificate as soon as possible.

Crash Reporting

Crash reporting is part of Winwdows for a while, but by default, only Microsoft gets to look at crashes. One can apply for a developer account with permission to look at your own crashes, but the instructions start with ‘get extended validation certificate from one of these 3 CA’. Extended validation is even more messy than organization validation, and Microsoft could well not approve us anyway, so I looked at other options.

Chrome includes a library called Breakpad and while they have no server-side, Mozilla fills the void with Socorro. The setup could be easiert—in particular there are no official Ubuntu packages, one should use specific deployment system, and it requires ELK stack. However, after a few hours I could get the first test crash reported, and was going to start using it for real when I came across DrDump.

That service provides a library to handle crashes, including UI, cloud backend to store crashes, and a web app to review the crashes. On a crash, minidump is sent automatically and user is prompted to submit a full dump, unless one was previously collected for the same stacktrace. Overall it took about an hour to integrate and play with, and it worked quite satisfactory since then. It was surprising, when asked about pricing, to hear that the service is free—reportedly because with matching crash stacktraces, the disk storage required for full dumps is quite low. I doubt it would be still free for an app with million users each hitting unique bugs, but it remains free for us.

Conclusion: DrDump is a fine solution for an early stage startup. Breakpad and Soccorro will be also fine when you have time for devops.

Analytics

The mechanics of collecting analytics is easy. We use Mixpanel for mobile analytics and wanted to use for desktop apps as well. On mobile, there’s SDK that sends events, collects system properties and manages event queue. There’s no such option for desktop, but there is a REST API, which is sufficient. Adding basic system details like OS version is easy, and we did not bother implementing event queue. Surely some events do get lost, but it is not a big practical problem.

With the data in, Mixpanel makes it very easy to show a chart of event counts, filtered and segmented as you wish. Whether it is useful is not clear.

  • No chart comes with any statistical analysis. Want to check whether Windows 7 users really have lower conversion rate, and you need to do the math using other tools.

  • Box plot, the standard way to look at a relation between a continuous and a categorical variable, is nowhere to be seen.

  • You can only look at 90 days of data.

In essence, given that drawing basic charts is frictionless while statistical analysis demands external tools, Mixpanel lures you into making simplistic analysis. In the end, I have just exported everything and looked at data in R.

Conclusion: you likely don’t need any analytics services. It’s easy to send data into a database, aggregate it, and analyze using a decent statistical package.

Summing it up

While there's no compherehensive platform that helps to quickly launch a desktop application, there are enough pieces of technology that can be put together. The most important I've learned are:

  • Pick a cross-platform UI framework; you probably don’t have time to write separate code for different operating systems. I found Qt to work OK, but you might want to also consider Xamarin.

  • Get code signing certificate early

  • Do your own analytics. Decide what will be most important when you launch, figure what statistical tools you’d need, and create events to support that.

No comments: