Object Oriented vs. Functional Programming in Elixir

Stephen Grider
A free video tutorial from Stephen Grider
Engineering Architect
4.7 instructor rating • 29 courses • 819,313 students

Learn more from the full course

The Complete Elixir and Phoenix Bootcamp

Master Functional Programming techniques with Elixir and Phoenix while learning to build compelling web applications!

17:19:33 of on-demand video • Updated May 2021

  • Think with a Functional Programming mindset
  • Use Phoenix to build compelling and FAST web apps
  • Understand common Elixir syntax and design patterns
  • Master the OAuth flow with Phoenix for authentication
  • Learn the hidden secrets of Phoenix
English [Auto] We've now covered all the really basic stuff around Elixir so far, like so how do I generate a project? How do I run some code, blah, blah, blah, you know, list strings, whatever, that boring stuff. That's the type of stuff that I would expect you to be able to go out to any existing resource, any document and kind of figure out, hey, how do I write a string and elixir? So in this section, we're going to start doing a big transition. And I want to focus a lot on a lot more about the design patterns of elixir. OK, so we're going to not write a lot of code in this section. We're going to focus a lot more on how do we write code helix or what type of approach do we want to take here? So let's get started with it, it's going to get along sections of Bucklin, we created a method in the last section called Create Deck, and I want you to take special notice of the fact that right now we are we're just returning an array of strings. Right. We've got an array of what we're calling cards, more or less an actual playing card. And we're doing that as opposed to, say, maybe assigning an instance variable to something like this dot my deck. And so this is what I'm about to write on the screen is not valid elixir code at all. So don't do it. You'll notice that we didn't do something like this on my deck. Right. And that's something we might do if we were working with Ruby or Java or even JavaScript. You might take this type of approach right here. But unless we did not do anything like that, we specifically returned a value from this method right here. So this is actually something that's extremely important when it comes to object oriented versus functional programming. So let's expand on this topic big time. This is going to be the first of many, many discussions about the differences between functional and object oriented programming out of everything that we're going to learn in this course. Making a clear distinction in your head between object oriented and functional programming is the most important thing that I want you to learn. OK, so even if you're not strictly familiar with object oriented programming, you know, if you didn't go through college classes or any type of academic instruction on object oriented programming or anything like that, I still encourage you to stick through this. It's absolutely valuable and you will gain a lot from it. OK, so I'm going to pull up a diagram and we're going to kind of walk through an object oriented approach right now. And so I know that this diagram looks a little crazy. Just just bear with me for one second. I want to assume for a second that we're developing. You and I are developers and we're writing some very traditional object oriented code in like Java, Ruby, whatever it is. And we want to put together this app that we're working on, something to deal cards, shuffle them in somehow, just like manipulate playing cards. So how might we approach that? How might we approach that with kind of an object oriented approach? Well, I'm going to suggest maybe we would make like two classes, right? Like a deck class and a card class. So the card class might have two properties. Maybe it'll have something like this dot suits to be something like, you know, diamonds, clubs, whatever. And it might also have a value that would record something like a two or three, four. And then when we put these two properties together, we would end up with something like King of Hearts, two of diamonds, ace of spades, whatever it might be. And then our deck class might create like an array of these cards we might have like this cards and it's an array of card objects. Then our deck class might also have instant's or instance methods like, you know, shuffle, save, load, all that kind of good stuff. So here's the important part here. Here's like the really important thing that I'm trying to point out. Each of these methods right here, like shuffle, save and load would work on its local instance variable like this, cards that like array of card objects. OK, that last part is very key in an object oriented approach. We could probably like definitely a valid way of approaching this problem or this application in an object oriented approach. We could have an instance of a class with some methods like shuffle, save and load that operate on its own local instance variable. Something like this cards. OK, so in practice, if we were going to write this out, I know this is kind of ugly here, but just bear with me. We might have some amount of code that looks like this. This is kind of like pseudocode on the left hand side and then kind of like the return values on the right hand side. OK, so we're kind of pretending this is code that I would write out here. Given a like deck class, I might do something like make a new deck. So like new deck and that makes an instance of the deck right here. So basically I got like this deck thing. Right. And it represents it has its own set of cards. I can shuffle them whatever it might be. And so if I reference, like, deck cards, I get back to the array of cards. If I say deck shuffle, it shuffles the cards and if I do deck deal, it'll return like my deck or like a new deck with just one card. Right. The whole point here, like the entire point of all this, is that I have this deck class and it has its own local collection of cards. Whenever I call a method on the class, it operates on that local collection. And that's like the whole big point. That's like one trying to get at here with an object oriented approach. So let's pivot now and we're going to talk about how we would approach this exact same application with a functional programming approach. And so this is like not even necessarily elixir right now. This is like how I might approaches with functional programming. And so I know this is another kind of crazy diagram here, but let's walk through it. This is a diagram of how we might approach this app with Elixir or, you know, again, any functional programming language in the middle. Here we have our cards module, our cards module. In this approach, we have no concept of a class or an instance of a class. So a module is a standalone object and it has absolutely no idea, no idea what an instance variable is. So there's no such thing as like this cards. There's no such thing as like this deck or anything like that. OK, that's not a thing, not a concept at all cards. That module is its own. Just going to stand alone. Things sitting there, memory. You can't create copies of it. You can instantiate it. Nothing like that. Modules and elixir are collections of methods and absolutely nothing more. So we have no instance variables whatsoever. That means that whenever we want to create a deck or like a collection of cards, we can call create deck. And instead of setting that deck to like, you know, this my deck or something like that, it's going to instead return our array or like list of strings where each string in there represents a single card. Similarly, whenever I want to shuffle a deck, whenever I want to shuffle like a list of cards, I will pass in an array of strings or like my array of cards right here and it will return back to me a new shuffled list of cards. So again, let me be clear, like the millionth time in Elixir, there's absolutely no concept of instance variables. All of the data that we work with inside of our application are going to be data structures made out of primitive variables like strings and numbers and stuff like that that represent the absolute bare essence of the data that we're working with. Whenever we want to take some action on a piece of data, we're going to take that data. We're going to pass it into a method. The method is going to process it, and then it's going to spit out some result back to us. And so the same exact thing happens down here. It's safe. So when I pass in my, like, list of cards, it goes into save. There's no instance variables, nothing like that in there. It just returns back a string that is a reference to the like or estimated the string that is the path to the save file. Similarly, whenever I want to load a deck of cards, I'll pass in a string that is the path to the save file and I'll get back like the return value is my array of cards. When I load a deck of cards, nothing like gets set to an instance variable or anything like that. So you might be thinking. I mean. All right. Seems simple enough like. But why bother. What's the difference here. Fantastic question. So that is the question that we are going to be answering throughout this entire course. You'll see has a few questions. Assume you express a few features that make writing apps with this approach just a total breeze. And as we learn more about Elixir, I think that this approach is really going to come very natural to use this type of approach of saying, I don't have an instance of a class, I just have some primitive data sitting around like a list of strings I pass into a method. The method does something to it and then it spits some result back out to us who. OK, so that's my first kind of big spiel on object oriented versus functional programming. Let's take this approach right here. It's kind of like idea of how we write code and let's start applying it in the next section.