Ошибки — это обычное явление в программировании, когда ни один разработчик не может написать код, который просто работает идеально, всегда будут ошибки. Итак, как мы можем отслеживать и исправлять ошибки?

Мы можем выделить 3 категории ошибок: синтаксические, во время выполнения и логические ошибки. В этой статье мы дадим введение каждому из них, подкрепим наши описания примерами, а затем покажем, как мы можем отследить и исправить ошибка при использовании таких инструментов, как компилятор, отладчик кода VS и тесты. Наконец, мы продолжим эту статью с сводной таблицы.

Типы ошибок
Есть 3 конкретных типа ошибок, которые могут возникнуть во время программирования.

Синтаксические ошибки

Представляя ошибку в синтаксисе кода. Часто это опечатка, неверно введенное имя переменной, несуществующая переменная, отсутствующие (или лишние) символы и т. д. Такие ошибки случаются часто, и в этом случае приложение не запускается.

  • Пример синтаксической ошибки
    В приведенном ниже коде я пытаюсь объявить 2 константы: first_name и last_name, используя ключевое слово «константа». Мы видим, что если мы удалим «t» из «const», это приведет к синтаксической ошибке, поскольку ключевое слово «cons» не существует.
const first_name = "Ahmad";
cons last_name = "MOUSSA";
  • Отслеживание и исправление синтаксической ошибки
    Синтаксическая ошибка всегда приводит к появлению сообщения об ошибке. Он будет автоматически создан компилятором при попытке выполнить код. Таким образом, код не будет компилироваться, пока не будут исправлены все синтаксические ошибки.

В большинстве случаев исправить синтаксическую ошибку несложно. Большинство IDE оказывают некоторую помощь, предупреждая нас о том, что в нашем синтаксисе что-то не так. И при наведении курсора на значок предупреждения мы можем увидеть некоторые полезные предложения или некоторые примечания об ошибке, которые могут быть полезны. В нашем примере мы видим, что ожидается точка с запятой (что не является реальной проблемой, но, по крайней мере, указывает на наличие проблемы в этой строке!).

Однако иногда может быть трудно найти синтаксическую ошибку. Например, в следующем коде я пытаюсь создать функцию, которая принимает first_name и last_name в качестве параметров, а затем возвращает полное имя, если 2 параметры существуют, в противном случае возвращается либо first_name, либо last_name.

function fullName(first_name, last_name) {
 if (!first_name)
   return last_name;
 };
 
 if (!last_name) {
   return first_name;
 };
 
 return first_name+ ' ' + last_name;
}

Я забыл добавить точку с запятой после оператора «if (!first_name)», поэтому я получил сообщение об ошибке «syntax_error» в конце файла, но не в правой строке оператора.

Так что такой случай деморализует, так как требуется некоторое время, чтобы пройтись по коду и выяснить причину ошибки.

Ошибки выполнения

Это не опечатки, а нарушение работы кода: исключения.

Когда при компиляции кода возникает синтаксическая ошибка, после компиляции и во время выполнения кода возникает ошибка времени выполнения. Например, когда функция вызывается, а затем происходит сбой.

  • Пример ошибки времени выполнения
    Очень простым примером может быть попытка чтения файла, который не существует. Это приведет к остановке выполнения остальной части код:
const fs = require('fs');
 
let data = "test";
data = fs.readFileSync('./test.json');
console.log(data);// will not be reached

В приведенном выше коде я пытаюсь прочитать несуществующий файл (test.json) с помощью функции readFileSync. Код будет аварийно завершать работу при попытке чтения данных из этого файла, и поэтому мы не сможем перейти к остальной части файла (т. е. к логированию данных).

  • Отслеживание и исправление ошибок выполнения
    Чтобы избежать нарушения выполнения кода, мы можем использовать оператор try..catch. Это не только сохранит выполнение сброса кода, но и поможет нам вернуть обратно сообщение об ошибке:
const fs = require('fs');
 
let data = "test";
try {
 data = fs.readFileSync('./test.json');
} catch (error) {
 console.log("Error when trying to read the file", error.message);// Error when trying to read the file ENOENT: no such file or directory, open './test.json'
}
console.log(data);// test

Логические ошибки

Представляет самый сложный тип ошибок, где мы никогда не увидим выдачу ошибки, и их может быть трудно найти. Код не будет работать так, как должен, лично я называю это «ошибкой поведения».

  • Пример логической ошибки
    Возьмем тот же пример функции fullName. Эта функция ведет себя следующим образом: она должна возвращать полное имя как объединение имени и фамилии в указанном порядке. Таким образом, логически, если я применю эту функцию к «Ахмаду» и «МУССА» в качестве параметров first_name и last_name соответственно, она должна вернуть «Ахмад МУССА».
function fullName(first_name, last_name) {
 if (!first_name) {
   return last_name;
 };
 
 if (!last_name) {
   return first_name;
 };
 
 return first_name+ ' ' + last_name;
};

Теперь предположим, что по причине забывчивости мы поменяли порядок first_name и last_name в конце функция:

function fullName(first_name, last_name) {
 if (!first_name) {
   return last_name;
 };
 
 if (!last_name) {
   return first_name;
 };
 
 return last_name + ' ' + first_name;
};

Теперь функция будет возвращать «МУССА Ахмад», а не «Ахмад МУССА», как ожидалось.

  • Отслеживание и исправление логических ошибок
    Ошибки такого рода можно отслеживать с помощью тестов, а затем исправлять путем отладки с помощью отладчика (т. е. >Отладчик кода VS).

Метод тестирования — использование Jest
Я буду использовать среду тестирования JavaScript Jest, чтобы создать простой тест. Для этого я создам простое приложение node.js. Я буду следовать шагу (A) в моей статье, чтобы создать простое приложение node.js:



Затем я добавлю искаженную функцию fullName в файл app.js и экспортирую ее для отображения.

app.js
------
function fullName(first_name, last_name) {
 if (!first_name) {
   return last_name;
 };
 
 if (!last_name) {
   return first_name;
 };
 
 return last_name + ' ' + first_name;
};
 
module.exports = fullName;

Затем я установлю модуль Jest, используя следующую команду:

npm install --save jest

Это создаст папку node_modules и файл package-lock.json.

Теперь я создам файл app.test.js, в котором я буду моделировать случай сценария, когда функция fullName вернет меня обратно “ Ахмад МУССА»:

app.test.js
-----------
const fullName = require('./app');
 
test("fullName('Ahmad', 'MOUSSA') return 'Ahmad MOUSSA'", () => {
 expect(fullName("Ahmad", "Moussa")).toBe("Ahmad MOUSSA");
});

Затем я обновлю тестовый раздел script в package.json, чтобы иметь возможность запускать наши тестовые файлы:

"scripts": {
   "test": "jest"
 },

Теперь все готово, мне просто нужно запустить тестовый скрипт как:

npm test

Тест завершится ошибкой со следующим сообщением:

Expected: “Ahmad MOUSSA”
Received: “Moussa Ahmad”

В сообщении ясно сказано, что я не получаю ожидаемого результата, а так как нет ни синтаксиса, ни ошибок времени, мы сталкиваемся с ошибкой поведения.

Чтобы определить источник этого обращения, нам нужно шаг за шагом пройтись по нашему коду, чтобы проверить, в чем проблема: отладка. Задача, которую может быть нелегко выполнить вручную!

К счастью, VS Code имеет встроенную поддержку отладки для любого языка, который транспилируется в JavaScript. Итак, в следующем разделе мы будем использовать этот встроенный отладчик для отладки нашего кода.

Метод отладки — использование отладчика кода VS
Если мы запустим отладчик в среде node js, а затем установим несколько точек останова, мы сможем заглянуть в наш код и как он работает.

Выполнение кода будет останавливаться в каждой точке останова, ожидая нашего разрешения на завершение до следующей точки останова. Например, мы можем навести указатель мыши на переменную, чтобы увидеть, что хранится внутри.

Кроме того, в специальном режиме отладки мы можем видеть ключевые переменные, доступные в нашем коде, мы также можем искать определенные переменные и наблюдать за ними, пока мы просматриваем код. Таким образом, мы можем сканировать наш код шаг за шагом, чтобы увидеть, когда он дает сбой или где он идет не так.

Заключение и резюме

В этой статье мы рассмотрели 3 вида ошибок: синтаксические (т. е. проблемы в синтаксисе кода), ошибки времени выполнения (т. е. исключения) и логические (т. е. поведенческие) ошибки.

Каждый тип ошибки имеет уровень возникновения: процесс компиляции, запущенный процесс и процесс тестирования соответственно.

Когда синтаксические ошибки и ошибки времени выполнения выдают полезное сообщение об ошибке в номерах строк, в которых происходит ошибка, логические ошибки часто сложнее исправить.

В следующей таблице представлены результаты этой статьи.