The Gist
Different programming languages have different features, or paradigms, that can be used to classify them.
Today we'll take a look at two of the most talked about, functional and object-oriented.
Edit #1: And as Adam pointed out, the two are not pitted against each other, they're just different! These are only two of a wide array of varying approaches that could all server(typos are the best puns) you better, so never stop doing your research!
The What
Firstly, let's take a look at some of the commonalities
- Things either approach will have to deal with
- Data
- what your program wants to KNOW and USE
- Behavior
- what your program is looking to DO and HOW
- Data
There's a reason why most coding boot camps start you off with ruby, or python, and that's because they're both very eye-friendly languages. Let's use Ruby for our walk through!
Object-Oriented Programming(OOP)
- Classes often used to generate object instances
- Class defines the attributes with which we want to imbue our object.
- We will give our class "instance methods", which will exist within our object.
- These instance methods can be called on the object itself.
- "initialize", is not an instance method, but instead tells the class what attributes it will have at the moment of it's creation.
- Every new instance of our object will contain preset data and behavior
- As noted above, data will be provided to our instance upon creation
- We then use methods on our instance object to manipulate it's data
- All of the important information our objects contain is stored safely within their classes. If you can imagine being an engineer at a fairly large company, with a lot of pre-written code, you can also see where this would come in handy.
-
Core Concepts
- Abstraction
- Inheritance
- Polymorphism
- Encapsulation
class Cat def initialize(name, mood) @name = name @mood = mood end def change_name(name) @name=name end def change_mood(mood) @mood = mood end end kuma = Cat.new("Kuma", "mischievous")
What happened above?
- We created a Cat class, or blue-print, for what we want to be able to do with our Cat instances
- We initialized our Cat with a name and mood. If you've ever hung out with cats, you'll know their mood is the second thing you remember about them after their name.
Now let's change their name and mood!
kuma.change_name("Grapefruit") kuma.name # "Grapefruit" kuma.change_mood("post-meal-happy") kuma.mood # "post-meal-happy"
What happened above?
- Using the change_name() method allowed us to change the name of our Cat class instance object
- Using the change_mood() method allowed us to change the mood of our Cat class instance object
- Our initialize method will take the name and mood we passed to our Cat object and store that information, so that we can easily access it later on
- '@' symbols are used for instance variables, these exist in an object(instance) and is used without being passed in
Functional Programming(FP)
- Uses a series of small methods that each do their own specific job.
- Implements composition or building of large tasks with smaller ones, which is also used in OOP languages, but it's pivotal to FP ones.
- Objects are immutable, can't be changed after being created
- Best fit for data science work
- A function is reusable
-
Core Concepts
- Higher Order Functions
- Pure Functions
- Recursion
- Strict & Non-Strict Evaluation
- Type Systems
- Referential Transparency
def doesOneThing(number){ return number * number end
What happened above?
- Above we have an example of a pure function
- The same value will always be returned, as long as the same input is given
- There is no other operation occurring within the function that could alter our result
- An instant benefit is fewer lines of code!
- In FP, we will be viewing every thing we do as transforming data by applying some sort of operation on it, and then returning a new data set
- We also often times default to using a map method, instead of each, which creates a new copy of the data and stores it in an array. The original array is unscathed as in FP, immutability of our data is key
- Immutability allows us to keep track of our data's value
Comparison Table
Topic | FP | OOP |
---|---|---|
DEFINITION | emphasizes evaluation of functions | based on concept of objects |
DATA | immutable | mutable |
MODEL | declarative programming | imperative programming |
SUPPORT | parallel programming supported | No Support |
EXECUTION | statements can be executed in any order | Need an order |
ITERATION | Recursion | Loops |
BASIC ELEMENTS | Functions & Variables | Objects & Methods |
USES | Few things with need for more operations | Many things with few operations |
But which one?
Well, as per this sick stackoverflow post, here are some key concepts to keep in mind when considering these two very popular approaches.
OOP
- Helpful when dealing with a fixed set of operations on things
- As your code evolves, you add new things
- this means that you add new classes, which make use of existing methods
- existing classes are left alone
Danger Zone
- Adding a new operation may require editing many class definitions to add a new method
FP
- Helpful when you have a fixed set of things
- As your code evolved, you add new operations on things.
- this means you add new functions which compute with existing data types
- existing functions are left alone
Danger Zone
- Add a new thing may require editing many function definitions to add a new case
TLDR;
Object-Oriented Programming uses Classes, objects and methods to achieve it's lofty goals. Functional Programming on the other hand makes use of an army of pure functions and variables to to build a larger whole. Languages dedicated to on or the other each come with their own gotchas (looking at you JavaScript 😭). Make sure to research the communities supporting whatever language or framework you're looking at, and you'll be steered in the somewhat right direction. That is, until you hit a huge bug and try to turn in the other direction...this is ill advised but not impossible. Still though, like adding Redux to your React app, why would you give yourself that extra work? Plan, plan, plannnn!
Top comments (23)
Hi Kurt. Listen... this:
Needs some work. I encourage everyone to explore and to find out whatever thing scratches their itch but OO and FP are not differentiated by classes, methods, objects and pure functions. Yes, these are a few differences but I would encourage you to look deeper (or, if you already have, to describe those differences here) as there's a world of different thought in there!
Currying, for example, is mind-blowing as are functors and monads. For instance, dig this:
That's a lambda in JavaScript which is "Curried" - instead of 3 arguments to a single function we've chained together 3 functions with a single argument. This allows reuse and composition:
The interesting thing is that I can capture/reuse these things functionally thus:
This is just the surface of functional programming and all the interesting things you can do with immutability and functional composition.
Monads (which you can arguably think of as chained promises) allow you to transform data within a transactional process. That's really the thrust of functional programming: data transformation that doesn't involve changing other data (side effects).
OK - I don't want to sound like a jerk! There's so much more here and I encourage people to look deeper :).
This sounds a bit misleading.
Yes, currying is nice, but there is nothing magical about it. You can achieve the same with objects
¯\_(ツ)_/¯
.Immutability is not something that adds capabilities to the system it rather restricts capabilities (you don't have the mutation). It is a trade-off. Developer agrees not to mutate things (as the result they can worry less about some edge cases), but the same time you need more memory (not necessary much more) and new tools (for example, lenses). There is a middle ground, like local mutation allowed and global mutations prohibited, for example in Pony language.
Absolutely not, Rob, not a jerk at all! I always value opinions backed up with evidence, it helps us all learn and grow. Personally I know that I actually need to spend more time looking into currying and monads, and it seems like that information would have helped me to write this article. Thanks for providing so that others who read this can reference your comment and keep on falling into the beautiful rabbit hole that is coding.
I also find OOP enticing when we don't understand the problem domain at all. We start creating objects, they start interacting, damn we're good! Then as you learn the problem domain, you realize that your model doesn't really make sense compared to how it exists in the domain. Now you have to do some major refactoring to match the domain accurately, or you just keep on creating more objects and pretend nothing is wrong.
Functional programming requires you to have a very clear understanding of the problem at hand (at least in my opinion). I also think that sometimes working "insides-out" is really effective to force yourself to get coding. By the time you start stringing something substantial together, you have a pretty good idea of what functions form a good public interface to your program.
haha, yessss, this is exactly what happened to me when I built my first large rails project. I created more objects to plug the holes in a sinking ship and then gave up and how to do a lot of refactoring. But it's also spurred me into looking at different back-end languages like Node and Golang, to see how forgiving either one can be when hitting that wall. Still working through them though. Have you found an OO back-end language where you feel it's easier to do that refactoring?
Hmm...not quite. C# is what I have been using for the past 7 years straight and is the language I know best by far. I'm so used to it, it might be difficult for me to objectively compare things. I think the implementation of generics is really solid, which reduces the number of objects I have to write. My only qualm that is language-specific is that functional programming constructs look really weird and take a ton of code...10 lines of F# can take 100 lines of C#, and the C# code looks hideous with generics everywhere.
I think that having a base Object class inherited by all objects is a huge mistake and brings no value whatsoever. All it does it ensure that I need to do a ton of defensive type checking and reflection whenever I try to compare two objects. There isn't really any behavior that belongs on that level that is applicable to every single object. I believe C++ does not fall victim to this base object mentality, and I have been studying C++ lately to try and get back into embedded/AI stuff.
Ironically, I have also been looking into Ruby because I have heard it is a developer's language and a really enjoyable experience. I have not gotten to the point of appreciating much of it, but I am going to keep trying, dammit!
I also played around with Racket (a Scheme dialog) and found myself intrigued by LISPs. Blurring the line between code and data is pretty neat, but sometimes it's so abstract that I have no idea if what I am doing works. And no way in hell I could explain the code to someone else confidently.
Honestly, maybe TypeScript? I like the typing because it prevents a bunch of stupid errors and guarantees some consistency between objects. It's such an easy language to hack around in, but most uses these days seem too primitive. Why deal with Express and write the same middleware that a million other developers have written to? Why not abstract that all away to a more mature back-end runtime? I guess that's the downside to needing thousands of random dependencies to accomplish anything, big building blocks are hard.
This a good post to show pals the differences between these two paradigms.
We're just all out here trying to get a handle on a wide range of topics, myself included. Glad I could put together some information in one place for you and the gang. Y cómete una arepa de choclo con quesito por mi porfa, tengo una tía Colombiana en Chile qué me las haćia!
jajajaj la arepa de choclo es popular en antioquia. Yo vivo en la costa norte, acá comemos es arepa con huevooo :D
It does not help to keep calling FP "declarative".
Functional programming is just as far from anything truly "declarative" as OOP.
Both paradigms are very low level and do not really help to adequately represent the complexities of the real world problems. More declarative paradigms fit much better, but for some weird reason people keep comparing FP to OOP, as if there is nothing else out there.
Ha this is true. Probably, OOP and FP are polorizing? There are a lot of ppl who will really dislike one or the other while less so about something more procedural?
I don't know but you are exactly right.
You can have encapsulation in FP as well.
Thanks for the heads up! I did some more research after you mentioned this and found a great article that talks about achieving "pseudo-encapsulation" through the use of factory functions and closures in JS for example. Really cool stuff
Why "pseudo-" though? It can hide variables the same way as class private fields.
Hmm, well according to his article he was saying it wasn't natively supported, in JS at least
The two are not opposed, just different, between oo and fp is ofp.
Thanks for pointing that out Adam, I made sure to put in a little disclaimer at the top of my article and linked your profile (let me know if that's cool, I could always un-link it!). And thanks for giving it a read (:
Ha that's ace, you sir are a gent.
I would also mention that FP encourages to handle "null" and exceptions in a different way using Maybe (or Option) and Either monads. The concept is called "Railway programming".
FP encourages lazy calculations. For example, IO monad doesn't run the effect until the very last moment. The same with Future (FP Promises).
FP has a different approach for reusing the code. For example, lenses can be applied on any object. Atomic functions can be composed and used to map data.
There are more differences but these came up in my mind besides things that were mentioned in the article and in the comments.
This is very helpful. Thanks:)
You're welcome Vijay! Your comment gave me a nice little push to keep writing, thank you for reading it 🙏🏽
Worst blog post ever, why did you not show the functional programming example of the oop example?
All good OOP winds up containing functions that do only one thing anyway. There's no difference in functional compostion and OOP. Non-OOP people just haven't realized that yet.