I read a heart-warming article on Time.com about a Southwest Airlines pilot. He delayed a plane full of passengers by waiting at the gate for a late arriving passenger.
Planes that depart late reflect poorly on the airline’s reputation and how customers evaluate them. There were 100+ passengers sitting in the plane and he’s not in the cockpit. His flight crew, and everyone else who is dependent on him, are forced to answer a lot of tough questions from those inquiring passengers.
Why would he do this?
Why does he still have a job?
He’s done everything that I’m sure all of the company policies and operational manuals tell him not to do. Not only does this fine pilot have a job, his company fully stands behind him and endorses his decision.
The passenger he was waiting for was just a regular guy, a grandfather. He wasn’t a celebrity, personal friend of the pilot, or some high-ranking executive with Southwest Airlines. Just a guy. A man who received some of the most difficult news any person could ever have to deal with. He was flying to Denver because they were pulling his 3 year-old grandson off life support. There was nothing the doctors could do to save him from the brutal act of inhumanity committed by his daughter’s boyfriend.
The grandfather received the news from his wife while he was on a business trip in Los Angeles. She offered to call and make his travel arrangements for him as he was emotionally devastated. She called Southwest Airlines and the lady who helped her book the flight could do very little to hold back her tears throughout the call.
Arriving at the airport two hours before his flight was scheduled to depart, long security lines reduced the probability of him making his flight. No one in the security lines gave a damn while the grandfather pleaded his case about missing his flight. I have to be honest, I would have thought it was a scam and told him that I was sympathetic … but no. I’ve been scammed one to many times to “fall” for that line.
It’s so easy to get caught up in life and become part of the machine. No one would have faulted the pilot for doing his job by departing on time while the grandfather was stuck in the TSA lines.
But Southwest Airlines is a different kind of company. Those who have flown on Southwest know they are a different kind of airline. They aren’t the stuffy type of airline that we’re all accustomed to. If you haven’t seen this video, you should watch it. While this is a clearly a highlight, it’s pretty typical from Southwest and represents just how different they are from other airlines.
From a corporate perspective, there’s a huge distance between the lady who took the phone call from the grandfather’s wife and the pilot who actually flies the airplane. I doubt they know each other even though they work for the same company. But this is where we start to see what kind of company Southwest really is. We get to see it’s true colors. On the Southwest website they say:
Fly Southwest Airlines because you want to be treated like a person
Most companies say crap like this in their mission statement or some marketing bullshit posted on their website. Nobody in their employ believes in it and they probably mock it. Very few companies actually walk-the-walk.
Southwest Airlines is one of those few companies that walks-the-walk.
After the Southwest booking agent got off the phone, she called the LA gate agent and informed her of the situation. The gate agent told the pilot. The pilot made the decision to go against everything his company pays him to do because … it was the right thing to do. He wasn’t concerned with business metrics or his upcoming employee review. He was a compassionate man with his heart on his sleeve, not a cog in the wheel of a business machine.
When the grandfather arrived at the gate, the pilot was waiting for him.
“Are you Mark? We held the plane for you and we’re so sorry about the loss of your grandson. They can’t go anywhere without me and I wasn’t going anywhere without you. Now relax. We’ll get you there. And again, I’m so sorry.”
This story could move a robot to tears.
Let’s think about the corporate culture that must exist within Southwest Airlines. They clearly hire compassionate people, but the company also gives them the freedom to make the right decisions. Even if they are against what the rules say. They trust their employees to do what their mission statement says; Fly with us because you want to be treated like a person.
This philosophy applies to everyone at Southwest Airlines. From the lady who booked the flight and stopped taking calls while she contacted the gate agent in LA, to the pilot who refused to board his plane while he waited for a passenger going through a tragic time in his life.
Read the comments on this website. Most of them say things like, “If you didn’t mention the airline, I would have totally guessed that it was Southwest.”
Would people say this about your company? Would you?
Alex Payne has written a wonderful article about why cross-platform development environments ultimately fail to deliver what customers really want; a great experience. Alex says:
This post is about platforms and doing the right thing by your customers. It’s about the one big thing that I think HipChat and some other great companies are doing wrong.
He nails the reason that cross-platform development tools and environments like Adobe’s Flash and AIR products are attractive from a business perspective but end up failing from the customers perspective. Ultimately, that circle of life will come back to haunt the business.
Many businesses are attracted to the idea of writing software once and deploying it across multiple platforms. From their perspective they have one development team, one code base, and one release cycle. What’s not to love?
That’s where most businesses stop their investigation. They fail to even think about what their customers want. They’ll quickly jump up and say, “What they want is our product on their platform. We’re giving them that!”
Yeah, but you’re giving them a turd and that’s insulting. I hear the next bit of verbal diarrhea spilling out of their mouth … and this part kills me.
“Well, at least they’ll have our product on their platform.”
Ouch. I think I just threw up a little while typing that.
What you’re communicating with a poorly-done AIR app is that your business priorities – namely, saving time and money – are more important than what your customers want.
Ironically paradoxical in nature because without customers there is no business.
Alex points out a few very well known products such as TweetDeck, Pandora, and Remember the Milk, where their users are begging for a native application. Sadly, the folks screaming for a native application for Remember The Milk have been flat out ignored by that company since 2007. Actually, that’s not ignoring them. That’s giving them the finger.
My team experienced a number of the usual problems one has with AIR applications: lousy performance, odd interface bugs, key combinations and UI elements that didn’t conform to our operating system. AIR apps exist in an uncanny valley between a web application and a desktop application, and the result is unsettling and annoying. Pretty soon, we were itching to go back to Campfire (via the native Mac client Propane), even though HipChat has better features and the promise of improved reliability.
Why are these cross-platform products so bad? Do users even know if a product is using a cross-platform development environment? Yup, they sure do. Users, even if they’re not geeks or developers like me, can smell a cross-development turd. I love how Alex wrote this:
Humans are gifted with extremely sensitive bullshit detectors. The average computer user may not internalize the difference between an AIR app and a native app, but he knows when something doesn’t feel right or work correctly. Your tech-stunted uncle may not ever request a native application with that terminology, but he’ll sure complain about his computer acting funny when he experiences the oddities of an AIR app.
Just read the comments at this site and you’ll quickly see the common threads:
Sucks up CPU cycles better than a Dyson
Doesn’t conform/take advantage of native UI
Lack of support for native OS features. Instead, uses the least common denominator solution that works across all-platforms
With comments like that, do you really think “investing” in that type of development environment is going to save you money/time in the long-run? Does this seem like the path to huge business profits and long-term customer loyalty?
Is it more expensive to create native applications across all of the different platforms? Yes and no. Yes, because it is an investment in the development of your product. No, because unless you’ve misjudged the market, this investment will more than pay for itself.
“We don’t have time” is the common excuse for delivering an AIR app instead of a good native app. Money, though, can buy someone else’s time. For a price, you can find a great contractor to build a native app for any platform under the sun. It’s an investment. Eventually, unless you’ve misjudged your market, the investment should pay off.
What should a company do when they don’t have the time, resources, or expertise to deliver a native application? You start by clicking on the link above.
Accessibility is one of those areas that most software engineers and product teams seem to have little or no knowledge of. When it is brought to the attention of the decision makers, I’ve heard all too often, “We’ll do that if we have time at the end of the project” or, “What is that? Why do I care about it?” What’s worse, is that in the eyes of many companies and project leads, they can easily rationalize to themselves why accessibility shouldn’t be included in the development cycle:
“Why would a blind person own a touch screen device?”
“I think you’re solving a problem that doesn’t exist.”
“That’s not our target demographic.”
“I can’t see how this would improve our App Store ratings.”
“QA doesn’t know how to test it.”
It’s really sad. Especially when Apple has made it so incredibly simple for us to implement. They’ve done all they heavy lifting for us and simply said, “Carry the baton across the finish line. Please.” And most of us drop the baton.
Honestly, it takes minutes to make your application accessible to a population that all too often gets the shaft. I am a fan of Matt Gemmell. Everything from his tweets to his blog. Even if you’re not a fan, I implore you to read just one article. It’ll make you a better software engineer, and you’ll make your software usable to an audience that seems to lack a voice.
Must-read for developers. Both a good high-level overview of what accessibility really means and who it helps, and a technical overview of how iOS developers can take advantage of it. iOS is simply leaps and bounds ahead of the competition in accessibility.
Everyone has their own vision of how things should work. As you gain more experience in your craft, you become more grizzled. Well learned. After some time, you earn the privledge of passing this experinece on. Oscar Wilde said it best:
Experience is simply the name we give our mistakes.
Multi-threading in software engineering has been around for a long time. Many mistakes have been made, thankfully. From those mistakes, experience was born. Most of the engineering books talk about the essentials, and the dangers that must be respected and adhered to. But while they talk about the pitfalls of what could happen, none of them really give you great guidelines. I’ve been doing this a long time and I’ve worked with people who should not have made some of the mistakes I’ve witnessed.
Are they bad engineers?
Was there a fundamental misunderstanding about multi-threading?
But there are some fantastic guidelines that aren’t well-established. It seems like Brent Simmons and I agree on a lot of the same principles. He’s written a great blog post about Cocoa Threading that every Cocoa developer should read and understand. He refers to his post as his, “barely-organized thoughts on threading and Cocoa applications” but it covers the points in a concise manner.
Thread Communication Exclusively on the Main Thread
First up is his philosophy on all communication between threads taking place on the main thread. He extends this to notifications as well. I’ll add one more to that list which is KVO notifications. This is essential because UIKit and Core Data don’t like operating on secondary threads. I don’t know how many times I’ve seen
NSAssert([NSThread isMainThread], @"This needs to run in the main thread");
go off because I received a notification or call from a secondary thread.
Communication between systems always happens on the main thread. (A system is one or more objects that work together.) In most cases, communication between objects in the same system happens on the main thread too.
If an object does something in the background, that is that object’s business and nobody else’s.
This extends to notifications: from background threads, I always make sure notifications get posted on the main thread. This way every notification observer can always assume that it’s getting called on the main thread.
Regarding KVO, Brent has this to say:
KVO is a trickier thing. Here’s how I handle that: anything happening in a background thread is not observable (by convention). Whatever is going on is private. When it’s time to set public stuff, stuff that could be observed, those things are set on the main thread.
There’s almost as many different ways to spin off a thread as there are people in the United States. Brent and I also agree on which methods we use:
I’m very deliberate about my threading. I like Grand Central Dispatch, but for my purposes NSOperationQueue works best. The formal, easily-monitored approach of NSOperationQueue works best here. I definitely recommend against anything but GCD and NSOperationQueue — anything else (NSThread’s detach method, etc.) is too random. (Yes, we used it for years, but we have better stuff now.) (In fact, I almost never even use NSInvocationOperation — I much prefer the structure and defined stop/start of NSOperation.)
I use an NSOperation subclass that takes a target and selector in its init method. When it’s finished, it calls the target and selector on the main thread. This way the caller only ever sees the main thread — it creates the operation on the main thread, then gets called back on the main thread. The fact that the operation happens in the background is unknown to the caller: the caller just knows that it’s async, and doesn’t know anything else.
I almost exclusively use NSOperation subclasses with NSOperationQueue in my applications for the same reasons that Brent outlines. You can create multiple NSOperationQueue’s if you need different operating parameters (for example, one queue that is sequential, another queue that can operate concurrently). Making dependencies between various NSOperation’s is as simple as making an addDependency call. Plus, they can have dependencies across different NSOperationQueue’s.
NSCache seems to have suffered from poor marketing. It’s a little gem that very few people seem to know about. I’ll bet most of you have written your own class that performs much of the same functionality. I’ll take the very-well tested and used NSCache, which is also thread-safe, any day.
Locking sucks. If you have to do it, you have to do it. It doesn’t mean you’ve failed — failure would be not-locking when you really do need a lock.
There are a couple other things you can do which make sense.
Use performSelectorOnMainThread to set some data that would otherwise require locking. (This is not a trick to use willy-nilly, though — typically it comes at the very end of an operation, not sprinkled throughout.)