You won't get very far into learning React until you hear it – "React is declarative". But, what does that even mean? If you try to dive deeper, you inevitably come across a definition that looks something like this, comparing it to imperative programming.

👁

Imperative vs Declarative Programming

Imperative programming is how you do something, and declarative programming is more like what you do.

That definition makes perfect sense... once you actually know the difference between imperative and declarative programming — but you don’t, which is why you're here.

It’s like trying to answer What came first, the chicken or the egg? except everyone seems to think the chicken did, but you don’t even like eggs, and you’re confused. Combine this frustration with the bastardization of the actual word “declarative” to basically just mean good and all of a sudden your imposter syndrome is tap dancing on your confidence, and you realize you don’t even like programming that much.

The hard part about this topic is, as my friend Merrick has observed, it's one of those things you have an intuition about, but can’t seem to explain. Vibe driven development, if you will.

So now, after years of teaching this topic, I've found that the most effective way to explain it seems to be with a combination of metaphors and code samples.

First, let’s go back to the initial definition we made fun of.

👁

Imperative vs Declarative Programming

Imperative programming is how you do something, and declarative programming is more like what you do.

There’s actually some good information hidden in here. Let’s first see the merit in this definition by taking it out of the context of programming and look at a real life example.

You decide that you’ve been spending too much time arguing about JavaScript Fatigue™ and your husband deserves a nice date. You choose to go to Red Lobster since you’ve been listening to a lot of Beyoncé lately. You arrive at Red Lobster, approach the front desk and say…

IMPERATIVE (HOW)

I see that table located under the Gone Fishin’ sign is empty. My husband and I are going to walk over there and sit down.

DECLARATIVE (WHAT)

Table for two, please.

The imperative approach is concerned with how you’re actually going to get a seat. You need to list out the steps to be able to show how you’re going to get a table. The declarative approach is more concerned with what you want, a table for two.

🤨

...ok let's try another metaphor.

I’m going to ask you a question. I want you to think of both an imperative response and a declarative response.

“I’m right next to Wal-Mart. How do I get to your house from here?”

IMPERATIVE

Go out of the north exit of the parking lot and take a left. Get on I-15 going North until you get to the 12th street exit. Take a right off the exit like you’re going to Ikea. Go straight and take a right at the first light. Continue through the next light then take your next left. My house is #298.

DECLARATIVE

My address is 298 West Immutable Alley, Eden, Utah 84310

Regardless of how I get to your house, what really matters is the car I drive. Am I going to drive an imperative stick shift car or a declarative automatic car? Enough metaphors?

Before we dive into the code, it’s important to realize that many declarative approaches have some sort of imperative abstraction layer.

Look at all of our examples:

  1. 1. The declarative response to the Red Lobster employee ("table for two, please") is assuming that the Red Lobster employee knows all of the imperative steps to get us to the table.
  2. 2. Knowing the address assumes you have some sort of GPS that knows the imperative steps of how to get to your house.
  3. 3. An automatic car has some sort of abstraction layer over shifting gears.

Now, we’re going to attempt to take the leap from metaphorical happy land to real-world code land. To make the jump more graceful, let’s look at some programming languages that are inherently declarative versus those which are more imperative by nature.

IMPERATIVE

  • C
  • C++
  • Java

DECLARATIVE

  • HTML
  • SQL

~BOTH

  • JavaScript
  • C#
  • Python

Think about your typical SQL or HTML code,

SELECT * FROM Users WHERE Country='Mexico';

<article>
<header>
<h1>Declarative Programming</h1>
<p>Sprinkle Declarative in your verbiage to sound smart</p>
</header>
</article>

By glancing at both examples, you have a clear understanding of what is going on. They’re both declarative. They’re concerned with what you want to be done, rather than how you want it done.

You’re describing what you’re trying to achieve, without instructing how to do it. The implementation of selecting all of the users who live in Mexico has been abstracted from you. You’re not concerned with how the web browser is parsing your article element and displaying it to the screen.

Your what is Mexican users or a new header and paragraph on your website.

So far, so good. Let’s dive into more some practical JavaScript examples now.

Here are 3 interview type questions. We're going to answer them imperatively, as if we're focused on how.

1.

Write a function called double which takes in an array of numbers and returns a new array after doubling every item in that array – double([1,2,3]) // [2,4,6].

function double(arr) {
let results = [];
for (let i = 0; i < arr.length; i++) {
results.push(arr[i] * 2);
}
return results;
}
2.

Write a function called add which takes in an array and returns the result of adding up every item in the array – add([1,2,3]) // 6

function add(arr) {
let result = 0;
for (let i = 0; i < arr.length; i++) {
result += arr[i];
}
return result;
}
3.

Using jQuery (or vanilla JavaScript), add a click event handler to the element which has an id of btn. When clicked, toggle (add or remove) the highlight class as well as change the text to Add Highlight or Remove Highlight depending on the current state of the element.

$("#btn").click(function () {
$(this).toggleClass("highlight");
$(this).text() === "Add Highlight"
? $(this).text("Remove Highlight")
: $(this).text("Add Highlight");
});

By examining what all three of these imperative examples have in common, we’ll be able to better identify what actually makes them imperative.

  1. 1. The most obvious commonality is that they’re describing HOW to do something. In each example, we’re either explicitly iterating over an array or explicitly laying out steps for how to implement the functionality we want.
  2. 2. This one might not be as obvious if you’re not used to thinking in the declarative or even more specifically functional way. In each example, we’re mutating some piece of state.
  3. 3. This one is a bit subjective, but to me, the code above isn’t very readable. I can’t just glance at the code and understand what’s going on. My brain needs to step through the code just as an interpreter would while also taking into account the context in which the code lives (another negativity of mutable data).

Now, let's take a look at some declarative examples. The goal is to fix all the problems from above. So each example needs to describe what is happening, can’t mutate state, and should be readable at a glance.

1.

Write a function called double which takes in an array of numbers and returns a new array after doubling every item in that array – double([1,2,3]) // [2,4,6].

function double(arr) {
return arr.map((item) => item * 2);
}
2.

Write a function called add which takes in an array and returns the result of adding up every item in the array – add([1,2,3]) // 6

function add(arr) {
return arr.reduce((prev, current) => prev + current, 0);
}
3.

Add a click event handler to the element which has an id of btn. When clicked, toggle (add or remove) the highlight class as well as change the text to Add Highlight or Remove Highlight depending on the current state of the element.

<Btn
onToggleHighlight={handleToggle}
highlight={highlight}>
{buttonText}
</Btn>

Notice that in the first two examples we’re leveraging JavaScript’s built-in map and reduce methods. This goes back to what we saw earlier – most declarative solutions are an abstraction over some imperative implementation.

In every example we’re describing what we want to happen rather than how (we don’t know how map and reduce are implemented, we also probably don’t care). We’re not mutating any state. All of the mutations are abstracted inside of map and reduce. It’s also more readable (once you get used to map and reduce, of course).

Now, what about the last example?

Well, I cheated a little bit and am using React — but note that all three imperative mistakes are still fixed. The real beauty of React is that you can create declarative user interfaces – simply by describing what you want your UI to look like based on your state.

Another less-spoken-of benefit to declarative code is that your program can be context-independent. This means that because your code is concerned with what the ultimate goal is— rather than the steps it takes to accomplish that goal — the same code can be used in different programs, and work just fine.

Look at all three of our examples above. We can consume both functions and component in any program we want. They’re program agnostic. This is hard to do with imperative code because often times, by definition, imperative code relies on the context of the current state.

🫶

Functional Programming

One thing that I didn’t go too far into is how functional programming is a subset of declarative programming.

If you haven’t already, I highly recommend getting more familiar with functional programming techniques in JavaScript. Start with .map, .reduce, .filter and work your way up from there. Odds are there isn’t a lower hanging fruit to improve your codebase than making it more functional.

Before we end, here are some other definitions that I've found from around the web regarding Imperative vs Declarative programming that may be helpful.

📢

Declarative programming is “the act of programming in languages that conform to the mental model of the developer rather than the operational model of the machine.”

📢

The declarative property is where there can exist only one possible set of statements that can express each specific modular semantic. The imperative property is the dual, where semantics are inconsistent under composition and/or can be expressed with variations of sets of statements.

📢

Declarative languages contrast with imperative languages which specify explicit manipulation of the computer’s internal state; or procedural languages which specify an explicit sequence of steps to follow.

📢

In computer science, declarative programming is a programming paradigm that expresses the logic of a computation without describing its control flow.

📢

I draw the line between declarative and non-declarative at whether you can trace the code as it runs. Regex is 100% declarative, as it’s untraceable while the pattern is being executed.