My Experience Working For The Royal Canadian Air Force As An iOS Developer

Alex Barbulescu
9 min readMay 11, 2019

--

First off, yes, I was an iOS developer for the Royal Canadian Air Force (you know, the military one with planes). It was my second co-op term and I will now be finishing off my second year of undergrad in Computer Engineering at the University of Waterloo.

From L to R: Vikki, Me, Justin Trudeau, Eddie, Kieran

The Royal Canadian Air Force Aerospace Warfare Centre Innovation Lab: Flight Deck

That’s quite a handful, essentially we’re known as the “Flight Deck” inside of Communitech, Canada’s largest innovation centre:

Making large corporations think like startups

We’re in a collaborative work environment with many different companies ranging from 2 person startups to other large corporations (if you consider a military branch to be a corporation). There’s endless coffee, meeting rooms, work booths, phone booths, and even a nap room 😴! This is honestly an amazing work environment, you (usually) don’t leave work feeling drained of life. It’s no wonder more and more companies are pushing this mindset and work environment.

I had the amazing opportunity to take the lead on our main project, an iOS application.

Our Project: FinTrax

The first ever iOS application used operationally worldwide supporting all air mobility squadrons within the RCAF

We had one goal: To help our Pilots and air crew on missions

From delivering supplies to the high Arctic to airlifting troops, equipment, and humanitarian loads worldwide, 8 Wing/Canadian Forces Base Trenton, Ontario, is the hub of air mobility operations in Canada.

Our app handles all mission related data and expense tracking from aircraft services to personal expenses and per diems. When our service members embark on missions they average around 5–6 stops with 6–7 air crew anywhere from a few days to weeks. Each aspect of the mission needs to be tracked at every location. And for reference, around 10 air mobility missions happen each week.

Before an aircraft takes off, there’s a magnitude of expenses that can occur. Anything from catering, fuelling, deicing and general services.

After an aircraft lands there are even more service options that will occur. These general services include everything from using a ramp to load off cargo, stairs to get off the plane, conveyor to load off cargo and lavatory emptying. (Yup, airports charge for everything).

Each one of these things need to be tracked and paid for at the time using a credit card or invoiced to the government of Canada at a later date.

Between flights, crew need to get transport to and from hotels, eat, and sleep. All of these need to be tracked down to the individual, the relevant location with the relevant reciept.

But it doesn’t stop there. The Pilots need to track their flying hours, during the day and night, the simulated time from the computer on the plane, and the actual time. Why are those last two important? Good question, I never asked so I don’t know 😜.

At every location, departure and arrival messages needed to be sent out with relevant data, to different parties of interest. If you think that’s annoying before and after a 10 hour flight, the mass of paperwork that all this data collection entailed was even worse.

What we solved

Data Entry

All this information was being tracked on a multitude of different forms. Some forms needed to go off to the chain of command and others needed to go out to finance. Across the forms there were a ridiculous number of repeated fields. We reduced the number of average fields one crew member had to fill out from a whopping 350 to just under 50. This isn’t just some wild statistic we whipped up as clickbait, this was actually counted. Instead of having multiple forms for the aircraft and for each crew memeber, all we have is one smart data model which is filled out throughout a mission’s lifetime and then spit out into all the relevant documents needed. Yay for relational databases!

source: giphy.gif

We take care of the heavy lifting, our users only need to provide the bare minimum needed for us to confidently extrapolate the rest of the information.

Errors

Long flight hours and strenuous missions around the world comes with a lot of data entry mistakes. Anything from forgotten expenses to unreadable penmanship, when is the last time you tried to fill out forms in the back of one of these mid-air?

CC-177 Globemaster. Don’t worry it’s not a glitch in the matrix, it’s just my crappy panorama timing.

These entry errors easily become compounded throughout leading to a lot of issues after the mission. If something is wrong on the forms, finance needs to chase down the perpetrators for correction, wasting both parties time.

Software Architecture

Some more nerdy stuff, I’ll try to keep it as brief as possible 😉.

Since this was a data entry heavy application, our Core Data model was the backbone for our UI layer. Take a look at the image below. Each section/card corresponds to an NSManagedObject 😄.

Being data entry and model heavy, our validation layer needed to be as flexible and concise as possible.

Low-level Validation Layer

The most basic validation needs to occur upon a user finishing entering data into a field. The data needs to be validated against the model and the user needs to be given UI feedback if something was wrong.

This begins with the model. Each field type needs to match up with the entity field in the model object it is populating.

Since this was a data entry heavy application with a lot of validation needed, the app uses my MaterialFields CocoaPod.

Material Fields is a Material Guidelines UI driven text entry and value selection framework for better UI and modular validation layers. It comprises of EntryFields (your UITextField), AreaFields (your UITextView), PickerFields (your UIPickerView) and DateFields (your UIDatePicker). All of them subclass a Field wrapper class allowing for modular validation and equal state functionality.

The MaterialFields framework allowed us to minimize our validation layer to only a handful of functions written as extensions of NSManagedObject.

We solved giving UI feedback and committing changes to our model’s context with as little lines of code as possible.

MaterialFields, Core Data and Case Iterable Enums

This combination is the powerhouse of our low-level validation layer. We can use CaseIterable enums describing the NSManagedObject’s key (String) as their hashValues and use their raw value (Int) as tags. By writing validation extensions on NSManagedObjects and passing in our fields we can create a simple to understand, modular, validation layer.

Since all the fields conform to the Field wrapper class, validation layers tied directly to the Fields has never been easier!

Lets define 3 fields, an EntryField, an AreaField, and a PickerField

let entryField = EntryField()
let areaField = AreaField()
let pickerField = PickerField()

Lets also define a CaseIterable enum:

extension CaseIterable where AllCases.Element: Equatable {
static func make(index: Int) -> Self? { //get key from index
let a = Self.allCases
if (index > a.count - 1) { return nil } //out of range
return a[a.index(a.startIndex, offsetBy: index)]
}

func index() -> Int { //get the index from the case
let a = Self.allCases
return a.distance(from: a.startIndex, to: a.firstIndex(of: self)!)
}
}
enum FieldKeys : String, CaseIterable {
case entry
case area
case picker
}

With our CaseIterable enum we can use the validation keys as tags for the fields!

entryField.tag = FieldKeys.entry.index()
areaField.tag = FieldKeys.area.index()
pickerField.tag = FieldKeys.picker.index()

Lets say we need to validate a generic string (relying on the validation rules set in the model) before committing changes to our model’s context. We simply write the validation function as an extension on NSManagedObject.

extension NSManagedObject {
func validateString(for view: Field,with key: String?){
var value = view.text as AnyObject?
do {
try self.validateValue(&(value), forKey: key)
} catch {
view.setError(errorText: “please try again”)
print(error)
return
}
self.setValue(value, forKey: key)
}
}

Similarly we can validate costs.

extension NSManagedObject {
func validateDecimal(view: Field, key: String){
var text = view.text
if(text == “” || text == nil){
text = “0”
}
let decimal = NSDecimalNumber(string: view.text)
if decimal.isEqual(to: NSDecimalNumber.notANumber){
view.setError(withText: “please enter a valid cost”)
return
}
do {
var value = decimal as AnyObject?
try self.validateValue(&(value), forKey: key)
} catch {
view.setError(withText: “please enter a valid cost”)
print(error)
return
}
self.setValue(decimal, forKey: key)
}
}

Now on any of the fields’ didEndEditing delegate methods we only need to 2 lines to validate our entry.

//EntryFieldDelegates
func entryFieldDidEndEditing(_ view: EntryField){
//the key reconstructed from our enum used for the field tags
gaurd let key = FieldKeys.make(index: view.tag) else {return}
ourNSManagedObject.validateString(for: view,with: key)
}
//AreaFieldDelegates
func areaFieldDidEndEditing(_ view: AreaField){
//the key reconstructed from our enum used for the field tags
gaurd let key = FieldKeys.make(index: view.tag) else {return}
ourNSManagedObject.validateString(for: view,with: key)
}
//PickerFieldDelegates
func pickerFieldDidEndEditing(_ view: PickerField){
//the key reconstructed from our enum used for the field tags
gaurd let key = FieldKeys.make(index: view.tag) else {return}
ourNSManagedObject.validateString(for: view,with: key)
}

We now have a validation layer capable of both data model validation and UI feedback!

High-level Validation Layer

Before the context is committed to the SQL database, higher level checks need to occur. All the little pieces need to fit together in a way that makes sense. What happens if someone payed for an expense with their credit card but forget to enter the cost or currency?

Unfortunately higher level validation is different for every little thing and situation and requires a lot of manual labour to gaurd against. It is impossible to make it generic enough to make the claim that it is “modular” and “scalable”.

Part of our high level validation layer includes pre-emptively blocking users from making the errors in the first place. Date-Time safetying was the biggest headache of all the validation. Forcing chronologically sound data was imperative to keeping the app functioning properly. You don’t want to be able to depart before arriving somewhere. What happens if you cross datelines? What if somebody changes around the dates after data was already filled out? All the core data objects had some form of date dependency leading to a lot of manual rule placement.

Working For Military

Privacy

source: giphy.gif

Just kidding 😄, our project is completely open to the public, no secrets here!

Obstacles

Part of having an “Innovation Branch” for any corporation (including military) is to remove unnecessary bureaucracy. There was still a lot of bureaucracy dealing with security. The only two pain points was lack of authorization to use cloud services and lack of wifi on base.

The former is understandable as you’re essentially putting the data in the hands of a 3rd party, regardless if all the information put inside the app is publicly accessible (if you request it).

The latter presented a problem with getting the data off the devices on the part of the base where the iPads reside. No wifi means no AirDrop or emails. They either had to take the data off the iPad beforehand or take it off manually by connecting it to a computer inside.

Some of my colleagues, including Air Force members, saw these rules as archaic and unnecessary. I may be a little more conservative in my thoughts as I completely understood precautions taken around those restrictions.

This leads to an interesting thought, what if we built a military from ground up with all the latest cutting edge features and systems? Now that would be an insanely optimized military, unfortunately that’s not really possible with an already standing system that has security restrictions in place.

Conclusion

Overall working for the Royal Canadian Air Force and doing what I love (iOS development) was an amazing experience. A lot of government jobs are touted as being boring and uninteresting amongst my classmates. Fortunately this was not my experience. I look forward to what awaits me in the future!

--

--