artalog – Telegram
artalog
4.21K subscribers
533 photos
40 videos
39 files
898 links
Развернутые ответы на вопросы в чатах, мысли от рабочих процессов.
Вопросы - @artalar.
Download Telegram
Gitpod

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

- Запуск ВМ (виртуальной машины) в облаке с vscode сервером для указанного git репозитория. Там можно запускать любые скрипты: дев сервер, тесты сборка, линтинг, есть полноценный терминал с рут доступом.
- Открытый порт на сервере может быть доступен по публичному урлу (прощай ngrok).
- Доступ разработчика к серверу осуществляется через браузер или десктопный vscode. Там же можно открыть терминал.
- Доступна полная кастомизация vscode: user, repo, vm instance.
- Есть собственный магазин расширений для vscode, в котором есть почти все.
- Есть поддержка IDE от JetBrains.
- Под каждый бранч каждого репо можно запустить отдельный инстанс.
- Можно загрузить свои дотфайлы (для глобальной настройки терминала)
- Из коробки итеграции с: Github (public or enterprise), Gitlab (public and selfhosted), Bitbucket.
- По умолчанию гитпод запускается из этого докерфайла, который часто обновляется и в какой-то момент может что-то сломаться (у нас так в очередной день ничего не запустилось из-за обновления версии ноды).
- В корне репозитория может быть файл конфигурации для описания скриптов лайфтайма: before, init, command.
- В файле конфигурации можно указать путь к своему докеробразу, который будет использоваться для запуска гитпод контейнера.
- В CI гит системы на каждый коммит можно пребилдить гитпод контейнер, который будет выполнять init скрипт. Например, на каждый ПР.
- Если клиент отключается от контейнера на 3 минуты или не активен (mouse / keyboard interactions) 30 минут, он останавливается.
- Только папка /workspace сохраняется между перезапусками контейнера.
- Стоимость, по моему мнению, не высокая, тем более что каждый месяц доступно 50 бесплатных часов для публичных репозиториев.
- Базовые сервера в облаке гитпода достаточно мощные.
- Запущенный гитпод контейнер можно шарить по ссылке. Например, это полезно при сложной последовательности воспроизведения проблемы, которой хочется поделиться. Или для парного программирования (по DX хуже live share).
- Можно и наоборот, подключаться сервисом в гитподе к локалхосту компьютера разработчика через Local Companion.

Когда я начинал пользоваться гитподом и половины этих фич не было, а вместо vscode была своя IDE без расширений. Но даже тогда это было очень полезный сервис, поэтому я не могу не рекомендовать попробовать его всем и каждому. Способов применений у него масса.

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

#tools
👍10
Реактивное программирование - парадигма программирования, предполагающая передачу ответственности за инициализацию обработки информации источнику информации.

Еще много теории и практики было бы хорошо мне затронуть в своей жизни, но на основе нескольких лет теоретических исследований и аналитики экосистемы разработки, определение выше я пропагандирую как единственно верное!
Краткое доказательство такое: обе библиотеки MobX и Rx реактивные и считаются стандартом в индустрии. При этом, они сильно отличаются, почти во всем. Но что их объединяет и как их принципы можно обобщить? См. определение выше.

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

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

Помню, как первый раз столкнулся с этим тестом и два часа пытался понять, что да как (там еще вокруг похожие тесты).

В рядовой разработке на JavaScript можно встретить очень много примеров: addEventListener позволяет установить функцию обратного вызова на появление какого-то события, менеджер состояние позволяет конструировать вычисления на основе данных других вычислений, а React.useEffect принимает вторым аргументов список зависимостей, при изменении которых эффект будет перевызван.

Но зачем все это? Реактивный интерфейс является мощным механизмом уменьшения зацепленности кода. Это влияет на архитектуру всего модуля / приложения и позволяет скейлить код чище и проще.
Так же, с реактивщиной получается автоматически соблюдать SSoT. А в случае со стейт менеджерами, мы избавляемся почти от всех проблем инвалидации кеша.

Обратной стороной гибкости реактивного программирования является сложность отслеживания связей и распространения информации, т.к. убирая зацепленность, мы лишаем код наглядности. Т.е. мы явно видим в коде какие модули использует каждый модуль, но мы не видим в коде модуля какие другие модули от него зависят. К счастью, современные средства разработки, вроде статических анализаторов (являющихся частью ЯП или IDE, или отдельные), помогают находить ссылки в коде на другие части программы и облегчаю ее дебаг. Прогрессивным, но не развитым, средством дебага является отображение связей в приложении в реальном времени, частично реализованное в devtools некоторых библиотек.

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

Еще одним недостатком реактивного программирования является нагрузка на рантайм производительность кода, т.к., фактически, формирование связей между частями кода - подписки мы описываем через какие-то методы, которые отрабатывают только в рантайме. Как и во всем, следует придерживаться баланса реактивного и процедурного программирования, не оборачивая абсолютно каждую мелкую операцию в реактивный контекст, чтобы предотвратить избыточные накладные расходы.


Еще материалы:
- Эта статья на вики лучше большинства блог постов.
- Лекция про транзакции в БД.
- Доклад по архитектуре про event driven design.
- Caching versus Memoization.
- Reactive Programming в Cycle.js.
- What is Reactive Programming? By Luca Mezzalira.
- Объектное Реактивное Программирование.
- A Hands-on Introduction to Fine-Grained Reactivity от автора Solid.js

#reactive #state_management
👍17
Войс через минут 20-30
Anonymous Poll
19%
Буду
81%
Не буду
👍5
Live stream started
Live stream finished (53 minutes)
Контроль доступа к рантайм данным.

При работе с данными реактивно нам нужно как-то описывать связи, на которые и осуществляется подписка. Для этого могут использоваться разные паттерны.

Selector.
Селектор - самый примитивный паттерн доступа к данным, он описывает функцию чтения данных (get / getter), которая принимает на вход какой-то объект и возвращает какую-то его часть (свойство).

const selectSome = (data) => data.some.property

Его преимущество в простоте и сильных возможностях композиции.

Lense.
Линза - это селектор, как геттер, и функция сеттер - установки значения по тому же, что и у селектора, свойству. Иногда, эффективнее отслеживать не изменение результата селектора (который может содержать вычислительную нагрузку), а сам факт изменения каких-то данных (отслеживание сеттера).


const lensSome = {
get: (data) => data.some.property,
set: (data, value) => data.some.property = value
}


Cursor.
Курсор - это более строгий паттерн, который предполагает точное указание необходимого для обработки свойтва. Это позволяет легко отслеживать входящие, исходящие и производные значению. Иногда, использование подобного подхода может показаться более вербозным, но он не накладывает ограничения как мы хотим работать с данными, а помогает лишь описать с какими данными мы хотим работать. Это может быть полезно для систем с условным использованием иммутабельных структур. Например, какие-то часто меняющиейся данные менеджер данных может мутировать, где-то использовать иммутабельные данные, где-то добавлять какие-то проверки на структуру входящих изменений, при этом приклодной API доступа к данным будет неизменным. Для удобства работы с курсорами над глубоковложенными данными можно создавать пути (path).

const data = { some: { test: 42 } }
const testPath = ['some', 'test']
const testCursor = new Cursor(data, testPath)


Proxy.
Перехватчик - это замаскированный, благодаря возможностям ЯП, курсор, который позволяет использовать все (многие) преимущества курсоров, при этом сильно упростив API.

const test$ = data$.some.test
const test = test$.get()


Интересно, что ImmutableJS предполагает работу с данными через курсоры и было бы достаточно просто сделать их реактивными. Как это пытается сделать \~/ kefir.atom.

#state_management
👍12
artalog
Voice message
^ Повспоминал свой опыт администрирования десять лет назад. Совсем в общем.
Думаю что делать с этой информацией, хочется поделиться же :) Попробую в следующий раз рассказать более детально про что-то конкретное: серверные комнаты и их устройство, организация мониторинга высоконагруженной критической (дорогой по даунтайму) системы, обслуживание распределенных сетей на системном и административном уровнях и тп.
👍9
Истинность пустоты.

А вы тоже не можете запомнить что some и every возвращают для пустого массива?
Интересно, что результаты разные и основаны они на математической логике (источников на русском мне найти не удалось).

Там приводится забавный пример. Утверждение, “каждый ребенок бездетного человека овца” верно, потому что мы не можем его проверить и опревергнуть. А вот, “какой-то ребенок бездетного человека овца” не верно, потому что “какой-то” предполагает успешную проверку элемента, которго нет.

Я для себя придумал запоминать так: количество символов в “false” для “some” и “true” для “every” разное (4 != 5).

У оригинального твита можно найти интересные ответы и цитирования.
🤔16👍5
Live stream started
Live stream finished (17 minutes)
Черновик постов про лидеров мнений, большие и маленькие компании, тишейп.
2022-02-07
artalog
👍4
Монотонный.

Есть у меня микромечта - монотонный дизайн кит для интерфейсов. Подчеркну, не монохромный (с градациями насыщенности / яркости / прозрачности), а монотонный, где есть только цвет фона и инверсивный цвет контуров.
На every-layout.dev можно посмотреть как это выглядит в качественном исполнении.

Интерфейс с таким подходом разговаривает с вами не цветом, а формой и это доступней и понятней. При этом, в нем пользователь может выбрать любой понравившийся цвет. А еще это просто, и простые и эффективные решения мне кажуться элегантными, красивыми и вдохновляющими.

Но меньше слов, давайте к делу. Есть у меня некоторые наброски в excalidraw, которые нужно: 1) реализовать в css; 0) подправить профессиональным дизайнером и перенести в фигму; 2) дополнить еще какими-то компонентами.

Если кто-то может с этим помочь - пишите в личку, давайте скооперируемся. Понятно, что мы выложим это все в OSS. У меня лично есть пара проектов в голове, которые я бы хотел попробовать сделать с таким дизайном.

#design #mono
👍14
Transient Data Structures

Я, как ярый фанат иммутабельности, прошу вас - мутируйте! Хуже не знания хороших практик только их избыточное применение.

Часто, можно встретить код редьюса в котором каждая итерация возвращает иммутабельный результат, вроде:
.reduce((acc, el) => ({ ...acc, [el.id]: el }), {})

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

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

.reduce((acc, el) => {
acc[el.id] = el;
return acc;
}, {})

Этот код будет намного быстрее и хотя мы мутируем здесь значение это невозможно обнаружить извне функции reduce, а значит и проблем с этим никаких не будет.

Каждую технику нужно применять по необходимости, по ссылке из заголовка вы можете почитать о том когда и как в Clojure используются мутабельные данные, хотя одной из ключевых фич этого ЯП является иммутабельность.

#immutable #perf
👍39🤔6🔥21👎1
За гранью Intel и Linux – необычные процессоры и операционные системы – Дмитрий Завалишин

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

Пофанатазируйте.

Во второй части доклада автор рассказывает про разрабатываемую им операционную систему Phantom, которая построенна вокруг идей иммутабельности и persistent memory.

Одно из преимуществ такого подхода заключается в безопасном распараллеливании работы с данными, что позволяет собирать мусор исключая проблему stop the world. Это то что меня впечатлило, но там еще много интересного, посмотрите доклад, он почти без слайдов, можно слушать фоном.

@Akiyamka ещё подсказал список статей по теме.

#immutable
👍7
Го войс через 10 мин
Live stream started
Live stream finished (48 minutes)