До 30 ноября

Скидки до 81 000 руб и вторая профессия в подарок!

Главная | Все статьи | Код

Совершенный код: нормализация данных

Время чтения статьи ~3 минуты 98
Совершенный код: нормализация данных главное изображение

Нормализация данных — подход, с помощью которого можно не только упростить логику кода, но и сделать сам код короче. Его принцип работы состоит в приведении данных к общему виду перед основным алгоритмом обработки этих данных. Посмотрим, как это работает на простом примере.

Представьте себе такую задачу: нужно извлечь из HTML все ссылки и загрузить их содержимое. Для простоты допустим, что HTML уже проанализирован, а ссылки собраны в массив. Кроме самих ссылок понадобится имя домена, на котором был расположен этот HTML. Это нужно для загрузки относительных ссылок, то есть тех ссылок, у которых не указан домен в HTML, например, /about. Ниже пример кода, решающего задачу в лоб:

// Кода здесь мало и код можно было бы оставить так,
// но именно на таких маленьких примерах и нужно отрабатывать хорошие практики

import axios from 'axios'; // http-клиент

// Эта функция анализирует HTML и извлекает ссылки
const getLinksFromHTML = /* определение функции */;
const domainName = /* тут имя домена, на котором расположен HTML */;
const html = /* сам html */;

// Подготовка данных
const links = getLinksFromHTML(html);

// Здесь основной алгоритм работы
const promises = links.map((link) => {
  // Определяем тип ссылки. Если домена нет, значит используем текущий 
  // Сама проверка упрощена. Для правильного анализа придется попотеть
  if (link.startsWith('/')) {
    return axios.get(`${domainName}/${link}`);
  }

  return axios.get(link);
});
// Выполняем запросы параллельно
const responses = await Promise.all(promises);

Обратите внимание на чёткое разделение двух этапов. У нас есть место, где готовятся данные, а есть место, где выполняется основная логика. В данном случае обе эти части предельно маленькие, но в реальных приложениях они могут содержать десятки строк, множество условных конструкций и циклов. Большую часть кода можно разделить как минимум на эти два этапа.

Подписывайтесь на канал Кирилла Мокевнина в Telegram — чтобы узнать больше о программировании и профессиональном пути разработчика

Самое примечательное в этом коде — условие, проверяющее относительность ссылки. Посмотрите внимательно на код, который внутри. Он не выполняет какую-то другую особую логику. Всё, что он делает — приводит данные к нужному для обработки виду. Именно здесь и подходит нормализация данных. Вместо того, чтобы строить ссылку по условию, код можно изменить так, чтобы ссылки были полными ещё до попадания в эту часть программы.

import axios from 'axios';
import { URL } from 'url';

const getLinksFromHTML = /* определение функции */;
const domainName = /* тут имя домена на котором расположен HTML */;
const html = /* сам html */;

const links = getLinksFromHTML(html);
// Возможно эту логику имеет смысл поместить в getLinksFromHTML
const urls = links.map((link) => new URL(link, domainName));

// toString преобразует объект обратно в строку
const promises = urls.map((url) => axios.get(url.toString()));
const responses = await Promise.all(promises);

В чём хитрость этого решения? Встроенный модуль url в JavaScript содержит специальную функцию-конструктор URL, с помощью которой создается объект, описывающий конкретный url. Внутри этого объекта есть информация о всех частях адреса. Так их удобнее извлекать и даже менять. У этой функции есть второй параметр — базовый адрес, хост, который будет использоваться в том случае, когда ссылка относительная:

(new URL('/pages/about', 'https://ru.hexlet.io')).toString();
// 'https://ru.hexlet.io/pages/about'

// Если адрес абсолютный то ничего не ломается!
(new URL('https://yandex.ru/pages/about', 'https://ru.hexlet.io')).toString();
// 'https://yandex.ru/pages/about'

Использование готовых инструментов — идеальное решение задачи. Даже если бы у нас не было такого модуля, как url, все равно имело бы смысл делать предварительную нормализацию данных. Как правило, в живых проектах обработка — это больше чем одна условная конструкция. Одни и те же данные могут использоваться много раз и по-разному. Такой код очень легко обрастает условиями и дублированием.

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

Аватар пользователя Kirill Mokevnin
Kirill Mokevnin 03 марта 2020
98
Рекомендуемые программы
профессия
Осваивайте разработку веб-страниц, оживляйте дизайн макетов, публикуйте сайты и приложения. Отслеживайте ошибки в интерфейсе и устраняйте их
10 месяцев
с нуля
Старт 28 ноября
профессия
Обучитесь разработке бэкенда сайтов и веб-приложений — серверной части, которая отвечает за логику и базы данных
10 месяцев
с нуля
Старт 28 ноября
профессия
Выполняйте ручное тестирование веб-приложений, находите ошибки в продукте. Узнайте все о тест-дизайне.
4 месяца
с нуля
Старт 28 ноября
профессия
Научитесь разработке веб-приложений, сайтов и программного обеспечения на языке Java, программируйте и используйте структуры данных
10 месяцев
с нуля
Старт 28 ноября
профессия
новый
Собирайте, анализируйте и интерпретируйте данные, улучшайте бизнес-процессы и продукт компании. Обучитесь работе с библиотеками Python
9 месяцев
с нуля
Старт 28 ноября
профессия
Занимайтесь созданием сайтов, веб-приложений, сервисов и их интеграцией с внутренними бизнес-системами на бекенд-языке PHP
10 месяцев
с нуля
Старт 28 ноября
профессия
Создание веб-приложений со скоростью света
5 месяцев
c опытом
Старт 28 ноября
профессия
Обучитесь разработке визуальной части сайта — фронтенда, а также реализации серверной — бэкенда. Освойте HTML, CSS, JavaScript
16 месяцев
с нуля
Старт 28 ноября
профессия
Разработка бэкенд-компонентов для веб-приложений
10 месяцев
с нуля
Старт 28 ноября
профессия
новый
Организовывайте процесс автоматизации тестирования на проекте, обучитесь языку программирования JavaScript, начните управлять процессом тестирования
8 месяцев
c опытом
Старт 28 ноября