Сова пишет…
3.14K subscribers
345 photos
37 videos
5 files
417 links
Frontend Senior Fullstack Backend Lead и прочие слова.
Изучаю самые современные технологии.
Обучаю разработчиков как стать сильнее — https://frontend.vision.

По коллаборациям и сотрудничеству пишите в сообщения канала!
Download Telegram
Остановимся на последнем примере — чейнджлоги изменений. Если взять в пример open source фреймворк или библиотеку, насколько действительно пользователю нужны полные списки изменений, “Вася изменил имя внутренней функции в ядре фреймворка, но при этом совместимость для пользователей не сломалась”. Гораздо правильнее и практичнее ситуация, когда авторы самостоятельно выбирают какие изменения нужно подсветить пользователю, пишут для них наглядные примеры подчеркивающие отличия, и такое сгенерировать уже невозможно.

В больших проектах все изменения, большие и маленькие добавляются через PullRequest, название которого выбирается осмысленно, да и причина наглядно объясняется в теле PR. Можно же использовать список PR для генерации release notes? Да, и в своих opensource проектах я перешел на такой подход, это даже отбивает желание пушить напрямую в мастер, ведь тогда изменения не будут видны в release notes, придется писать вручную, а я люблю автоматизацию.
Но с другой стороны это слегка вербозно, особенно если ведешь проект самостоятельно.

С энтерпрайз разработкой всё ещё бесполезнее, ведь там release notes либо вообще не пишутся, либо их пишет продуктовая команда на основе списка story из JIRA, а разработчикам генерировать release notes для себя не особо надо. Кроме случая, когда пишешь внутреннюю библиотеку для нескольких команд, но и там решается через PullRequests.

Какой же тут может быть вывод? Я вижу основной плюс в conventional commits — это дисциплина и чистота. Когда все участники команды стараются четко описывать характер изменений, особенно если лид проекта держит историю git в чистоте. Такой подход помогает выявлять изменения и причину сразу через git blame, без томных походов в задачи JIRA и перечитывание сотен комментариев, если они вообще остались, ведь в теле коммита можно сразу описать причины такого кода “поговорил с Васей, он утверждает, что может быть дыра в безопасности, если не подставить костыль сейчас”.

Инструментарий вроде commitizen и commitlint позволят сгенерировать и провалидировать полученный коммит автоматически, сохранив при этом ясную структуру. Я бы рекомендовал выбрать тот формат, который удобен команде, conventional commits слишком длинный, я бы посмотрел на gitmoji как альтернативу.

Я не вижу практического смысла в программном анализе истории коммитов и генерации release notes из этого, ведь там не будет бизнес-ценности, а вычленять её и писать сложные эвристики ради этого кажется нерациональной тратой времени. Release notes лучше генерировать из списка PullRequest.
Сова пишет…
Немного обсуждений в @effectorjs чате натолкнули меня на мысль изменить подход к описанию логики в effector+react. Я стараюсь разделять представление и логику. Если взять в пример страницы, рядом с файлом компонента страницы лежал файл логики на эффекторе.…
Год назад я описал свои размышления по разделению логики и представления при описании страниц на Effector + React.

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

Раньше, я импортировал сторы и ивенты из модели прям в файл с компонентом. Такой подход позволяет легко тестировать саму модель — замокал api и внешние сервисы и погнали.

Но вот с тестированием компонента проблема, так просто замокать сторы не получится, придется прибегать к костылям в jest. Казалось бы, почему я не могу тестировать компоненты сразу с запущенной моделью. А ответ кроется в деталях реализации модели: в тест компонента попадают моки апи и фич, что неприемлемо, ведь при модификации модели без изенения апи, упадет тест компонента, а это вообще не то, что хотелось бы.

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

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

Я не хочу разделять свою модель на state, init и index, потому то не люблю, когда логика размазывается по нескольким файлам. Да, мы все помним .h файлы в C++, только вот новые языки не разделяют определение и реализацию, потому что определение это зачастую важная часть логики. В моем случае так же: combine, attach, .map и прочие фабрики сущностей должны быть размещены в state и index по дефолтной рекомендации эффектора, в то время как в них лежит логика.
Например:
$formPending = combine(fx.pending, email.map(fn), ...)

Я продолжаю описывать логику в одном файле соответствуя описаной ранее структуре, но никто не мешает мне отделить фазу соединения компонента и модели — так называемый init-файл. Да, моё предложение сводится только к объединению идеи init-файлов и логики в едином файле.

А работает это очень просто:
- в модели как и ранее описывается вся логика и все ивенты необходимые для работы. Только полностью удаляются любые упоминания view-слоя, в моём случае React.
- в файле компонента описывается jsx и привязки к сторам и ивентам эффектора, но никаких импортов модели не производится. Все необходимые юниты создаются сразу же в файле компонента и экспортируются. Теперь файл компонента я называю page.tsx
- init-файл я называю index.ts и в нем размещаю связи между сторами/событиями компонента и модели. Фактически производится форвард из сторов модели в сторы страницы и из событий страницы в события модели.

События страницы всегда пересылаются в модель, но не наоборот. Модель не может влиять на страницу через события, react-компонент просто не подписывается на события, ему это не нужно.
А вот сторы всегда пересылаются в обратном направлении — из модели в страницу. Реакт компонент становится функцией от состояния, он умеет только отправлять события и рендериться на основе данных.

Тесты писать крайне просто: импортируем компонент, форкаем root-домен, проставляем нужные значения в сторы компонента и проверяем результат. Аналогично поступаем с событиями, просто проверяем, что они вызываются с правильными ивентами и значениями.
Сова пишет…
Год назад я описал свои размышления по разделению логики и представления при описании страниц на Effector + React. Весь 2020 год я искал подход, который позволил бы мне очень сильно упростить разработку и тестирование, при этом имея разделенные слои вью и…
Хотелось бы написать, что я на этом остановился, но нет.
Писать пачку forward в index.tsx оказалось несколько утомительно. К тому же, пришлось группировать forward по ивентам и сторам, чтобы случайно не перепутать порядок:
сторы — из модели в страницу
ивенты — из страницы в модель

Поэтому поковырявшись в Typescript я написал функцию bus(), типизировать которую оказалось задачей не из легких, решить которую мне помог @uid11, отдельное большое спасибо за это.

Фактически, функция делает forward за меня, сразу в несколько target. То есть позволяет просто и наглядно соединить пары ивентов и пары сторов.

Практиковать этот подход я начал на проекте Accesso, а pull request с изменениями можно посмотреть здесь — go.sova.dev/effector/split-page-and-model

Как писать тесты покажу позже, сразу с практическими примерами и практиками.
За что я не люблю экосистему React.

Сборка проекта разваливается после установки react testing library, которая никаким образом типы роутера и реакта не обновляла.

Ещё и как чинить не понятно
¯\_(ツ)_/¯
Я сижу на BigSur с бета теста для разработчиков. Утекло очень много всяких багов и к релизе пофиксили почти все, что я нашел.

Но вот этот, лично у меня самый частый баг новой ОС
НАКОНЕЦ-ТО!
ГОСПОДИ!
Не прошло и трех лет
This media is not supported in your browser
VIEW IN TELEGRAM
У меня две претензии:
- Почему гугл решил не писать "Day 1" и "Day 2" в локальной таймзоне? Че это за прикол.

- Имя докладчика? Неее, зачем вообще такое надо.
Сейчас немного постримлю livecoding.
Буду подключать аутентификацию через accesso к cardbox.
https://youtu.be/ffRthDqp1sI
LiveCoding #2 уже на Youtube
Я покрываю тестами страницу login в Accesso, стараюсь объяснять что и зачем делаю, попутно решаю возникающие проблемы.

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

https://youtu.be/Ozg6mV8Grlw
Второй Talkstream!

Обсудили Server-push, performance, загрузку данных на фронтенде и менеджеры состояний

https://youtu.be/iC_uJ2XYUdM
Сегодня отмечается католическое рождество. Этот праздник вызывает у меня сильнейший прилив ностальгии. В связи с этим мы подготовили рождественский выпуск подкаста, в котором я подвожу итоги 2020 года, вспоминаю все интересные события и новости.

Послушать можно на всех платформах:
- https://podcast.sova.dev
- https://go.sova.dev/podcast/soundcloud
- https://go.sova.dev/podcast/vk
- https://go.sova.dev/podcast/apple
- https://go.sova.dev/podcast/yandex

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

Меня можно поддержать в ВК и на Patreon, а в благодарность почитать полный текст выпуска:
- patreon.com/sergeysova
- vk.com/sovadev
Уже совсем скоро наступит новый 2021 год!
Хочется написать много красивых слов, но я сомневаюсь, что это будет искренне.
Хочется пожелать, чтобы новый год стал проще. Не хочу через полгода вспоминать 2020 год добрым словом, потому что стало хуже!

Пожелайте близким людям здоровья!
Сколько ещё нужно аргументов, чтобы перестать называть файлы в разных регистрах?

(На системе с фс независимой от регистра этот код работает, с регистрозависимой фс код падает, приятного дебага)

param-case решает все проблемы: 1) регистронезависимые фс, 2) компонент или нет
На выходных провел несколько часов погрузившись в Rust.
В свободное время стараюсь изучать чужие open-source проекты, в этот раз я изучал lemmy — распределенный аналог Reddit.

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

Задача: у меня есть несколько больших сервисов в виде апишек разного уровня: public, internal, private, admin, у них у всех равный доступ к БД, но некоторые находятся в разных подсетях и хост базы отличается, а также сервисы имеют разные настройки http-сервера, плюс к этому, нужно легко настраивать каждый сервис для локальной разработки.

Раньше: использовался dotenv и длинный список env переменных, при старте приходилось установить весь список переменных, либо вынуждать разработчика клонировать .env.sample и править под себя.

Сейчас: я создаю базовый конфиг в директории config сразу для всех апишек, ещё один базовый конфиг для разных окружений и наконец по ещё одному конфигу для каждой апишки. Могу создать отдельный конфиг для апишки в определенном окружении.
Выглядит так:
config/default.toml — базовый конфиг для всех
config/default-development.toml — конфиг для всех апишек во время разработки
config/internal.toml — конфиг для внутренней апишки
config/public.toml — для публичной апишки
config/private-production.toml — для приватной апи в продакшене

Конфиги не перетирают друг друга, а мержатся с учетом структуры(не проверял на массивах). Крейт config поддерживает сразу несколько форматов(toml, hjson, json, ini, yaml), можно писать в удобном формате или даже в разных.

Помимо этого я могу определить локальные конфиги, которые в .gitignore и не попадут в репозиторий. Это удобно, когда нужно запустить сразу все апишки без докера на разных портах, или дать им разные параметры http-сервера, чтобы поймать ошибку. Получается вот такое:
.config.toml
.config-production.toml
.config-internal.toml
.config-internal-production.toml


При этом не обязательно создавать все конфиги из списка, достаточно иметь config/default.toml и любой конфиг из списка по необходимости.

Реализовать такое оказалось делом 10 строк. Поглядеть можно здесь. Большинство строк файла — определение структур для конфига, в методе Settings::new загружаются конфиги в определенном порядке.

И конечно же, можно любой параметр конфига переопределить через переменные окружения. Например, server.keep_alive устанавливается через переменную ACCESSO_SERVER__KEEP_ALIVE.

На Youtube есть канал по Rust, есть видео про Actix, который я использую для бекенда Accesso.
Я использую парную тему Bluloco для iTerm2 и VSCode.

Для VSCode тема есть в Extensions Marketplace. А Color presets для iTerm скину в комментарии