Forward Slash.

a codetrip to the wild west

A Conversation About Abstraction

Today, rather than an educational presentation, I wanted to have an open dialogue about abstraction when we write code. What is it? Why is it great? Is it ever bad?

First of all, what exactly is abstraction? I would define it as the removal of details so that whatever thing it is we’re abstracting moves farther and farther away from the literal representation of itself. Abstraction is wonderful for programmers because it allows us to create dynamic code that can be used and reused again without having to actually type out every line each time. The best way for me to describe it would be with some examples.

Let’s take this series of methods from a lab we did in class the other day:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def build_artists_index
  FileUtils.mkdir_p(rendered_path + "/artists")

  template = File.read("./app/views/artists/index.html.erb")
  page = ERB.new(template).result(binding)
  File.write("#{rendered_path}/artists/index.html", page)
end

def build_genres_index
  FileUtils.mkdir_p(rendered_path + "/genres")

  template = File.read("./app/views/genres/index.html.erb")
  page = ERB.new(template).result(binding)
  File.write("#{rendered_path}/genres/index.html", page)
end

def build_songs_index
  FileUtils.mkdir_p(rendered_path + "/songs")

  template = File.read("./app/views/songs/index.html.erb")
  page = ERB.new(template).result(binding)
  File.write("#{rendered_path}/songs/index.html", page)
end

These are pretty much all the same method except for one part of the path so we can abstract it by creating another method which all of these methods can call, so we only have to type those four lines of code once. Like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def gen_index(dir="")
  FileUtils.mkdir_p(rendered_path + dir)

  template = File.read("./app/views#{dir}/index.html.erb")
  page = ERB.new(template).result(binding)
  File.write("#{rendered_path}#{dir}/index.html", page)
end

def build_artists_index
  gen_index("/artists")
end

def build_genres_index
  gen_index("/genres")
end

def build_songs_index
  gen_index("/songs")
end

There are ways to abstract this further so we only have to call the method once instead of three times, but I don’t want to confuse you too much.

Another example which we (at the Flatiron School!) have been working with lately is ActiveRecord. It’s an extremely useful class which wraps up a whole bunch of methods for you (so you don’t have to write them yourself, you can simply reap their benefits by calling them) to make extracting, creating, and persisting data to a database very easy. It writes all your sql statements for you, so you can continue working blissfully with ruby.

I think it’s pretty clear how powerful abstraction can be. I helps us be more efficient, less redundant, and make beautiful code. However, something I have been pondering lately is this: is there ever a point in which we have abstracted something too much? I would say yes. Let’s look at those flowers up top. Now draw a line on a piece of paper. I’m telling you now that the line you just drew is an abstract flower. What do you think? That’s stupid isn’t it? Because it’s unrecognizable. It looks like nothing in particular, but it’s actually an abstract flower, you just can’t tell.

Now, over-abstracting code isn’t as simple as that, but if you wrote some super clever and abstract code, then look back at it a month later and have no clue how it’s actually working, I might consider it a little too abstract. That being said, I also think it depends on how experienced you and the people around you are. Take someone like me, at this point in my programming education, I need most things to be on the explicit side, but five years in, I’ll probably be writing two lines of Ruby in what takes me 50 lines to do now, but as long as I (and the people I work with) can still understand its functions, I say: abstract away.