Getty Images

Tip

Functional vs. object-oriented programming: The basics

Choosing between functional programming vs. object-oriented programming isn't easy, but there are plenty of key factors that may help make the decision easier.

Committing to a programming paradigm is an important step in any application development effort. While they are hardly the only two options when it comes to overarching development models, the choice between functional programming and object-oriented programming is one that an increasing number of developers face today.

Object-oriented programming is a widely accepted development approach, and often underlies the structured programs most developers learn to write in the early stages of their career. Many of these languages include elements that are almost indistinguishable from functions, but they're a far cry from the mechanisms behind a purely functional programming language such as Haskell.

In this piece, we'll review the major differences between functional and object-oriented programming, offer up a few examples of how they work, and review the considerations that matter most when making the choice between these coding paradigms.

Functional vs. object-oriented programming methods

In essence, functional programs behave like common math functions, such as the calculations behind a conversion from Celsius to Fahrenheit. With functions, the same inputs consistently lead to the same result. A "pure" function is deterministic and will not produce side effects -- in other words, it will always return the same value when called and will not modify anything outside of its scope or parameters.

One incredibly powerful example of the functional method is Google's implementation of MapReduce and its approach to returning results to certain search terms. MapReduce connects search terms in the form of key/value pairs using a function called reduce. This process aggregates the terms and assigns each one a value that will indicate what type of result it should return. Given the same data set, Google will spit out the same answer every time without side effects.

On the other hand, object-oriented programming can contain state-dependent variables, which means objects don't necessarily retain consistent values. For example, if you call a method that returns a salary, you may get $50,000 back. But if you run a method that adds 10% to that total, then ask for the salary again, the returned value is $55,000. Object-oriented programs may also contain things like global variables and static variables that will make the responses to requests different every time.

To add state to functional programs, use a programming language that is not purely functional, such as F#. You could also add functions to a more traditional program such as LINQ.

Code examples for functional programming vs. object-oriented programming

The following is a code example for functional programming featuring the FizzBuzz coding challenge in F#. FizzBuzz is a common coding test where developers create a program that prints a series of letters and numbers based on a simple set of rules. First, if the number is divisible by three, print the word Fizz in its place. Next, for numbers divisible by five, substitute the word Buzz. Finally, if the number is divisible by both three and five, print FizzBuzz. In a functional language, such as F#, this logic can be structured as functions. The program is composed entirely out of those functions, as shown in the example below.

open System

let isFizzBuzz value =
 (value % 15) = 0

let isFizz value =
 (value % 3) = 0

let isBuzz value =
 (value % 5) = 0

let output (value : int) =
 if isFizzBuzz value then
   "FizzBuzz"
 else if isFizz value then
   "Fizz"
 else if isBuzz value then
   "Buzz"
 else
   string value

[< EntryPoint >]
let main argv =
 let message =
   seq { for i in 1..100 do output i}
   |> String.concat " "
 printfn "%s" message
 printfn "Done"

Next, we'll review the object-oriented approach using C# as the language. While the logic is similar, the big difference with the object-oriented approach is that it is wrapped in an object that keeps the current number of the loop as a variable.

There are a few advantages to this object-oriented approach. First, if the application is constructed of a series of logic, the objects can interact through simplified interfaces. Second, to make a series of games similar to FizzBuzz, a programmer could use inheritance to add and change logic as needed. Here's the C# implementation as a class, as well as a more traditional main routine to perform the print process.

public class Fizzer {
   private int _val;
        
   public Fizzer() {
     _val = 1;
   }
 
   public string getNewVal() {
       string answer = "";
       if (_val%5==0) answer = "Fizz";

       if (_val%3==0) answer+= "Buzz";

       if (!(_val%3==0 || _val%5==0)) answer = Convert.ToString(_val);
 
       answer+="\n";
       _val+=1;
       return answer;
   }
}

class Program {
    static void Main(string[] args) {
        Fizzer f = new Fizzer();
        for (int idx=1;idx<100;idx++){
            Console.Write(f.getNewVal());
        }
    }   
}

For a higher level of abstraction, an object could loop through from start to finish and call the method. This is useful when the programmer wants to swap games at runtime, or build the program using rules from a file that might change over time. To see an actual object-oriented implementation of FizzBuzz, look at this C# object-oriented example from Steve Poling, a former software engineer and technical consultant at Excelon Development. Notice that there are more lines of code that may have value for reuse.

Use cases for functional programming vs. object-oriented programming

User interface design is a natural fit for the object-oriented approach. The windows that appear on a user's screen are often built using buttons, text boxes and menus. These windows have state -- for example, with the text on a page in a word processor, the state changes as the user types. Once the basic layout of a window is available, other programmers can inherit and reuse that code, starting with a shell and filling in the objects.

Functional programming is the best option when the application will be composed of functions that build upon one other. For example, in Unix it is common to tie together a large number of small programs, sending the results of a process listing to a specific search like grep, or to one page at a time with less.

Combining functional and object-oriented programming

An unfortunate downside of object-oriented programming is the risk of creating a complex code base that becomes increasingly difficult to manage over time. Even for sophisticated development shops that use the object-oriented approach, the code often resembles the example above -- a few objects scattered amongst a fair amount of procedural code.

It can be difficult to test or debug objects that create other objects or have ties to external databases and APIs. In the event of an error, the programmer is unlikely to know the values in all of the objects or exactly how to replicate them, even with a full record of the error. There are certainly some design patterns that address these issues, but industry adoption of these patterns is somewhat limited. At any rate, development shops committed to the object-oriented approach are often challenged by difficult code reviews and maintenance projects.

Functional programming, meanwhile, presents a different challenge: It can be very hard to learn and put into practice. The functional approach requires an entirely different form of thinking about code, a considerable time investment and rigorous attention to detail. For these reasons, IT leadership may see functional programming as a risk.

However, there is a middle ground. Programmers could use the functional approach to create a small part of a major application. Any logic that takes data and produces results in batch is a good candidate for this strategy. This includes insurance quoting routines, product scheduling, and extract, transform and load. It's also possible to add state to functional programs by using a programming language that is not purely functional, such as F#.

It's similarly possible to add functions to programs based in traditional, object-oriented languages. For instance, languages such as C# and Java now possess features that enable a functional approach. One of these features includes the ability to write code in F# that interoperates with C# through the Common Language Runtime.

Dig Deeper on Enterprise application architecture

SearchSoftwareQuality
SearchCloudComputing
TheServerSide.com
Close