Technical Interviews, Node Experiments (nodexperiments), and More
Well, it's been a while my fellow tumblizens. I thought I'd stop by to write a little post on my experience doing my first technical interview and the strange/interesting/sadistic challenges I encountered along the way.
So lets rewind to about three weeks ago. Picture a strangely dressed kid with a green complexion who's fiddling with a half-full bottle of 5 hour energy sitting across from you on the Q train. That's me, a nervous, nauseas wreck 20 minutes before my interview.
Having heard plenty of horror stories about technical interviews before, I show up at my interview expecting to be taken to a fluorescently lit room with whiteboards covering every inch of available wall space, where there are three intense looking programmers with furrowed brows sitting at a long table. The moment I walk into the room, however, I'm greeted by the same guy I had a coffee with the first time I got introduced to the company, and led to two small artsy armchairs that sat in the middle of an open room where everyone was working. At this point, despite realizing my imagination had gotten the best of me, my adrenaline is through the roof. I still had no idea what to expect in terms of questions.
The first interviewer sits down, asks me about my background and other questions that I'm used to being able to hit the ball back on. Then we start talking about the projects I've worked on at Flatiron:
"So tell me about the last project, and some of the challenges you faced while working on it?"
"Why did you decide to use angular in your project?"
"So tell me a bit about your database schema. Why did you set it up like that?"
"Lets take a look at your Javascript"
The entire time I was answering these, in my head I couldn't stop asking: "Wait... are these the technical interview questions? When am I going to be handed a whiteboard marker and be asked an algorithm question? IS EVERYTHING I'VE BEEN TOLD UP TO THIS POINT A LIE?"
As it turns out, yes. Well, for this interview anyway.
The technical interview actually ended up feeling a lot more like a casual conversation about frameworks and gems and libraries than a brutal gauntlet of algorithm questions. It was possibly the most relieving feeling in the world to have finished the conversation and realize that I wasn't going to end up having to touch a white board marker. Instead of feeling like I was taking the SAT again, I felt like I was just talking with a fellow coder about something I had been working on.
I knew I hadn't gotten off the hook that easy though. They still needed to test my coding ability somehow. What I found out after the interview was over was that I'd be getting a "take home" assessment--two mini projects that would test my ability to work with APIs and use frameworks outside of my zone of comfort. Which, believe me, was a huge relief to hear after a week of pulling my hair out trying to understand big O notation and hash tables.
Here are both of the questions:
1. Build a landing page with custom form validation
Requirement #1: The email field needs to check to make sure the user submits a company email address. If the user tries to submit the form with a gmail, hotmail, etc. address, trigger a form validation error and tell the user they need to submit a company email
Requirement #2: Split the name field into first_name and last_name delimited by a space
Requirement #3: Post the form to a MailChimp email list
2. Retrieve and format data from MixPanel's Data API
Requirement #1: Solution has to be done in 100% javascript
Requirement #2: Final output data should be in a csv or comma-delimited file
Requirement #3: from_date: '2014-01-01', to_date: '2014-03-10'
API host: 'data.mixpanel.com', path: '/api/2.0/export/?' + params
So, the first project was pretty easy. You can check out my solution here. After reading Sandi Metz POODR, I've been obsessed (perhaps a bit to a fault in that I'm always distracting myself from the task at hand) with eliminating dependencies on external gems or libraries by wrapping their methods in my own methods. If methods ever change in a library/gem and you need to update to a newer version of that library/gem without completely messing up your application because method names have been changed **ahem ActiveRecord ahem** , you can simply go back and change that gem's method inside your wrapper class and it is instantly fixed throughout your app! Yay for reducing external dependencies!
(kicking external dependencies in the face)
So as you can tell by the fact that I went on this huge tangent, my decision to approach the problem this way did take some extra time, but I think it was worth it. At this point I'm just hoping that they'll take the time to notice that I put in the effort to make the wrapper class for the gem I used (gibbon, a ruby gem wrapper for MailChimp).
Anyway, the real difficulty came in when I approached the second project. Can you guess why? I'll tell you why. Because JavaScript (and sadistic API's)
Fortunately, I had the opportunity recently to take a class with the nodeschool peeps on the basics of node, which made getting started with making a HTTP request to an API in Node a lot easier. This is simply done using Node http module
In any http request, you need to specify an .on("end"...), since the request is made asynchronously. If you don't know what that means, you can read my last blog post! An interesting aspect of the way Node make's requests is that it actually gets "chunks" or what are called packets of data at a time. The packets are retrieved in the .on("data"...) block above. As you can see, I concatenate the data (which is a Buffer object and a way that node deals with and stores binary data. You can read the docs for the class here) that is converted to another string called body every time node retrieves a new packet. At the end of the request, I do some magic stuff with the data and convert ultimately call a method which converts it to CSV format. THIS was the hard part of the project.
So for some god forsaken reason, the particular route I was given to request data from Mixpanel was one in which the data returned wasn't REALLY JSON:
While it LOOKS like JSON, you can see that the JavaScript objects aren't actually contained within an array. After some toying around with it, I realized that they were in fact separated by return characters. While this isn't a huge deal, it did take some finagling just to get it back into JSON format... I'm not entirely sure if this particular API request was given to me because they knew that it was a tough one to work with in terms of formatting or not, but the story gets a bit worse...
After managing to get my data into JSON format, I realized that the event objects weren't all consistent with one another. Event event objects of similar types didn't always have the same amount of properties. This meant that getting them into a format which I can use to export to CSV was going to be a bit more of a challenge (I needed an array of arrays, where the first array were the column names, and all the arrays afterward were rows in the table).
Ultimately these are the steps I took to do that:
1. Flatten the event objects so that none of them had nested objects as attributes. (I was fortunate enough to have found a gist that did just this. )
2. Iterate over the first object's properties and create an array of column names based on its properties
3. Iterate over the rest of the objects. For each object, iterate over their properties and the value of each property to an array of values.
4. Push the column_names and object_values arrays to an outputToCSV array.
I THOUGHT this would be a foolproof plan. After quite a bit of hard typing labor, I found out that there was something wrong with Step 3 that was going to cause my value arrays to be inconsistent in length. Can you guess what it was?
I was iterating over each object's properties and adding their values to a new array each time, whereas what I should've been doing is iterating over the column names I had for each object and calling each column name property on each object. If the property didn't exist for that particular object, I would just get an 'undefined' value returned, and wouldn't end up with an array that was a different size than other value arrays.
Anyway, you can take a look at the result here:
It was definitely an interesting project to work on, and I did enjoy working with an entirely new server side language. Probably the most valuable thing I learned from this project was how to deal with API data that isn't always consistent.
Well, that's all for now folks! I have plans on writing another post on my technical interview at HowAboutWe yesterday, so more on that soon.