I was given good instructions, simple designs, and 48 hours.

Read my update here.

What is worth the time?

Yes.

This time.

The Good

If you’ve ever dismissed a job because of a coding challenge, I recommend you give it a second thought next time.

When I was presented with the challenge, I decided that, at the very least, I would get some good experience.

I thought I may even end up with something I could show off or write about.

It turned out to be a good way for me to get to know the hiring company a bit better; it gave me an understanding of what they might expect for the role and from their developers in general.

The challenge also gave me chance to try a new framework — CodeIgniter.

Most of my backend experience is with Laravel and WordPress.

I enjoyed the change.

The Not-So-Good

It took me nearly two days to complete the assignment, and that’s a big investment when you need a job in a certain amount of time.

My advice would be to only consider doing a challenge if you know you really want the job.

Fortunately, before the challenge, I was able to speak with a developer at the company and get some real insight into how they like to do things. I liked what I heard, so I chose to give it a shot.

My advice would be to do the same before investing time in a lengthy interview process. Going through all that trouble only to find out you won’t like the company would be a big let down.

If a prospective company is going to ask you to do a coding challenge, I don’t think it would be too out of line to ask to speak with one of their developers for a few minutes first.

The Challenge Begins

The challenge was to build an app to manage customers.

display a list of stores for a chosen country / city

display a list of customers at a selected store

create / edit / delete customers

While it didn’t look like much, I remembered how easy it is to get bogged down in details and non-essentials.

I determined to not waste time configuring the perfect build system or designing the most robust architecture.

I was going to focus on writing clean and easy-to-read code.

Time Left: 48 hours

I was given a fresh install of CodeIgniter and a database to get setup.

My instructions were to use jQuery, underscore / lodash, and Bootstrap only.

This meant no fancy JS framework me, and that was probably the most frustrating part of the whole challenge; the amount of code I had to write to do what I wanted to the UI was exhausting. I sorely missed the conveniences of a nice framework (my favorite is Vue.js).

Step 1: The Front End Workflow

Modules and ES6 are a must, so I put together a very simple Webpack setup. Nothing fancy. All it did was transpile and bundle the JS.

I then downloaded Bootstrap and jQuery and put the minified versions in my project. If I had time I would see about managing those dependencies properly, but my focus was on the big unknown — CodeIgniter.

Time Left: 47 hours

Step 2: Getting into Uncharted Waters

Getting started with CodeIgniter wasn’t too bad.

At first, I had those butterflies that always appear when I’m about to start something new. But CI is very approachable, and I was up and running pretty quickly.

I managed to find some playlists on YouTube that got me acclimated to how CI likes to do things. In about 20 minutes I had some basic routes set up, and had a working understanding of configuration, models and controllers.

Time Left: 46 hours

Step 3: How to load my JS modules?

Not having the convenience of a front end router, I decided to try another approach to loading my modules on their proper pages.

This is what I came up with:

import main from './assets/main' import stores from './assets/stores' import customers from './assets/customers' $( document ).ready(function() { const page_id = document .getElementById('page_id') .getAttribute('data-module') const modules = { home : main, about : main, stores_index : stores, store_customers : customers } modules[page_id] ? modules[page_id].run() : false });

I had the CI Controller inject a unique identifier on each view file loaded.

On ‘ready’ I would grab the id from the page and load the appropriate module.

This worked rather well.

I had a stores module to handle the main store listing page, and then a customers module to handle the manage customers page.

Time Left: 45 hours

Step 4: Reviewing the Requirements

Now that I had a decent foundation laid, I needed to focus on understanding the app and how I was going to put it together.

Kudos to the company for giving some pretty clear instructions. I was even allowed some creative freedom provided I met all minimum requirements for functionality.

display a list of stores for a chosen country / city

display a list of customers at a selected store

create / edit / delete customers

I grabbed a piece of paper and started sketching out ideas.

I learned long ago that one should spend a generous amount of time thinking through a feature before writing any code. Proper planning will save you many hours of unnecessary refactoring.

Time Left: 44 hours

Step 5: REST API with CodeIgniter

This is easily where most of my time went.

I got tripped up on the following:

CI Query Builder (I really missed Eloquent — Laravel’s ORM)

Returning a proper response with status, data and message.

Accessing the payload on a PUT / PATCH request.

Like some, I am guilty of getting comfortable with certain tools without ever rolling something myself to understand what happens under the hood. I am looking forward to grabbing some time to properly understand why I was having such difficulty accomplishing this with CI.

In the end, I figured out how to do all the above with the tools I was given.

Maybe some devs more familiar with CI could take a look at what I came up with as the model for listing customers:

public function list($store_id) { $results = $this->db ->from('customer') ->where('customer.store_id', $store_id) ->join('rental', 'rental.customer_id = customer.customer_id', 'left') ->join('inventory', 'inventory.inventory_id = rental.inventory_id', 'left') ->join('film_text', 'film_text.film_id = inventory.film_id', 'left') ->select('customer.customer_id, customer.first_name, customer.last_name, inventory.inventory_id, inventory.film_id, customer.create_date, customer.last_update, customer.active, rental.return_date, rental.rental_date, customer.email, customer.address_id, film_text.title, film_text.description') ->get() ->result_array(); // rental details grouped by customer_id $customers = group_by($results, 'customer_id'); $customer_list = array_map(function ($customerData) { $rentals = array_filter($customerData, function ($data) { return !empty($data['film_id']); }); // alpha sort usort($rentals, function ($a, $b) { return strcmp($a["title"], $b["title"]); }); $rental_count = count($rentals); $customer = [ 'active' => $customerData[0]['active'], 'create_date' => $customerData[0]['create_date'], 'last_update' => $customerData[0]['last_update'], 'rental_date' => $customerData[0]['rental_date'], 'return_date' => $customerData[0]['return_date'], 'address_id' => $customerData[0]['address_id'], 'email' => $customerData[0]['email'], 'customer_id' => $customerData[0]['customer_id'], 'first_name' => $customerData[0]['first_name'], 'last_name' => $customerData[0]['last_name'], 'rentals' => $rentals, 'rental_count' => $rental_count, ]; return $customer; }, $customers); $customer_list = array_values($customer_list); usort($customer_list, function ($a, $b) { return strcmp($a["last_name"], $b["last_name"]); }); return !empty($results) ? [ 'status' => 200, 'message' => 'Success', 'data' => $customer_list ] : [ 'status' => 204, 'message' => "There aren't any customers at this location.", 'data' => [] ]; }

and I found this little helper for formatting my json response:

function json_output($response) { $ci =& get_instance(); $ci->output->set_content_type('application/json'); $ci->output->set_status_header($response['status']); $ci->output->set_output(json_encode($response)); }

Time Left: 40 hours

Life, Rest & Sleep

Step 6: Building a Smooth UI sans Framework

Time Left: 24 hours

After I got a better grip on setting up API endpoints, I was finally ready to focus more on the UI.

This was comfortable and familiar territory, and I was excited to produce something slick.

I tried to avoid obsessing too much over names and css class organization, and just got to work.

Here are some snapshots of the code:

All this work just to update UI on the fly made me appreciate just how good we have it with frameworks like Vue, React and even Angular.

Some key features:

first and last names were required to add / edit a customer. The specs called for a warning on submission if either was missing, but I instead opted to just disable the save button until both inputs were filled out.

I added some error and success messaging after most operations.

I used Bootstrap modals for add, edit and deletion of customer data.

I’m not a designer, so I was happy to have Bootstrap.

Have a look:

After lots of work and some sleep…

Time Left: 0 hours

Would I do this again?

Yes.

While this simple CRUD app barely scratches the surface of what makes a competent developer, it gave me a clear path to demonstrating some of what I can do.

I wouldn’t want to do this for every job I apply for, but I think it was a good use of my time.

Found this interesting / helpful?

If this short post has helped you in any way, please remember to give this a recommendation below and post a brief comment to support me.

Comments, questions and constructive feedback are always welcome.

My name is Patrick O’Dacre, and I am a software developer that loves building great things with great people.

I have had the pleasure of creating ground-breaking e-commerce order systems, beautiful sales dashboards, and complex data grids with some incredibly talented people that made sure work never felt like work.

Some of my favorite tools include Vue.js, React.js, Node.js and Laravel, and I’m always excited to learn new things.

I am currently available for new opportunities, so don’t hesitate to get in touch.