Saturday, September 7, 2013

Developing Trackpad: An 18 second Vine documentary

My goal was simple. I wanted to be able to control my Mac's mouse from my Nexus 7. These following Vines document an evening's attempt at that.

Phase 1 - Basic Android application. Just getting set up.

Phase 2 - Server setup. My mouse now speaks http.

Phase 3 - Hook server up to application. World's hackiest wireless mouse.

Check out the android app here
Accompanying scala Play service here.

Monday, September 2, 2013

Hacking the coding interview

The technical interview process used to hire software engineers/developers hasn't changed much over the years. A couple of coding problems to solve on a whiteboard for roughly an hour a piece over the course of a day. Intersperse lunch & bathroom breaks for fluid I/O needs. Leave feeling exhausted, perhaps regretting how silly you were to forget the algorithm for merge sort on that 3rd interview.

Over the last 7 years I've given and received enough interviews to see a couple of patterns emerge. I think it's rather unfortunate, but proper preparation and foreknowledge of "the process" can make as much difference as simply being the right person for the job. As a result, I've also seen a lot of false positives & negatives occur. I'm really interested in getting to the bottom of this since the most important decision a company makes is who to hire. One rock-star engineer you can trust to get the job done is worth five mediocre ones. Hiring the wrong people can have disastrous consequences on effectiveness, morale and culture.

What I'd like to do is spend the remainder of this post being a hacker who's goal is to get the best offer at a company possible (compensation, position). We will employ all means at our disposal, save for anything dishonest. Think of this as attacker-centric threat modeling. Once we gain an understanding of how one can optimize & exploit the existing process, we can look at flaws and propose a fix.

Know what you're up against
These are the typical steps in the interview process from first contact to offer letter:

At any point, the process can dead end --- for a variety of reasons.  There's a lot to say for each step, but I'd like to focus on the on-site interview for now.

There's a good bit of variety in how on-site interview panels are set up, but at the end of the day this is what will be used to judge whether you get a job or not:
  • 3 to 6 interviewers. Mostly developers, usually includes a hiring manager and sometimes product manager(s). Sometimes you will have 2 interviewers at a time; this usually means a junior interviewer is "shadowing" a more senior one.
  • 45-60 minute interview sessions in a room with a whiteboard. The whiteboard may be replaced with a laptop in some cases, but this is less common.
Some companies are moving away form the last point and doing things like pair programming and live code debugging. I think this move is very interesting, but I haven't seen this applied in a scalable way at larger companies.

Before the Interview
Defining a model for interviews success
I propose the following model as predictor of offer quality:

# of offers = (coding interview skill) x (raw intelligence/skill) x (# companies interviewed)
and
offer quality (position & compensation) = (# of offers) x (Experience in CV)

Out goal is to optimize for offer quality. More offers = more choice = more negotiation leverage = higher pay/better position.

Assuming we can't increase the interviewer's raw intelligence or experience in a short time span, we will focus on the following:
  1. Build a solid "lead generation pipeline" to increase # of companies interviewed
  2. Train the interviewer's brain to be a "coding problem pattern recognizer" to improve coding interview skill
From here on out let's assume you have 1 month to prepare for the interview, nothing lined up, and about 2 hours a day to spend, every day, during evenings and weekends. We'll also assume you're working at a job during this time. Let's be clear, your success will be directly correlated to how much time can be spent studying & on LinkedIn. Remind yourself how badly you want this.

Generating leads
If you're buying a house, you'd be silly to put an offer for the first one you see. Likewise, with interviewing, you should look at as many options as possible. Lead generation is the idea of advertising yourself in such a way that you generate maximum possible interview interest. How can we do this?
  1. LinkedIn --- Update LinkedIn profile as soon as possible to highlight your latest work. Also start reaching out to all friends you have to see if their company is hiring. Get co-workers to write recommendations for you; the more the better. 
  2. A-List --- Identify the companies on your "A-list", places you'd really love to work. If you have any contacts at these companies, reach out to them expressing interest early on. Referrals can work on the inside to get you an interview. Their past experience with you is usually seen as huge plus that can override poor interview feedback in some cases. If you are applying cold to companies on your A-list, go to the careers\job section of their website (these always exist) and apply directly.  
  3. Interview everywhere --- If you're already getting InMail requests on LinkedIn, reply to all of them (even those that you're not interested in). Many requests come from come from headhunters who can connect you with companies you might care about interested in. 
  4. B-List --- For companies that you wouldn't want to work at, but would be easy to interview at, add these to a "B-list". We'll want to interview at these places first to use them as "practice runs".
The idea is that after a couple of weeks you should have a couple of B-list phone screens & on-sites done. If any A-list interview opportunities come up, push them out so that you can have enough B-list preparation. You might even have a couple of offers by the time you start "A-listing". 

Training your Brain
In parallel with lead generation, we need to train your brain to think in terms of coding interviews. This is where you will spend the majority of your time every day. This way of thinking is extremely different from how you approach writing software on your own with an IDE & internet connection. So different, that this is the number one reason for false negatives in interviews.
  1. Language --- First, pick the language you are most comfortable with. I've seen many candidates go into an interview and decide on the spot they wanted to use Scala instead of Ruby. Or C instead of Java. Mistake. Pick one language and stick with it for all your time studying & interviewing. Know the ins and outs of the language so that you can write code without hesitation. Remember, time is limited in interviews, and you don't want to waste it fumbling. Consider picking a language with good library support. Using the provided HashMap in Java beats writing your own from scratch in C.
  2. Study Material --- Next, get a good set of sample interview questions with solutions. We're going to use multiple sources for this. Our mainstay will be Cracking the coding interview which neatly divides problems between discrete domains (get a physical copy off amazon). We'll also be looking at the Berkely cs riddles forum and codercharts.com as backups.
  3. Paper --- From here on out we will only be coding on paper since this mirrors the interview environment best. Being near a computer helps to look up syntax/algorithms, but write everything out by hand. This will help greatly building muscle memory for algorithms. 
  4. Time --- Every day, you should aim to get 4-5 interview questions completed. You will do this until the last day you accept an offer. If you have 15 minutes to spare, do an interview question. This is your new hobby, which you will eat, sleep and breathe.
  5. Work & Study --- In order to buy time for yourself, you'll need to stop doing any overtime at your current job\school. Do the minimum possible to meet your commitments, but no more. Your priority now is your job hunt.
  6. Focus Areas --- In "cracking the coding interview", questions are divided between different categories which require specific approaches we'll want to master. The most important types of problems to master are(in order):
    1. Primary: Trees & Graphs, Recursion & Dynamic Programming, Arrays & Strings, Sorting & Search, Stacks & Queues, OO Design, Linked Lists,  Bit Manipulation, 
    2. Domain Specific (depends on job): Math & Prob, Scalability & Memory, Testing, Databases, Threads & Locks
  7. Bread & Butter Algorithms --- The following algorithms are useful to know in an interview, but you might not use day-to-day: Breadth-first search, Depth-first search, Dynamic Programming, Binary tree traversal, Merge Sort(asked a lot for some reason), Djikstra's algorithm, Tail recursion, Threading & concurrency patterns. 
    • I've seen that the first 4 algorithms in the list apply to a disproportionate amount of interview questions (~1/3).
  8. Tracking --- Track your progress as you go through problems every day. Do all your work in a notebook where you write down each problem on a separate page; this will be useful as you start to see patterns between problems. Keeping a sheet that records all the problems you go through helps build confidence and a sense of accomplishment. Here is an example:

  9. Problem solving approach --- Never, ever jump straight into a question. Think of exactly what clarifying questions you would want to ask had this been an in person interview. Many candidates get dinged for jumping into a question they don't really understand. For each interview question you study, clearly define an interface for the algorithm. If you can think of multiple solutions, learn to pick the best one(see next point #10). Explicitly call out edge cases as you're coding. Once you finish writing code, you're not actually done; verbally go through the code you wrote and confirm it does what it should. Catching bugs in your code without being told is a plus.
  10. O(N) Everything --- Understand Big-O notation and how to apply it to any algorithm you write. Time and space complexity analysis is always asked as part of the coding interview. For every coding problem you solve, you should learn to subconsciously apply this when evaluating the optimal approach.
  11. Talk --- Your ability to verbally communicate your thought process during the interview will be a huge asset. Practice talking to yourself while coding (maybe using the inside voice if you're shy).
  12. Progression --- Your progress will be very slow at first. Painfully so. You won't remember basic algorithms from CS 101 and you'll feel stupid and scared about the interview. You'll be very nervous until you start doing some of the B-list interviews. And then, all of a sudden, things will start to click and you'll start seeing patterns. A scary looking graph question is a simple matter of applying BFS (which you can write up blindfolded now), linked list questions will be a joke, you will be a master of recursion... etc. 
  13. Soft Questions --- You will probably get "soft" questions and these should be part of your training regimen. You should have well thought out, convincing, canned answers for some of the following: ["Describe the current project you're working on", "Describe a time you had a disagreement with a colleague and how you handled it", "What's your biggest weakness", "Why do you want to work here"]. Some of these questions are valid (always know why you want to work at a place you're interviewing). Some are bullshit since if you're caught off guard, you can give a terrible answer that ends up inadvertently hurting your chances.
  14. Puzzle\Riddle Questions --- are pure BS in my opinion, and generally acknowledged to not be a very good indicator of job performance, but you will see them. The key to these is being very methodical, asking smart questions and hoping the problem doesn't have an impossible trick. I wouldn't spend too much time studying these, but you should look at a couple.
  15. Study human relations --- Not, like, the whole field :) But read How to win friends and influence people by Dale Carnegie.  Many points brought up in this book are directly applicable to the "soft" side of the interview process. Seriously, consider this mandatory reading.
  16. Remove Fear --- If you're lucky enough to have an offer from another company before going in to interview, you will do amazing. There will be no fear to hold you back, your self confidence will be sky high and you'll simply do your best without worry. If your lead generation is able to yield enough interviews, this might happen, and you'll be golden.
During the interview
So you've been training hard for a couple of weeks and your lead generation pays off. You land an onsite interview and you want to do well. You'll always be nervous beforehand, but the trick is to A) let your training kick in and B) apply a deep understanding of human relations.
  1. Communication --- ABC. Always be communicating. Candidates that get a problem and write code for 45 minutes without saying a word will not get hired. Communication abilities are as important as coding abilities in a software development environment. Ask questions. If you get stuck, spell out your exact thought process and what you're trying to do next. Even if you don't solve a problem, being able to explain what's going on in your head counts for a lot.
  2. Getting stuck --- You're asked to solve a problem, and you pull a complete blank. You force yourself to solve the problem in a way you're not sure will work. After 20 minutes, you coding in circles. This is a very common pattern and results in a poor interview. In order to recover, communicate as much as possible you thought pattern. Spell out all assumptions you've made up until this point and question them in a conversational way with the interviewer. In the end, interviewers will usually give hints if they see that you're too stuck.
  3. Build Rapport --- If someone likes you, they are more likely to give a "hire". This doesn't happen all the time and interviewers might not realize that it happens, but it does play a role. Two things to try in every interview are 1) try to get the interviewer to laugh and 2) try to get them to tell you something personal about themselves. Doing this at the beginning of the interview is best, and it only works if it feels natural (as with all things).
  4. Hand Writing --- Write neat code. This sounds silly, but you will get dinged if your code is illegible and hard to understand.
  5. Solve what's asked --- Don't try to solve problems that aren't asked. It's very easy to start solving a problem, and suggest going down a very complex route. Make sure you're only solving what's being asked, otherwise you can hurt yourself. Sometimes interviewers will let you go down a winding path if they haven't prepared for the interview. Which leads to my next point ...
  6. Simplify --- When interviewers propose a problem, you can ask a clarifying question that steers the problem in an easier direction by calling out simplifying assumptions. The opportunity to do this comes up more often than you'd think and is easier the more you study. Ex: Instead of coding a sort method from scratch, assume you can use the inbuilt sort method. Boom, you saved 20 minutes.
  7. Never Argue --- Never argue with the interviewer, even if they're wrong. You should politely point out if you think things are obviously incorrect, but if they insist they're right, don't press the issue. The interviewer's pride is not to be trifled with, and doing so will always backfire. Agree that you're wrong and move on; the interviewer usually realizes things on their own after.
  8. Don't eat too much --- So you're interviewing at Google and lunch time comes around. Food is free so you eat way too much, especially carbs. Your post-lunch interview is a disaster since you have trouble focusing due to lethargy. True story.
  9. Keep notes --- Bring a notepad with you and write the names of each of the interviewers you talk to during the day. Writing their name down at the beginning of the interview looks professional and will help you remember their name during the interview. Once the interview is done, write what question they asked you and how you think you did for each question. Be self-critical and drill into areas you think you were weak in future studies.
  10. Get cut short --- If you're scheduled for 6 interviews and you do 3, this usually means you got cut short. That is, your performance was so bad, someone felt it was a waste to have 3 more people interview you. This sometimes happens for the wrong reasons, so don't feel too bad. Keep calm, keep training.
Conclusion
In summary, the real hack to the coding interview is that if I have a big pipeline of companies all using this interview technique then if I screen at Company A on Tuesday and bomb out on a question, I may well get the same question on Thursday from Company B. Company A evaluates me to be low skill and Company B evaluates me to be high skill. Sooner or later, someone will ask me questions I know and I'll be evaluated as high skill.

We should presuppose this happens, and focus on building "pattern recognition" before even entering the first interview. The faster the interviewee gets to "peak pattern" (a level that varies by individual) the more offers and leverage they have.

The fact that I can write this, and it's true, is the saddening fact I'm trying to change.

Next Steps
I'll probably add to this over the coming days if I can think of more. I'd like to get feedback and dissect some of what's going on here. A lot of what I'm suggesting to do is pretty extreme. A lot of the skills here are not something you learn by doing a standard software engineering job (or get coming out of college). It's especially hard for more senior engineers to do technical interviews since most have limited time due to familial obligations and haven't taken CS 101 for quite some time. 

I think there is a better way, and I hope to find it. 

Sunday, September 1, 2013

Triggered breakpoints in Android Studio

I found a nice timesaver in Android Studio. The IDE can automatically set a breakpoint whenever an exception is thrown. This is instead of waiting for one to happen, looking at the callstack, manually placing a breakpoint, restarting the debugger and trying to repro.

To do this:
1- Start the debugger

2- Click "View Breakpoints"

3- Check "Any Exception"

4- You'll see a triggered breakpoint appear any time there is an exception