Code-Y/redux-fluent

View on GitHub
gitbook/motivations/design-goals.md

Summary

Maintainability
Test Coverage
# Design Goals

We know we could write a program directly in bytecode,
and that everything else can be an example of "syntactic sugar",
but isn't it life an endless attempt to improve _"how we communicate with each other"_?

<br />

### Expressiveness

We've been writing redux-fluent with functional programming in mind, we wanted it as much declarative as it can be.
We wanted to hide the _"how this is happening"_ and surface the "what is happening". 
The application flow should be easy to grasp at first glance.

```typescript
GIVEN I have a counter                     /**/ 
WHEN action is of type 'INCREMENT'         /**/ 
THEN state is equal to state plus one      /**/   const counter = createReduce('counter')
                                           /**/     .actions(
GIVEN I have a counter                     /**/       ofType('INCREMENT').map((state) => state + 1),
WHEN action is of type 'DECREMENT'         /**/       ofType('DECREMENT').map((state) => state - 1),
THEN state is equal to state minus one     /**/       ofType('RESET').map(() => 0),
                                           /**/     )
GIVEN I have a counter                     /**/     .default(() => 0);
WHEN action is of type 'RESET'             /**/
THEN state is equal to zero                /**/
```

<br />

### Type Safety

Type Safety is a must have for a great developer experience, and we've been building redux-fluent with that in mind.
We've got first-class support for typescript declarations so that you can benefit from it in your projects (whether they are on typescript or javascript).

![redux-fluent-typescript-definitions.gif](https://github.com/Code-Y/redux-fluent/blob/master/gitbook/redux-fluent-typescript-definitions.gif?raw=true)

<br />

### λ Going Functional

Redux is a perfect fit for functional programming,
it leverages on [Immutability](https://en.wikipedia.org/wiki/Immutable_object),
makes it easy to think in terms of [state machines](https://en.wikipedia.org/wiki/Mealy_machine)
and its architecture clearly defines how to handle side-effects so that your entire state management can be left pure.

However, in real world applications, reducers tend to easily grow uncontrolled and become unmaintainable. 
This is due to a reducer having to handle the whole life cycle of its state (embed update logic, case logic and handle default values).

We wanted to offer a pattern for [splitting up reducers](https://redux.js.org/recipes/structuring-reducers/splitting-reducer-logic#splitting-up-reducer-logic).
A way to stop piling up switch-cases and start doing some function composition!

- Reducers as function combinators to build up complex behaviour by composing small functions together.
- Action Filters to nail down the case logic (the _"which action to respond to"_).
- Action Handlers to granularly define transition logics (`A ~> B`). 

```typescript
import { ofType, createReducer } from 'redux-fluent';

export const fooReducer = createReducer('foo')
  .actions(
    // nail down to a specific action of type `bar`
    ofType('bar')
      // work out what's the new state value for actions of type bar
      .map((state, action) => { /* do Something */ }),
  )
  // define default state value
  .default(() => 'foobar');
```

<br />

### FSA by design

[Flux Standard Action](https://github.com/redux-utilities/flux-standard-action) 
represents the most established design pattern for shaping actions in a flux-like application.
It enables interoperability so that it becomes possible to build extensions ([read about the need of a standard](https://github.com/redux-utilities/flux-standard-action/issues/4)).

redux-fluent is just built around FSA. That's it. Flux Standard Actions are first-class citizens in redux-fluent.

```typescript
import * as actions from './todos.actions';

actions.addTodo({ title: 'Play some music' }, { date: new Date() });

{
  type: 'ADD_TODO',
  payload: { title: 'Play some music' },
  meta: { date: 'Thu Dec 19 2019 19:05:16 GMT+0000 (Greenwich Mean Time)' },
}
```