Object-Oriented vs. Functional Programming

Published July 13, 2014, by @jhendge

All programming is not made equal

As a relative noob to the programming game, I always knew there were a variety of different programming languages that each existed to perform slightly, or in some cases totally, different things. I knew that HTML was used to build websites and that JavaScript, not Java, helped to make them more dynamic. I knew that C (yes, just "C") was popular for programming games and that there were a whole host of other languages with curious names like C++, C#, Perl, PHP, Pascal, and Ruby which I had practically no clue what they did but I knew they sounded pretty awesome.

What I didn't know was that these languages are actually split into different groups based on what kind of programming they perform. For instance, Ruby is part of the object-oriented programming (OOP) family and the OOP family alone. Others, like C++, are more versatile in nature and can be a part of a number of groups. C++ can perform imperative, structured, procedural, and OOP. Wow! But for the sake of this blog post and our precious time, I'm going to focus on just two of our programming groups: object-oriented and functional programming (FP).

While countless articles, white pages, and blog posts have been written about the differences between the aforementioned programming groups, my goal is not to try and compile all of that information into a sort of magnum opus blog post filled with technical jargon and hell bent on making sure I fulfill my "explanation" requirement while leaving you to choke on the dust of convoluted examples and misguided logic. Rather, my goal is to be direct and succinct. As a result, some of the following might come across as "short" and the reason for that is twofold: 1) these programming groups can be thought of as deep wells and the further you go down the well, the more intricate and complex the group becomes. As such, I'd only like to present you with a scoop of information from the top! 2) Programming is supposed to be fun so there's no point in scaring people away with things like, "side effects through monads" and "referential transparency" so let's move on before I make my own head hurt!

You down with OOP?

At Dev Bootcamp, our primary focus is on class-based object-oriented languages such as Ruby. But what does "class-based object-oriented" even mean? Well, writing code suggests that we are creating or using existing data (for instance, variables) and doing something with it, giving it some kind of behavior. In Ruby, data and its corresponding behavior are wrapped together in one nice, pretty package called... wait for it... an object. Everything in Ruby is an object. And these objects have behavior that is inherit to them and to the classes that they belong to.

Classes, while they are not specifically referred to as objects, are indeed objects! They are objects that are organized to hold other objects. The reason why this is so very crucial and a key differentiating point between OOP and other forms of programming, such as functional, is because the operations that work with specific objects are built into the objects themselves instead of into the syntax of the language. Think about that... Because certain behaviors are built into objects, we do not need to re-code the behavior every time we want to use the object, it is already there. We can then manipulate objects or combine them to create new objects with new behaviors. The possibilities are seemingly endless. If behavior was built into the syntax and not the objects themselves, we would be limited to how the language was written and confined to the walls of its code. We could only do so much.

Now we can answer the question as to what a "class-based object-oriented" language is. Class-based OO languages like Ruby allow you to define a class that provides a blueprint for the construction of similar objects. A class defines methods (definitions of behavior) and attributes (definitions of variables). Objects invoke one another's behavior by sending each other messages and methods get called on in response to messages. As such, it is up to Ruby to find and invoke the right method of the correct object for any message sent.

The nice part about Ruby is that we don't have to create tons of new classes (though we totally can), it comes with a number of predefined classes. There's a String class that defines strings (letters, words, etc.) and one another, Fixnum, which defines integers. There's actually a pre-existing class for every data type that you would expect a programming language to supply. But as I mentioned above, since classes are objects and objects' inherent behavior can be altered, we aren't limited to a small set of built-in types and pre-predefined operations. Instead, we can invent brand new types on our own. Each OO application thus gradually becomes a unique programming language that is specifically tailored to our own domain.

Now you might be wondering to yourself, "If we can customize our OOP language to fit our needs and do what we want, then why aren't all languages written like this? What does functional programming bring to the table?" Well, let's check out FP and see how it differs from OOP.

(Fun)ctional programming?

In FP, programs are executed by evaluating expressions (like mathematical expressions!), whereas with OOP, programs are composed of methods and statements which change the state of objects. Since mathematical expressions are typically seen in academia, FP has long been popular in that sphere. After all, the primary focus of FP is on the return values of functions and that's not really what Ruby and other OOP languages are all about.

OOP programs tend to emphasize the series of steps taken by a program in carrying out an action, while functional programs tend to focus on the composition and arrangement of functions, often without specifying steps. In this sense, FP and OOP are opposites. In order to highlight this, I have included an example below which illustrates the difference between how an OOP language like Ruby or Python might deal with calculating Fibonacci numbers and how an FP language such as Haskell would handle it.

Ruby

Haskell

Unlike in OOP code where a program's output is dependent upon variable definitions, classes, and more, FP emphasizes functions that produce results that depend only on their inputs and not on the program state (*cough* *cough* mathematical functions). In functional code, the output value of a function depends only on the arguments that are input to the function, so calling a function f twice with the same value for an argument x will produce the same result f(x) both times. As part of this, and consequently also a huge difference between FP and OOP, is that it is best to eliminate side effects, changes in state that do not depend on the function inputs, so that it is easier to understand and predict the behavior of the program.

Now that we know a little bit about FP and how it is different from OOP, how do we know when to choose functional programming over object-oriented? Well as we've seen, OO languages are suitable when you have a fixed set of operations on things and, as the program's code evolves, new things will be added. This can be accomplished by adding new classes which implement existing methods, and the existing classes are left alone. On the other hand, functional languages are preferred when you have a fixed set of things and, as the program's code evolves, new operations are added to existing things. This can be accomplished by adding new functions which compute with data types, and the existing functions are left alone.

Phew! Time to breathe. I'm afraid that if I take one step further, all of our heads might spontaneously combust so let's take a break right here.