Add best practices to readme
This commit is contained in:
parent
41c41738c6
commit
acb098c296
1 changed files with 82 additions and 1 deletions
83
README.md
83
README.md
|
@ -7,20 +7,101 @@ The exercices consist of unimplemented functions and their associated failing
|
||||||
tests.
|
tests.
|
||||||
|
|
||||||
To run the tests, simply run
|
To run the tests, simply run
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ yarn test
|
$ yarn test
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also run them in watch mode:
|
You can also run them in watch mode:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ yarn test:watch
|
$ yarn test:watch
|
||||||
```
|
```
|
||||||
|
|
||||||
Finally, if you wish to only run the tests for a given exercice `exoN`, you can
|
Finally, if you wish to only run the tests for a given exercice `exoN`, you can
|
||||||
run the following:
|
run the following:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ yarn test[:watch] exoN
|
$ yarn test[:watch] exoN
|
||||||
```
|
```
|
||||||
|
|
||||||
The exercices are organized into `exoN` folders and most of what is required to
|
The exercices are organized into `exoN` folders and most of what is required to
|
||||||
complete each is detailed in the comments.
|
complete each is detailed in the comments.
|
||||||
|
|
||||||
|
## fp-ts typescript style guide
|
||||||
|
|
||||||
|
- Use `flow` instead of `pipe` when possible
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Bad
|
||||||
|
const myFunc = (user: User) => pipe(user, getUserName, formatUserName);
|
||||||
|
|
||||||
|
// Good
|
||||||
|
const myFunc = flow(getUserName, formatUserName);
|
||||||
|
```
|
||||||
|
|
||||||
|
- Avoid using `boolean` method `match` when unecessary
|
||||||
|
> Why? boolean.match can reduce the global understanding of a method and enforce nested pipes. Using classic `if/else` is often the best option
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Bad
|
||||||
|
const myFunc = (condition: boolean) => pipe(
|
||||||
|
condition === true,
|
||||||
|
boolean.match(
|
||||||
|
() => doSomethingOnFalse(...),
|
||||||
|
() => doSomethingOnTrue(...)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Good
|
||||||
|
const myFunc = (condition: boolean) => {
|
||||||
|
if (condition === true) {
|
||||||
|
return doSomethingOnTrue(...);
|
||||||
|
}
|
||||||
|
return doSomethingOnFalse(...);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
- Split piping from logical actions
|
||||||
|
> Why? Mixing them makes it harder to understand and read the code. We want to favor the usage of atomic methods that do not know anything about the piping
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Bad
|
||||||
|
const myFunc = () => pipe(
|
||||||
|
rte.Do,
|
||||||
|
rte.bind('aggregate', () => getAggregateById(...)),
|
||||||
|
rte.bindW(...),
|
||||||
|
...,
|
||||||
|
rte.chainW(({ aggregate }) => pipe(
|
||||||
|
aggregate.something,
|
||||||
|
doSomething,
|
||||||
|
doSomethingElse,
|
||||||
|
...
|
||||||
|
)
|
||||||
|
),
|
||||||
|
rte.chainW(storeAggregate),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Good
|
||||||
|
const myFunc = () => pipe(
|
||||||
|
rte.Do,
|
||||||
|
rte.bind('aggregate', () => getAggregateById(...)),
|
||||||
|
rte.bindW(...),
|
||||||
|
...,
|
||||||
|
rte.chainW(doEverything),
|
||||||
|
rte.chainW(storeAggregate),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Best
|
||||||
|
const buildProps = (...) => pipe(
|
||||||
|
rte.Do,
|
||||||
|
rte.bind('aggregate', () => getAggregateById(...)),
|
||||||
|
rte.bindW(...),
|
||||||
|
...
|
||||||
|
);
|
||||||
|
const myFunc = () => pipe(
|
||||||
|
buildProps(...),
|
||||||
|
rte.chainW(doEverything),
|
||||||
|
rte.chainW(storeAggregate),
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
Reference in a new issue