As a computer programmer, you are going to write a lot of code. Or so your boss hopes. But writing good code goes far beyond just language syntax.

I often come across code that makes me wonder, “Did the person writing this think of anything beyond the syntax of this function? Did they take into account what depends on it, how it could be abused by a hacker or that it simply isn't intuitive to read?”

Here’s the truth: code is not written in a vacuum. Most likely, code you write is going to be reused. Code you refactor is probably being used in a different place already. If you only think about your specific use case, you are going to cause issues now or in the future.

So what are the things you should be thinking about with each line of code you write? Well, here’s my list:

Functionality: “Does the damn thing work?”

Regressions: “What else is using this code, and will changing it break that code?”

Security: “How would I hack this or misuse it?”

Performance: “Will this take 10 years to run, or is there a faster way to do it?”

Clarity: “If I came back to this in 3 months, will I intuitively know what it’s doing?”

Style: “Is this easy to read and does it conform to the appropriate style guide?”

In this post I’m going to walk you through a simple, single line method written in Ruby. Here it is:

def anItem

@item = Note.findby(params[:id])

end

This is a bad block of code. Like really bad. To be honest, I don’t think I’ve ever seen one this bad. Thankfully.

Let’s assume this is a private method in a Rails controller that might look something like this:

class NotesController < ApplicationController

before_action :set_note def show

respond_to do |format|

format.html

end

end private # Our code here end

There are 6 things wrong with this method, namely the 6 things in our list above. Below, we’ll address each of these issues and talk a bit about techniques for how to avoid writing horrible, no good, very bad code like this.

And not just for Ruby! Our example code is Ruby, but these suggestions will (hopefully) be generic enough to be applied to other languages as well.

This post is geared towards new-ish developers looking to take their skills to the next level, but I’m hoping most people will be able to take something away from it.

If you think a section could be improved or added to, please comment on it! I’d love to make this as valuable as possible for everyone who reads it, and I certainly don’t have all the answers.

Okay, here we go!

Functional

This is the most obvious section is this post. Simply put, your code needs to work. The code we have will not even run, because `findby` is not an ActiveRecord method (it’s `find_by`). Let’s fix our code:

def anItem

@item = Note.find_by(params[:id])

end

Okay, looks a bit better. I can see this method actually doing something. It still has a regression, but we’ll fix that in the next section.

As far as helping you out with getting better at this step, I don’t have too much for you. Learning programming syntax is not the focus of this post, but I will say this: as a new developer, I seriously undervalued documentation because it was so freaking verbose.

Don’t do that.

With the insane number of programming languages, frameworks and tools to pick from, knowing how to read documentation adds more value than memorizing syntax (that will come as you use the language / framework / tool).

Regressions

Turns out, we’re never even going to get to this method. Why? Well, the programmer before us is using a `before_action` hook at the top of this controller that looks for a `set_note` method. So we need to update our method name:

def set_note

@item = Note.find_by(params[:id])

end

I use two techniques to avoid introducing regressions in code.

First, I look for references to the method / function I’m changing (I’ll use “method” and “function” interchangeably in this post). Where is it called? Are they actually calling this method I’m changing, or is it just one with the same name?

Make grep your best friend, or better yet the_silver_searcher which is faster. Also, editors like Sublime default to showing search results from libraries you've installed or compiled source, so configuring your tools to create less work for you and reduce false positives helps a lot.

Then it’s useful to pay attention to parameters that are being passed into the function you’re refactoring. Don’t need them for your use case? 10 bucks says they’re important, so don’t just remove them! Go find where this method is being called and what’s being passed in, and make sure you account for those use cases as well.

Testing frameworks really shine when it comes to reducing regressions. When my team and I were working on the first pass of our product we didn't have any tests and couldn't deploy code without breaking something. Once we added even a hundred tests, this became almost a non-issue.

Security

Do you want to be the developer who writes that one line of code that causes a Jeep to crash, United to cancel thousands of flights or even a bullet to go the wrong direction?

I didn't think so. So please, always, ask yourself this when you’re writing code: “How would I hack this?”

Right now, ours is susceptible to a simple SQL injection, due to an incorrect use of `find_by`.

Um, let’s fix that:

def set_note

@item = Note.find_by(id: params[:id])

end

Much better.

So this is just one small vulnerability ― how about all the other ones to consider? I can tell you from personal experience that this book will teach you more than a college degree in computer security (seriously!). It might be a bit dated now, but I’m sure there are newer versions just as good.

Yeah, 720 pages is long, but so is the amount of time you’ll need to wait for people to forget your name when you’re responsible for the vulnerability that exposed their… “sensitive information”.

Performance

Performance has a huge impact on today’s users, who are accustomed to pages loading in a few milliseconds and didn't grow up when configuring your browser to ignore images so the page would load was a common trick.

In our example, the performance degradation wouldn't be that noticeable. Unless of course our “notes” database table doesn't have an index on the “id” column and a few million records, in which case you’re very likely to notice.

Why? Well, what if we wanted to use `set_note` a few times in the same request? Right now it would re-query the database each time we call `set_note`, but here’s how to fix it:

def set_note

@item ||= Note.find_by(id: params[:id])

end

This will coalesce `@item`, which means the portion after the `=` is only called if `@item` is `nil` or falsy.

If we’re going to call this method multiple times (probably not the case here, but very likely in other situations) we want to avoid repeating work, namely doing a non-index scan on the “notes” table.

Learning about performance is a very big subject, but to learn the basics I’d suggest reading articles about database performance like the ones here and learning about various (basic) data structure performance. Tools like `EXPLAIN` in PostgreSQL can also come in handy for evaluating queries you've constructed and help you spot problem areas.

Clarity

Well, we've come a long way from that initial messy, broken function! Now let’s make sure that what we've written is clear to future developers.

One issue I see right now is that this method is defining something called `@item`, but we can be more specific:

def set_note

@note ||= Note.find_by(id: params[:id])

end

Much better, this makes much more sense. We’re setting a note, so calling it `@item` just doesn't seem right.

It’s hard to illustrate an improvement in clarity in such a short function, but writing clean code is a huge part of being a developer. Having a good understanding of the correct style is part of it (see below), and beyond that the best way to learn this is just to read other people’s code.

Go take a look at a GitHub repository with a lot of stars, or find a prominent open source developer and take a look at their code. No guarantees that their code will set a good example for you, but it’s a great place to start!

Style

Many programming languages (or even larger companies) have predetermined style rules that your code should only follow. For example, for Ruby we have this one and Python gets official with PEP8.

Our code is almost correct, and it might be hard to spot the issue using Medium’s code blocks, but we actually have two extra spaces to remove:

def set_note

@note ||= Note.find_by(id: params[:id])

end

To familiarize yourself with these rules I suggest reviewing the style guide for the language(s) you’re working with and linting your code (which checks for style guide violations).

Summary

That’s all I have for you! I hope this has been useful.

Remember:

Code is not written in a vacuum.

By recognizing this and writing code that takes it into account, you’ll become a better developer and have a greater appreciation for each line of code you write.

If you want to get in touch with me, hit me up on Twitter or comment on this post.

Cheers!