Lessons in Development: my first phase in review

After having gone through the first half of the curriculum, I don’t doubt the fact that I’ve grown as a developer. I’ve faced a lot of tough challenges and had my share of losses, but came out stronger each time. Here’s some of the things that I’ve learned.

Avoid excessive normalization

So I’ve always had this tendency to be very granular with my ActiveRecord models. The way I see it, if it’s something that can ‘owned’ by another and can have its own unique set of attributes, it needs its own model.

This is a part of a sketch I made for planning out my Danebook’s models. The idea was to have the user choose only among a pre-loaded set of address components which they would select using a collection tag. Each component would belong to an Address model, which would belong to a polymorphic :addressable identifier. This identifier would serve as a generic pointer that would allow me to add parent models as needed.

This setup quickly proved to be very difficult to work with.

First, I would’ve had to actually populate the tables for these ‘address components’. Never mind the fact that I would have had to scour the web for a suitable open dataset; having an entire world’s worth of addresses would bloat my database and slow it down considerably.

So much for scale.

Second, it wouldn’t be enough to just have data for these models. Each one would have to relate to the other, since a City is nested within a State, which in turn is nested within a Country. This means more code than is necessary for such a simple problem, and therefore more assumptions that need to be made when iterating on the project. In other words, it’s a brittle solution.

Don’t normalize unless absolutely necessary, especially when the problem is a very simple one to begin with.

Still, I didn’t want the user to simply input random data as an address. I wanted my app to only accept legitimate and verified physical addresses.

Delegate when it’s an option

My solution was to utilize the Google Geocoder API.

Using a plain old ruby object(PORO), I wrote some helper methods to query the Geocoder API. Basically, I’d grab the address information from the parameters in the POST request, prepare it for use in the PORO, then query the API for a matching location. A response of ‘ZERO_RESULTS’ means that the user has to input another set of address information in order to complete his profile. It’s a far more elegant solution because I’m delegating a task to a more qualified source. And who can be more qualified than Google in verifying addresses?

Lesson learned: delegate tasks when the option is available.

You need to deploy.

You have a deadline. Your team won’t wait for you. You need to deploy, and you need to deploy yesterday (yes, I mean yesterday).

Things can go wrong, sometimes through some fault of your own. That doesn’t change the fact that your team needs something from you. And that something is your feature.

So find a solution. Think hard, and think fast. Try this, or maybe that. You can’t let your team down.

You need to deploy.

Take risks

Our team was not expected to utilize javascript for our first group project. We were not prohibited from doing so, but we were not encouraged either since the staff at Viking Code School wanted us to avoid biting more than we can chew. We understood the good intentions, but we wanted Google Maps on our search results page.

It was non-negotiable.

We queried the Zillow API for neighborhoods around the user’s location. The user would then be greeted with a search results page, with a map of the area to his left and bootstrap cards for each neighborhood on his right.

I’ve never actually worked with Google Maps prior to this. I’ve dabbled with javascript in Code Academy, read a few chapters from a book, but never actually developed with it.

But we needed that map, we needed it to have markers, and we we needed the labels to pop up whenever he clicked on the corresponding card.

It was uncharted waters for me, but I pressed on.

I wasn’t quite sure exactly how to pass Rails data unto javascript. I knew that the framework utilized javascript, but I wasn’t familiar with how to actually do so myself. All I knew was that the template was basically an html file that allowed for some ruby logic through ERB.

I tried interpolating my coords hash, the same way I would interpolate ruby logic in the rest of the template. It seemed to work, but I serialized it to JSON to be sure.

Once I knew that it worked for the user’s location, I applied this process to the neighborhoods.

Apparently javascript had a map method similar to ruby.

Next step was to instantiate a Google map object. This part was pretty painless; it really was no different from creating a class instance, except that you needed this object to point to the node representing the map on the DOM, and then pass what appeared to be a ruby hash (but was actually an ‘object’ in javascript) containing your map’s configuration.

This is where things get tricky. I needed to add a marker for each of the neighborhoods from the search results. I also needed a marker for the user.

For the first, it was a matter of iterating through the array of neighborhoods. Javascript had forEach(), which worked similar to ruby, but involved a callback that I wasn’t ready to tackle quite yet. I just wanted something that worked, given the time constraint.

A quick google search allowed me to recall my Code Academy days. And this is what I came up with:

The javascript way of iterating was no different than using a while loop in ruby (and in fact, javascript likewise has a while loop). Actually, it was easier to write than a while loop since the index declaration, conditional, and incrementing could all be written in one line.

I concluded this for loop by tacking on a listener to the current iteration’s marker and pushing that marker to an array.

So the markers were working, the on-click events were firing, and all was well. The project was completed and presented during our final SCRUM meeting before the break.

But I felt like the maps needed one last little bit of polish: events that would fire other events.

Some research showed me that it was actually possible to grab an array of nodes in the DOM tree by class name. Who knew?

I had more time on my hands, so I didn’t mind using a function that utilized a callback, such as find(). Seemed simple enough: use the same logic from earlier code and iterate through the cards, finding each one’s corresponding marker, and tacking on a listener.

And it worked!

… except for the fact that each card fired the event for the same marker.

Apparently, javascript has a weird scoping issue. When you write a function within a function, the child function becomes a ‘closure’ in the sense that covers the parent function’s scope, such as the variables declared and assigned within. So whereas the data in a function normally disappears after it is called, a function that contains a closure remains for as long as the latter needs it. If you have a function that iterates through something and defines a function each time, all of these functions will remember the exact same environment within which they were declared. Each one will refer to the exact same variables and values. To avoid this, you need to give each function its own copies of those variables and values as well as its own scope.

Basically, just nest the iteration’s function in an Immediately Invoked Function Expression (IIFE) and pass the value you want it to have a copy of, as an argument to that IIFE.

This was a bit of a gamble on my part because I wasn’t confident in my javascript skills as of yet. But it paid off because we got exactly what we wanted for our app, and it turned out beautifully.

Final lesson before the break: take some risks. Sometimes, all it takes is a leap of faith.