declarative vs imperative programming

declarative vs imperative programming

When working with React, we have undoubtedly come across the term declarative. It is also mention in the React documentation. Declarative programming is one of the reasons, why React is so a powerful library.

Imperative programming is a way in which you describe how things work, while in declarative programming we describe what you want to achieve. Let's understand this concept by using real-life examples.

You enter a coffee shop in the imperative world, where you give the following instructions to the barista:

1. Find a cup and collect it from the shelf.
2. Take coffee and place it in the coffee machine.
3. Collect the coffee under the coffee machine.
4. Pour the coffee into the cup until the glass is full.
5. Hand me the glass.

In the declarative world, you would just say "Can I have a cup of black coffee, please?"

The declarative approach assumes that the barista knows how to make the coffee, an important aspect of the way declarative programming works.

Let's move to code

We will write a function in JavaScript to convert the array of lowercase strings to an array of uppercase strings.

toUpperCase(['joe', 'john']) // ['JOE', 'JOHN']

An imperative function to solve the problem would be implemented as follows:

const toUpperCase = input => {
const output = []

for ( let i = 0; i< input.length ; i++) {
  output.push(input[i].toUpperCase())
}
 return output
}

First of all, an empty array to contain the result is created. Then, the function loops through all the elements of the input array and pushes the uppercase values into the empty array. Finally, the output array is returned.

A declarative solution would be as follows:

const toUpperCase = input => input.map(value => value.toUpperCase())

The items are passed to the map function that returns a new array containing the uppercase values.

There is some significant difference to note in the example. The former is less elegant and it required more effort to be understood. While, the latter is easier to read, which makes a huge difference in big codebases, where maintainability is crucial. In the declarative example, there is no need to create an extra variable.

Now, let's take a React example. We will create a simple toggle button.

Imagine a toggle button, when you click it, it turns green(on) if it was previously gray(off) or vice-versa.

The imperative way of doing this would be as follows:

const toggleButton = document.querySelector('#toggle')

toogleButton.addEventListener('click', () => {
if (toggleButton.classList.contains('on')) {
toggleButton.classList.remove('on')
toggleButton.classList.add('off')
} 
else {
toggleButton.classList.remove('off')
toggleButton.classList.add('on')
}
})

A decelerative solution would be as follows:

// To turn on the Toggle
<Toggle on />
// To turn off the toggle
<Toggle />

React offer a declarative approach, which makes it easy to use, and consequently, the resulting code is simple, which leads to fewer bugs and more maintainability.