Мы, разработчики, находимся в постоянной гонке за создание все более сложных вещей, чтобы упростить (# !?) нашу жизнь. Если нужно достичь сингулярности, JavaScript обязательно поразит ее первым, потому что sh * t производится с агрессивной экспоненциальной скоростью. npm скоро понадобится сборщик мусора.

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

На самом деле, я не могу поверить в то количество фреймворков, построенных примерно на 20 тысяч строк, которые были написаны в поисках простоты. Они часто приносят с собой еще большую экосистему инструментов, потому что, очевидно, вам нужна помощь, чтобы использовать основной артефакт. Внедрение основных, усовершенствованных и быстрых функций браузера поверх браузеров - это не путь. Нет, вы не лучший тест. Прекратите изобретать сложную, автоматическую, волшебную чушь. Мы больше не способны ни понять это, ни поспевать за ним. Мы даже не можем должным образом классифицировать это в своей голове. Они часто устраняют какие-то проблемы, я вам это даю, но они всегда создают новые. Проблемы, которые сложнее отладить. Если нам повезет, мы, по крайней мере, будем наслаждаться собственным изумлением, глядя на всю эту бесконечную неразборчивую трассировку стека. Если это просто гвоздь, возьми молоток, черт возьми. Возьмите свои виртуальные космические корабли в другое место.

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

После травмы с AngularJS я стал особенно озабочен безопасностью типов. На самом деле, опечатки - это нормально, их не нужно превращать в ошибки. Итак, я подумал, что было бы неплохо начать с некоторого типобезопасного HTML. Как насчет того, чтобы дать TypeScript шанс?

p({}, [
    'This is awesome ',
    abbr({title: 'Super-Human Ingenious Trick'}, 'SHIT'),
    '!'
})

Конечно, есть еще шум. Я принимаю это. Не то чтобы HTML уже стал супер-чистым. Это безопаснее, и нам нравится безопаснее. Теперь нам просто нужно выяснить, как создавать собственные элементы, чтобы кому-то не потребовалась степень магистра, чтобы знать, как их использовать, не говоря уже о реализации.

Вот скромное предложение, проиллюстрированное еще более скромным встречным компонентом:

import {h, extend} from '@soil/web'

const counter = (input: {value?: number} = {}) => {

    const $count = h.span({})

    const $counter = h.div({}, [
        h.button({onclick: () => api.value = api.value - 1}, '-'),
        $count,
        h.button({onclick: () => api.value = api.value + 1}, '+')
    ])

    const state = {
        value: input.value || 0
    }

    const api = {
        get value() {
            return state.value
        },
        set value(v: number) {
            state.value = v
            $count.textContent = '' + v
        }
    }

    // Initilization.
    api.value = api.value
    // Think as Object.assign, not ignoring getters and setters.
    return extend($counter, api)
}

И это все. Хорошо, давайте немного подведем итоги. Все это просто функция. Он принимает некоторые входные данные и возвращает элемент HTML, улучшенный с помощью пользовательского API. Сюда входят геттер и сеттер; они могли бы быть обычными функциями получения и установки, но именно так это делают собственные компоненты - круто, неважно. Наконец, внутри компонента мы находим его шаблон и внутреннее состояние. Все просто, правда? Потребовалась всего одна маленькая, легко запрограммированная таинственная зависимость.

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

const popcornCounter = (popcornService = new PorncornService) =>
        (input: {value?: number} = {}) => {
    // ...
}

Если бы другой компонент теперь зависел от popcornCounter, он мог бы делать это без необходимости знать о транзитивных зависимостях.

const popcornPage = (popcornCounter = popcornCounter()) => () => {
    const $popcornCounter = popcornCounter({value: 500})
    // ...
}

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

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