OOP vs Functional vs Procedural
Learn via video courses
Overview
Over the years, various requirements and developer practices lead to different programming paradigms, which are Procedural programming, Object-oriented programming, and Functional programming.
Procedural programming organizes the code into chunks of procedures, Object-oriented code helps the programmer think of objects which represent a concept or real-world component, and Functional programming orients the programmer in the world of pure functions. In this article, we will discuss the difference between these three paradigms of interest.
Scope of article
- In this article we will discuss the difference between Procedural, OOP, and Functional Programming in detail.
- We will also see their use cases in various situations.
Introduction
Throughout the course of human history, we have encountered problems and discovered solutions. We form a set of beliefs about factors that contribute to the problem, and we form patterns of solutions that have helped to tackle similar problems. In time, we confirm our formed beliefs against evidence that verify our methods. Different problem domains have different paradigms. (A paradigm is a set of concepts that reflects our current understanding of the field and practices that model how one might express existing solutions.)
Programming languages are tools for solving particular problems. Programming paradigms are a set of rules that prescribes an approach to thinking about the problem. Programming languages support a set of paradigms that one can use to implement algorithms. Some programming languages are adherent to a single or multiple set of paradigms. Lisp advocated functional programming, C endorsed procedural programming, and Simula subscribed to Object-Orientation. Modern programming languages support more than one paradigm of programming.
The knowledge of more than one paradigm expands the mind to create and express innovative algorithms.
We will discuss each of the three paradigms in the subsequent sections.
Procedural Programming
The basic construct of procedural programming is blocks of code known as procedures or routines. Procedures contain sequence instructions that specify a computational step carried out upon execution.
Features of Procedural Programming
- Scoping: Scoping refers to a concept that sets the locality of entities (objects) in a procedural program. Scoping keeps procedures modularized by preventing one from accessing non-local variables from other procedures without explicit clearance.
- Modularity: It is a technique that organizes functionality into interchangeable chunks (pieces) of modules that encourage reusability and enables code sharing.
- Parameter Passing: A mechanism that moderates how parameters might get passed into a procedure call. Parameters may be passed by reference or passed by value.
Advantages of Procedural Programming
- Easy and Simple: It is relatively simple and easy to implement compilers and interpreters that parse through a Procedural program. By the same token, this approach is simple to learn and practice.
- Modularized Programs: Procedural programs are modularizable, which lessens redundancy and increases productivity.
- Better Organized: Concepts are better contained and organized in a module which can be combined together to build new modules.
- General-purpose: Great for general-purpose programming.
Disadvantages of Procedural Programming
- Exposed Data: Data is exposed publicly. There is no restriction to accessing and modifying data. This causes unintended alteration and increases the chances of committing serious mistakes that are hard to keep track of.
- Procedural approach: The focus of this approach is procedures - rather than data organization. This can obscure the thought process of mapping concepts into code.
Languages that follow Procedural Programming
- C
- C++
- Python
- Dart
- Swift
- Algol
- Ada
- Rust
- Bash
- PowerShell
Object-Oriented Programming (OOP)
The main building block of OOP are objects that represent a mental model of an actual object in the real world. An object has an internal state of attributes (or properties) and a group of associated actions (or behavior) that implements a mental model of an object in the real world.
For example, we can model a car as an object that can start, accelerate, and stop. A car also has a model name and speed, which are represented in its attributes. The main idea behind OOP is to communicate with objects through their public attributes.
OOP Principles
-
Abstraction. The process of hiding the implementation details and showing what is only necessary to the outside world. The outside world can interact with an object through its interface. For e.g., A user only knows how to use an application like WhatsApp, and other things like codes are hidden from the user.
-
Encapsulation. Encapsulation can be defined as wrapping the code or methods (properties) and the related fields or variables together as a single unit. TThe variables or fields can be accessed or updated only by getter or setter methods and can be hidden from the other classes using the private access modifier.
-
Inheritance. It refers to a concept where a subclass, also known as a child class or derived class, is the class that inherits the properties and behaviors of another class known as the superclass. The subclass can then access to methods and attributes of a superclass and add more methods and attributes. For e.g., A BMW car inherits the property of a CAR, while a CAR inherits the property of a VEHICLE.
-
Polymorphism. The process allows one name to take many forms. It allows the same object to behave differently depending on the context. OOP allows two forms of polymorphism:
- Runtime polymorphism (Overriding) - allows a function to override the previous implementation of a method inside the superclass.
- Compile-time polymorphism (Overloading) - allows a function to have multiple implementations based on function signature.
For e.g., A man at the same time is a son, a father, and a husband. Hence, the same person holds different behavior under different conditions.
Advantages and Disadvantages
Advantages of Object-Oriented Programming
- Direct mapping of concepts and methods: Organization of concepts is simple to express. The concepts and methods in a problem domain can be mapped directly in Object-Oriented programs.
- Extensible codebase: With the right design, Object-Oriented programs are made to scale. The hierarchy of concepts is easy to impose.
- Simple Object Interaction: Provides a simple way for objects to interact and communicate with other objects.
- Less Redundant: Reusable software components. Less redundant codebase.
- Safe and Secure: Encapsulation allows data to be hidden, which increases resource safety.
Disadvantages of Object-Oriented Programming
- Requires more effort: It requires some amount of work to implement parallelizable programs.
- Not straightforward to reason with: Bad design can lead to an unnecessary amount of indirections that result in unreadable esoteric code.
- Larger Programs: Often results in larger programs than procedural code.
Languages that follow Object-Oriented Programming
- Simula
- Ruby
- Python
- Small Talk
- JavaScript
- TypeScript
- Dart
- Java
- C#
- C++
Functional Programming
The basic units of functional programming are functions. In this paradigm, functions are first-class citizens of the language. We can assign a function to a variable, pass it as an argument or return it from a function just like a regular variable. That means a function can be defined and invoked in any context just as much as a variable can. The idea is to remove the difference between functions and data.
Concepts and Terminology of Functional Programming
This section introduces the core concepts and terminologies behind functional programming.
Terminologies
- Side effect - Refers to the act of modifying non-local attributes inside a function. Programming languages that allow side effects are known as impure functional languages.
- Immutability - values assigned to a variable are unable to change throughout the program.
- Functional Composition - The act of applying functions to another function and chaining them together, e.g. f(g(x)).
Core Concepts
- Ad Hoc Polymorphism: A mechanism that allows a compiler/interpreter to distinguish which implementation of a function is invoked based on the types of arguments a function is called. This is otherwise known as overloading, where functions may have multiple implementations for different parameter types or signatures.
- Subtyping: A method of defining a subset-superset relationship among types. For instance, a Cat and a Dog are subtypes of an Animal.
- First-class functions: These functions are treated like any other variable. For example, in such a language, a function can be passed as an argument to other functions, can be returned by another function, and can be assigned as a value to a variable. Example:
- Higher-order functions: These functions take functions as arguments or functions that return functions. This is possible because functions and data are the same.
- Recursion: It is a functional equivalent of iterative loops where a function calls itself until the base case is met. Most languages that advocate for functional programming optimize the performance overhead of recursion via Tail-Call Optimization or Compiler Optimization, which translates a recursive function into iterative loops.
- Pure Function: A function that returns a value and does not alter the state of a non-local attribute.
- Referential transparency: A mechanism that does not permit one to change the value of a variable once defined. This mechanism guarantees functional programs to be referentially transparent i.e., if a == b, then f(a) == f(b). This property of purely functional languages makes programs easier to reason and optimize.
Note:
Tail-call optimization is where you are able to avoid allocating a new stack frame for a function because the calling function will simply return the value that it gets from the called function.
Advantages and Disadvantages
Advantages of Functional Programming
- Easier to model and reason: Programs are easier to prove for correctness because functional programs do not change their states. This makes functional programs easier to model and reason.
- Ideal for concurrent and parallel programming: In Concurrent programming, multiple tasks are executed concurrently (not necessarily simultaneously), while in parallel programming, multiple tasks are executed parallelly (simultaneously).
- Better Compiler Optimization: Compilers can easily optimize and substitute complex expressions into simpler ones. Referential integrity gives the compiler more freedom to re-arrange expressions
- Secured and Safe Programs: Programs are guaranteed to be secured and safe since functions are independent of one another. Resource leaks and accidental modification of critical information is no longer a problem.
- Elegant Programs: Allows you to express elegant programs.
Disadvantages of Functional Programming
- Costly: Immutability may cost significant resources since every value counts for a new space in memory.
- Performance Overhead: Compilers that do not optimize for recursion will incur significant performance overhead.
- Difficult: Writing functional programs requires you to think mathematically. That means it imposes a mathematical model for programs that is not the most convenient way of organizing concepts. In other words, it is not easy to write functional programs.
Languages that follow Functional Programming
- Lisp
- Haskell
- Scala
- Julia
- R
- C++
- Python
- Java
- C#
- Swift
Difference between Functional vs. Object-Oriented vs. Procedural Programming
Functional Programming | Object Oriented Programming | Procedural Programming |
---|---|---|
Data and functions are the same things; the main focus is on function composition. | Objects are composed of methods and attributes; the main focus is communication among objects. | Data and functions are not the same; the focus is on procedures (operations). |
Ideal for concurrent and parallel programming | Ideal for scalable software systems | Ideal for general-purpose programming |
For pure functional programming, data are immutable. | Data and methods can be hidden. | Data is exposed, and it can be changed in any context. |
Declarative style: Developer describes what your objectives are in code | Imperative style: Developer specifies how to reach the goal in code. | Imperative style: Developer specifies how to reach the goal in code. |
Code is organized into functions and modules. | Code is organized into objects. | Code is organized into modules and procedures. |
Conclusion
- Programming paradigms provide a pattern of thinking about approaching a problem.
- Such paradigms consist of principles and methods that govern the practice.
- Procedural programming gives focuses on procedures (operations) rather than data. Procedural programs are reusable, modular, and ideal for general-purpose programming.
- Object-Oriented programming maintains the idea that everything can be modeled in objects.
- Object-Oriented programming is ideal for scalable software systems because objects are highly reusable.
- Functional programming maintains the idea that functions are data. Hence, it can be declared and called in any context that a piece of data might appear.
- Functional programming is ideal for concurrent programming and has two major categories: pure and impure functional programming.