Index Your Foreign Keys

We add indexes to our database in order to speed up read operations. Basically, an index is a sorted copy of a particular set of columns the database uses to quickly look up the attributes of another table, most commonly, foreign keys of relations. There are several ways this can actually be implemented on the database; essentially, we tell the database which values we'll be looking up most often and it sorts the logical and physical storage of the information to make those operations faster.

One downside to this process is that it takes more physical space on disk because we're keeping extra copies of data in our database. Another drawback is that because we're keeping these indexes up to date, we also have extra writes whenever that data changes.

I would advise you to index all of your foreign keys, unless you have good reasons not to. Also, if you're already down with indexes, don't produce any example migration code that doesn't include `index: true` on your foreign keys. I think I was late to the database index game because not enough people are preaching it.

To add indexes to your database, create a migration.

You can use this script to find missing indexes in your application.

Here are some performance numbers from an application I have been working on, before and after adding database indexes.

Speed increased by 4.4x on a simple query and 2.2x on a complex query. Looking around the internet you will find many other people with even greater speed gains.

You can index non-foreign key fields if you query them a lot, such as `name`, or some other alternative id, and see incredible performance improvements.

Originally posted on the MHS Blog

ActiveRecord Associations & You

I love abstraction. It's great to compartmentalize complexity and keep your application modular. SQL is not that. Relying on SQL strings in your code ties your implementation directly to the type, structure, and even the version of your database. ActiveRecord (the ORM behind Rails) is great for letting us focus on our application and not worry so much about the database particulars.

However, understanding relational databases can really help improve the quality and speed of your application. Being able to compose an ERD of your system and understand how to normalize a database will lead to better system design.

ActiveRecord Associations

Let's look at the different ActiveRecord relations and point out what is going on in the database. I am going to assume you know how to create migrations to add attributes to a model and focus on the associations.

belongs_to, has_one

These are pretty straightforward and are 2 sides of the same relationship. The table of the `belongs_to` model contains a column with the foreign key of the `has_one` model. ActiveRecord expects only one `belongs_to` model to match up to the `has_one`. The `has_one` model should be the one that semantically makes more sense to own the other. For instance, it makes more sense for a profile to `belong_to` a user, rather than the other way around.

Before 4.1, there was a peformance benefit from specifiying that the `has_one` and `belongs_to` were related, but now rails guesses the inverse based on hueristics. If you are on a version previous to 4.1 or your relationship uses a different class name, or other options, you may want to specify the `inverse_of` attribute. This will reduce the number of database calls since ActiveRecord will not go to the database if the object has already been loaded from another association.

belongs_to, has_many

The same as above, except the `has_many` model is expected to have 0 - Infinity of the `belongs_to` model. For instance, a group might be able to have many members, but a user can only belong to one group.

has_one :through

This is a way to relate two models through a third model. If a user `has_one` profile, and a profile `has_one` avatar, we can access the user's avatar directly without having to load the entire profile.

has_many :through

Similar to `has_one :through`, this allows us to connect two models through a third model. A user might have many uploaded avatars they can choose from that are associated to the user through the profile.

In some instances it will make sense to create a new connecting model to represent the relationship. For instance a `membership` might make sense to be its own model that can have methods and be queried more easily using activerecord.

has_and_belongs_to_many

This is used when you want a many-to-many relationship but you don't actually need to interact with the relationship itself. You might have a user with a simple reference to groups they join. Under the hood this is actually just another version of `has_many :through`, but the connector is a join table instead of a "real" model. We don't create a separate class to represent it.

Originally posted on the MHS Blog

(Over)simplify Your Code

One of my eureka moments as a developer came when my programming pair suggested I separate some very simple math in the body of a method into another method. At the time it seemed like overkill to create an entirely new method when the operation was so simple. Wouldn't that make it *more* complicated? But I quickly realized the benefits outweighed the cost.

The first benefit is code reuse. This is rather obvious; If we think we might need to do a thing more than once, we throw it into a method so we don't have to write it again.

The next benefit is that when the code needs to change, we can fix it in one place. Pretty straightforward stuff.

Having many small methods separates our code into bite-size chunks that are easier to test. Testing greatly increases the quality of the software we write. Whether you actually practice unit testing or not, you know you should be.

You might think you've heard all this before. However, I'm contending that you should break your code into small methods even if you don't plan on reusing it; even if you don't expect it to change; even if you don't do any unit testing.

I would first argue that you may eventually want to reuse the code, the code *will* need to change at some point, and you *should* be doing some unit testing. Not convinced? Well I have one more benefit for you...

The advantage that didn't hit me until I was encouraged to over-simplify my code is that you no longer have to think about the code in that method, like, at all. Even if it is as simple as dividing two numbers, there is at least a little cognitive overhead in looking at those numbers and determining their function. That subtracts from the mental capacity we have for the problem we are actually trying to solve. Likewise, when we want to work on what the small, extracted operation is actually doing, we don't need to worry about all of the other context of the system.

I love one line methods (as long as they only do one thing). I love taking complex things and breaking them up into simpler pieces. You probably do this most of the time too, but do you still have methods that look like this?

In the "shorter" example we have to keep track of the fact that we are actually calculating density, and that density is mass divided by volume, and that the density needs to be less than one for something to float, and to question what the number "1" means. In the example that is broken into methods our brain only has to recognize that the density of the thing needs to be less than the density of water. Not to mention the code is more reusable, flexible, and testable.

Once I challenged myself to over-simplify my code, I became a much stronger developer.

Originally posted on the MHS Blog

Math Is Not Necessary for Software Development

As a developer, written communication and reading comprehension are more valuable than math proficiency.

Sometimes, I tweet. When I tweet, sometimes people agree with me. One such occasion happened recently when I said this.

This was part of a string of tweets that was kicked off by seeing the following image tweeted by Sara Chipps.

I think the main thing to take away from that image is that if you are looking for a new career and you aren't involved computer science or mathematics, you should be, and I hope my post here encourages you to get involved, especially if math has been scaring you away. It also means we should be providing more and better training for these jobs - but that's another post entirely.

So here's my question about that chart, why are computer science and mathematics combined? Why are computer science and mathematics *always* combined? In my day-to-day as a developer I rarely do what I would call *math*. Now admittedly, computer science is different than software development, but I don't think laypeople know that. I don't think that high school kids who are deciding what do do with their lives know that. Our industry desperately needs more talented developers - and it turns out that the skills that make a good mathematician don't necessarily line up with the skills that make a good software developer.

Logic > Math

People who are good at math are good at breaking problems down into parts, recognizing patterns, and applying known formulae to those parts to arrive at *the one right answer*. This skill will definitely help you solve some problems in software development. However, in software we are constantly running into interesting new problems that don't have a singular *right answer*. This is where we get to use our creativity to create solutions. Rarely in math are you coming up with a new way to solve a problem, but in software development you do that all the time!

If you don't like math because it is repetitive and boring, look into software development!

Modern tools have abstracted away (almost) all of the ugly 1s and 0s from software development. Modern developers can focus on crafting a solid system, and (for the most part) not have to worry about things like memory management, endianness and other computer science gobbeldy-gook. Sometimes it is fun to deal with low-level stuff like that - but you don't need to understand it to build a CRUD app.

Certain types of software development do require quite a bit of math: statistical/financial software, and games involving physics - for example. However, these require math because that is the *thing* that the software does, it's not simply a fact of building software. When we do need math, we have code libraries and computers to help us!

The majority of code for something like Facebook or Twitter probably involves very little math.

The math that we do use everyday in software development is called Mathematical Logic. In particular, software development involves a lot of Boolean Algebra. Known broadly as Discrete Math, it was one of my favorite classes in college, and I would recommend it to anyone, even if you aren't really a fan of numbers (also, take an Astronomy class!). I was blown away by this whole new type of thinking. If you are unfamiliar with discrete math, evaluating "`if true and false`" won't make any sense to you - but software developers deal with statements like this all the time.

Written Communication && Reading Comprehension

Taking the idea in your head and writing code to make it happen is clearly an important part of being a software developer. However, if you are doing custom development for a client, you need to start by being able to take their idea and get it into your brain. You need to be able to ask the right questions, and understand what they are telling you, and a *ton* of that happens through written communication like email. Effective communication is a requirement.

Writing code is like writing in another language, so language skills are extremely important! Not only do you need to understand what people before you have written in code, you need to write code in such a way that those who come after you can understand what you were trying to say. With enough experience, writing code that you and the computer understand is relatively easy - writing code that you, the computer, and *future you* understand is a whole 'nother story. But it's not even just future you, when other developers get involved, they will need to be able to understand the code.

Interestingly, some of the worst code can come out of very smart people thinking they're being clever. Smart people can write really complex code in a complicated way and understand it. Smart people aren't bothered by an `x` for a variable name because they can hold the whole system in their head and they remember what all those variables represent. A very smart person doesn't need to write any comments, the code is obvious to them!

Someone lacking superhuman mental capacity forgets what `x` is supposed to represent and so they name it something meaningful like `target_value`. This person gets lost in the middle of a 300 line function and thinks "Can I break this up into smaller parts so I stop getting so confused?" In the long run this person will be able to create better software as a system grows and the interactions become too big for *anyone* to hold in their head all at once.

If Only I Had Known Then...

I really wish high school Ross had read this blog post. High school Ross was good at math, but didn't really enjoy it. High-school Ross was even better at language arts, but he wanted to get a good job <*zing*>. I was turned off from getting involved in software because I didn't want to do math and I didn't think my skillset matched.

I was also told that great white whale of a lie that we have all heard, that all IT jobs have been shipped overseas - refer to the job growth chart above to see how that is working out!

Originally posted on the MHS Blog

Pages

Subscribe to Front page feed