Lessons: 15Length: 1.6 hours

Next lesson playing in 5 seconds

  • Overview
  • Transcript

2.1 Getting Declarative

Declarative style lets us offload pieces of our program into chunks, or functions, so that reading through an application becomes easier and more self-documenting. In this lesson we’ll begin to make our app more declarative by moving some repeated actions into functions.

Related Links

2.1 Getting Declarative

So here I have the Beer List website running in my browser. I showed you how to download that in the last video. So if you would like to grab this code and you missed that video, just go back and take a look. Let's take a look at the code right now, cuz we're going to make some changes to it, but I kind of want to set up why we want to make those changes. So here's our app.js, it's in our folder that we downloaded from GitHub. So in app.js, the style of code you're that you're seeing in here is what's known as imperative code. So it starts at the top, things happen, and we, in the code are writing and just telling the computer what to do step by step. So we're saying, okay, set the beer list, which weve got up here as an element in the DOM, and take its inner HTML and set it to this templated version of the beerTemplate as it's applied to the beerData, which we've also got above. Now, there is an element of clarity to this, right. We, we can see what's going on. We then add an event listener, and inside there we do step one, then step two, then step three, we go through a for loop. Everything that's happening is right on the page. And some people would say that that's an advantage of imperative style, which, in a small application, is probably true. But this is pretty small, and it's already gotten to be kind of a mess, in my opinion. We have to hold a lot of things in our head whenever we're looking at something, like, what's going on here, it's a for loop, we're looping over some links, and we're, what are we doing? We're removing the active but, okay, oh, I see, okay, we're doing some state management on the buttons, that's what this is doing. And so then the next thing you'll often see in this style is this, right. You'll see add active link, active class, to the currently selected filter. And so you're, you're giving yourself kind of a clue of, what is going on with this chunk of code, in a comment. We're gonna try to apply a different style, called functional style, where we're going to wrap up chunks of code in functions that have intuitive names so that when we read through the code, we're actually just saying what we want to happen and letting the code do the work for us. And that will allow us to offload some of the stuff we have to hold in our human memory as we read through a file of code. So the first easy thing we can do is, you can see here we're, we're setting the innerHTML to beerList, and then at the very bottom here, we do the same thing. And so one of the principles for what you would wanna wrap up into a function and be more declarative is something called DRY, meaning don't repeat yourself. So, if we're repeating yourself, that's a, a really good candidate for a place where you could substitute a function instead. So we're gonna do this. We're gonna create a function called loadBeers. And we'll accept a list of beers. [BLANK_AUDIO] And we'll copy, well, actually, we'll remove this line and put it inside the function. And then we'll say that what we wanna do is have an object here where we have a beers key, and we'll set the value of that key to the beers that were passed in in the function. So now this allows us to reuse this function. Now, the only problem is, when we go to load the beers first, we have to call this function right now, and we actually need the original list of beers. Now, if I pass the beerData in, let's look at it. The beerData's going to be this outer object that has a key of beers. What it's expecting is actually an array of beer objects, and it's expecting that because later, when we filter beers, that's what we'll have. And so we're already doing it this way down here. We want to keep it consistent. So, in order to do this, I think the easiest thing is just going to be to remove this. And even though it's all kind of using the same name, beers, and getting a little confusing, right, this is our actual array of beers, okay. And so that won't affect this parameter. It still expects a list, it doesn't know anything about what list it gets. But here, when we call the function, we can actually pass in this beers, okay, and that will actually pass in that array of beers and then will get set. So, before we actually do anything else, let's just verify that this still works. We'll refresh here, and we still have our full list of beers. All right, and so to make sure the filter works with our new function, we're gonna go ahead and just, instead of doing all this with the filtered beers, we can remove all of this and just say loadBeers. Now, before we do that, actually, I'm gonna undo. Take a look at this, all right. When we're getting to the end of this switch statement and we see beerList.innerHTML again, you really have to read this to understand what's happening. All right, we're getting a template, beerTemplate. I guess that came from above. And the filtered beer just said, and I guess that's the data it needs, and so, I guess we're loading the beers, right. That's what happens in your head every time you look at this code, especially if you haven't been in this file for a while, you may not remember what's happening down there. If you're new, any number of reasons why. This takes a little bit of parsing to figure out what's going on here. Watch what happens when we switch it for loadBeers and give it the filteredBeers. Immediately, the function itself is telling us what's going on. We know we've already set a filteredBeers array, where we did some sort of filtering, and now we're just loading them. Right, so whatever happens, we don't care so much. We can just say, I see, we're loading the filtered beers. If at any point you're curious of what's happening with loadBeers, you just find the loadBeers function and read it. But you don't have to read it every single time you come across that function, or that chunk of code, I should say. So we'll remove that. Save this file. And let's just make sure that our filters are still working. Okay. Good. So we've made a little bit of a gain here. What else could we do? I think I said this chunk of code was bothering me. We have to look at this and try to determine what's happening here. And what's really happening is, we're trying to set the active filter, right, so setActiveFilter, and we wanna know what the active one is, and that should give us everything we need. So now we can actually group this chunk of code together. Remember, before, if we add a comment here saying what we're doing, it's not actually clear that this part is part of that comment. All right, so you, you, you have to look at this and try to really figure out which chunks of code go together. And so by being declarative and saying, we're just gonna say, set the active filter and give it the active one and let it do its job. Then we don't have to worry so much, right. We're, we're doing the same work in a different place. But the setup is allowing us to be more clear about what's going on. So, let's remove this, I'll put it in our setActiveFilter function. And now it's not clicked, it is actually active. So it's still gonna go get the filter links that we already cached a copy of, from the DOM. It's gonna loop over them, it's gonna remove the btn-active class if it was there, and then for the active one that's passed in, it will re-add the btn-active class. And that's what makes that filter red. And so we set this function, and then in here, instead of doing all of that, we can simply call setActiveFilter and give it the clicked one. And now our semantics are correct, too. We're saying, in this case, we wanna say it's the clicked one, cuz that's what happened. We're inside of a click event, we're saying, all right, take the clicked link and set it as the active filter. And so this line tells us everything we need to know about what's happening. In setActiveFilter, it doesn't know about clicked, it doesn't care. If we wanted to set the active filter based on hover or just based on some other kind of event, it, we could continue to use this function over and over. And all we have to do is just give it the link, a reference to the link that we want it to actually be active, and it will do that for us. So it does the work without knowing anything about being clicked. And so our semantics are lined up correctly with what's happening in each place. So let's just make sure this is still working as expected. We can click our filters and we still get the active state applied. And so that's a first step in making our code more declarative. So we've moved from an imperative style to a slightly more declarative style. And you may be thinking to yourself, aren't you really just adding functions to your code? And the answer is kind of, yes, that's, functional programming is a lot about just adding functions. But you can see we're adding functions for good reasons. We're saying, we want things that are repeated to be encapsulated in a function. We want things that are happening as a group to be clear and easier to understand as a set of actions. And so this is a really good first step to making our code clearer, easier to reason about, and thus easier to maintain and fix and add to as we move on. In the next video we're going to take it another step further for declarativeness, and we're going to change all of this filter logic to use a declarative style as well.

Back to the top