Skip to content

Commit

Permalink
Optimized sytax and fixed typos
Browse files Browse the repository at this point in the history
  • Loading branch information
Bruno Scheufler committed Dec 27, 2017
1 parent 6957380 commit 555cd18
Show file tree
Hide file tree
Showing 23 changed files with 118 additions and 99 deletions.
2 changes: 1 addition & 1 deletion sections/codestylepractices/eslint_prettier.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ Source: [https://github.com/prettier/prettier-eslint/issues/101](https://github.

### Integrating ESLint and Prettier

ESLint and Prettier overlaps in the code formatting feature but it can be easily solved by using other packages like [prettier-eslint](https://github.com/prettier/prettier-eslint), [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier), and [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier). For more information about their differences, you can view the link [here](https://stackoverflow.com/questions/44690308/whats-the-difference-between-prettier-eslint-eslint-plugin-prettier-and-eslint).
ESLint and Prettier overlap in the code formatting feature but can be easily combined by using other packages like [prettier-eslint](https://github.com/prettier/prettier-eslint), [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier), and [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier). For more information about their differences, you can view the link [here](https://stackoverflow.com/questions/44690308/whats-the-difference-between-prettier-eslint-eslint-plugin-prettier-and-eslint).
8 changes: 4 additions & 4 deletions sections/errorhandling/apmproducts.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

### One Paragraph Explainer

Exception != Error. Traditional error handling assumes the existence of Exception but application errors might come in the form of slow code paths, API downtime, lack of computational resources and more. This is where APM products come handy as they allow with minimal setup to detect a wide variety of ‘burried’ issues proactively. Among the common features of APM products are alerting when HTTP API returns errors, detect when API response time drops below some threshold, detection of ‘code smells’, monitor server resources, operational intelligence dashboard with IT metrics and many other useful features. Most vendors offer a free plan.
Exception != Error. Traditional error handling assumes the existence of Exception but application errors might come in the form of slow code paths, API downtime, lack of computational resources and more. This is where APM products come in handy as they allow to detect a wide variety of ‘burried’ issues proactively with a minimal setup. Among the common features of APM products are for example alerting when the HTTP API returns errors, detect when the API response time drops below some threshold, detection of ‘code smells’, features to monitor server resources, operational intelligence dashboard with IT metrics and many other useful features. Most vendors offer a free plan.

### Wikipedia about APM

Expand All @@ -14,11 +14,11 @@ Major products and segments

APM products constitues 3 major segments:

1. Website or API monitoring – external services that constantly monitor uptime and performance via HTTP requests. Can be setup in few minutes. Following are few selected contenders: Pingdom, Uptime Robot, and New Relic
1. Website or API monitoring – external services that constantly monitor uptime and performance via HTTP requests. Can be set up in few minutes. Following are few selected contenders: [Pingdom](https://www.pingdom.com/), [Uptime Robot](https://uptimerobot.com/), and [New Relic](https://newrelic.com/application-monitoring)

2. Code instrumentation – products family which require to embed an agent within the application to benefit feature slow code detection, exceptions statistics, performance monitoring and many more. Following are few selected contenders: New Relic, App Dynamics
2. Code instrumentation – product family which require to embed an agent within the application to use features like slow code detection, exception statistics, performance monitoring and many more. Following are few selected contenders: New Relic, App Dynamics

3. Operational intelligence dashboard – these line of products are focused on facilitating the ops team with metrics and curated content that helps to easily stay on top of application performance. This usually involves aggregating multiple sources of information (application logs, DB logs, servers log, etc) and upfront dashboard design work. Following are few selected contenders: Datadog, Splunk
3. Operational intelligence dashboard – this line of products is focused on facilitating the ops team with metrics and curated content that helps to easily stay on top of application performance. This usually involves aggregating multiple sources of information (application logs, DB logs, servers log, etc) and upfront dashboard design work. Following are few selected contenders: [Datadog](https://www.datadoghq.com/), [Splunk](https://www.splunk.com/), [Zabbix](https://www.zabbix.com/)



Expand Down
6 changes: 3 additions & 3 deletions sections/errorhandling/asyncerrorhandling.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ doWork()
```javascript
getData(someParameter, function(err, result){
if(err != null)
//do something like calling the given callback function and pass the error
// do something like calling the given callback function and pass the error
getMoreData(a, function(err, result){
if(err != null)
//do something like calling the given callback function and pass the error
// do something like calling the given callback function and pass the error
getMoreData(b, function(c){
getMoreData(d, function(e){
if(err != null)
//you get the idea? 
// you get the idea? 
});
});
```
Expand Down
8 changes: 4 additions & 4 deletions sections/errorhandling/catchunhandledpromiserejection.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@

### One Paragraph Explainer

Typically, most of modern Node.JS/Express application code runs within promises – whether within the .then handler, a function callback or in a catch block. Suprisingly, unless a developer remembered to add a .catch clause, errors thrown at these places are not handled by the uncaughtException event-handler and disappear. Recent versions of Node added a warning message when an unhandled rejection pops, though this might help to notice when things go wrong but it's obviously not a proper error handling. The straightforward solution is to never forget adding .catch clause within each promise chain call and redirect to a centralized error handler. However building your error handling strategy only on developer’s discipline is somewhat fragile. Consequently, it’s highly recommended using a graceful fallback and subscribe to process.on(‘unhandledRejection’, callback) – this will ensure that any promise error, if not handled locally, will get its treatment.
Typically, most of modern Node.JS/Express application code runs within promises – whether within the .then handler, a function callback or in a catch block. Suprisingly, unless a developer remembered to add a .catch clause, errors thrown at these places are not handled by the uncaughtException event-handler and disappear. Recent versions of Node added a warning message when an unhandled rejection pops, though this might help to notice when things go wrong but it's obviously not a proper error handling method. The straightforward solution is to never forget adding .catch clauses within each promise chain call and redirect to a centralized error handler. However building your error handling strategy only on developer’s discipline is somewhat fragile. Consequently, it’s highly recommended using a graceful fallback and subscribe to `process.on(‘unhandledRejection’, callback)` – this will ensure that any promise error, if not handled locally, will get its treatment.

<br/><br/>

### Code example: these errors will not get caught by any error handler (except unhandledRejection)

```javascript
DAL.getUserById(1).then((johnSnow) => {
//this error will just vanish
// this error will just vanish
if(johnSnow.isAlive == false)
throw new Error('ahhhh');
});
Expand All @@ -23,11 +23,11 @@ DAL.getUserById(1).then((johnSnow) => {

```javascript
process.on('unhandledRejection', (reason, p) => {
//I just caught an unhandled promise rejection, since we already have fallback handler for unhandled errors (see below), let throw and let him handle that
// I just caught an unhandled promise rejection, since we already have fallback handler for unhandled errors (see below), let throw and let him handle that
throw reason;
});
process.on('uncaughtException', (error) => {
//I just received an error that was never handled, time to handle it and then decide whether a restart is needed
// I just received an error that was never handled, time to handle it and then decide whether a restart is needed
errorManagement.handler.handleError(error);
if (!errorManagement.handler.isTrustedError(error))
process.exit(1);
Expand Down
8 changes: 4 additions & 4 deletions sections/errorhandling/centralizedhandling.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ Without one dedicated object for error handling, greater are the chances of impo
### Code Example – a typical error flow

```javascript
//DAL layer, we don't handle errors here
// DAL layer, we don't handle errors here
DB.addDocument(newCustomer, (error, result) => {
if (error)
throw new Error("Great error explanation comes here", other useful parameters)
});

//API route code, we catch both sync and async errors and forward to the middleware
// API route code, we catch both sync and async errors and forward to the middleware
try {
customerService.addNew(req.body).then((result) => {
res.status(200).json(result);
Expand All @@ -28,7 +28,7 @@ catch (error) {
next(error);
}

//Error handling middleware, we delegate the handling to the centralized error handler
// Error handling middleware, we delegate the handling to the centralized error handler
app.use((err, req, res, next) => {
errorHandler.handleError(err).then((isOperationalError) => {
if (!isOperationalError)
Expand All @@ -53,7 +53,7 @@ function errorHandler(){
### Code Example – Anti Pattern: handling errors within the middleware

```javascript
//middleware handling the error directly, who will handle Cron jobs and testing errors?
// middleware handling the error directly, who will handle Cron jobs and testing errors?
app.use((err, req, res, next) => {
logger.logError(err);
if(err.severity == errors.high)
Expand Down
4 changes: 2 additions & 2 deletions sections/errorhandling/documentingusingswagger.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

### One Paragraph Explainer

REST APIs return results using HTTP code, it’s absolutely required for the API user to be aware not only about the API schema but also about potential errors – the caller may then catch an error and tactfully handle it. For example, your API documentation might state in advanced that HTTP status 409 is returned when the customer name already exist (assuming the API register new users) so the caller can correspondingly render the best UX for the given situation. Swagger is a standard that defines the schema of API documentation offering an eco-system of tools that allow creating documentation easily online, see print screens below
REST APIs return results using HTTP status codes, it’s absolutely required for the API user to be aware not only about the API schema but also about potential errors – the caller may then catch an error and tactfully handle it. For example, your API documentation might state in advanced that HTTP status 409 is returned when the customer name already exist (assuming the API register new users) so the caller can correspondingly render the best UX for the given situation. Swagger is a standard that defines the schema of API documentation offering an eco-system of tools that allow creating documentation easily online, see print screens below

### Blog Quote: "You have to tell your callers what errors can happen"
From the blog Joyent, ranked 1 for the keywords “Node.JS logging”
Expand All @@ -12,4 +12,4 @@ From the blog Joyent, ranked 1 for the keywords “Node.JS logging”

### Useful Tool: Swagger Online Documentation Creator
![alt text](https://github.com/i0natan/nodebestpractices/blob/master/assets/images/swaggerDoc.png "API error handling")
![Swagger API Scheme](https://github.com/i0natan/nodebestpractices/blob/master/assets/images/swaggerDoc.png "API error handling")
10 changes: 5 additions & 5 deletions sections/errorhandling/failfast.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ We all know how checking arguments and failing fast is important to avoid hidden

### Wikipedia: Defensive Programming

Defensive programming is an approach to improve software and source code, in terms of: General quality – reducing the number of software bugs and problems. Making the source code comprehensible – the source code should be readable and understandable so it is approved in a code audit. Making the software behave in a predictable manner despite unexpected inputs or user actions.
Defensive programming is an approach to improve software and source code, in terms of: General quality – reducing the number of software bugs and problems. Making the source code comprehensible – the source code should be readable and understandable so it is approved in a code audit. Making the software behave in a predictable manner despite unexpected inputs or user actions.



Expand All @@ -22,25 +22,25 @@ var memberSchema = Joi.object().keys({

function addNewMember(newMember)
{
//assertions come first
// assertions come first
Joi.assert(newMember, memberSchema); //throws if validation fails
//other logic here
// other logic here
}

```

### Anti-pattern: no validation yields nasty bugs

```javascript
//if the discount is positive let's then redirect the user to pring his discount coupons
// if the discount is positive let's then redirect the user to pring his discount coupons
function redirectToPrintDiscount(httpResponse, member, discount)
{
if(discount != 0)
httpResponse.redirect(`/discountPrintView/${member.id}`);
}

redirectToPrintDiscount(httpResponse, someMember);
//forgot to pass the parameter discount, why the heck was the user redirected to the discount screen?
// forgot to pass the parameter discount, why the heck was the user redirected to the discount screen?

```

Expand Down
2 changes: 1 addition & 1 deletion sections/errorhandling/monitoring.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Title
# Monitoring


### One Paragraph Explainer
Expand Down
12 changes: 6 additions & 6 deletions sections/errorhandling/operationalvsprogrammererror.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@

### One Paragraph Explainer

Distinguishing the following two error types will minimize your app downtime and helps avoid crazy bugs: Operational errors refer to situations where you understand what happened and the impact of it – for example, a query to some HTTP service failed due to connection problem. On the other hand, programmer errors refer to cases where you have no idea why and sometimes where an error came from – it might be some code that tried to read an undefined value or DB connection pool that leaks memory. Operational errors are relatively easy to handle – usually logging the error is enough. Things become hairy when a programmer error pops up, the application might be in an inconsistent state and there’s nothing better you can do than restart gracefully
Distinguishing the following two error types will minimize your app downtime and helps avoid crazy bugs: Operational errors refer to situations where you understand what happened and the impact of it – for example, a query to some HTTP service failed due to connection problem. On the other hand, programmer errors refer to cases where you have no idea why and sometimes where an error came from – it might be some code that tried to read an undefined value or DB connection pool that leaks memory. Operational errors are relatively easy to handle – usually logging the error is enough. Things become hairy when a programmer error pops up, the application might be in an inconsistent state and there’s nothing better you can do than to restart gracefully



### Code Example – marking an error as operational (trusted)

```javascript
//marking an error object as operational
// marking an error object as operational
var myError = new Error("How can I add new product when no value provided?");
myError.isOperational = true;

//or if you're using some centralized error factory (see other examples at the bullet "Use only the built-in Error object")
// or if you're using some centralized error factory (see other examples at the bullet "Use only the built-in Error object")
function appError(commonType, description, isOperational) {
Error.call(this);
Error.captureStackTrace(this);
Expand All @@ -31,18 +31,18 @@ From the blog Joyent, ranked 1 for the keywords “Node.JS error handling”

> …The best way to recover from programmer errors is to crash immediately. You should run your programs using a restarter that will automatically restart the program in the event of a crash. With a restarter in place, crashing is the fastest way to restore reliable service in the face of a transient programmer error…
### Blog Quote: "No safe way to leave without creating some undefined brittle state"
### Blog Quote: "No safe way to leave without creating some undefined brittle state"
From Node.JS official documentation

> …By the very nature of how throw works in JavaScript, there is almost never any way to safely “pick up where you left off”, without leaking references, or creating some other sort of undefined brittle state. The safest way to respond to a thrown error is to shut down the process. Of course, in a normal web server, you might have many connections open, and it is not reasonable to abruptly shut those down because an error was triggered by someone else. The better approach is to send an error response to the request that triggered the error, while letting the others finish in their normal time, and stop listening for new requests in that worker.

### Blog Quote: "Otherwise you risk the state of your application"
### Blog Quote: "Otherwise you risk the state of your application"
From the blog debugable.com, ranked 3 for the keywords “Node.JS uncaught exception”

> …So, unless you really know what you are doing, you should perform a graceful restart of your service after receiving an “uncaughtException” exception event. Otherwise you risk the state of your application, or that of 3rd party libraries to become inconsistent, leading to all kinds of crazy bugs…
### Blog Quote: "Blog Quote: There are three schools of thoughts on error handling"
### Blog Quote: "Blog Quote: There are three schools of thoughts on error handling"
From the blog: JS Recipes

> …There are primarily three schools of thoughts on error handling:
Expand Down
Loading

0 comments on commit 555cd18

Please sign in to comment.