Refactoring imperative to functional

Pros of functional programming

  • Readibility
  • Adds an abstraction
  • Easy way to compose and chain
  • Avoid side effects
  • Easier testing

Cons of functional programming

  • Performance
  • State handling

A simple example

```js const altLabels = ['Logo France Bleu', 'Logo France Culture', 'Logo FIP'] const themes = ['news', 'culture', 'music'] const projects = [ { name: 'France Bleu', link: 'https://www.francebleu.fr/', }, { name: 'France Culture', link: 'https://www.franceculture.fr/', }, { name: 'FIP', link: 'https://www.fip.fr/', }, ] ```

The imperative way

```js const addProjectInfo = () => { for (let i = 0; i < projects.length; i++) { projects[i].altLabel = altLabels[i] projects[i].theme = themes[i] } } addProjectInfo() ```

The functional way

```js const addProjectInfo = (projectsList, altLabelsList, themesList) => { return projectsList.map((project, index) => { const extraValues = { altLabel: altLabelsList[index], theme: themesList[index], } return { ...project, ...extraValues }; }) } const result = addProjectInfo(projects, altLabels, themes) ```

Result

```js [ { name: 'France Bleu', link: 'https://www.francebleu.fr/', altLabel: 'Logo France Bleu', theme: 'news', }, { name: 'France Culture', link: 'https://www.franceculture.fr/', altLabel: 'Logo France Culture', theme: 'culture', }, { name: 'FIP', link: 'https://www.fip.fr/', altLabel: 'Logo FIP', theme: 'music', }, ] ```

Another example

```js const notesList = [ { title: "Buy milk and bread", createdAt: '2020-04-04', dueDate: null, archived: false, }, { title: "Pick up package at mail office", createdAt: '2020-04-04', dueDate: null, archived: false, }, { title: "Take a walk with Yoda", createdAt: '2020-04-04', dueDate: null, archived: true, }, { title: "Read 15 minutes", createdAt: '2020-03-07', dueDate: '2020-03-08', archived: false, }, { title: "Do 30 minutes workout", createdAt: '2020-03-01', dueDate: '2020-03-04', archived: false, }, ] ```

Lodash

```js import _ from "lodash" _.chain(notesList) // Lancer un chaînage lodash .filter(['archived', false]) // Filtrer par notes non archivées .sortBy('createdAt') // Trier par date de création .groupBy(n => n.dueDate ? 'reminders' : 'notes') // Grouper par type .pick(['title', 'createdAt', 'dueDate']) // Ne garder que quelques proprietés .value() // Récupérer la valeur après chaînage ```

Lodash/fp

```js import { filter, sortBy, groupBy, pick, compose } from "lodash/fp" const filterNotes = filter(['archived', false]); // Filtrer par notes non archivées const sortByCreatedAt = sortBy('createdAt'); // Trier par date de création const groupByType = groupBy(n => n.dueDate ? 'reminders' : 'notes') // Grouper par type const pickImportantFields = pick('title', 'createdAt', 'dueDate'); // Ne garder que quelques proprietés const filterByType = compose(groupByType, sortByCreatedAt) // Filtrer par type const sortedNotes = compose( pickImportantFields, filterByType, filterNotes ) sortedNotes(notesList) ```

Result

```js { "notes": [ { "createdAt": "2020-04-04", "dueDate": null, "title": "Buy milk and bread" }, { "createdAt": "2020-04-04", "dueDate": null, "title": "Pick up package at mail office" } ], "reminders": [ { "createdAt": "2020-03-01", "dueDate": "2020-03-04", "title": "Do 30 minutes workout" }, { "createdAt": "2020-03-07", "dueDate": "2020-03-08", "title": "Read 15 minutes" } ] } ```

Links