Fortune said you should do free work to get hired. I for one disagree that advice – unless you don’t have anything other to do. There are three major reason for this.
- If the opportunity didn’t convert, then you just wasted time and effort that could be spent better elsewhere.
- You’ve just devalued yourself and your fellow professionals – If they can get work done for free, why pay?
- Those who ask you to do free work don’t value your time. Do you really want to work for these kind of companies?
Not too long ago I was on the receiving end of this. Yes, I was externalized and did free work as part of a hiring process. I had a strong hunch that I shouldn’t do this – but my logic was dazzled by the halo of its brand. The job seemed good and the company was profitable and reputable. I was proven wrong.
However in retrospect I now have two open-source demo projects that you can use. One is a movie catalog and the other is a clone of Apple wallet. By looking at these project’s sources, you can learn a thing or two about:
- Movie Database API. Where to get reviews of movies, synopsis, thumbnails, even trailers as an Internet-accessible API.
- How to correctly load images for retina displays.
- Applying physics for real-world user interfaces.
- Some clever caching tricks without needing to go Core Data.
I’ve released two demo projects with sources – Cheesy Movies and Card Tray Demo. Both were initially done within a very short time (in hackathon-like time frames) as part of a hiring process. Both were originally targeted for iOS 9 / Swift 2 but I’ve migrated them to Swift 3 recently. If you’re looking for some of my codes (as one HR person puts it), you’ve come to the right place as I don’t typically release the sources of most software that I wrote — either they were done for another company or I make money by selling them to end users.
Got bored by blockbuster movies? Have a look at Cheesy Movies. This movie app highlights less-popular movies – lookup unpopular movies by genre or release year, see who are the actors and actresses, and play the trailer for most of them. You can also share links to their web sites – or at least their IMDB page – to your friends to add to their Netflix queue.
Why Cheesy Movies? Well, the name is more or less derived from the assignment description:
Everyone loves movies, and sometimes we even love BAD movies, “Snakes on a Plane” anyone? So, using the openly available APIs (OMDB, Rotten Tomatoes, etc), create an app that:
- Allows the user to search by genre (action, romantic, etc) and year released
- Based on the search criteria will return a sortable list of the 10 WORST movies: sortable by rating.
- The user can then select a movie and the app will reveal more info about this cinematic travesty: plot, actors, etc
So “here you go boss” – an app to browse bad movies. It also shows the trailer if one is present in the database. As a plus you can also use the app to share the movie’s URL (either home page or IMDB page) to friends and colleagues.
As part of the assignment, I browsed a number of movie databases available on the Internet – including the suggested OMDB and Rotten Tomatoes – and settled on The Movie Database (TMDb).
Rotten Tomatoes required me to “submit a proposal” and wait for some time to get an API key. This was unacceptable since I had a hard deadline of 48 hours to build the app. Moreover rumors say that they only give access to US-based developers.
The Internet Video Archive seems promising at first. However I poked around at their API manually and some features didn’t seem to work as advertised. One thing that I noted down was their trailer video API. The API returned a URL that doesn’t seem to point to neither a video file nor a web page that shows a video. So I moved on.
OMDB was one of the data providers recommended by the assignment. However it didn’t seem to provide movie trailers (which was a bonus point in the assignment). They also don’t have a search functionality – a feature which seemed important at the beginning of the project, but not really essential after I re-read the assignment description.
Finally I settled on TMDb. It has an open API (just sign up with an e-mail address to get a key). It has trailers, search, and relatively flexible JSON API needed to implement a movie browser.
Since the end results looks pretty much like a real app (i.e. functional), I’ve made it available on the App Store as a free app. Go look it up: Cheesy Movies.
By default, the app shows recently-released movies that are not too popular. You can also filter the list by genre and year of release. By default it looks for movies with a Lowe popularity rating but with a minimum number of votes. The problem with least popular movies is that their entry tend to be very sparse; often doesn’t have any images nor trailers. Fortunately enforcing a minimum number of people who rated the movie took care most of this metadata issue.
Selecting a movie in the list shows the detail for the movie. You can see the thumbnail poster, summary of the movie, and the people involved. If there is an associated trailer, you will see a play button overlaid on top of the splash picture. Tapping that button plays the video in-app (which is usually hosted on YouTube).
At this point I probably should link the video detail to a purchase link in iTunes and get some download commission. But unfortunately I haven’t been able to figure out a way to link between TMDB and iTunes. Besides, in retrospect the download figures are abysmal – even as a free app. Thus even if I take more effort and finally made the link, there probably wont be much purchases from the iTunes store that can give me commissions due to the low download/usage figures in the first place. Showing worst movies was a lame product idea after all.
Two other things that I’m somewhat proud of besides the backend API selection are the image loading and caching mechanisms. There were some smarts applied that to correctly select image dimensions for the variety of devices that iOS 9 runs on – from the non-retina iPad 2, the smallest iPhone 4S, the 3x iPhone 6 Plus, and the gigantic iPad Pro. The short deadline on the project limits the amount of code that I can write – yet I manage to put in a pretty good caching mechanism.
I’ve made the source code for Cheesy Movies available on Github. Go have a look at the code and see how image loading and caching was done. Use it as a reference for your own work.
Card Tray Demo
Curious how the Wallet app user interface works? Need to scan credit cards? Want an inspiration to apply UIKit Dynamics to an app? You should take a look at my Card Tray Demo. This is a rough demo of a hypothetical app that keeps virtual copies of credit cards – including a semi-skeuomorphic screen showing a pile of cards that the user can re-order or just toy around.
One hard lesson I learned doing this project is that standard optical character recognition (OCR) won’t work to scan credit card numbers. Apparently how the numbers are printed gets in the way of recognizing them – none of the embossed numbers and text got recognized. However normal printing of the card (the non-personalized flat enamel print portions) often got recognized correctly as text.
The demo app has a feature to add a credit card by taking a picture of it to save the user from typing those long card numbers. Originally I tried this by running the picture through Tesseract OCR to convert the credit card picture into text. It failed miserably. Originally I thought it was the resolution or image orientation – so I did a number of small experimentations to take the best picture possible (I used an iPhone 6S Plus) in all possible orientations. After browsing around, I discovered that the machine learning models for training Tesseract weren’t equipped to read embossed text. Fortunately PayPal released CardIO, an open source library designed specifically to scan credit cards with the camera. It worked quite well to read the card numbers. However at the time it couldn’t parse the cardholder name nor expiry date of the card.
I’ve made good use of UIKit Dynamics in this Wallet clone. I was able to replicate the card tray interface in iOS’s built-in API. This includes pulling down cards and having it snap back to the top of the stack.
There are three primary physics behavior at play here. Each card is displayed in its own
UIView instance. In this setup, there are always two behaviors configured – a snap-to-center behavior and a sliding behavior. When the user drags a card, a third snap behavior gets added to snap the card to the user’s touch point. When the drag ends, that last snap point is removed and the default snap-to-center behavior takes over to return the card to its preferred location.
It turns out that there was a bug in iOS 9’s physics engine. If I changed the z-order of a view and there are three or more views involved in the scene, it seems like the top-left coordinate of the view being reordered gets re-set to zero for a few milliseconds. This gave the impression of a slight flicker when re-ordering the cards in the tray. I found this out when programming the UIKit Dynamics portion of the card tray. I’ve tried to find various workarounds and still couldn’t get it right after about a day or so. The issue doesn’t seem to resurface in iOS 10 though, so I guess it was a real bug and not my programming error.
Behind the Scenes
Once upon a time I was looking out for jobs working in the Apple stack because the last re-org in my day job just eliminated any work scope doing iOS. Then there was this job vacancy from a large credit card company wanting a senior iOS person for its innovation center. In one version of the job description, it mentioned an upper bound of S$12,775.00 monthly salary. I applied and got called for an interview.
The hiring manager seemed like a nice guy at the time. He was also a new hire of four months and came from a failed startup. It has a fancy new office in a financial center with an auto-rickshaw located just after the reception area.
A few days after the initial interview, an HR representative called. He and told me that the manager wanted me to do a “small project” that has a time limit of 48 hours. At the time, the next weekend was an extended one – the first of May fell on a Sunday and I had three full days to do this. Similarly during that time period, my wife and kid were also away for an extended stay with our parents, leaving the flat empty. So I accepted. They used HackerRank to handle the submission – but it seems like they wrote the assignment myself and used the site just to received source code upload.
The feedback was positive. Both the HR representative and hiring manager told me they were impressed. This was the Cheesy Movies app; original submission was on commit ID 1c9fbed. Within the 48 hours time frame, it probably took me around 40 real-hours of sprint-work – after discounting some minimal time to sleep and eat. Not only I uploaded the sources to HackerRank, I’ve also sent out a TestFlight invite to both the hiring manager and HR representative.
Then it went quiet for a few weeks. Afterwards were a few interviews then a request for yet another sample project. At this point I’m already weary of such demo requests, but since there was no time limit, I did it anyway as a last throw. I talked myself into doing this demo because of the potential salary of the job. It probably took another 40 hours of work – 1.5 weekends plus about two hours or so at nights in the weekdays. This was the Card Tray Demo app; original submission was on commit ID 349cb94. This time they didn’t use HackerRank but asked to upload sources to Github instead.
After uploading the sources to Github, notifying the HR manager and sending out another TestFlight release to the hiring manager, things went quiet for many months. Fairly recently the hiring manager messaged via LinkedIn and apologized. He said he was impressed with both works but he has a tiny budget and his bosses were looking for purple squirrels. He has been trying to hire for six months but couldn’t find a good candidate and was “… frustrated as hell, especially after your work…”. Yeah, he’s frustrated. I felt cheated. It turned out that the advertised salary was probably a big lie. In any case I’m the fool for being too trusting and bedazzled by unsaid promises, cool offices, and a brand name.
In recap, here is the long and painful hiring process.
- 15 April 2016 – first call.
- 20 April 2016 – first interview.
- 26 April 2016 – first project request.
- 1 May 2016 – first project delivery (Cheesy Movies).
- 10 May 2016 – second interview.
- 6 June 2016 – third interview.
- 8 June 2016 – second project request.
- 19 June 2016 – second project delivery (Card Tray Demo).
- 10 September 2016 – the hiring manager apologized.
You might ask, “Which company is this?” No, I won’t name anyone to protect the guilty (and myself for that matter). But with some investigation, you could make an intelligent guess who put me through this peril.
There is a saying, “Its good to learn from experience but its better to learn from other’s experiences.” You can take away some lessons that I learn the hard way:
- Beware of vacancies that have been open for too long or closed and re-opened for many times. They could be looking for purple squirrels. That is, probably they want too much for too little.
- Job descriptions and advertised salaries could be cattle excrement. Even from well known large corporations.
- Don’t do free work as part of a hiring process. Don’t participate in any evaluation process that consumes your time significantly more than the time they are spending on you. This shows that the people involved do not respect your time. If they ask for such tasks, politely decline and refer them to this article. That is, unless you’re desperate and don’t have anything else better to do.
That’s all for now. Live long and prosper 🖖
Do you enjoy this post? Enter your e-mail address below to receive articles like this one in your mailbox.