diff --git a/README.russian.md b/README.russian.md index afd758f7..e1e4c27a 100644 --- a/README.russian.md +++ b/README.russian.md @@ -90,9 +90,9 @@ ## ![✔] 1.4 Разделяйте Express "приложение" и "сервер" -**TL;DR:** Избегайте неприятной привычки определять все приложение [Express] (https://expressjs.com/) в одном огромном файле -- разделите определение "Экспресс" как минимум на два файла: декларация API (app.js) и сетевые задачи (www). Для еще лучшей структуры локализуйте объявление API в компонентах. +**TL;DR:** Избегайте неприятной привычки определять все приложение [Express](https://expressjs.com/) в одном огромном файле -- разделите определение "Экспресс" как минимум на два файла: декларация API (app.js) и сетевые задачи (www). Для еще лучшей структуры локализуйте объявление API в компонентах. -**Иначе:** Ваш API будет доступен для тестирования только через HTTP-вызовы (медленнее и намного сложнее создавать отчеты о покрытии). Скорее всего, не составит большого труда хранить сотни строк кода в одном файле. +**Иначе:** Ваш API будет доступен для тестирования только через HTTP-вызовы (медленнее и намного сложнее создавать отчеты о покрытии). Скорее всего, вы не будете испытывать огромное удовольствие, если будете хранить сотни строк кода в одном файле. 🔗 [**Подробнее: Разделяйте Express "приложение" и "сервер"**](/sections/projectstructre/separateexpress.russian.md) @@ -102,7 +102,7 @@ **TL;DR:** Идеальная и безупречная конфигурация должна обеспечивать (а) считывание ключей из файла И из переменной среды, (б) хранение секретов вне основной кодовой базы, (в) иерархическую структуру для облегчения поиска. Есть несколько пакетов, которые могут помочь поставить галочку в большинстве таких полей, как [rc](https://www.npmjs.com/package/rc), [nconf](https://www.npmjs.com/package/nconf), [config](https://www.npmjs.com/package/config), and [convict](https://www.npmjs.com/package/convict) -**Иначе:** Невыполнение каких-либо требований к конфигурации приведет к срывам в работе разработчиков или devops командой. Вероятно, и тех и других. +**Иначе:** Невыполнение каких-либо требований к конфигурации приведет к срывам в работе разработчиков или devops-команды. А вероятно, и тех и других. 🔗 [**Подробнее: Используйте конфигурацию с учетом среды, безопасную и иерархическую конфигурацию**](/sections/projectstructre/configguide.russian.md) @@ -116,7 +116,7 @@ **TL;DR:** Обработка асинхронных ошибок в стиле обратного вызова, вероятно, является самым быстрым путем в ад (еще говорят "Callback Hell" или "The Pyramid of Doom"). Лучший подарок, который вы можете сделать своему коду, -- это использовать надежную библиотеку обещаний или async-await, что позволяет использовать более компактный и знакомый синтаксис кода, такой как try-catch. -**Иначе:** Стиль обратного вызова Node.js, функция (err, response), является многообещающим способом создания непригодного для использования кода из-за сочетания обработки ошибок со случайным кодом, чрезмерных вложений и слабых шаблонов кодирования. +**Иначе:** Callback-стиль Node.js, function(err, response), является многообещающим способом создания непригодного для использования кода из-за сочетания таких проблем, как обработка ошибок со случайным кодом, чрезмерные вложения и неудобные шаблоны проектирования. 🔗 [**Подробнее: Используйте Async-Await или обещания для асинхронной обработки ошибок**](/sections/errorhandling/asyncerrorhandling.russian.md) @@ -132,21 +132,21 @@

-## ![✔] 2.3 Различайте ошибки в работе и программировании +## ![✔] 2.3 Различайте операционные ошибки и ошибки программиста -**TL;DR:** Операционные ошибки (например, API получил неверный ввод) относятся к известным случаям, когда влияние ошибки полностью осознается и может быть обработано вдумчиво. С другой стороны, ошибка программиста (например, попытка прочитать неопределенную переменную) относится к неизвестным ошибкам кода, которые требуют изящного перезапуска приложения. +**TL;DR:** Операционные ошибки (например, API получил неверный ввод) относятся к таким случаям, когда влияние ошибки полностью осознается и может быть обработано вдумчиво. Ошибка программиста (например, попытка прочитать undefined-переменную) относится к неизвестным ошибкам, которые требуют безопасного перезапуска приложения. -**Иначе:** Вы всегда можете перезапустить приложение, когда появляется ошибка, но зачем подводить ~5000 онлайн-пользователей из-за незначительной, прогнозируемой, операционной ошибки? Обратное также не идеально -- поддержание приложения в том случае, если возникла неизвестная проблема (ошибка программиста), может привести к непредсказуемому поведению. Разграничение между ними позволяет действовать тактично и применять сбалансированный подход, основанный на данном контексте. +**Иначе:** Вы всегда можете перезапустить приложение, когда появляется ошибка, но зачем подводить ~5000 онлайн-пользователей из-за незначительной и прогнозируемой операционной ошибки? Обратное также не является идеальным -- отсутствие перезапуска приложения в случае, если возникла неизвестная проблема (ошибка программиста), может привести к непредсказуемому поведению. Понимание типа ошибки позволит действовать тактично и применять сбалансированный подход, основанный на предоставленном контексте. -🔗 [**Подробнее: Различайте операционные и программистские ошибки**](/sections/errorhandling/operationalvsprogrammererror.russian.md) +🔗 [**Подробнее: Различайте операционные ошибки и ошибки программиста**](/sections/errorhandling/operationalvsprogrammererror.russian.md)

-## ![✔] 2.4 Обрабатывате ошибки централизованно, а не в промежуточном слое Express +## ![✔] 2.4 Обрабатывате ошибки централизованно, а не в промежуточных обработчиках Express -**TL;DR:** Логика обработки ошибок, такая как уведомление по почте администратора или ведение журнала, должна быть заключена в выделенный и централизованный объект, который вызывается всеми конечными точками (например, промежуточные слои Express, задания cron, модульное тестирование) при возникновении ошибки. +**TL;DR:** Логика обработки ошибок, например, как уведомление по почте администратора или ведение журнала, должна быть инкапсулирована в выделенный и централизованный объект, который вызывается всеми точками входа (обработчиками Express, cron-задачами, юнит-тестами) при возникновении ошибки. -**Иначе:** Необработка ошибок в одном месте приведет к дублированию кода и, возможно, к ошибкам, обработанным неправильно. +**Иначе:** Отсутствие обработки ошибок в едином месте приведет к дублированию кода и, возможно, к неверной обработке ошибок. 🔗 [**Подробнее: Обрабатывайте ошибки централизованно. Не в промежуточных слоях**](/sections/errorhandling/centralizedhandling.russian.md) diff --git a/sections/errorhandling/asyncerrorhandling.russian.md b/sections/errorhandling/asyncerrorhandling.russian.md index 24fbc7d0..5cf3ad2c 100644 --- a/sections/errorhandling/asyncerrorhandling.russian.md +++ b/sections/errorhandling/asyncerrorhandling.russian.md @@ -2,7 +2,7 @@ ### Объяснение в один абзац -Обратные вызовы плохо масштабируются, так как большинство программистов не знакомы с ними. Они заставляют проверять ошибки повсюду, имеют дело с неприятным вложением кода и затрудняют анализ потока кода. Библиотеки Promise, такие как BlueBird, async и Q, упаковывают стандартный стиль кода, используя RETURN и THROW для управления потоком программы. В частности, они поддерживают любимый стиль обработки ошибок try-catch, который позволяет освободить путь к основному коду от ошибок в каждой функции +Обратные вызовы плохо масштабируются, так как большинство программистов не знакомы с ними. Они заставляют проверять ошибки повсюду, иметь дело с неприятной вложенностью кода и затрудняют анализ потока кода. Библиотеки обещаний (promise), такие как BlueBird, async и Q, упаковывают стандартный стиль кода, используя RETURN и THROW для управления потоком программы. В частности, они поддерживают наилучший стиль обработки ошибок try-catch, который позволяет освободить основной код от обработки ошибок в каждой функции. ### Пример кода – использование обещаний для отлова ошибок @@ -15,7 +15,6 @@ return functionA() .then(alwaysExecuteThisFunction) ``` - ### Пример кода - использование async/await для отлова ошибок ```javascript @@ -34,7 +33,7 @@ async function executeAsyncTask () { } ``` -### Антипаттерн. Обработка ошибок в стиле обратного вызова +### Антипаттерн. Обработка ошибок в callback-стиле
Javascript @@ -42,14 +41,14 @@ async function executeAsyncTask () { ```javascript getData(someParameter, function(err, result) { if(err !== null) { - // 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 + // вызываем коллбек функцию и передаем ошибку getMoreData(b, function(c) { getMoreData(d, function(e) { if(err !== null ) { - // you get the idea? + // вы поняли идею? } }) }); @@ -66,14 +65,14 @@ getData(someParameter, function(err, result) { ```typescript getData(someParameter, function(err: Error | null, resultA: ResultA) { if(err !== null) { - // do something like calling the given callback function and pass the error + // вызываем коллбек функцию и передаем ошибку getMoreData(resultA, function(err: Error | null, resultB: ResultB) { if(err !== null) { - // do something like calling the given callback function and pass the error + // вызываем коллбек функцию и передаем ошибку getMoreData(resultB, function(resultC: ResultC) { getMoreData(resultC, function(err: Error | null, d: ResultD) { if(err !== null) { - // you get the idea? + // вы поняли идею? } }) }); @@ -90,20 +89,20 @@ getData(someParameter, function(err: Error | null, resultA: ResultA) { > … На самом деле, обратные вызовы делают что-то еще более зловещее: они лишают нас стека, что мы обычно принимаем как должное в языках программирования. Написание кода без стека очень похоже на вождение автомобиля без педали тормоза: вы не понимаете, насколько сильно оно вам нужно, пока не дойдете до него, а его там нет. Весь смысл обещаний состоит в том, чтобы вернуть нам языковые основы, которые мы потеряли при асинхронности: возврат, выброс и стек. Но вы должны знать, как правильно использовать обещания, чтобы воспользоваться ими. -### Цитата блога: "Метод обещаний гораздо более компактен" +### Цитата блога: "Подход с обещаниями гораздо более компактен" Из блога gosquared.com -> … Метод обещаний гораздо компактнее, понятнее и быстрее для написания. Если ошибка или исключение происходят в любом из операций, они обрабатываются одним обработчиком .catch(). Наличие единого места для обработки всех ошибок означает, что вам не нужно писать проверку ошибок для каждого этапа работы. +> … Подход с обещаниями гораздо компактнее, понятнее и быстрее для написания. Если ошибка или исключение происходят в любой из операций, они обрабатываются одним обработчиком .catch(). Наличие единого места для обработки всех ошибок означает, что вам не нужно писать проверку ошибок для каждого этапа работы. -### Цитата блога: "Обещания являются родными ES6, могут использоваться с генераторами" +### Цитата блога: "Обещания являются нативными в ES6, могут использоваться с генераторами" Из блога StrongLoop -> … Обратные вызовы имеют паршивую историю обработки ошибок. Обещания лучше. Объедините встроенную обработку ошибок в Express с обещаниями и значительно снизьте вероятность возникновения необработанного исключения. Обещания являются родными ES6, могут использоваться с генераторами, а предложения ES7, такие как async/await, через компиляторы, такие как Babel. +> … Обратные вызовы имеют паршивую историю обработки ошибок. Обещания лучше. Объедините встроенную обработку ошибок в Express с обещаниями и значительно снизьте вероятность возникновения необработанного исключения. Обещания являются нативными в ES6, могут использоваться с генераторами, а proposals из ES7, такие как async/await, могут использоваться через компиляторы, такие как Babel. ### Цитата из блога: "Все те обычные конструкции управления потоком, к которым вы привыкли, полностью разрушены" Из блога Бенно -> … Одно из лучших преимуществ асинхронного программирования на основе обратного вызова состоит в том, что в основном все эти обычные конструкции управления потоком, к которым вы привыкли, полностью разрушены. Тем не менее, я считаю, что больше всего разрушения коснулись обработки исключений. Javascript предоставляет довольно знакомую конструкцию try…catch для работы с исключениями. Проблема с исключениями состоит в том, что они обеспечивают отличный способ сокращения ошибок в стеке вызовов, но в конечном итоге оказываются совершенно бесполезными, если ошибка происходит в другом стеке… +> … Одно из лучших преимуществ асинхронного программирования на основе обратного вызова состоит в том, что в основном все эти обычные конструкции управления потоком, к которым вы привыкли, полностью разрушены. Тем не менее, я считаю, что больше всего разрушения коснулась обработка исключений. Javascript предоставляет довольно знакомую конструкцию try…catch для работы с исключениями. Проблема с исключениями состоит в том, что они обеспечивают отличный способ сокращения ошибок в стеке вызовов, но в конечном итоге оказываются совершенно бесполезными, если ошибка происходит в другом стеке… \ No newline at end of file diff --git a/sections/errorhandling/centralizedhandling.russian.md b/sections/errorhandling/centralizedhandling.russian.md index e0cc92ce..30329ba9 100644 --- a/sections/errorhandling/centralizedhandling.russian.md +++ b/sections/errorhandling/centralizedhandling.russian.md @@ -2,7 +2,7 @@ ### Объяснение в один абзац -Без специального выделенного объекта для обработки ошибок больше шансов на то, что важные ошибки скрываются под радаром из-за неправильного обращения. Объект обработчика ошибок отвечает за отображение ошибки, например, путем записи в хорошо отформатированный регистратор, отправки событий в некоторые продукты мониторинга, такие как [Sentry](https://sentry.io/), [Rollbar](https://rollbar.com/) или [Raygun](https://raygun.com/). Большинство веб-фреймворков, таких как [Express](http://expressjs.com/en/guide/error-handling.html#writing-error-handlers), предоставляют механизм промежуточного программного обеспечения для обработки ошибок. Типичный поток обработки ошибок может быть следующим: какой-то модуль выдает ошибку -> маршрутизатор API перехватывает ошибку -> он передает ошибку промежуточному программному обеспечению (например, Express, KOA), которое отвечает за перехват ошибок -> вызывается централизованный обработчик ошибок -> промежуточному программному обеспечению сообщается, является ли эта ошибка ненадежной (не работающей), чтобы она могла корректно перезапустить приложение. Обратите внимание, что обычная, но неправильная практика - обрабатывать ошибки в промежуточном программном обеспечении Express - это не распространяется на ошибки, возникающие в не-веб-интерфейсах. +Без выделенного объекта для обработки ошибок есть больше шансов на то, что ошибки потеряются с радара из-за их неправильной обработки. Объект обработчика ошибок отвечает за отображение ошибки, например, путем записи в логгер, отправки событий в сервисы мониторинга, такие как [Sentry](https://sentry.io/), [Rollbar](https://rollbar.com/) или [Raygun](https://raygun.com/). Большинство веб-фреймворков, таких как [Express](http://expressjs.com/en/guide/error-handling.html#writing-error-handlers), предоставляют механизм обработки ошибок с помощью функций промежуточной обработки (**middlewares**). Типичный поток обработки ошибок может выглядеть следующим образом: какой-то модуль выдает ошибку -> API-маршрутизатор перехватывает ошибку -> он передает ошибку функции промежуточной обработки (Express, KOA), которая отвечает за перехват ошибок -> вызывается централизованный обработчик ошибок -> функции промежуточной обработки передается информация о том, что является ли эта ошибка ненадежной (необрабатываемой), чтобы она могла корректно перезапустить приложение. Обратите внимание, что обычная, но неправильная практика - обрабатывать ошибки в функции промежуточной обработки Express - это не распространяется на ошибки, возникающие в не-веб-интерфейсах. ### Пример кода - типичный поток ошибок @@ -10,13 +10,14 @@ Javascript ```javascript -// DAL layer, we don't handle errors here +// DAL-слой, мы не обрабатываем ошибки тут 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-маршрутизатора, мы обрабатываем как sync +// так и async ошибки и переходим к middleware try { customerService.addNew(req.body).then((result) => { res.status(200).json(result); @@ -28,7 +29,7 @@ catch (error) { next(error); } -// Error handling middleware, we delegate the handling to the centralized error handler +// Обработка ошибок в middleware, мы делегируем обработку централизованному обработчику ошибок app.use(async (err, req, res, next) => { const isOperationalError = await errorHandler.handleError(err); if (!isOperationalError) { @@ -42,13 +43,14 @@ app.use(async (err, req, res, next) => { Typescript ```typescript -// DAL layer, we don't handle errors here +// DAL-слой, мы не обрабатываем ошибки тут DB.addDocument(newCustomer, (error: Error, result: 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-маршрутизатора, мы обрабатываем как sync +// так и async ошибки и переходим к middleware try { customerService.addNew(req.body).then((result: Result) => { res.status(200).json(result); @@ -60,7 +62,7 @@ catch (error) { next(error); } -// Error handling middleware, we delegate the handling to the centralized error handler +// Обработка ошибок в middleware, мы делегируем обработку централизованному обработчику ошибок app.use(async (err: Error, req: Request, res: Response, next: NextFunction) => { const isOperationalError = await errorHandler.handleError(err); if (!isOperationalError) { @@ -82,9 +84,9 @@ module.exports.handler = new errorHandler(); function errorHandler() { this.handleError = async (err) { await logger.logError(err); - await sendMailToAdminIfCritical; - await saveInOpsQueueIfCritical; - await determineIfOperationalError; + await sendMailToAdminIfCritical(err); + await saveInOpsQueueIfCritical(err); + await determineIfOperationalError(err); }; } ``` @@ -97,9 +99,9 @@ function errorHandler() { class ErrorHandler { public async handleError(err: Error): Promise { await logger.logError(err); - await sendMailToAdminIfCritical(); - await saveInOpsQueueIfCritical(); - await determineIfOperationalError(); + await sendMailToAdminIfCritical(err); + await saveInOpsQueueIfCritical(err); + await determineIfOperationalError(err); }; } @@ -108,13 +110,14 @@ export const handler = new ErrorHandler();
-### Пример кода - антипаттерн: обработка ошибок в промежуточном программном обеспечении +### Пример кода - антипаттерн: обработка ошибок в middleware
Javascript ```javascript -// middleware handling the error directly, who will handle Cron jobs and testing errors? +// middleware, обрабатывающий ошибки напрямую. +// А кто будет обрабатывать ошибки возникшие в Cron или при юнит-тестировании? app.use((err, req, res, next) => { logger.logError(err); if (err.severity == errors.high) { @@ -132,7 +135,8 @@ app.use((err, req, res, next) => { Typescript ```typescript -// middleware handling the error directly, who will handle Cron jobs and testing errors? +// middleware, обрабатывающий ошибки напрямую. +// А кто будет обрабатывать ошибки возникшие в Cron или при юнит-тестировании? app.use((err: Error, req: Request, res: Response, next: NextFunction) => { logger.logError(err); if (err.severity == errors.high) { @@ -145,20 +149,20 @@ app.use((err: Error, req: Request, res: Response, next: NextFunction) => { ```
-### Цитата из блога: "Иногда нижние уровни не могут сделать ничего полезного, кроме как сообщить об ошибке вызывающей стороне" +### Цитата из блога: "Иногда нижние слои не могут сделать ничего полезного, кроме как сообщить об ошибке вызывающему слою" -Из блога Joyent, занимающий 1 место по ключевым словам "Обработка ошибок Node.js" +Из блога Joyent, занимающего 1 место по ключевым словам "Обработка ошибок Node.js" -> … Вы можете обработать одну и ту же ошибку на нескольких уровнях стека. Это происходит, когда нижние уровни не могут сделать ничего полезного, кроме как передать ошибку вызывающей стороне, которая передает ошибку своей вызывающей стороне, и так далее. Зачастую только вызывающий пользователь верхнего уровня знает, что является подходящим ответом: попытка повторить операцию, сообщить пользователю об ошибке или что-то еще. Но это не значит, что вы должны пытаться сообщать обо всех ошибках в один обратный вызов верхнего уровня, потому что сам этот обратный вызов не может знать, в каком контексте произошла ошибка … +> … Вы можете обработать одну и ту же ошибку на нескольких слоях. Это происходит, когда нижние слои не могут сделать ничего полезного, кроме как передать ошибку вызывающему слою, который передаст ошибку своему вызывающему слою, и так далее. Зачастую только самый верхний слой знает, что является подходящим действием на ошибку: попытка повторить операцию, сообщить пользователю об ошибке или что-то еще. Но это не значит, что вы должны пытаться сообщать обо всех ошибках в один верхний callback, потому что этот callback не может знать, в каком контексте произошла ошибка … -### Цитата из блога: "Обработка каждой ошибки по отдельности приведет к огромному дублированию" +### Цитата из блога: "Обработка каждой ошибки по отдельности приведет к ужасному дублированию" -Из блога JS Recipes, занимающий 17 место по ключевым словам "Обработка ошибок Node.js" +Из блога JS Recipes, занимающего 17 место по ключевым словам "Обработка ошибок Node.js" -> … Только в контроллере api.js Hackathon Starter имеется более 79 случаев появления объектов ошибок. Обработка каждой ошибки в отдельности привела бы к огромному количеству дублирования кода. Следующее, что вы можете сделать, это делегировать всю логику обработки ошибок в промежуточное ПО Express … +> … Только в контроллере api.js Hackathon Starter имеется более 79 объектов ошибок. Обработка каждой ошибки в отдельности привела бы к ужасному дублированию кода. Следующее, что вы можете сделать, это делегировать всю логику обработки ошибок в middleware Express … ### Цитата из блога: "В коде вашей базы данных нет места ошибкам HTTP" Из блога Daily JS, занимающем 14 место по ключевым словам "Обработка ошибок Node.js" -> … Вы должны установить полезные свойства в объектах ошибок, но использовать их последовательно. И не пересекайте потоки: в коде вашей базы данных нет места ошибкам HTTP. Или для разработчиков браузеров, ошибки Ajax имеют место в коде, который общается с сервером, но не в коде, который обрабатывает шаблоны усов … +> … Вы должны добавлять полезные свойства в объекты ошибок, но использовать их согласовано. И не пересекайте логику: в коде вашей базы данных нет места ошибкам HTTP. Или, например, для frontend-разработчиков, ошибки Ajax имеют место в коде, который общается с сервером, но не в коде, который работает с шаблонами Mustache … diff --git a/sections/errorhandling/operationalvsprogrammererror.russian.md b/sections/errorhandling/operationalvsprogrammererror.russian.md index 544dbd3c..bfb78c40 100644 --- a/sections/errorhandling/operationalvsprogrammererror.russian.md +++ b/sections/errorhandling/operationalvsprogrammererror.russian.md @@ -1,20 +1,20 @@ -# Различайте операционные и программистские ошибки +# Различайте операционные ошибки и ошибки программиста ### Объяснение в один абзац -Различение следующих двух типов ошибок минимизирует время простоя вашего приложения и помогает избежать сумасшедших ошибок: Операционные ошибки относятся к ситуациям, когда вы понимаете, что произошло, и влияние этого - например, запрос к какой-либо службе HTTP не выполнен из-за проблемы с подключением. С другой стороны, ошибки программиста относятся к случаям, когда вы не знаете, почему, а иногда и откуда возникла ошибка - это может быть какой-то код, который пытался прочитать неопределенное значение или пул соединений с БД, который приводит к утечке памяти. Операционные ошибки относительно легко обрабатываются - обычно достаточно регистрации ошибки. Вещи становятся неприятными, когда появляется ошибка программиста, приложение может быть в несовместимом состоянии, и нет ничего лучше, чем перезапуск изящно. +Разделение ошибок на эти два типа минимизирует время простоя вашего приложения и помогает избежать сумасшедших ошибок: операционные ошибки относятся к ситуациям, когда вы понимаете происходящее и влияние ошибки на программу. Например, запрос к какой-нибудь службе HTTP не выполнен из-за проблемы с подключением. С другой стороны, ошибки программиста относятся к случаям, когда вы не знаете, почему, а иногда и откуда возникла ошибка - это может быть какой-то код, который пытался прочитать undefined-значение или код, который использует пул соединений с БД и приводит к утечке памяти. Операционные ошибки относительно легко обрабатываются - обычно достаточно логирования ошибки. Хуже становиться, когда появляется ошибка программиста, приложение может быть в несогласованном состоянии, и все, что вы можете сделать - перезапустить приложение. -### Пример кода - пометка ошибки как рабочей (доверенной) +### Пример кода - помечаем ошибку как операционную (доверенную)
Javascript ```javascript -// marking an error object as operational -const myError = new Error('How can I add new product when no value provided?'); +// помечаем объект ошибки, как операционный +const myError = new Error('Как мы можем добавить продукт, если значение не задано?'); 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") +// или, если вы используете централизированную фабрику ошибок (смотрите другие примеры в статье "Используйте только встроенный объект Error") class AppError { constructor (commonType, description, isOperational) { Error.call(this); @@ -25,7 +25,7 @@ class AppError { } }; -throw new AppError(errorManagement.commonErrors.InvalidInput, 'Describe here what happened', true); +throw new AppError(errorManagement.commonErrors.InvalidInput, 'Описываем, что произошло', true); ```
@@ -34,7 +34,7 @@ throw new AppError(errorManagement.commonErrors.InvalidInput, 'Describe here wha Typescript ```typescript -// some centralized error factory (see other examples at the bullet "Use only the built-in Error object") +// или, если вы используете централизированную фабрику ошибок (смотрите другие примеры в статье "Используйте только встроенный объект Error") export class AppError extends Error { public readonly commonType: string; public readonly isOperational: boolean; @@ -42,7 +42,7 @@ export class AppError extends Error { constructor(commonType: string, description: string, isOperational: boolean) { super(description); - Object.setPrototypeOf(this, new.target.prototype); // restore prototype chain + Object.setPrototypeOf(this, new.target.prototype); // восстанавливаем цепочку прототипов this.commonType = commonType; this.isOperational = isOperational; @@ -51,7 +51,7 @@ export class AppError extends Error { } } -// marking an error object as operational (true) +// помечаем объект ошибки, как операционный (true) throw new AppError(errorManagement.commonErrors.InvalidInput, 'Describe here what happened', true); ``` @@ -59,27 +59,27 @@ throw new AppError(errorManagement.commonErrors.InvalidInput, 'Describe here wha ### Цитата блога: "Ошибки программиста - это ошибки в программе" -Из блога Джойент, занявшему 1 место по ключевым словам "Обработка ошибок Node.js" +Из блога Джойент, занявшего 1 место по ключевым словам "Обработка ошибок Node.js" -> … Лучший способ исправить ошибки программиста - это сразу же аварийно завершить работу. Вы должны запустить свои программы, используя перезапуск, который автоматически перезапустит программу в случае сбоя. С перезапуском на месте сбой является самым быстрым способом восстановления надежного сервиса перед лицом временной ошибки программиста … +> … Лучший способ исправить ошибки программиста - это сразу же аварийно завершить работу. Вы должны запускать свои программы, используя сервис перезапуска, который автоматически будет перезапускать программу в случае сбоя. Сервис перезапуска является самым простым способом надежного восстановления сервиса при возникновении временной ошибки программиста… -### Цитата из блога: "Нет безопасного способа уйти, не создав неопределенного хрупкого состояния" +### Цитата из блога: "Нет безопасного способа продолжить без возникновения хрупкого undefined-состояния системы" Из официальной документации Node.js -> … По самой природе того, как throw работает в JavaScript, почти никогда не существует способа безопасно "выбрать то, на чем остановился", без утечки ссылок или создания какого-либо другого неопределенного хрупкого состояния. Самый безопасный способ отреагировать на возникшую ошибку - завершить процесс. Конечно, на обычном веб-сервере у вас может быть открыто много подключений, и нет смысла внезапно закрывать их, потому что кто-то еще вызвал ошибку. Лучший подход - отправить ответ об ошибке на запрос, который вызвал ошибку, позволяя остальным завершить работу в обычное время, и прекратить прослушивание новых запросов этого работника. +> …По самой природе того, как throw работает в JavaScript, почти всегда нет способа безопасно "начать оттуда, где мы остановились", без утечки ссылок или создания другого undefined-состояния. Самый безопасный способ отреагировать на возникшую ошибку - завершить процесс. Конечно, на обычном веб-сервере у вас может быть открыто много подключений, и нет смысла внезапно закрывать все, потому что кто-то другой выбросил ошибку. Лучший вариант - отправить ответ об ошибке на запрос, который ее вызвал, позволяя остальным завершить работу в удобное время, и после прекратить прослушивание новых запросов в воркере, в котором возникла ошибка. ### Цитата блога: "В противном случае вы рискуете состоянием вашего приложения" Из блога debugable.com, занявшего 3 место по ключевым словам "Node.js uncaught exception" -> … Итак, если вы действительно не знаете, что делаете, вам следует выполнить постепенный перезапуск службы после получения события исключения "uncaughtException". В противном случае вы рискуете привести к несогласованности состояния вашего приложения или сторонних библиотек, что приведет к всевозможным сумасшедшим ошибкам … +> …Итак, если вы действительно не знаете, что делаете, вам следует выполнить постепенный перезапуск службы после получения события исключения "uncaughtException". В противном случае вы рискуете привести к несогласованности состояния вашего приложения или сторонних библиотек, что приведет к всевозможным сумасшедшим ошибкам… ### Цитата блога: "Есть три школы мысли об обработке ошибок" Из блога: JS Recipes -> … Существует три основных направления работы с ошибками: +> …Существует три основных направления работы с ошибками: 1. Дайте приложению упасть и перезапустите его. -2. Обрабатывайте все возможные ошибоки и никогда не роняйте. -3. Сбалансированный подход между двумя предыдущими. +2. Обрабатывайте все возможные ошибоки и никогда не роняйте сервис. +3. Сбалансированный подход между двумя предыдущими. \ No newline at end of file diff --git a/sections/errorhandling/useonlythebuiltinerror.russian.md b/sections/errorhandling/useonlythebuiltinerror.russian.md index ca6bb827..4688bbcf 100644 --- a/sections/errorhandling/useonlythebuiltinerror.russian.md +++ b/sections/errorhandling/useonlythebuiltinerror.russian.md @@ -2,20 +2,20 @@ ### Объяснение в один абзац -Гибкая природа JavaScript наряду с его разнообразием параметров потока кода (например, EventEmitter, Callbacks, Promises и т.д.) приводит к значительному расхождению в том, как разработчики выдают ошибки - некоторые используют строки, другие определяют свои собственные пользовательские типы. Использование встроенного объекта Error в Node.js помогает сохранить единообразие в вашем коде, а с помощью сторонних библиотек он также сохраняет важную информацию, такую ​​как StackTrace. При возникновении исключения обычно рекомендуется заполнить его дополнительными контекстными свойствами, такими как имя ошибки и связанный код ошибки HTTP. Чтобы добиться этого единообразия и практики, рассмотрите возможность расширения объекта Error дополнительными свойствами, см. пример кода ниже. +Гибкая природа JavaScript наряду с его разнообразием вариантов потока кода (например, EventEmitter, Callbacks, Promises и т.д.) приводит к значительному расхождению в том, как разработчики выдают ошибки - некоторые используют строки, другие определяют свои собственные пользовательские типы. Использование встроенного объекта Error в Node.js помогает сохранить единообразие в вашем коде, а с помощью сторонних библиотек он также сохраняет важную информацию, такую ​​как StackTrace. При возникновении исключения обычно рекомендуется заполнить его дополнительными контекстными свойствами, такими как имя ошибки и связанный код ошибки HTTP. Чтобы добиться этого единообразия и практики, рассмотрите возможность расширения объекта Error дополнительными свойствами, см. пример кода ниже. ### Пример кода - делай все правильно ```javascript -// throwing an Error from typical function, whether sync or async +// пробрасываем Error из типичной async или sync функции if(!productToAdd) throw new Error('How can I add new product when no value provided?'); -// 'throwing' an Error from EventEmitter +// пробрасываем Error из EventEmitter const myEmitter = new MyEmitter(); myEmitter.emit('error', new Error('whoops!')); -// 'throwing' an Error from a Promise +// пробрасываем Error из Promise const addProduct = async (productToAdd) => { try { const existingProduct = await DAL.getProduct(productToAdd.id); @@ -31,23 +31,23 @@ const addProduct = async (productToAdd) => { ### Пример кода - антипаттерн ```javascript -// throwing a string lacks any stack trace information and other important data properties +// пробрасывая строку, теряем информацию о stack trace и другие важные параметры if(!productToAdd) throw ('How can I add new product when no value provided?'); ``` -### Пример кода - делаем это еще лучше +### Пример кода - делаем еще лучше
Javascript ```javascript -// centralized error object that derives from Node’s Error +// главные объект ошибки производный от нодовского Error function AppError(name, httpCode, description, isOperational) { Error.call(this); Error.captureStackTrace(this); this.name = name; - //...other properties assigned here + //... другие параметры тут }; AppError.prototype = Object.create(Error.prototype); @@ -55,7 +55,7 @@ AppError.prototype.constructor = AppError; module.exports.AppError = AppError; -// client throwing an exception +// клиент пробрасывает исключение if(user == null) throw new AppError(commonErrors.resourceNotFound, commonHTTPErrors.notFound, 'further explanation', true) ``` @@ -65,7 +65,7 @@ if(user == null) Typescript ```typescript -// centralized error object that derives from Node’s Error +// главные объект ошибки производный от нодовского Error export class AppError extends Error { public readonly name: string; public readonly httpCode: HttpCode; @@ -74,7 +74,7 @@ export class AppError extends Error { constructor(name: string, httpCode: HttpCode, description: string, isOperational: boolean) { super(description); - Object.setPrototypeOf(this, new.target.prototype); // restore prototype chain + Object.setPrototypeOf(this, new.target.prototype); // восстанавливаем цепочку прототипов this.name = name; this.httpCode = httpCode; @@ -84,7 +84,7 @@ export class AppError extends Error { } } -// client throwing an exception +// клиент пробрасывает исключение if(user == null) throw new AppError(commonErrors.resourceNotFound, commonHTTPErrors.notFound, 'further explanation', true) ``` @@ -96,22 +96,22 @@ if(user == null) Из блога Бен Надель, занял 5 место по ключевым словам "объект ошибки Node.js" -> … Лично я не вижу смысла в том, чтобы иметь множество различных типов объектов ошибок - JavaScript, как язык, похоже, не предназначен для поиска ошибок на основе конструктора. Таким образом, дифференцирование по свойству объекта кажется гораздо проще, чем по типу Constructor … +> … Лично я не вижу смысла в том, чтобы иметь множество различных типов объектов ошибок - JavaScript, как язык, похоже, не предназначен для поиска ошибок на основе конструктора. Таким образом, определение по свойству объекта кажется гораздо проще, чем по типу Constructor … ### Цитата блога: "Строка не является ошибкой" Из блога devthought.com, занял 6 место по ключевым словам "Объект ошибки Node.js" -> … передача строки вместо ошибки приводит к снижению совместимости между модулями. Он нарушает контракты с API, которые могут выполнять проверки ошибок instanceof или хотят узнать больше об ошибке. Объекты ошибок, как мы увидим, обладают очень интересными свойствами в современных механизмах JavaScript, помимо хранения сообщения, переданного конструктору … +> … передача строки вместо ошибки приводит к снижению совместимости между модулями. Это нарушает контракты с API, которые могут выполнять проверки ошибок с помощью instanceof или хотят узнать больше об ошибке. Объекты ошибок, как мы увидим, обладают очень интересными свойствами в современных механизмах JavaScript, помимо хранения сообщения, переданного конструктору … -### Цитата из блога: "Наследование от ошибки не увеличивает ценность" +### Цитата из блога: "Наследование от ошибки не увеличивает их ценность" Из блога Machadogj > … Одна проблема, которую я имею с классом Error, заключается в том, что его не так просто расширить. Конечно, вы можете наследовать класс и создавать свои собственные классы ошибок, такие как HttpError, DbError и т.д. Однако это занимает время и не добавляет слишком много значения, если вы не делаете что-то с типами. Иногда вам просто нужно добавить сообщение и сохранить внутреннюю ошибку, а иногда вам может понадобиться расширить ошибку с помощью параметров, и так далее … -### Цитата из блога: "Все ошибки JavaScript и системы, возникающие в Node.js, наследуются от ошибок" +### Цитата из блога: "Все ошибки JavaScript и системы, возникающие в Node.js, наследуются от Error" Из официальной документации Node.js -> … Все ошибки JavaScript и System, возникающие в Node.js, наследуются или являются экземплярами стандартного класса JavaScript Error и гарантированно предоставляют как минимум свойства, доступные в этом классе. Общий объект JavaScript Error, который не обозначает каких-либо конкретных обстоятельств, по которым произошла ошибка. Объекты ошибок фиксируют "трассировку стека", детализирующую точку в коде, в которой был создан экземпляр ошибки, и могут предоставлять текстовое описание ошибки. Все ошибки, сгенерированные Node.js, включая все системные ошибки и ошибки JavaScript, будут либо экземплярами класса Error, либо наследоваться от него … +> … Все ошибки JavaScript и System, возникающие в Node.js, наследуются или являются экземплярами стандартного класса JavaScript Error и гарантированно предоставляют как минимум свойства, доступные в этом классе. Общий объект JavaScript Error, который не обозначает каких-либо конкретных обстоятельств, по которым произошла ошибка. Объекты ошибок фиксируют "трассировку стека", детализирующую точку в коде, в которой был создан экземпляр ошибки, и могут предоставлять текстовое описание ошибки. Все ошибки, сгенерированные Node.js, включая все системные ошибки и ошибки JavaScript, будут либо экземплярами класса Error, либо наследоваться от него … \ No newline at end of file diff --git a/sections/projectstructre/createlayers.russian.md b/sections/projectstructre/createlayers.russian.md index 7579e046..00d5e69b 100644 --- a/sections/projectstructre/createlayers.russian.md +++ b/sections/projectstructre/createlayers.russian.md @@ -1,4 +1,4 @@ -# Выделяйте ваши компоненты в отдельный слой, держите Express в его граница +# Выделяйте ваши компоненты в отдельный слой, держите Express в его границах