Imperative And Declarative Styles Of Programming
Tags: java, programming, beginners, tutorial
Published: 2022-03-01 05:57:36

## Imperative Programming

Here are some facts about the imperative style of programming.

Object-Oriented programming is an imperative style of programming.

It focuses on how to do things. For example, in imperative programming, we sort of do the following steps to run a use-case. For example:

1. Set the `counter` to `0`, run a loop of the first `100` values and add each number to the `counter`.

2. Set `data` equal to `0`, add the first number in the array to `data` and repeat this for the rest of the numbers in the array and divide `data` by the `length` of the `array`.

Here, we treat values as buckets. So the value can be modified in the application at any time. Embraces object mutability.

Variables declared hold some value and change at some point in the program. Think of POJO class variables with setters.
Modification of variable value is allowed. 

Think of loops where we iterate through each value and before processing each item, we update the garbage variable we initialized in the loop. 

Step-by-step instructions on how to achieve an objective.

### Example 01: List of objects
In the imperative approach, we make use of the loops. The following example contains an algorithm that makes this happen.

`Book` POJO with constructor, getters, and setters.
```java
class Book {
  String title;
  String author;
  Integer year;
  Integer copiesSoldInMillions;
  Double rating;
  Double costInEuros;

  public Book(String title, String author, Integer year, Integer copiesSoldInMillions, Double rating, Double costInEuros) {
    this.title = title;
    this.author = author;
    this.year = year;
    this.copiesSoldInMillions = copiesSoldInMillions;
    this.rating = rating;
    this.costInEuros = costInEuros;
  }

  public Double getCostInEuros() {
    return costInEuros;
  }

  @Override
  public String toString() {
    return "Book{" +
      "title='" + title + '\'' +
      ", author='" + author + '\'' +
      ", year=" + year +
      ", copiesSoldInMillions=" + copiesSoldInMillions +
      ", rating=" + rating +
      ", costInEuros=" + costInEuros +
      '}';
  }
}
```

`BookDatabase` for dummy data injection.
```java
import java.util.Arrays;
import java.util.List;

public class BookDatabase {
  public static List<Book> getAllBooks() {
    return Arrays.asList(
      new Book("Don Quixote", "Miguel de Cervantes", 1605, 500, 3.9, 9.99),
      new Book("A Tale of Two Cities", "Charles Dickens", 1859, 200, 3.9, 10.0),
      new Book("The Lord of the Rings", "J.R.R. Tolkien", 2001, 150, 4.0, 12.50),
      new Book("The Little Prince", "Antoine de Saint-Exupery", 2016, 142, 4.4, 5.0),
      new Book("The Dream of the Red Chamber", "Cao Xueqin", 1791, 100, 4.2, 10.0)
    );
  }
}
```

Here is our `BookApplication` class that does the imperative programming or mutations on `book` variable inside `for-loop`.

```java
import java.util.ArrayList;
import java.util.List;

public class BookApplication {
  public static void main(String[] args) {
    List<Book> books = BookDatabase.getAllBooks();
    List<Book> imperativeWay = new ArrayList<>();

    for (Book book : books) {
      if (book.getCostInEuros() >= 5) {
        imperativeWay.add(book);
      }
    }

    imperativeWay.forEach(System.out::println);
  }
}
```

### Explanation

1. We have a list of books data.

2. We then used a for-loop to iterate through all the book objects.

3. Inside for-loop, we are constantly changing the `book` variable data and further checking the `if` check to add the filtered data into another list.

4. So we are mutating, which means we are changing the `book` variable that’s holding a value from one state to another.

5. We are printing the filtered data using a loop.

### Example 02: Unique Integers
Another simple example is that removes duplicates from the list of input integers. This example is to make you understand how imperative programming is actually done.

Example 01, is how we do in real-time on production grade applications.

**Sample code**

```java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

class UniqueElements {
  public static void main(String[] args) {
    List<Integer> integerList =
      Arrays.asList(1, 1, 2, 2, 3, 4, 5, 6, 7, 7, 8);

    List<Integer> uniqueList = new ArrayList<>();

    // "integer" variable is changed/updated for each iteration.
    for (Integer integer : integerList) {
      if (!uniqueList.contains(integer)) {
        uniqueList.add(integer);
      }
    }
    System.out.println("Unique list : " + uniqueList);
  }
}
```

### Explanation

1. We have a list of integer values.

2. We then used a for-loop to iterate through all the list values.

3. Inside for-loop, we are constantly changing the `integer` variable data and further checking the if check to add the unique data into another list.

4. So we are mutating, which means we are changing the `integer` variable that’s holding a value from one state to another.

5. We are loading all the unique values into another list, and printing them at the last.

---


## Declarative Programming

Here are some facts about the declarative style of programming.

Functional programming is a declarative style of programming. It puts more focus on what things are, for example:

1. Set the counter as the sum of all numbers from 0 to 100.

2. `data` is the sum of all the numbers in the array. divided by the length of the array.

In functional programming, we don’t assign values as we do in imperative. Embraces object immutability. Think of variables as constants declared with final, just so you can get an idea of what we are discussing here. Modifying a value is not allowed.

This is analogous to SQL(Structured Query language). Use of functions that are already part of the library to achieve an objective. 

With **Streams API**, we move from imperative to declarative programming.

### Example 01: List of objects
In the declarative approach, we make use of the streams and then a chain of methods, which are called intermediate and terminal operations. 

The following example contains an algorithm that makes this happen.

`Book` POJO with constructor, getters, and setters.
```java
class Book {
  String title;
  String author;
  Integer year;
  Integer copiesSoldInMillions;
  Double rating;
  Double costInEuros;

  public Book(String title, String author, Integer year, Integer copiesSoldInMillions, Double rating, Double costInEuros) {
    this.title = title;
    this.author = author;
    this.year = year;
    this.copiesSoldInMillions = copiesSoldInMillions;
    this.rating = rating;
    this.costInEuros = costInEuros;
  }

  public Double getCostInEuros() {
    return costInEuros;
  }

  @Override
  public String toString() {
    return "Book{" +
      "title='" + title + '\'' +
      ", author='" + author + '\'' +
      ", year=" + year +
      ", copiesSoldInMillions=" + copiesSoldInMillions +
      ", rating=" + rating +
      ", costInEuros=" + costInEuros +
      '}';
  }
}
```

`BookDatabase` for dummy data injection.
```java
import java.util.Arrays;
import java.util.List;

public class BookDatabase {
  public static List<Book> getAllBooks() {
    return Arrays.asList(
      new Book("Don Quixote", "Miguel de Cervantes", 1605, 500, 3.9, 9.99),
      new Book("A Tale of Two Cities", "Charles Dickens", 1859, 200, 3.9, 10.0),
      new Book("The Lord of the Rings", "J.R.R. Tolkien", 2001, 150, 4.0, 12.50),
      new Book("The Little Prince", "Antoine de Saint-Exupery", 2016, 142, 4.4, 5.0),
      new Book("The Dream of the Red Chamber", "Cao Xueqin", 1791, 100, 4.2, 10.0)
    );
  }
}
```

Here is our `BookApplication` class that does the declarative programming or immutability on each `book` object.

```java
import java.util.List;
import java.util.stream.Collectors;

public class BookApplication {
  public static void main(String[] args) {
    List<Book> books = BookDatabase.getAllBooks();

    List<Book> declarativeWay =
      books.stream()
        .filter(book -> book.getCostInEuros() >= 5)
        .collect(Collectors.toList());

    declarativeWay.forEach(System.out::println);
  }
}
```

### Explanation

In the above, we have a list of the books and we are running some chain of methods on it like a filter, map, etc. This chain of method calls is called a **Stream Pipeline**.

> This is called functional programming as we are passing functions to the operations in the form of lambda expressions and method references.

Let us see what’s happening in each line

1. We are first filtering the `books` whose cost is greater than or equal to `5` using a lambda expression `.filter(book -> book.getCostInEuros() >= 5)`.

2. We now have a `list` of books whose close is above `5` euros. We chain this to another method `.collect(...)` which converts the stream data into a list using `Collections.toList()` and return the list and store it in `declarativeApproach` reference variable.

3. We print it by calling `.forEach(...)` on the reference variable.

### Example 02: Unique Integers

Another simple example is that removes duplicates from the list of input integers. This example is to make you understand how imperative programming is actually done.

Example 01, is how we do in real-time on production grade applications.

**Sample Code**

```java
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

class UniqueElements {
  public static void main(String[] args) {
    List<Integer> integerList =
      Arrays.asList(1, 1, 2, 2, 3, 4, 5, 6, 7, 7, 8);

    List<Integer> uniqueList =
      integerList.stream()
        .distinct()
        .collect(Collectors.toList());

    System.out.println("Unique list1 : " + uniqueList);
  }
}
```

### Explanation

1. We have a list of integer values.

2. We then added `.stream()`, so the collections of integer values get converted into streams of integer values.

3. we chained it with another function called `distinct()` that removes the duplicate elements from the `list`.

4. Once we go through all the filtered data, we need to terminate the stream and we are doing it with `.collect(...)`.

1. The `.collect(...)` has `Collections.toList()` which converts the stream data into a list and the results are loaded into `integerList1` variable.

## Read More

1. [Introduction To Java Streams API](https://dev.to/ggorantala/introduction-to-java-streams-api-1d05)

2. [How Does Streams API Work? A Deep Dive on Stream Operation Flow](https://dev.to/ggorantala/how-does-streams-api-work-a-deep-dive-on-streamoperation-flow-4e07)

3. [What Are Java Method References And Kinds Of Method References Available?](https://dev.to/ggorantala/what-are-java-method-references-and-kinds-of-method-references-available-d34)

4. [Functional Programming And Programming Paradigms in Java](https://dev.to/ggorantala/functional-programming-and-programming-paradigms-in-java-323f)