To be honest, I didn’t pick the title :) I was applying for work with a company that does a lot of survey data analytics. The person who was interviewing me asked whether I’d prefer to take their front-end or back-end code challenge. I chose the front-end one, and ‘remove-rails’ landed in my inbox. I can only suppose that the company used to do a lot of this data-crunching on the back-end using Rails, before switching to a font-end framework to take some load off their servers.
Anyway, the project brief was to produce a web front-end to display survey data served up by an API in the form of JSON files. The survey data in the JSON files was raw, and required some processing before being displayed in the UI. It was an interesting challenge as I’d never written anything dealing with an API on a server before.
Writing the App
I chose to do the project in AngularJS, mostly because I’ve been learning it recently, but also because testing was part of the requirements. I’d never done any testing in Angular before, but I knew about the testing eco-system built around the framework and thought it was about time I played with that as well.
The first thing the app does after bootstrapping is attempt to load
index.json from the server (which can theoretically be anywhere, but in reality was at
localhost:8000 being served by python’s trusty simple HTTP server).
index.json contains high-level data about all the survey results that can be accessed by the user, including the url of the raw JSON files, the survey names, number of participants, etc.
The buttons on the UI are generated based on the number of surveys listed by
index.json, and when clicked, direct the app to load the raw data for the selected survey, process it, and display it on screen.
To handle all the data loading and processing, I wrote an Angular factory service called DataOp. I’d never done this before, so it was a good learning exercise. The service does all the heavy lifting and the controller is simply the glue logic that wires it to the view. All my previous projects using Angular had relied entirely on the controller, but I much prefer this approach. Finally, I was using the controller simply to control the flow of data between the services and the view based on a set of pre-defined rules. It’s much better :)
Doing the data crunching was interesting. The surveys each have a number of ‘themes’, each theme has multiple questions, and each question has a type associated with it. For example, you might have a question in the form of a statement requiring you to reply with one of ‘strongly agree, agree, neutral, disagree, strongly disagree’, or perhaps there might be a binary yes or no, or there could be some free-form answer. You don’t know until you actually get to the question and check it.
I wrote a data crunching function which steps through the questions in each theme, checks what type they are, then calls the appropriate function to deal with it. That function then does all the data processing and collation, storing the results in a new
collated_data object within the original data structure. In addition to the collated data, it also stores the URL of the mark-up template required to actually display the data structure to the user.
The view then steps through each theme and renders the collated data for each question, calling the appropriate template as it goes. This set-up makes the app very modular and it’s easy to add new quesiton types to the surveys - all you have to do is write a new function to deal with the new data structure required, and a bit of mark-up to display it - and the app does the rest.
Testing the App
The unit tests, however, were much more difficult and I didn’t write as many as I’d have liked. The documentation for dependancy injection in Angular leaves a lot to be desired and it took me a long time to figure out how to get it up and running. Thankfully, I did at least manage to get something working, even if the test coverage isn’t very good.
Writing good tests seems to be something of an artform in itself, and I’m looking forward to having a bit more experience there.