Пишите меньше кода

Самый важный показатель, на который вы не обращаете внимания

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

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

На самом деле, широко известно, что, с увеличением кодовой базы приложения, время разработки проекта и количество багов растут даже не с линейной, а с квадратичной зависимостью. Этим можно объяснить наше подсознательное поведение, когда пулл-реквесту на 10 строк мы с лёгкостью уделим такой уровень внимания, который редко достаётся коду размером более 100 строк. А как только код становится слишком длинным, и перестаёт помещаться на одном экране, когнитивные усилия, необходимые для его понимания, значительно возрастают. Мы пытаемся исправить ситуацию путём рефакторинга и добавлением комментариев — действия, которые почти наверняка приводят к ещё бо́льшему количеству кода. Это порочный круг.

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

Читаемость кода — это важно

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

for (let i = 0; i <= 100; i += 1) {
  if (i % 2 === 0) {
    console.log(`${i} — чётное`);
  }
}

...во что-то неудобоваримое:

for (let i = 0; i <= 100; i += 1) if (i % 2 === 0) console.log(`${i} — чётное`);

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

Да, я говорю о Svelte

Сокращение объёма кода, который нужно писать, является очевидным преимуществом Svelte. Чтобы проиллюстрировать это, давайте посмотрим на очень простой компонент, реализованный на React, Vue и Svelte. Сначала, версия Svelte:

Как мы сделаем то же самое в React? Скорее всего, это будет выглядеть примерно так:

import React, { useState } from 'react';

export default () => {
  const [a, setA] = useState(1);
  const [b, setB] = useState(2);

  function handleChangeA(event) {
    setA(+event.target.value);
  }

  function handleChangeB(event) {
    setB(+event.target.value);
  }

  return (
    <div>
      <input type="number" value={a} onChange={handleChangeA}/>
      <input type="number" value={b} onChange={handleChangeB}/>

      <p>{a} + {b} = {a + b}</p>
    </div>
  );
};

И, наконец, в Vue:

<template>
  <div>
    <input type="number" v-model.number="a">
    <input type="number" v-model.number="b">

    <p>{{a}} + {{b}} = {{a + b}}</p>
  </div>
</template>

<script>
  export default {
    data: function() {
      return {
        a: 1,
        b: 2
      };
    }
  };
</script>

Иначе говоря, требуется 442 символа в React и 263 символа в Vue, чтобы достичь чего-то, что в Svelte занимает 145 символов. Версия React буквально в три раза больше!

Такая сильная разница скорее исключение — из моего опыта, компонент React обычно примерно на 40% больше, чем его эквивалент на Svelte. Давайте теперь взглянем на особенности Svelte, которые позволяют компактнее излагать наши идеи.

Элементы верхнего уровня

В Svelte компонент может иметь столько элементов верхнего уровня, сколько вам нужно. В React и Vue компонент обязан иметь единственный элемент верхнего уровня — в случае React попытка вернуть два элемента верхнего уровня из функции компонента приведет к синтаксической ошибке. Вы можете использовать фрагмент — <> — вместо <div>, но дополнительный уровень вложенности никуда не денется.

В Vue разметка должна быть размещена внутри элемента <template>, который, на мой взгляд тут лишний.

Привязки

В React мы должны самостоятельно обрабатывать события полей ввода вроде <input>:

function handleChangeA(event) {
  setA(+event.target.value);
}

Это не просто весьма скучная конструкция, занимающая место на экране, это ещё и дополнительная часть кода, где могут появиться ошибки. Концептуально, значение текстового поля привязано к значению a и наоборот, но это отношение не выражено чётко — вместо этого у нас есть два тесно связанных, но физически отдельных фрагмента кода (обработчик события и свойство value={a}). Кроме этого, мы должны помнить, что необходимо принудительно привести строковое значение в числовое с помощью оператора +, иначе 2 + 2 будет равно 22 вместо 4.

Как и в Svelte, у Vue есть свой способ выразить привязку — атрибут v-model, но, и тут мы должны быть внимательны и использовать v-model.number, несмотря на то, что берём значение из <input type="number">.

Стейт

В Svelte обновление локального состояния компонента происходит с помощью простого оператора присваивания:

let count = 0;

function increment() {
  count += 1;
}

В React, мы используем хук useState:

const [count, setCount] = useState(0);

function increment() {
  setCount(count + 1);
}

Тут сильно больше постороннего шума — оба фрагмента кода выражают одну и ту же концепцию, но во втором случае было использовано на 60% больше символов. Поэтому, когда вы читаете такой код, вам придётся приложить гораздо больше усилий, чтобы понять замысел автора.

Ну, а в Vue у нас есть экспорт по умолчанию, содержащий функцию data, которая возвращает литерал объекта со свойствами, соответствующими локальному состоянию приложения. Отмечу также, что в Vue нельзя просто импортировать и сразу использовать в разметке такие вещи, как функции из внешних файлов и дочерние компоненты, так как сначала их необходимо 'зарегистрировать', указав в определённой части экспорта по умолчанию.

Забудем про шаблонный код

Это лишь малая часть возможностей Svelte, которые помогают с минимальными усилиями создавать UI приложения. Есть ещё много других — например, реактивные объявления, которые по своей сути выполняют работу функций useMemo,useCallback и useEffect из React без лишнего многословного шаблонного кода (который при этом сильно нагружает сборщик мусора созданием инлайновых функций и массивов при каждом изменении состояния приложения).

Как? Мы выбрали путь, позволяющий обойти ограничения среды выполнения в браузере. Поскольку Svelte — это компилятор, мы не привязаны к особенностям JavaScript: мы можем создавать метод разработки компонентов как нам нравится, а не приспосабливать его к семантике языка. Как это ни парадоксально, но с таким подходом код становится более идиоматическим. Например, мы используем переменные естественным путём, а не через прокси или хуки, при этом получая значительно более производительные приложения.