From acb098c296303f073c8a33f297125ce716b0a1a6 Mon Sep 17 00:00:00 2001 From: Scott Picquerey Date: Thu, 31 Mar 2022 16:29:10 +0200 Subject: [PATCH] Add best practices to readme --- README.md | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d6bfecf..ed8c0ed 100644 --- a/README.md +++ b/README.md @@ -7,20 +7,101 @@ The exercices consist of unimplemented functions and their associated failing tests. To run the tests, simply run + ```sh $ yarn test ``` You can also run them in watch mode: + ```sh $ yarn test:watch ``` Finally, if you wish to only run the tests for a given exercice `exoN`, you can run the following: + ```sh $ yarn test[:watch] exoN ``` The exercices are organized into `exoN` folders and most of what is required to -complete each is detailed in the comments. \ No newline at end of file +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), +); +```