My Point of View
I’ve been working in the mobile space since 2000 at least, and so much of my mindset is definitely on how to design and build mobile apps. With Desktop Informant we’ve stepped into the more powerful and less-restrictive space of desktop applications. Much of the time our mobile mindset works really well for design, but sometimes I’m wrong. One of those times was in the necessity for Informant to have a helper or not. So what is a helper?
A helper is an application runs all the time in the background doing things for the main app even if the main app is not running. For example, for the forthcoming Desktop Informant the helper handles Quick Entry, the menubar Focus View, and sync. So why wouldn’t we think we needed one?
So as everyone knows on mobile when you leave the app, iOS or Android will kind of freeze the app so its not using up battery. This is a good thing because it allows for resource management. However it also means the app can’t handle sync or other things without the OS waking up the app periodically. Since iOS 7 we have the ability to have “background-refresh” that allows that – so all good!
On Mac OS X apps don’t quit when you leave them and in general I leave most of my apps just open and running. If the OS X needs more RAM or what not, it usually takes parts of the app’s memory and “pages” it to disk or what not – but in general you can keep apps running and so an app like Informant can be kept open (the window can even be closed or hidden and it still runs), so sync, quick entry can all still run. In my mind this was good and worked and there was no reason to work on doing nothing more than breaking the app into pieces. My bad… it seems that everyone wants this. I can sort of understand it, but I misunderstood the priority for many. As happens relatively often in my life – both professional and personal – I learn that perhaps I need to adjust my POV just a bit and decided to design a new app architecture for the future.
A couple months ago I began the work to break Informant up into two pieces with most of the work being done in August and debugging continuing into September. This job was a lot more difficult than expected because we’re dealing with two separate processes touching the same database, and needing to keep each one abreast of the changes. What if the two apps talk to the same record at the same time? We can’t bring up a GUI dialog to the customer asking them what to do. We have to keep settings synchronized, database synchronized, and the two need to be coupled as closely as possible – while understanding that because of their separation some of our built-in assumptions on how data lived in the app no longer applied. Some of these assumptions lived in the code so deeply that its taken weeks to shake them out; and none of these were bad assumptions when we first wrote it and in fact kept things simple, maintainable, and reliable. We had to rework some of those into a new multi-process architecture that was still relatively simple, maintainable and reliable.
The process has taking longer than expected. We’d run our internal betas for a few days to iron wrinkles out, and then debug for a couple more days, and then back to running another internal release beta. Furthermore, we spent 2 weeks wrangling with an issue that turned out to be an OS X development bug, so we wasted a bit of time on that too. So what have we ended up with? This part gets a bit technical, but some might find it interesting.
Currently the helper runs as a faceless background application that uses XPC services to talk back and forth between the main app. Internally we keep our preferences and databases processing real-time changes between each other so that each is kept up – at least within one run-loop cycle – of each change. The helper takes care of the following services:
- Synchronization with our services. This means that sync can run even when Informant is not running at any time.
- Alarms. OS X already handles the timing of some of this for us so that Informant didn’t have to be running for an alarm to fire, but now we can do a bit more. For example Informant doesn’t have to come to the forefront if you complete a task from a notification – since the Informant Helper actually is the one dealing with the alarm
- Reminders. Informant reads Mac Calendar events straight from the source in real-time, but Reminders we integrate into our database of tasks so that we can properly sort, group, and deal with them better. However Reminders access is slow and worse can sometimes pause the app for a second or two when refreshing just due to the OS X API. Since the helper now handles reading in the Reminders, the main app is no longer ever affected.
- Quick Entry. The helper now registers itself as the quick entry keyboard shortcut implementation. This means that Quick Entry can now work even if Desktop Informant is not running – and it can run on any Full Screen app. OS X does not allow apps (like Informant) to bring up a window on another Full Screen app because only that one app can exist in a full screen mode (except in El Capitan where two can). However, an app that is considered “faceless” like the Helper can bring up a window.
- Menu Bar Focus View. Like the Quick Entry, the helper now runs the menu bar focus view. That means it too can show up in Full Screen app windows, and it is running at all times.
We’re ready to be sandboxed as well for the Mac App Store, but we’re not doing that yet – that’s just one too many big changes in one release.
On a side note, one might think that the Helper should be a much smaller app – but its not because it has to contain all the editors, and much of our UI building blocks to support the Focus View menu bar.
So what else have we been working on? Lots. Chris has spent the last 6 weeks fixing bugs, improving nearly all aspects of the app. We’ve been hitting our list of “tasks” for R6 and just made a lot of headway. One of the most exciting things for me is the new Week View that matches our Pocket Informant 5 style. I’ve rewritten our welcome screens, reworked our versioning, rewritten parts of the app into Swift, added considerable support for El Capitan, and in general been focusing on making R6 a really powerful solid release.