Как фронтендеры изобретали чистые функции и TDD
Обо мне

- Python разработчик в Cindicator
- В недавнем прошлом заносило тимлидить
- Организатор PiterPy Meetup
- Иногда кому-нибудь что-нибудь преподаю
- Люблю Python и Vue неосознанной любовью

Чистые функции
Доктор, какие побочные эффекты?
Функция<Математика>
Математики придумали функции:
принимает что-то на вход и выдаёт результат.

Свойства функции
Три нужных нам свойства
-
Полная определенность
-
Детерменированность
-
Отсутствие побочных эффектов
Полная определенность
Что не скорми — всё прожуёт
На самом деле секрет в том, чтобы не кормить лишним

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

Отсутствие побочных эффектов
Не лезет куда не надо
Математики такого явно не говорили, но мы такое придумали: взять что-то не из аргументов, сходить в API, мутировать аргумент

Чистые функции
В идеале чистая функция:
- работает для любых аргументов
- всегда возвращает одинаковый результат на одинаковые аргументы
- не лезет наружу и не мутирует

Почему в идеале?
def divide(a: float, b: float):
if b == 0.0:
raise DivideByZeroException("потому что жизнь тлен")
return a/b
Зачем?
А как же пользовательский ввод и рандом?
Интерактивность
Отладка
Тестирование
Легко–Сложно
def divide(a: float, b: float):
if b == 0:
raise DivideByZeroException("Я почти чистая")
return a/b
assert divide(6.0, 2.0) == 3.0
assert divide(1.0, 0.0) exception raised
Легко–Сложно
import coeff
import external_api
def divide(a: float, b: float):
return external_api.call(a, b, coeff)
assert divide(6.0, 2.0) == ???
assert divide(1.0, 0.0) ???
Легко–Сложно
mock coeff as 0
mock external_api as return 3.0
assert divide(6.0, 2.0) == 3.0
mock external_api as raise exception
assert divide(1.0, 0.0) raised exception
Test Driven Development
А кто-то этим пользуется?

Фронтенд
Компонетный подход
Эволюция

Эволюция

Сначала мы писали страницу модулями — блоками вёрстки, которую кусочно генерировали на сервере
Эволюция
Потом мы поняли, что блоки одни и те же, и вынесли их в компоненты
Которые зависели только от данных

Эволюция
Если блоки зависят только от данных, то можно пользоваться единым хранилищем данных
Эволюция

Ну и в чём проблема?

Побочные эффекты

Глупые и умные компоненты
Представительные и контейнеры
Разделяй и властвуй
Придумываем механизм общения и делим компоненты

Копнём чуть глубже

Копнём чуть глубже

Копнём чуть глубже

Копнём чуть глубже

Копнём чуть глубже

Копнём чуть глубже

Копнём чуть глубже

Разработка через визуальное тестирование
Просто TDD

HTML Snapshot

Visual TDD

Visual TDD

Первая итерация
Просматриваем состояния и придумываем то что входит

Реализуем

Вторая итерация
Просматриваем состояния и придумываем что выходит

Реализуем!

Третья и последующие итерации
Находим косяки, проверяем что стили совпадают с дизайн-макетом, находим улучшения и несоответствия
Декомпозируем на компоненты, пишем истории и для них

Component-Driven Development
- Разрабатываем компоненты в изоляции друг от друга ("чистые" компоненты)
- Разрабатываем итеративно, декомпозируя на маленькие независимые компоненты
- Добавляем Visual TDD, пишем истории и на каждом шаге проверяем не нужно ли что-нибудь поменять в ТЗ

Storybook
UI Component Workshop
Плюшки
База компонентов
У всех разработчиков, менеджеров и дизайнеров есть реальный интерактивный набор компонентов

Граничные случаи
Историями легко показать как компонент ведёт себя в граничных случаях, как выводит ошибки и как ведёт себя на тёмном фоне

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

Визуальное тестированиие (снова)
Специальный вид тестирования, когда специальная утилита делает скриншот каждой истории и сравнивает их между релизами

Изучайте концепции
Не будьте занудами
Использованные материалы

Дополнительные материалы
[polytech] Как фронтендры изобретали чистые функции и TDD
By b0g3r
[polytech] Как фронтендры изобретали чистые функции и TDD
- 202