A few weeks ago, we discussed one of the major developers' holy wars – which is better: native or cross-platform applications. Now it’s the time for the second one – functional programming or OOP.
Before diving in, here’s a brief description of each paradigm to clarify what, exactly, they promote.
OOP is a software development paradigm based on the concept of objects which usually include data in the form of attributes and procedures in the form of methods. Methods can access and alter data stored in attributes.
In OOP, objects are normally instances of a class and are considered to be separate entities that can interact with each other.
Let's imagine, for example, that we're writing a simple program for a Harry Potter's Sorting Hat. This is how it would look in Ruby:
We are creating a class – Student – for every newcomer. Assuming each of them has a name and is assigned to one of four houses, we initialize name and house attributes. Since it’s possible that some students could suddenly turn out to be someone's heir or refuse to go to Slytherin, having a method that reassigns these faculties would be very handy.
Object-oriented programming key features
So, to make a long story short, let's mark up the main features of the OOP paradigm:
- Abstraction: It helps a programmer hide all but the important data, thus making the development process less complex and more effective.
- Inheritance: It allows attributes and methods to be duplicated from a base class to a derived one.
- Polymorphism: It allows one task to be handled in different ways with overloading and overriding.
- Encapsulation: It hides all sensitive data from a user, thus minimizing the risk of unauthorized access.
- In OOP, objects can be reused, maintained and modified in other apps.
- OOP manages memory effectively and is very advantageous for creating large applications. Since you can divide a large program into smaller components, it also helps with identifying the elements or equations that need to be run in a certain way.
In a nutshell, FP focuses on the behavior of a program – not on the data. Objects can't be modified and share no scope with each other. Functions, though, are treated like royalty.
Functional programming key features
- FP unites concepts like higher order functions (functions that take functions as arguments or returns functions), pure functions (functions in which return values depend only on income values and can't be affected by DB calls or other side effects), anonymous functions (those assigned to a variables ), recursion and referential transparency (meaning that you can replace an expression according to its value without affecting the result of the program)
- FP offers high performance, lazy evaluation, lower bug rate, support of parallel programming and many other useful benefits.
- Functions can be reused, meaning you don't need to rewrite the same statement several times for different cases but can use the same one instead.
- FP languages are Lisp, Clojure, Wolfram, Erlang, Haskell, F#, R, etc.
OOP vs FP
To make the difference more obvious, we'll review both approaches via an example.
Let's imagine we are professor Snape, who woke up on the wrong side of the bed. To make the morning a little bit brighter, we decide to evaluate all Gryffindor students' homework as poor.
Here's how we would act using our programming paradigms:
- Create a Student class with name and mark attributes as well as change_mark method.
- Create instances of students.
- Use the each method to change their marks to “Poor” or even “Troll”.
- Create an array of arrays with name and marks called Students.
- Create a change_mark function that returns a copy of a student and his/her updated mark.
- Create a function that maps through the Students array and calls the change_mark function for every student.
- Use both functions to create a dataset named Stupid_Students and rejoice.
As you can see from the comparison, each approach manages data in a completely different ways. Since OOP creates instances with mutable data and built-in functions, it's almost impossible to define if the function was called. FP maps through the array and returns the new one as a result. Thus, we can be 100% confident that the changes were applied.
You can discover more about the major differences between the two approaches in the vivid infographic below:
What’s the dispute about?
Both approaches have their fans and opponents. OOP fans argue that concepts of encapsulation and inheritance make data manageable, allow a larger portion of code to reused and minimize the chance of unauthorized access to valuable data.
Controversially, FP fans emphasize that the higher level of abstraction, reached by the separation of data and processes, reduces the rate of mistakes.
Even though functional and object-oriented programming are quite polar concepts, they pursue the same goal – the creation of easy-to-understand, bug-free and effective programs – and both do their job well.
So, the right question is not which method is better but which best solves your problem.
And even if you use the optimal paradigm, your program risks falling apart if it becomes too complex. The problem is that it's rather hard to avoid complexity in large projects that involve many people. Such cases may require your team to create a hybrid approach that unites the advantages of both methods.
Such solutions require a high level of expertise and vast prior experience. If you're looking for specialists like that, feel free to contact us for consultation.