# Тысяча фичей — все выпуски > Дистиллированный слой всех выпусков: краткие описания, основные мысли, главы, гости и ссылки. Расшифровки сюда не включены. ## #72: Зачем IDEA в 2026 - Markdown: https://apkhmv.xyz/podcast/episode-72/index.md - Гости: [Антон Архипов](https://apkhmv.xyz/people/anton-arhipov/index.md) Александр Пахомов и Антон Архипов — Developer Advocate в JetBrains, Java Champion, в прошлом разработчик JRebel — разбирают вопрос, который Антон задал Java-сеньорам на анконференции JCrete: нужна ли вообще IDE, если код пишут агенты? Все ответили «нужна», но объяснить зачем смогли только крайние случаи: Клифф Клик открывает IDE, чтобы дебажить, Питер Лори переписывает сгенерированный код руками. Отсюда разговор идёт к тому, что узкое место переехало из написания кода в code review, инструменты ревью не менялись пятнадцать лет, а люди превращаются в «клей между двумя Клодами». Во второй половине собеседники придумывают IDE будущего — завод по переработке задач с наблюдаемым пайплайном, бюджетами токенов и доказательствами на выходе, — спорят, что из этого сожрут OpenAI и Anthropic и почему LSP, скиллы и другие надстройки обнуляет каждая новая модель, и заканчивают ответственностью за код, который никто не читал, и ответом Антона на вопрос «нужна ли IDE в августе 2026». ### Главное - На JCrete все опрошенные Java-сеньоры с 20+ годами опыта ответили, что IDE им нужна, но почти никто не смог сказать зачем. Внятные ответы дали только крайние случаи: Клифф Клик пишет большую часть кода с Claude Code и открывает IntelliJ IDEA, чтобы дебажить Java, а Питер Лори генерирует весь код агентом и переписывает его руками — и по его же замерам стал выдавать заметно больше кода в день. - Пока код остаётся центром продукта, инструменты для работы с кодом никуда не денутся, но их задача сместилась: не писать и не рефакторить, а проверять. По теории ограничений Голдратта узкое место переехало из написания кода в code review — раньше в команде был один человек, наваливающий PR на три тысячи строк, теперь таких десяток, и они делают это очень быстро. - Инструменты ревью не менялись пятнадцать лет: максимум, что появилось, — комментарии к строчкам в GitHub, а AI-ревьюеры вроде Greptile и CodeRabbit выдают тот же дифф с замечаниями. Антон хочет «историю инкремента»: семантическое объяснение, как и почему изменилась функциональность, со ссылкой на задачу и на то, как поменялся тест-сьют. - Когда автор сгенерировал PR своим Клодом, ревьюер сгенерировал замечания своим, а автор скормил их обратно своему, люди становятся «клеем между двумя Клодами»: это коммуникация со сжатием с потерями, где решений минимум, а ресурсов и времени уходит много. - Инструмент будущего по версии Александра — завод по переработке задач: артефакты на входе (тикет, транскрипт созвона, дамп из головы), наблюдаемый пайплайн с бюджетом токенов на каждом шаге, в который можно «зачерпнуть зерно» и заглянуть, тесты в середине, метрики перформанса и end-to-end-валидация агентом на выходе. - Всё, что строится поверх агента — скиллы, LSP, MCP-серверы, self-review-плагины, — экономит токены только до выхода следующей модели, а полезные надстройки Anthropic и OpenAI поглощают за месяцы. Делать на них ставку — борьба с ветряными мельницами; нишу стоит искать там, куда «два динозавра» не пойдут: комбинация ограниченных контекстных окон, локальные модели, работа с результатом, а не с входом. - IDE перестаёт быть essential-инструментом: агенту хватает bash, file и ещё пары тулов, а JetBrains, всегда делавшая обязательные для программиста продукты, впервые оказывается в категории nice-to-have — как когда-то JRebel. При этом Codex и Claude Code по факту строят IDE нового образца: сессии, диффы, ветки, интерактивный plan mode. - Принимать ответственность за код, который никто не читал, помогает не знание, а доказательства: SRE или менеджер раскатывают релиз по зелёному пайплайну и аппрувам, не заглядывая в код. Разработчику нужна такая же система — иначе, починив агентом баг импорта Maven в IDEA, ты не знаешь, что при этом сломал. - Ответ Антона на вопрос «нужна ли IDE в августе 2026»: для части рынка она уже nice-to-have, но маятник стандартизации вернёт индустрию к общему инструменту — сегодняшняя IDE трансформируется или её сменит новое поколение, и это всё равно будет IDE. ### Главы - [00:00](https://apkhmv.xyz/podcast/episode-72/?t=0) Вступление: Антон Архипов, JetBrains, выходной в Эстонии и вопрос «нужен ли вам IDE?» - [02:32](https://apkhmv.xyz/podcast/episode-72/?t=152) JCrete: анконференс на Крите, рулетка Хайнца Кабуца, лекции Клиффа Клика и AI-Crete - [09:06](https://apkhmv.xyz/podcast/episode-72/?t=546) Пузыри и ожидания: вопрос сеньорам с 20+ годами Java и взгляд патологоанатома - [11:39](https://apkhmv.xyz/podcast/episode-72/?t=699) Ответы: Клифф Клик дебажит в IDE, Питер Лори переписывает сгенерированный код руками - [16:38](https://apkhmv.xyz/podcast/episode-72/?t=998) Зачем вообще код, code review как главная задача и «moment of shame» того, кто не читает код - [22:16](https://apkhmv.xyz/podcast/episode-72/?t=1336) Хрустальный шар: 80%, что инструмент уже не нужен, страх и идентичность вокруг кода - [26:58](https://apkhmv.xyz/podcast/episode-72/?t=1618) Цена инференса: две тысячи в месяц на токены и код лучше, чем у 90% программистов - [29:18](https://apkhmv.xyz/podcast/episode-72/?t=1758) Теория Голдратта: горлышко переехало в code review, PR на 10 тысяч строк и зачем ревью на самом деле - [34:41](https://apkhmv.xyz/podcast/episode-72/?t=2081) Инструменты ревью не менялись 15 лет: хочу историю инкремента, а не дифф с комментариями - [39:23](https://apkhmv.xyz/podcast/episode-72/?t=2363) «Мы клей между двумя Клодами»: ревью через агентов и коммуникация с потерями - [42:29](https://apkhmv.xyz/podcast/episode-72/?t=2549) Чат вместо редактора: как Антон смотрит диффы, а Саша программирует графы агентов - [47:07](https://apkhmv.xyz/podcast/episode-72/?t=2827) Задачи инструмента: дебаггинг, ревью, артефакты на входе — Jira, транскрипт созвона, дамп из головы - [52:33](https://apkhmv.xyz/podcast/episode-72/?t=3153) Завод по переработке задач: наблюдаемость пайплайна, зерно на ладони и артефакт на выходе - [56:27](https://apkhmv.xyz/podcast/episode-72/?t=3387) Доказательства: тесты в середине, метрики перформанса на выходе и делегирование валидации агенту - [1:00:18](https://apkhmv.xyz/podcast/episode-72/?t=3618) Визуальный пайплайн с бюджетами, агенты общаются между сессиями, токены как новый ресурс и канбан агентов - [1:07:21](https://apkhmv.xyz/podcast/episode-72/?t=4041) Скиллы, экономия токенов и как Клод поглощает надстройки: self-review, отчёты, Codex строит IDE - [1:10:32](https://apkhmv.xyz/podcast/episode-72/?t=4232) Борьба с ветряными мельницами: новая модель обнуляет ваши тулы, агент пишет инструменты на лету - [1:15:14](https://apkhmv.xyz/podcast/episode-72/?t=4514) LSP для агента: поиск, рефакторинги, matklad с грепом и юниксовые тулзы - [1:19:56](https://apkhmv.xyz/podcast/episode-72/?t=4796) Essential против nice-to-have: JRebel, компилятор, git и где теперь живут незаменимые инструменты - [1:23:01](https://apkhmv.xyz/podcast/episode-72/?t=4981) Два динозавра OpenAI и Anthropic: где не стоять на пути, контекстное окно и локальные модели - [1:27:40](https://apkhmv.xyz/podcast/episode-72/?t=5260) Терминал или UI: Codex Desktop, глючный Claude Desktop и Джонни Мнемоник в VR - [1:30:48](https://apkhmv.xyz/podcast/episode-72/?t=5448) Если редактор заменить на Codex: список сессий и новый плагин JetBrains - [1:33:08](https://apkhmv.xyz/podcast/episode-72/?t=5588) Видимость работы и отчётность: токены на задачу, governance-слой, Central, покупка DX Atlassian-ом - [1:41:01](https://apkhmv.xyz/podcast/episode-72/?t=6061) Динамический UI на пути динозавров: интерактивный plan mode и инструмент для принятия решений - [1:44:14](https://apkhmv.xyz/podcast/episode-72/?t=6254) Раскол комьюнити и псевдокод-дифф: понять критичный код без чтения тысяч строк - [1:49:51](https://apkhmv.xyz/podcast/episode-72/?t=6591) Баг импорта Maven в IDEA: починил агентом и не знаю, что сломал; legacy, COBOL и adoption 5% - [1:55:44](https://apkhmv.xyz/podcast/episode-72/?t=6944) Ответственность: агент-археолог на 10 миллионов токенов, индемнити Copilot и последняя кнопка перед уходом домой - [2:00:47](https://apkhmv.xyz/podcast/episode-72/?t=7247) Урок девопсов: меньше знаешь — лучше спишь, Fable находит баги в проде, баги есть всегда - [2:06:32](https://apkhmv.xyz/podcast/episode-72/?t=7592) Софт для самолётов и спутников: избыточность, 10 записей в студии и 10 отказов - [2:12:17](https://apkhmv.xyz/podcast/episode-72/?t=7937) Волшебная кнопка: чёрный ящик, потеря экспертизы, франкенштейн Саши на Opus 4.5 и вакансии внедрения - [2:18:06](https://apkhmv.xyz/podcast/episode-72/?t=8286) Финальный вопрос: нужна ли IDE в августе 2026, маятник стандартизации и once in a lifetime ### Ссылки - [JCrete — анконференс Java-разработчиков на Крите](https://www.jcrete.org) - [Антон Архипов — сайт и блог](https://antonarhipov.com) - [JRebel](https://www.jrebel.com) - [Koog — агентский фреймворк JetBrains на Kotlin](https://github.com/JetBrains/koog) - [Greptile](https://www.greptile.com) - [CodeRabbit](https://www.coderabbit.ai) - [Теория ограничений Голдратта](https://ru.wikipedia.org/wiki/Теория_ограничений) - [Выпуск 45: TigerBeetle — matklad в гостях](https://apkhmv.xyz/podcast/episode-45/) ## #71: Как работает IMDG Apache Ignite - Markdown: https://apkhmv.xyz/podcast/episode-71/index.md - Гости: [Станислав Лукьянов](https://apkhmv.xyz/people/stanislav-lukyanov/index.md) Александр Пахомов и Станислав Лукьянов разбирают in-memory data grid снизу вверх: от локальной HashMap до распределённого хранилища с логическими шардами, репликами, консенсусом и SQL. На примере Apache Ignite они показывают, как коллокация данных и вычислений убирает сетевые пересылки, зачем Java-системы ушли в off-heap и где остаются проблемы GC, JIT, безопасности и эксплуатации. В финале формулируют критерии выбора такой технологии и обсуждают её возможное будущее в памяти агентов и LLM KV-кэшах. ### Главное - In-memory data grid — не просто кэш: система объединяет память нескольких машин и строит API так, чтобы минимизировать I/O, сетевые пересылки и движение данных между диском и памятью. - Ключ сначала отображается в логический шард, а шард — в физический узел; consistent и rendezvous hashing позволяют менять состав кластера, не перекладывая заново весь набор данных. - Репликация требует явного выбора между доступностью и консистентностью: Ignite 2 предлагал режимы Primary Sync и Full Sync, а Ignite 3 использует Raft и подтверждает запись большинством реплик. - SQL поверх распределённого key-value-хранилища становится эффективным, когда связанные данные коллоцированы: partition pruning и локальные join'ы убирают shuffle между узлами. - Collocated compute переносит Java-бизнес-логику к данным и сводит операцию к одному сетевому переходу, но повышает требования к безопасности, изоляции, multi-tenancy и квалификации команды. - Переход в off-heap решал сразу три задачи: снижал давление на Garbage Collector, давал предсказуемый бинарный layout для индексов и SQL и позволял сохранять страницы на диск. - Распределённое хранилище оправдано при сочетании низкой latency и большого параллелизма; прежде чем вводить его сложность, стоит проверить scale-up, кэш и репликацию обычной базы. - Идеи data grid могут вернуться в AI-инфраструктуре как масштабируемый слой памяти агентов, семантических кэшей и распределённого хранения LLM KV-кэшей рядом с инференсом. ### Главы - [00:00](https://apkhmv.xyz/podcast/episode-71/?t=0) Вступление: Ignite - [01:00](https://apkhmv.xyz/podcast/episode-71/?t=60) Как Apache Ignite стал технологическим феноменом - [08:06](https://apkhmv.xyz/podcast/episode-71/?t=486) Что такое in-memory data grid - [13:10](https://apkhmv.xyz/podcast/episode-71/?t=790) Серверная обработка и бесконечная мапа - [19:40](https://apkhmv.xyz/podcast/episode-71/?t=1180) От Java HashMap к распределённому хранилищу - [27:15](https://apkhmv.xyz/podcast/episode-71/?t=1635) Как разложить огромную мапу по машинам - [33:36](https://apkhmv.xyz/podcast/episode-71/?t=2016) Эластичное шардирование: consistent и rendezvous hashing - [44:46](https://apkhmv.xyz/podcast/episode-71/?t=2686) High availability начинается с репликации данных - [50:07](https://apkhmv.xyz/podcast/episode-71/?t=3007) CAP-теорема: консистентность или доступность при разделении - [58:04](https://apkhmv.xyz/podcast/episode-71/?t=3484) Подтверждение записи: от Primary Sync до Raft - [1:03:05](https://apkhmv.xyz/podcast/episode-71/?t=3785) За пределами key-value: документы и SQL - [1:09:38](https://apkhmv.xyz/podcast/episode-71/?t=4178) Decision support без превращения в OLAP - [1:12:28](https://apkhmv.xyz/podcast/episode-71/?t=4348) Зачем SQL понадобился поверх хеш-мап - [1:18:19](https://apkhmv.xyz/podcast/episode-71/?t=4699) Распределённый SQL, частичные результаты и shuffle - [1:26:47](https://apkhmv.xyz/podcast/episode-71/?t=5207) Коллокация: связанные данные должны лежать вместе - [1:36:37](https://apkhmv.xyz/podcast/episode-71/?t=5797) Join, который наглядно объясняет коллокацию - [1:40:41](https://apkhmv.xyz/podcast/episode-71/?t=6041) Collocated compute: переносим бизнес-логику к данным - [1:46:45](https://apkhmv.xyz/podcast/episode-71/?t=6405) Динамический деплой кода, лямбды и sandbox - [1:54:47](https://apkhmv.xyz/podcast/episode-71/?t=6887) Почему русскоязычные инженеры полюбили data grid - [1:58:34](https://apkhmv.xyz/podcast/episode-71/?t=7114) Garbage Collector встречает low-latency-нагрузки - [2:07:15](https://apkhmv.xyz/podcast/episode-71/?t=7635) От распределённых объектов к off-heap storage - [2:12:01](https://apkhmv.xyz/podcast/episode-71/?t=7921) Три причины перехода на off-heap - [2:18:44](https://apkhmv.xyz/podcast/episode-71/?t=8324) Делает ли современный ZGC off-heap ненужным - [2:23:33](https://apkhmv.xyz/podcast/episode-71/?t=8613) JIT-компиляция: Java против движков баз данных - [2:29:35](https://apkhmv.xyz/podcast/episode-71/?t=8975) Когда не стоит выбирать распределённое хранилище - [2:34:09](https://apkhmv.xyz/podcast/episode-71/?t=9249) Где data grid оправдывает свою сложность - [2:39:17](https://apkhmv.xyz/podcast/episode-71/?t=9557) Кризис идентичности in-memory data grid - [2:42:10](https://apkhmv.xyz/podcast/episode-71/?t=9730) Могут ли data grid пригодиться AI-агентам - [2:46:01](https://apkhmv.xyz/podcast/episode-71/?t=9961) KV-кэши и распределённый AI-инференс - [2:49:03](https://apkhmv.xyz/podcast/episode-71/?t=10143) Напутствие: изучайте системы, потом выбирайте инструмент ### Ссылки - [Apache Ignite](https://ignite.apache.org) - [GridGain](https://www.gridgain.com) - [Hazelcast](https://hazelcast.com) - [Oracle Coherence](https://www.oracle.com/middleware/technologies/coherence.html) - [Redis](https://redis.io) - [Database Internals — Alex Petrov](https://www.oreilly.com/library/view/database-internals/9781492040330/) - [Выпуск 24: B-tree и B+tree](https://apkhmv.xyz/podcast/episode-24/) ## #70: Режим 9-9-6 для Claude - Markdown: https://apkhmv.xyz/podcast/episode-70/index.md - Гости: [Станислав Лукьянов](https://apkhmv.xyz/people/stanislav-lukyanov/index.md) Александр Пахомов и Станислав Лукьянов — коммитер Apache Ignite, инженер GridGain (теперь часть MariaDB), ранее Java Platform в Oracle, последние годы живёт в Нью-Йорке — записывают незапланированный выпуск: интро к разговору про in-memory data grid переросло в двухчасовую беседу о том, как AI меняет работу инженера. Обсуждают 9-9-6 и тревожность по ту сторону океана, поколение AI-native фаундеров, которые не читают код, и то, во что вкладываться сейчас: системное мышление, математику, системное программирование и семантический слой для агента. Вторая половина — про экономику и про себя: токены как новый ресурс и бюджеты, которые растут вместе с грейдом, три грани ответственности, массовая слежка за сессиями и этика чужих промптов, FOMO пятичасового окна, сон, спорт и легализация отдыха на 24 часа без компьютера. ### Главное - Режим 9-9-6 — история в первую очередь про Долину: в Нью-Йорке это ощущается слабее, но расслоение (инженер в AI-лабе за ~900 тысяч против инженера в банке за 150) заставляет думать об этой гонке даже тех, кто в неё не хочет. - Дифференциация сместилась с механического навыка писать и ревьюить код к умению «видеть лес за деревьями», но в сложных системах старый опыт всё ещё выигрывает: Митчелл Хашимото соптимизировал руками в пятьдесят раз то, что агент ускорил в пять. - Работа с агентом — это построение онтологии и семантического слоя: у модели нет встроенного понимания, что «яблоки надо сравнивать с яблоками», и всё, что попало в контекст, для неё вещи одного порядка. - Оба ведущих сидят на ванильном сетапе: скиллы дают контекст-полюшен, и никто не публикует эвал, который проверял бы, что скилл НЕ инвочится, когда не надо, — на длинной сессии он подгрузится почти наверняка. - Unfair advantage индустрии — не понимание того, как устроены LLM, а пятьдесят лет автоматизации работы с текстом: терминал и `git` оказались лучшей средой для агентов, чем Excel или Google Docs. - Практический совет по токенам: пока вы не выжираете лимиты 20-долларовой подписки — токен-максьте; оптимизировать имеет смысл там, где вы упираетесь в окно. На энтерпрайзе (у Anthropic Team — до 150 мест, дальше Enterprise) включается pay-per-token, и трейд-офф «бюджет против throughput» станет темой 2027 года. - Прогноз к 2030-му: бюджет на агентов станет частью грейда — джуну двадцатидолларовая подписка, staff-инженеру тысячи долларов, principal — десятки тысяч; отчитываться придётся и за перерасход, и за недоиспользование бюджета. - Ответственность распадается на три грани — accountability за ресурсы, принятие рисков (one neck to chop) и ownership; централизованный анализ сессий даёт организации value, но неизбежно превращается в массовую слежку, поэтому агрегаты должны быть за семью замками. ### Главы - [00:00](https://apkhmv.xyz/podcast/episode-70/?t=0) Вступление: случайность вместо выпуска про базы данных - [01:14](https://apkhmv.xyz/podcast/episode-70/?t=74) Гость: Apache Ignite, GridGain и переезд в Нью-Йорк - [02:48](https://apkhmv.xyz/podcast/episode-70/?t=168) 9-9-6, Долина и permanent underclass - [07:01](https://apkhmv.xyz/podcast/episode-70/?t=421) AI-native фаундеры, которые не читают код - [11:26](https://apkhmv.xyz/podcast/episode-70/?t=686) Опыт инженера: мудрость или якорь - [14:36](https://apkhmv.xyz/podcast/episode-70/?t=876) Критические секции: где остаётся ценность системного программирования - [21:09](https://apkhmv.xyz/podcast/episode-70/?t=1269) Математика как запасной план - [26:59](https://apkhmv.xyz/podcast/episode-70/?t=1619) Системное мышление как универсальный скилл - [30:07](https://apkhmv.xyz/podcast/episode-70/?t=1807) Онтология системы и семантический слой для агента - [33:02](https://apkhmv.xyz/podcast/episode-70/?t=1982) «Не можешь объяснить — значит, сделал херню» - [34:50](https://apkhmv.xyz/podcast/episode-70/?t=2090) Клод смешивает контексты; инженер как психолог - [41:00](https://apkhmv.xyz/podcast/episode-70/?t=2460) Ванильный Клод против скиллов и контекст-полюшен - [48:24](https://apkhmv.xyz/podcast/episode-70/?t=2904) Возврат в терминал: git, tmux и наш unfair advantage - [54:45](https://apkhmv.xyz/podcast/episode-70/?t=3285) Оператор ПК → оператор IntelliJ → оператор Клода - [57:21](https://apkhmv.xyz/podcast/episode-70/?t=3441) Медицина, «Доктор Хаус» и специализированные операторы Клода - [1:04:28](https://apkhmv.xyz/podcast/episode-70/?t=3868) Когнитивная нагрузка: контекст-свитчинг вместо потока - [1:06:42](https://apkhmv.xyz/podcast/episode-70/?t=4002) FOMO пятичасового окна и работа инжиниринг-менеджера - [1:12:45](https://apkhmv.xyz/podcast/episode-70/?t=4365) Экономика токенов: подписки, энтерпрайз и бюджеты - [1:15:49](https://apkhmv.xyz/podcast/episode-70/?t=4549) Мета-харнес: анализ сессий и оптимизация трат - [1:23:06](https://apkhmv.xyz/podcast/episode-70/?t=4986) Слежка за сессиями и этика чужих промптов - [1:29:22](https://apkhmv.xyz/podcast/episode-70/?t=5362) Бюджет, который растёт вместе с грейдом - [1:33:42](https://apkhmv.xyz/podcast/episode-70/?t=5622) Три грани ответственности - [1:39:10](https://apkhmv.xyz/podcast/episode-70/?t=5950) Токены как новое электричество - [1:40:58](https://apkhmv.xyz/podcast/episode-70/?t=6058) Персональные workflow: NeoVim, tmux и их ROI - [1:45:04](https://apkhmv.xyz/podcast/episode-70/?t=6304) Сон и режим дня: сколько агентов ты вытягиваешь - [1:57:32](https://apkhmv.xyz/podcast/episode-70/?t=7052) Простить себя: тренды, лупы и графы - [2:03:46](https://apkhmv.xyz/podcast/episode-70/?t=7426) Кто реально шипит: вайбкодинг у нетехнических фаундеров - [2:11:21](https://apkhmv.xyz/podcast/episode-70/?t=7881) Спорт, добавки и work-life balance - [2:16:17](https://apkhmv.xyz/podcast/episode-70/?t=8177) Легализация отдыха: 24 часа без компьютера - [2:18:48](https://apkhmv.xyz/podcast/episode-70/?t=8328) Limitless: кем ты хочешь быть через три часа - [2:23:17](https://apkhmv.xyz/podcast/episode-70/?t=8597) 37signals, чистый стол и Rework - [2:26:59](https://apkhmv.xyz/podcast/episode-70/?t=8819) Открытый микрофон ### Ссылки - [Apache Ignite](https://ignite.apache.org) - [GridGain](https://www.gridgain.com) - [Ghostty — терминал Митчелла Хашимото](https://ghostty.org) - [37signals](https://37signals.com) ## #69: Психология инженера с Александром Орловым - Markdown: https://apkhmv.xyz/podcast/episode-69/index.md - Гости: [Александр Орлов](https://apkhmv.xyz/people/alexander-orlov/index.md) Александр Пахомов и Александр Орлов — сооснователь Школы менеджмента «Стратоплан», ранее Sun Microsystems и Intel, психолог по второму образованию — разбирают работу инженера как психологическую. Почему поток так трудно поймать и удержать, что происходит с командой в фазах форминга и шторминга по Такману и почему спор о скобке в code style на самом деле спор об иерархии и уважении. Обсуждают эго-состояния по Берну, три способа реагировать на неустраивающую ситуацию (изменить, принять, выйти) и четвёртый, худший — терпеть; ресурсы, которые определяют вашу раздражительность на код-ревью; visibility через уровень как механику карьеры. В финале — как агентская разработка поднимает когнитивную нагрузку до потолка и почему soft skills дорожают именно сейчас. ### Главное - «Десять сеансов психотерапии не помешают никому»: вторая вышка по психологии для инженерной позиции скорее избыточна, а терапия даёт больше — но важен мэтч со специалистом, который складывается не с первой встречи даже по рекомендациям. - На вход в поток уходит 15–20 минут, и любое прерывание обнуляет их; воспроизводимые условия у обоих участников похожи — сон, изоляция, лёгкий стимулятор и ранние часы до того, как открыты рабочие чаты. - Модель Брюса Такмана: группа проходит форминг → шторминг → норминг → перформинг, и это цикл, а не прямая; на первых двух фазах команда работает хуже, чем те же люди поодиночке, а перформинг — это, по сути, командный поток. - Участие команды в найме и честно проговорённая ценность человека («ты лучший из пятидесяти») почти убирают шторминг — но только если это правда: неискренность считывается моментально. - За спором о code style стоит не код, а выстраивание социальной иерархии: кто кого слушает и чьё мнение весит больше. Скобку переставит скрипт — вопрос всегда был не в ней. - Есть три способа реагировать на ситуацию, которая вас не устраивает: изменить, принять или озвучить своё отношение и выйти. Чаще всего выбирают четвёртый — терпеть, и он заканчивается смещением: срывом на коллегах или дома. - Транзактный анализ Берна: конструктив идёт из позиции «взрослый — взрослый», а формальные погоны часто переключают человека в «родителя» — и любая транзакция «родитель — ребёнок» пересекается и вызывает эмоции вместо решения. - «Карьера — это сумма решений, которые в отношении нас принимают другие люди» (Миша Завилейский): отсюда важность visibility через уровень — и сокращения, и повышения решаются на уровень выше вашего непосредственного руководителя. ### Главы - [00:00](https://apkhmv.xyz/podcast/episode-69/?t=0) Тизер: либидная и мортидная энергия - [01:15](https://apkhmv.xyz/podcast/episode-69/?t=75) Гость: от Sun и Intel к Школе менеджмента - [05:01](https://apkhmv.xyz/podcast/episode-69/?t=301) Вторая вышка или психотерапия: что нужнее инженеру - [07:44](https://apkhmv.xyz/podcast/episode-69/?t=464) Онлайн или офлайн и почему состояние психики влияет на код - [09:12](https://apkhmv.xyz/podcast/episode-69/?t=552) Недооценённая когнитивная нагрузка общения - [10:28](https://apkhmv.xyz/podcast/episode-69/?t=628) Что такое поток и как в него попадать - [12:34](https://apkhmv.xyz/podcast/episode-69/?t=754) Рецепт потока: сон, изоляция, ранние часы - [15:26](https://apkhmv.xyz/podcast/episode-69/?t=926) Кризисы 30–35 и 40–45; пять утра для себя - [19:09](https://apkhmv.xyz/podcast/episode-69/?t=1149) Мыслительный эксперимент: собираем команду с нуля - [20:51](https://apkhmv.xyz/podcast/episode-69/?t=1251) Модель Такмана: форминг, шторминг, норминг, перформинг - [24:27](https://apkhmv.xyz/podcast/episode-69/?t=1467) Эффект первого дня в детском саду и спор о скобках - [28:41](https://apkhmv.xyz/podcast/episode-69/?t=1721) «Самая сильная команда, которую я видел»: как убрать шторминг - [32:39](https://apkhmv.xyz/podcast/episode-69/?t=1959) Руководитель — не родитель и не психолог - [34:47](https://apkhmv.xyz/podcast/episode-69/?t=2087) За code style прячется борьба за иерархию - [37:28](https://apkhmv.xyz/podcast/episode-69/?t=2248) Потребности, которые выбирают нас - [40:11](https://apkhmv.xyz/podcast/episode-69/?t=2411) Как заметить, что вас задело - [42:03](https://apkhmv.xyz/podcast/episode-69/?t=2523) Ковать железо, пока холодно: пауза вместо срача - [44:46](https://apkhmv.xyz/podcast/episode-69/?t=2686) Пять ресурсов и почему вы раздражаетесь на код-ревью - [47:35](https://apkhmv.xyz/podcast/episode-69/?t=2855) Ритуал check-in Джима Маккарти - [49:19](https://apkhmv.xyz/podcast/episode-69/?t=2959) Созвон, который мог быть письмом - [52:38](https://apkhmv.xyz/podcast/episode-69/?t=3158) Три способа реагирования — и четвёртый, худший - [56:58](https://apkhmv.xyz/podcast/episode-69/?t=3418) Эрик Берн: родитель, взрослый, ребёнок - [1:03:25](https://apkhmv.xyz/podcast/episode-69/?t=3805) Конструктивная конфронтация и умение слушать - [1:06:45](https://apkhmv.xyz/podcast/episode-69/?t=4005) Упражнение «Кулак» - [1:10:07](https://apkhmv.xyz/podcast/episode-69/?t=4207) Личность меняется, но не быстрее чем за полгода - [1:13:30](https://apkhmv.xyz/podcast/episode-69/?t=4410) Четыре сферы жизни по Пезешкиану - [1:16:10](https://apkhmv.xyz/podcast/episode-69/?t=4570) Soft skills на обеих карьерных лестницах - [1:17:11](https://apkhmv.xyz/podcast/episode-69/?t=4631) Visibility: кто на самом деле решает вашу карьеру - [1:18:23](https://apkhmv.xyz/podcast/episode-69/?t=4703) Почему soft skills дорожают в эпоху агентов - [1:21:01](https://apkhmv.xyz/podcast/episode-69/?t=4861) Как агентская разработка меняет команды - [1:23:10](https://apkhmv.xyz/podcast/episode-69/?t=4990) Десять окон агентов и потолок когнитивной нагрузки - [1:26:15](https://apkhmv.xyz/podcast/episode-69/?t=5175) Заниматься собой как активом ### Ссылки - Нет. ## #68: Исследуем границы современных моделей вместе Владимиром Ситниковым - Markdown: https://apkhmv.xyz/podcast/episode-68/index.md - Гости: [Владимир Ситников](https://apkhmv.xyz/people/vladimir-sitnikov/index.md) Александр Пахомов и Владимир Ситников — мейнтейнер PostgreSQL JDBC-драйвера (pgjdbc) и Apache JMeter, около двадцати лет в Java и производительности SQL-систем — разбирают агентскую разработку на конкретных артефактах: тридцать тысяч строк подсистемы кодеков, которые невозможно отревьюить глазами, кросс-ревью тремя моделями, скилл технического английского, появившийся после того, как правки в документацию отклонили как AI-слоп. Обсуждают, что идёт в скилл, а что в CLAUDE.md, APM как пакетный менеджер для агентских конфигов, орду ревьюеров-персон, профилировщик и фаззинг как обязательные гейты агентского SDLC, комментарии, которые описывают прошлое, и декомпиляцию вместо чтения исходников. В финале — где проходят границы моделей и человека и на что инженеру сейчас тратить время. ### Главное - Тридцать тысяч строк кодеков, сгенерированных агентом, человек физически не может отревьюить — выход в том, чтобы ревьюить тем же инструментом: три независимых ревью (Opus, GPT, Fable) плюс кросс-сравнение вердиктов, где каждая модель находит что-то своё. - Промпт «сделай ревью» бесполезен, пока не выбран фокус: построчное ревью, архитектурное или план дальнейших действий — сужение фокуса дало заметно лучший результат на всех моделях. - Скилл технического английского (компиляция публичных style guides) появился после того, как правки в документацию pgjdbc отклонили как AI-слоп; теперь он стоит глобально и, в частности, формирует описание PR — «почему это делается». - Оба сидят на минималистичных сетапах: развесистые чужие скиллы дают контекст-полюшен. Писать стоит только то, на чём модель уже спотыкалась, — к тому же выводу приходит и разбор CLAUDE.md у Тео Брауна. - APM (Microsoft Agent Package Manager) — фактически npm для агентских конфигов: версионируемые пакеты скиллов, хуков и промптов, переносимые между Claude Code и Codex; корпоративные конвенции ставятся одной зависимостью. - Профилировщик и фаззинг должны стать частью агентского SDLC наравне с юнит- и интеграционными тестами: без жёстких верификаторов агент не понимает, где важна производительность, а где — краевые случаи. - Coverage-guided фаззинг (JQF + JetCheck) нашёл в кодеках реальные баги — например, `+Infinity`, подобранный эволюционно, а не «придуманный» моделью. При этом сам код фаззера модель пишет плохо: в обучающих выборках фаззеров почти нет. - Модель не умеет оценивать сложность и экспертность: для неё `A + B` и дерево Фенвика примерно одно и то же — поэтому она не понимает, что комментировать, а что нет, и пишет комментарии про то, почему не работал старый код. ### Главы - [00:00](https://apkhmv.xyz/podcast/episode-68/?t=0) Гость: pgjdbc, JMeter и программные комитеты - [02:29](https://apkhmv.xyz/podcast/episode-68/?t=149) Project Hub: работа с двадцатью репозиториями - [04:10](https://apkhmv.xyz/podcast/episode-68/?t=250) Промпт для ревью: код, архитектура или план - [07:26](https://apkhmv.xyz/podcast/episode-68/?t=446) Тридцать тысяч строк, которые не помещаются в голову - [08:53](https://apkhmv.xyz/podcast/episode-68/?t=533) Кросс-ревью тремя моделями - [10:59](https://apkhmv.xyz/podcast/episode-68/?t=659) Куда девать промпты, планы и ресёрчи - [13:00](https://apkhmv.xyz/podcast/episode-68/?t=780) Скилл кросс-ревью через Codex - [14:34](https://apkhmv.xyz/podcast/episode-68/?t=874) Инженерная гигиена: брутальное ревью на каждый PR - [17:03](https://apkhmv.xyz/podcast/episode-68/?t=1023) Свои скиллы против чужих - [18:25](https://apkhmv.xyz/podcast/episode-68/?t=1105) Скилл технического английского и ярлык «AI-слоп» - [22:46](https://apkhmv.xyz/podcast/episode-68/?t=1366) Скиллы устареют? Адаптировать модель или себя - [25:22](https://apkhmv.xyz/podcast/episode-68/?t=1522) Что идёт в скилл, а что в CLAUDE.md - [30:00](https://apkhmv.xyz/podcast/episode-68/?t=1800) Кто должен писать CLAUDE.md - [31:33](https://apkhmv.xyz/podcast/episode-68/?t=1893) APM: пакетный менеджер для агентских конфигов - [35:47](https://apkhmv.xyz/podcast/episode-68/?t=2147) Орда ревьюеров: UX, совместимость, маркетолог - [39:12](https://apkhmv.xyz/podcast/episode-68/?t=2352) Не производим ли мы слоп для чужих мозгов - [41:22](https://apkhmv.xyz/podcast/episode-68/?t=2482) Ответ для людей и ответ для агентов - [43:27](https://apkhmv.xyz/podcast/episode-68/?t=2607) Где смотреть код, а где не смотреть - [45:50](https://apkhmv.xyz/podcast/episode-68/?t=2750) Недосказанность: что не попадает в pull request - [48:24](https://apkhmv.xyz/podcast/episode-68/?t=2904) Комментарии, которые описывают прошлое - [52:06](https://apkhmv.xyz/podcast/episode-68/?t=3126) Модель не умеет оценивать сложность - [55:58](https://apkhmv.xyz/podcast/episode-68/?t=3358) Тулинг для людей, сорцы для нейронок - [58:27](https://apkhmv.xyz/podcast/episode-68/?t=3507) Агентские сессии как база знаний проекта - [1:01:47](https://apkhmv.xyz/podcast/episode-68/?t=3707) JAVA_HOME, тулчейны и где модель спотыкается - [1:04:46](https://apkhmv.xyz/podcast/episode-68/?t=3886) CLAUDE.md: писать только то, где модель накосячила - [1:05:34](https://apkhmv.xyz/podcast/episode-68/?t=3934) Скепсис к исследованиям: исследователь сам себя - [1:08:03](https://apkhmv.xyz/podcast/episode-68/?t=4083) Инструментарий: терминал, tmux, GitHub - [1:09:26](https://apkhmv.xyz/podcast/episode-68/?t=4166) Почему десктоп-приложение вместо CLI - [1:13:00](https://apkhmv.xyz/podcast/episode-68/?t=4380) Свой тулинг: дашборды и CLI под себя - [1:15:59](https://apkhmv.xyz/podcast/episode-68/?t=4559) Можно ли глазами понять, что код быстрый - [1:19:14](https://apkhmv.xyz/podcast/episode-68/?t=4754) Профилировщик как часть агентского SDLC - [1:24:11](https://apkhmv.xyz/podcast/episode-68/?t=5051) Фаззинг: случайные байты и структурные объекты - [1:29:35](https://apkhmv.xyz/podcast/episode-68/?t=5375) Coverage-guided фаззинг и генетические алгоритмы - [1:31:49](https://apkhmv.xyz/podcast/episode-68/?t=5509) PR через шесть лет и +Infinity, найденный перебором - [1:36:34](https://apkhmv.xyz/podcast/episode-68/?t=5794) «Шашечки или ехать»: Fable против Opus - [1:38:15](https://apkhmv.xyz/podcast/episode-68/?t=5895) Прощупывание пределов моделей - [1:40:23](https://apkhmv.xyz/podcast/episode-68/?t=6023) Как Opus написал парсер хипдампа - [1:42:11](https://apkhmv.xyz/podcast/episode-68/?t=6131) Логи и CI: скрипт вместо каждого грепа - [1:46:13](https://apkhmv.xyz/podcast/episode-68/?t=6373) Декомпиляция вместо чтения исходников - [1:53:06](https://apkhmv.xyz/podcast/episode-68/?t=6786) Что стоило бы деливерить вместе с библиотекой - [2:00:08](https://apkhmv.xyz/podcast/episode-68/?t=7208) На что инженеру тратить время: границы сферы - [2:01:56](https://apkhmv.xyz/podcast/episode-68/?t=7316) Круги Эйлера: границы модели и твои собственные - [2:06:51](https://apkhmv.xyz/podcast/episode-68/?t=7611) Писать код руками — потеря времени? - [2:10:10](https://apkhmv.xyz/podcast/episode-68/?t=7810) Кто такой современный программист - [2:14:18](https://apkhmv.xyz/podcast/episode-68/?t=8058) Дерево Фенвика - [2:17:02](https://apkhmv.xyz/podcast/episode-68/?t=8222) Открытый микрофон: в Клоде нет социума ### Ссылки - [pgjdbc — PostgreSQL JDBC Driver](https://github.com/pgjdbc/pgjdbc) - [Apache JMeter](https://jmeter.apache.org) ## #67: Java и Spring в 2026 - Markdown: https://apkhmv.xyz/podcast/episode-67/index.md - Гости: [Миша Поливаха](https://apkhmv.xyz/people/misha-polivakha/index.md) Александр Пахомов и Миша Поливаха — практикующий Java-разработчик, стоявший у истоков сообщества Spring.io, — разбирают, на чём держится Java в 2026-м. Почему энтерпрайз не переписывает и не апгрейдит (патчинг CVE для Java 6 как живой бизнес), как Spring выиграл у Java EE на скорости эволюции и правильных продуктовых решениях Рода Джонсона и команды Spring Boot, чем занят Project Leyden и почему AppCDS отбирает у Quarkus его главное преимущество. Вторая половина — спор двух подходов: для гостя тулинг это IDE, стартеры и dev mode, для ведущего, который код руками не пишет, — quality gates, которыми обкладывают агента; отсюда претензии к Java-экосистеме на фоне `clippy --fix`, история отказа OpenJDK принимать сгенерированные PR и финальное расхождение о том, можно ли нарастить экспертизу, не написав код руками. ### Главное - Java держится в энтерпрайзе не техническим превосходством, а консолидацией экосистемы: одна проблема — один канонический способ решения, единый «паровоз» (виртуальные потоки Spring поддержал сразу) и взаимозаменяемость инженеров между командами. - Java EE проиграла Spring на скорости: спецификации согласовывались годами (многострадальный JSR-305 в итоге отозвали, а JSpecify появился уже силами консорциума — Google, JetBrains), и Oracle в конце концов отдал javax в Eclipse Foundation. - Ключевых решений у Spring два: Spring Boot признал, что 80% конфигурации никто не переопределяет, и дал дефолты; и Spring не поворачивался спиной к экосистеме — в отличие от Quarkus, который заперся в Jakarta EE и остался «чёрным лебедем» со своими реализациями всего. - Project Leyden и AppCDS съедают главное преимущество Quarkus — быстрый старт. Команды Oracle и Spring работают настолько плотно, что Spring PetClinic фигурирует в официальных JEP'ах как референсная имплементация. - У собеседников разное понимание тулинга: для Поливахи это то, что помогает писать код (IDE, стартеры, Docker Compose Starter, dev mode), для Пахомова, который код руками не пишет, — quality gates, которыми обкладывают агента, чтобы проще брать на себя ответственность за его код. - Претензия к Java: в Rust `clippy --fix` и `rustfmt` идут батарейкой вместе с языком и снимают сам спор о стиле, а в Java форматтеры и статические анализаторы собираются плагинами — и обсуждения code style живы до сих пор. Контраргумент гостя: это вопрос инженерной культуры и экспрессивности языка, а не тулинга. - Долгий Java-билд — это почти всегда тесты (подъём Spring-контекстов, Testcontainers), а не компиляция: монорепа Axelix с полутора тысячами тестов собирается за две-три минуты. - OpenJDK отказался принимать сгенерированные pull request'ы, потому что у них боттлнек не в написании кода, а в дизайне и согласовании совместимости. Пахомов видит в этом риск остаться за бортом, Поливаха — разумную выжидательную позицию, как у Линуса Торвальдса: «несите ответственность за свой код». ### Главы - [00:00](https://apkhmv.xyz/podcast/episode-67/?t=0) Гость: Java, Spring.io и конференции - [00:51](https://apkhmv.xyz/podcast/episode-67/?t=51) Что сейчас происходит в JVM-мире - [04:50](https://apkhmv.xyz/podcast/episode-67/?t=290) Консолидация против «библиотеки из Небраски» - [06:14](https://apkhmv.xyz/podcast/episode-67/?t=374) Сертификации Oracle и вьетнамские флешбеки - [07:43](https://apkhmv.xyz/podcast/episode-67/?t=463) Почему энтерпрайз не переписывает и не апгрейдит - [14:07](https://apkhmv.xyz/podcast/episode-67/?t=847) «Работает — не трожь» и взаимозаменяемые юниты - [15:40](https://apkhmv.xyz/podcast/episode-67/?t=940) Кроме Spring, ничего нет - [16:33](https://apkhmv.xyz/podcast/episode-67/?t=993) Род Джонсон и боли Java EE - [17:28](https://apkhmv.xyz/podcast/episode-67/?t=1048) Что такое Java EE и откуда взялась Java - [20:52](https://apkhmv.xyz/podcast/episode-67/?t=1252) Eclipse Foundation как чердак истории - [24:29](https://apkhmv.xyz/podcast/episode-67/?t=1469) Почему Java EE проиграла: JSR-305 и медленная эволюция - [28:17](https://apkhmv.xyz/podcast/episode-67/?t=1697) Появляется Spring Boot - [30:22](https://apkhmv.xyz/podcast/episode-67/?t=1822) Дефолты, которые никто не переопределяет - [33:00](https://apkhmv.xyz/podcast/episode-67/?t=1980) Quarkus и ставка на Jakarta EE - [37:35](https://apkhmv.xyz/podcast/episode-67/?t=2255) Project Leyden, AppCDS и ramp-up - [43:41](https://apkhmv.xyz/podcast/episode-67/?t=2621) JEP'ы, PetClinic и связка Oracle со Spring - [48:24](https://apkhmv.xyz/podcast/episode-67/?t=2904) Как ведущий писал Spring Boot-стартеры - [50:45](https://apkhmv.xyz/podcast/episode-67/?t=3045) Продуктовый майндсет Рода Джонсона - [55:47](https://apkhmv.xyz/podcast/episode-67/?t=3347) Догфудинг и лидер, принимающий решения - [1:00:09](https://apkhmv.xyz/podcast/episode-67/?t=3609) Что даёт IntelliJ: дебаггер, декомпиляция, база данных - [1:02:59](https://apkhmv.xyz/podcast/episode-67/?t=3779) Поддержка фреймворков и сборщиков - [1:09:54](https://apkhmv.xyz/podcast/episode-67/?t=4194) Quality gates: Spotless, Error Prone, NullAway - [1:12:33](https://apkhmv.xyz/podcast/episode-67/?t=4353) Тулинг глазами оператора агентов - [1:16:29](https://apkhmv.xyz/podcast/episode-67/?t=4589) Спор о форматтерах: культура или тулинг - [1:21:10](https://apkhmv.xyz/podcast/episode-67/?t=4870) Время запуска и цикл обратной связи для агента - [1:23:02](https://apkhmv.xyz/podcast/episode-67/?t=4982) Что на самом деле долгое в Java-билде - [1:29:46](https://apkhmv.xyz/podcast/episode-67/?t=5386) Кэширование Spring-контекстов и флаки-тесты - [1:32:51](https://apkhmv.xyz/podcast/episode-67/?t=5571) Останется ли Java для новых проектов - [1:39:14](https://apkhmv.xyz/podcast/episode-67/?t=5954) Мы пережили Stack Overflow - [1:42:38](https://apkhmv.xyz/podcast/episode-67/?t=6158) Род Джонсон делает фреймворк для агентов - [1:45:06](https://apkhmv.xyz/podcast/episode-67/?t=6306) Почему агенты ломаются на обновлениях - [1:49:56](https://apkhmv.xyz/podcast/episode-67/?t=6596) Spring AI: зонтик проектов - [1:54:38](https://apkhmv.xyz/podcast/episode-67/?t=6878) Почему у Spring нет своих скиллов - [1:58:13](https://apkhmv.xyz/podcast/episode-67/?t=7093) OpenJDK не принимает сгенерированные PR - [2:03:04](https://apkhmv.xyz/podcast/episode-67/?t=7384) Боттлнек не в коде, а в ревью и дизайне - [2:06:15](https://apkhmv.xyz/podcast/episode-67/?t=7575) Позиция Линуса: несите ответственность за свой код - [2:11:16](https://apkhmv.xyz/podcast/episode-67/?t=7876) Экспертиза как то, что дорожает - [2:17:37](https://apkhmv.xyz/podcast/episode-67/?t=8257) Не подпускать агента туда, где учишься - [2:19:40](https://apkhmv.xyz/podcast/episode-67/?t=8380) Нейрофизиология: мы учимся руками - [2:23:34](https://apkhmv.xyz/podcast/episode-67/?t=8614) Напутствие: развивайте глубину экспертизы ### Ссылки - [Spring AI](https://spring.io/projects/spring-ai) - [Embabel — фреймворк Рода Джонсона для агентов на JVM](https://github.com/embabel/embabel-agent) - [Spring PetClinic](https://github.com/spring-projects/spring-petclinic) ## #66: Veai: БАЗА ПО КОДИНГ АГЕНТАМ - Markdown: https://apkhmv.xyz/podcast/episode-66/index.md - Гости: [Михаил Костицын](https://apkhmv.xyz/people/mikhail-kositsyn/index.md) Александр Пахомов и Михаил Костицын (разработчик кодинг-агента veai, IDE-native агента для JetBrains IDE) по шагам «собирают» кодинг-агента: от ассистента-чата к агенту с инструментами — терминалом, чтением/записью файлов, поиском — и разбирают ключевой трейд-офф между свободой (один универсальный терминал) и контролем (набор узких, надёжных тулов), а также контекст-менеджмент как главный ресурс. Отталкиваясь от IntelliJ-платформы, они показывают, что даёт агенту IDE поверх терминала — LSP и PSI, инспекции, декомпиляцию, дебаггер и «формальные методы» (инструментация байткода, анализ моргающих тестов, символьное исполнение, SAST), — и обсуждают enterprise-спрос на локальные модели, бенчмарк-систему veai с верифайерами и LLM-судьёй, проблему бенчмаксинга и dogfooding. ### Главное - Кодинг-агент = LLM плюс чат плюс инструменты: инструмент — это функция `input → output`, о которой модель узнаёт через специальный tool-call-токен и описание в системном промпте. - Каждый добавленный тул живёт в «горячем» контексте, который гоняется на каждом шаге; лишние тулы (и MCP, и скиллы) съедают контекст, а после ~80–85% заполнения модели начинают деградировать — проверяйте это через `/context`. - Главный трейд-офф — один универсальный терминал (безграничная свобода, но и безграничное пространство ошибок и риск безопасности) против набора узких, надёжных тулов (`read`, `write`, `search`, `ls`), которые контролируемы и экономят токены; практичное решение — совмещать, оставив терминал на крайний случай. - IDE — это готовая абстракция над language-specific туллингом: вместо отдельных тулов на каждый язык агенту дают высокоуровневые `build`/`test`/`fmt`, которые инкапсулируют язык внутри, а IntelliJ-платформа определяет язык проекта через включённые плагины. - `LSP` приносит в редактор синтаксис (лексер + парсер → AST) и базовый автокомплит; `PSI` (Program Structure Interface) в IntelliJ добавляет семантику — `findUsages`, различение использования и override — и потому куда лучше подходит как инфраструктура для агента, чем греп в терминале. - IDE-инспекции, декомпиляция и дебаггер — киллер-инструменты для агента: инспекции дают статический анализ без запуска, декомпилятор превращает `.class`/зависимости без документации в читаемые исходники, а встроенный дебаггер (breakpoint + evaluate expression) экономит время и токены против цикла «добавь принт → пересобери». - Ставка veai на IntelliJ обоснована enterprise-спросом: банки и финтех не готовы «сливать код в Anthropic», поэтому нужны локальные модели в контуре (`GLM`, `DLP`-шлюз), а мощные IDE-тулы позволяют слабее-догадливым моделям работать надёжно. - Качество агента veai мерят бенчмарк-системой с эмулятором пользователя, жёсткими верифайерами (сборка/тесты/покрытие) и LLM-судьёй; набор верифайеров работает как система сдержек и противовесов против бенчмаксинга, а поверх всего — ручное QA и dogfooding. ### Главы - [00:00](https://apkhmv.xyz/podcast/episode-66/?t=0) Вступление: гость, veai и голос ведущего - [02:21](https://apkhmv.xyz/podcast/episode-66/?t=141) Что такое кодинг-агент: от ассистента к агенту - [05:01](https://apkhmv.xyz/podcast/episode-66/?t=301) Первый инструмент: tool-call-токен и описание для модели - [14:41](https://apkhmv.xyz/podcast/episode-66/?t=881) Аналогия «мозг в банке» - [20:36](https://apkhmv.xyz/podcast/episode-66/?t=1236) Дизайн тулов: чтение, запись, поиск, список файлов - [30:45](https://apkhmv.xyz/podcast/episode-66/?t=1845) Терминал: свобода против контроля и безопасности - [44:00](https://apkhmv.xyz/podcast/episode-66/?t=2640) Билд и тесты: IDE как абстракция над языками - [53:56](https://apkhmv.xyz/podcast/episode-66/?t=3236) CLI- против IDE-агентов; выбор IDE - [1:01:38](https://apkhmv.xyz/podcast/episode-66/?t=3698) LSP: синтаксис и AST в редакторе кода - [1:08:50](https://apkhmv.xyz/podcast/episode-66/?t=4130) PSI: семантика поверх AST и findUsages - [1:19:52](https://apkhmv.xyz/podcast/episode-66/?t=4792) Инспекции IntelliJ как инструмент; история с ID-инспектом - [1:28:35](https://apkhmv.xyz/podcast/episode-66/?t=5315) Декомпиляция и месяц с ReSharper в Rider - [1:39:43](https://apkhmv.xyz/podcast/episode-66/?t=5983) Дебаггер внутри агента - [1:52:53](https://apkhmv.xyz/podcast/episode-66/?t=6773) Enterprise и безопасность: локальные модели - [2:01:52](https://apkhmv.xyz/podcast/episode-66/?t=7312) Формальные методы: инструментация и анализы - [2:10:11](https://apkhmv.xyz/podcast/episode-66/?t=7811) Метрика успеха: бенчмарки, верифайеры и судья ### Ссылки - [veai — IDE-native AI-агент для JetBrains IDE](https://veai.ru) - [Claude Code](https://www.anthropic.com/claude-code) ## #65: AI-кисы: нейрослоп против авторского контента - Markdown: https://apkhmv.xyz/podcast/episode-65/index.md - Гости: [Дмитрий (Kisa)](https://apkhmv.xyz/people/kisa/index.md) Александр Пахомов и Дмитрий (Kisa) — автор канала о нейросетях, пришедший в вайб-кодинг из криптоиндустрии, — разбирают, как генеративный AI меняет работу автора и инженера: где проходит граница между авторским контентом и «нейрослопом», как через `Claude Code` и `Remotion` собираются YouTube-ролики, и почему картиночная ниша (включая 18+) держится на китайских open-source-моделях и локальных `ComfyUI`-воркфлоу, а не на зацензуренных фронтир-моделях. Во второй половине — теория «мёртвого интернета», выгорание от скорости агентов, деградация моделей (`4.6` против `4.7`, кодекс) и большой мотивационный разговор про ответственность и «эпоху эгоистов». ### Главное - Граница между авторским контентом и «нейрослопом» — в предпосылке: генерируешь текст/голос ради трафика (слоп) или используешь нейросеть как инструмент, оставляя авторство (сценарий, голос, вкус) за собой. - `Claude Code` — это агент, обученный управлять системой, поэтому им можно делать что угодно, а не только писать код: ролики в `Remotion` (React-кадры, которые пишет сам Claude), обложки через CSS-графику, вызов внешних image-моделей по API. - Хайп `Claude Code` в массах начался с выхода `Opus 4.5`: до него код приходилось ревьюить и направлять, после — задаёшь спецификации и архитектуру, а код и тесты модель пишет почти автономно. - 18+-генерация и провокационный контент держатся на локальных китайских open-source-моделях (`ComfyUI`-воркфлоу, Lora, `Wan`, `Seedance`, `Kling`), потому что фронтир-модели зацензурены; коммерческих open-source-моделей под баннеры/обложки при этом нет. - Теория «мёртвого интернета» (2020) сбылась: в 2026 объём AI-контента превысил человеческий — существуют сервисы, автоматизирующие и написание постов, и комментарии-реплаи ботами, чтобы привлечь живой трафик. - Скорость агентов вызывает новый тип выгорания: пятидневная задача схлопывается до 20 минут, и человек не успевает осознать, что построил, — лечится только настоящим перерывом на неделю, а не «дотягиванием лямки». - Инструкции агенту (`AGENTS.md`, память) лучше всего пишет и понимает та же модель, что их создала: markdown, написанный `Opus` под себя, хуже воспринимается `GPT`, и при смене модели инструкции приходится переписывать. - Дипфейки с политиками не взлетели, а 18+-генерация стала целой индустрией — вероятно, потому что аналитическая часть мозга сразу «палит» фейк-политика, а древняя (либидо) на сгенерированность не реагирует; секс по-прежнему продаёт. ### Главы - [00:00](https://apkhmv.xyz/podcast/episode-65/?t=0) Холодный интро: главное — не быть глупым - [01:04](https://apkhmv.xyz/podcast/episode-65/?t=64) Как Дима пришёл в вайб-кодинг из крипты - [08:07](https://apkhmv.xyz/podcast/episode-65/?t=487) Знакомство: Kisa, криптомедиа и блог про нейросети - [10:46](https://apkhmv.xyz/podcast/episode-65/?t=646) Claude как новый интерфейс: Remotion и ролики - [17:34](https://apkhmv.xyz/podcast/episode-65/?t=1054) Нейрослоп против авторского контента - [21:50](https://apkhmv.xyz/podcast/episode-65/?t=1310) Код утилитарен, а текст и голос — авторские - [27:57](https://apkhmv.xyz/podcast/episode-65/?t=1677) Теория мёртвого интернета - [31:56](https://apkhmv.xyz/podcast/episode-65/?t=1916) Что дальше: сингулярность и философия - [34:38](https://apkhmv.xyz/podcast/episode-65/?t=2078) Плыть по течению: вайб-кодинг как поток - [44:00](https://apkhmv.xyz/podcast/episode-65/?t=2640) Сон, отдых и выгорание от скорости агентов - [48:59](https://apkhmv.xyz/podcast/episode-65/?t=2939) Деградация моделей: 4.6 против 4.7 и кодекс - [1:06:17](https://apkhmv.xyz/podcast/episode-65/?t=3977) Генерация картинок и ниша 18+ - [1:18:56](https://apkhmv.xyz/podcast/episode-65/?t=4736) Дипфейки, секс и мёртвый интернет - [1:24:27](https://apkhmv.xyz/podcast/episode-65/?t=5067) Нищепанк, комплекс бога и «сахарная» аналогия - [1:31:00](https://apkhmv.xyz/podcast/episode-65/?t=5460) Нормесы, эго и гигиена работы с AI - [1:40:20](https://apkhmv.xyz/podcast/episode-65/?t=6020) Ответственность, «эпоха эгоистов» и мотивационный финал ### Ссылки - [Remotion — видео на React](https://www.remotion.dev) - [ComfyUI — нодовый интерфейс для генеративных моделей](https://github.com/comfyanonymous/ComfyUI) - [Cursor — AI-редактор кода](https://cursor.com) - [Polymarket — рынок предсказаний](https://polymarket.com) ## #64: Быстрее Кафки на два порядка: Алексей Лебедев про то как строить сложные системы - Markdown: https://apkhmv.xyz/podcast/episode-64/index.md - Гости: [Алексей Лебедев](https://apkhmv.xyz/people/alexei-lebedev/index.md) Александр Пахомов и Алексей Лебедев — инженер систем низкой задержки, создатель стриминговой платформы AlgoX2 («убийца Kafka») и открытого фреймворка кодогенерации OpenACR — разбирают, как строить большие системы из простых, доказуемо корректных частей. Первые два часа сознательно исключают «агентную разработку»: single entry / single exit и single static action, программа как вложенные циклы и глобальная in-memory база данных, отказ от исключений и многопоточности в пользу однопоточных процессов, общающихся сообщениями (CSP, RDMA/InfiniBand, scale-out). На этом фундаменте построена AlgoX2 — «файловая система из стримов», где всё есть append-only-стрим и управление идёт через тот же стриминг; она обгоняет Kafka по latency в 10–100 раз. Ядро системы генерируется из SSIM-описаний генератором, который на 95% состоит из собственного сгенерированного кода. В финале — как Claude Code усиливает такой подход и какой навык остаётся ключевым для инженера. ### Главное - Single entry / single exit (SESE) делает программу самоподобной: любой блок можно вырезать и вставить как одну строку в другой, а к каждой точке привязать инвариант в духе preconditions Дейкстры; из этого же следует запрет на исключения — `throw` есть многоуровневый `return` на неизвестно сколько уровней вверх. - Single static action: любое поле любой структуры пишется ровно в одном месте кода, поэтому весь стейт можно держать в единой глобальной in-memory-«базе данных» `db` — глобальные переменные не вредны сами по себе, вредна их модификация из разных мест. - Программы у Лебедева однопоточные; масштабирование — не потоками, а деревом процессов, общающихся только сообщениями (идея из `Communicating Sequential Processes` Хоара, наследники — каналы Go и Plan 9 / 9P). - Ставка на однопоточность оправдалась через scale-out: RDMA-карты (InfiniBand/Mellanox, теперь внутри Nvidia) пишут байт в память соседнего хоста за ~600 нс с kernel bypass и умеют multicast — «железо догонит», а latency между дата-центром и одним компьютером объяснять не нужно. - AlgoX2 — «Distributed OS», где всё есть append-only-стрим (2^64 сообщений, две операции: дописать и прочитать), а управление кластером идёт через служебный стрим `/sys/cmd`, который каждый процесс читает с нуля; Kafka по сути single-host-система, а её `topic` + `partition` — это просто стрим. - Внутренние компоненты работают с `ACK level` 1 (сообщение существует в одном экземпляре), внешние потребители — с уровнем 2–3 (реплицировано и надёжно); один и тот же механизм подписки реализует и то, и другое. - Хранение — строго append-only ради NVMe: флеш нельзя перезаписать без стирания блока (wear-leveling), при random-write включается garbage collection и производительность падает в ~100 раз; свой движок пишет и данные, и индекс в один файл (структура «Log Structured Try»). - Ядро системы задаётся `SSIM`-файлами (реляционные key-value-записи) и генерируется фреймворком OpenACR (`acr`/`amc`): на одну рукописную строку приходится ~20–25 сгенерированных, ~95% кода генерирует генератор, который сам на 95% состоит из собственного сгенерированного кода — без темплейтов, с одним breakpoint на функцию. - AlgoX2 обгоняет Kafka по latency в 10–100 раз (например 50 мкс против 5 мс) и по throughput в десятки раз под нагрузками с жёстким окном задержки; при насыщении ресурсов, где Kafka упирается в железо, преимущества нет. - Claude Code для Лебедева — «велосипед»: он написал почти весь движок, попав туда же, куда дошёл бы пешком; маленький код, делающий много, умещается в голову, а дефицитным ресурсом инженера становится время и умение решать, где углубиться, а что делегировать модели. ### Главы - [00:00](https://apkhmv.xyz/podcast/episode-64/?t=0) Вступление - [01:38](https://apkhmv.xyz/podcast/episode-64/?t=98) Single entry, single exit: программа как вложенные циклы - [13:50](https://apkhmv.xyz/podcast/episode-64/?t=830) Транспонированная модель, flowchart и самоподобность - [27:58](https://apkhmv.xyz/podcast/episode-64/?t=1678) Single static action и единая база данных стейта - [34:36](https://apkhmv.xyz/podcast/episode-64/?t=2076) Глобальные переменные, DOM и отказ от ООП - [42:49](https://apkhmv.xyz/podcast/episode-64/?t=2569) Исключения как многоуровневый return; про баги - [46:53](https://apkhmv.xyz/podcast/episode-64/?t=2813) Однопоточные процессы и Communicating Sequential Processes - [52:45](https://apkhmv.xyz/podcast/episode-64/?t=3165) HFT, InfiniBand и scale-out через RDMA - [59:31](https://apkhmv.xyz/podcast/episode-64/?t=3571) AlgoX2: всё есть стрим, /sys/cmd и Distributed OS - [1:06:03](https://apkhmv.xyz/podcast/episode-64/?t=3963) Как устроена Kafka: брокер, topic, partition, offset - [1:16:00](https://apkhmv.xyz/podcast/episode-64/?t=4560) Scale-out через multicast: latency против throughput - [1:22:38](https://apkhmv.xyz/podcast/episode-64/?t=4958) Путь записи в AlgoX2: секвенсор и ACK level - [1:28:47](https://apkhmv.xyz/podcast/episode-64/?t=5327) Commit, NVMe, wear-leveling и append-only - [1:37:58](https://apkhmv.xyz/podcast/episode-64/?t=5878) Цифры против Kafka: latency в 10–100 раз - [1:40:42](https://apkhmv.xyz/podcast/episode-64/?t=6042) Кодогенерация: OpenACR, SSIM и model-компилятор - [1:53:42](https://apkhmv.xyz/podcast/episode-64/?t=6822) Самоприменимость: Lisp REPL, self-hosting генератор - [2:13:50](https://apkhmv.xyz/podcast/episode-64/?t=8030) Возвращение в 2026: Claude Code и эта система - [2:23:29](https://apkhmv.xyz/podcast/episode-64/?t=8609) Опыт с Claude Code: «велосипед» для инженера - [2:29:57](https://apkhmv.xyz/podcast/episode-64/?t=8997) Какой навык остаётся ключевым; финал ### Ссылки - [OpenACR — фреймворк кодогенерации (acr/amc, SSIM) Алексея Лебедева](https://github.com/alexeilebedev/openacr) - [Communicating Sequential Processes — C.A.R. Hoare](https://www.cs.cmu.edu/~crary/819-f09/Hoare78.pdf) - [LevelDB — движок хранения на основе LSM (Jeff Dean, Sanjay Ghemawat)](https://github.com/google/leveldb) - [Apache Pulsar — распределённая стриминговая платформа](https://pulsar.apache.org) - [SPDK — Storage Performance Development Kit (доступ к NVMe из user space)](https://spdk.io) ## #63: Системное мышление для инженера - Markdown: https://apkhmv.xyz/podcast/episode-63/index.md - Гости: [Иван Закутний](https://apkhmv.xyz/people/ivan-zakutniy/index.md) Александр Пахомов и Иван Закутний (инженер и engineering manager, ученик мастерской инженеров-менеджеров Анатолия Левенчука) разбирают, как остаться востребованным инженером в 2026 году, когда `Claude Code` и агенты обесценили «перекладывание JSON». Их ответ — системное мышление и `First Principles Framework` (FPF) Левенчука: спецификация на ~800 тысяч токенов, которая через RAG заставляет LLM рассуждать по ADI-циклу (abduction–deduction–induction), формализовать уровни доверия L0/L1/L2 и оставлять за собой decision records. По пути — почему галлюцинируют и люди, и модели, чем задача отличается от проблемы, зачем нужно «мышление письмом» и экзокортекс, и как не свалиться в дофаминовую яму от четырёх параллельных агентов. ### Главное - Кормушка не сужается, а возвращается к норме: написание кода всегда было ~5–15% работы, а с `Claude Code` этот навык обесценился — ценность смещается к системной инженерии и менеджменту. - Узкая специализация в старом смысле (оптимизировать горячие пути, переписывать на ассемблер) ведёт к прямой конкуренции с моделями; выигрывает дженералист-инженер-менеджер, который умеет правильно делегировать. - `First Principles Framework` (FPF) Анатолия Левенчука — спецификация ~65 тысяч строк / ~800 тысяч токенов, дистиллирующая практики системного мышления в контекст для LLM; целиком в контекст не влезает. - Базовый приём FPF — ADI-цикл: `abduction` (выдвинуть гипотезы), `deduction` (проанализировать, на чём они основаны), `induction` (проверить минимальным POC/тестом); он же — ядро научного подхода. - Лучший практический способ применения FPF — не агент, а проект в `ChatGPT Pro` (Extended Thinking): туда drag-and-drop'ом кладётся Markdown-спека, индексируется под RAG, и модель начинает рассуждать по FPF даже в бытовых вопросах. - FPF формализует уровни доверия (L0 — сырая гипотеза, L1 — подтверждённая источником, L2 — проверенная) и оставляет decision records с датой и причинами — экзокортекс, к которому можно вернуться через недели. - Задача — то, что ты уже умеешь решать (замедляться не надо); проблема требует затормозить и включить «медленное мышление» по Канеману — тут и полезны FPF, TDD и BDD, а `code review` и Agile-церемонии обесцениваются. - «Мышление письмом» остаётся тренажёром собственных мозгов и маркером сильного инженера: те, кого не увольняют и зовут на работу, обычно ведут текстовый блог; голосовые интерфейсы хороши для команд, но не для моделирования. ### Главы - [00:00](https://apkhmv.xyz/podcast/episode-63/?t=0) Заходим в «виртуальный бар» - [00:35](https://apkhmv.xyz/podcast/episode-63/?t=35) Как остаться у кормушки: она не сужается - [04:29](https://apkhmv.xyz/podcast/episode-63/?t=269) Узкая специализация против конкуренции с моделями - [07:53](https://apkhmv.xyz/podcast/episode-63/?t=473) Инженеры и CEO движутся навстречу (FOMO) - [11:51](https://apkhmv.xyz/podcast/episode-63/?t=711) Системное мышление и мастерская инженеров-менеджеров - [14:56](https://apkhmv.xyz/podcast/episode-63/?t=896) Что такое FPF — First Principles Framework - [25:31](https://apkhmv.xyz/podcast/episode-63/?t=1531) ADI-цикл: abduction, deduction, induction - [30:53](https://apkhmv.xyz/podcast/episode-63/?t=1853) Задача против проблемы; когда замедляться по Канеману - [37:07](https://apkhmv.xyz/podcast/episode-63/?t=2227) Как применять FPF: проект в ChatGPT и RAG - [44:31](https://apkhmv.xyz/podcast/episode-63/?t=2671) Интеграция в Claude Code, skill-pack, Qwen Code - [53:56](https://apkhmv.xyz/podcast/episode-63/?t=3236) Прокачивать надо собственные мозги - [59:34](https://apkhmv.xyz/podcast/episode-63/?t=3574) Agile, Scrum и код-ревью на пенсию - [1:11:50](https://apkhmv.xyz/podcast/episode-63/?t=4310) Уровни доверия L0/L1/L2 и decision records - [1:20:38](https://apkhmv.xyz/podcast/episode-63/?t=4838) Дофаминовая яма и контекст-свитчинг - [1:35:45](https://apkhmv.xyz/podcast/episode-63/?t=5745) Мышление письмом, экзокортекс и личный блог - [1:47:29](https://apkhmv.xyz/podcast/episode-63/?t=6449) Moldbook, prompt injection и заключение ### Ссылки - [Гарри Поттер и методы рационального мышления — Элиезер Юдковский](https://hpmor.com/) - [Школа системного менеджмента (Анатолий Левенчук)](https://system-school.ru/) - [Блог Анатолия Левенчука (ailev)](https://ailev.livejournal.com/) ## #62: AI в Энтерпрайзе - Markdown: https://apkhmv.xyz/podcast/episode-62/index.md - Гости: [Иван Чернов](https://apkhmv.xyz/people/ivan-chernov/index.md) Александр Пахомов и Иван Чернов (системный архитектор в Островке) разбирают, как выглядит внедрение ИИ не в демках, а в реальном энтерпрайзе. Иван рассказывает про свой путь от GitHub Copilot к Cursor и Claude Code, про безопасную среду на базе LiteLLM и OpenWebUI, три риска информационной безопасности (персданные, коммерческая тайна, и почему код сам по себе ничего не стоит), токеномику и лимиты для пользователей, дообученную локальную модель для переводов, ИИ-ревьюера за 8 центов и Bitter Lesson как рамку для техно-оптимизма. Александр держит контрапункт от лица индивидуального контрибьютора, который просто заливает задачи Opus 4.5 напрямую. ### Главное - В энтерпрайзе точка контроля — прокси (`LiteLLM` + `OpenWebUI`): она регулирует бюджет, разрешённые модели и `guardrails`, позволяя гонять `Claude Code` без индивидуальной учётки Anthropic через выданный `API`-токен. - Информационная безопасность выделяет три риска работы модели на кодовой базе — персональные данные, коммерческая тайна и credentials; сам по себе код почти ничего не стоит — ценность в договорах, людях и операционке вокруг него. - Пользователям нужны жёсткие лимиты: без ограничения (по умолчанию ~$100/мес на учётку) новички за 36 часов сжигают сотни долларов — ответственность за среду несёт тот, кто её организует, а не пользователи. - Дообученная `LoRA` локальная модель для переводов интерфейса (с `self-judge` по confidence и откатом на краудсорсинг) срезала ~95% затрат и повысила среднее качество относительно краудсорса. - ИИ-ревьюер, реализованный не агентом, а прогоном диффа с задачей и контекстом, дал ~8 центов за ревью против ~$2–3 у `slash review`; ускорил мерж веток на ~10%, хотя precision около 50% и со временем появляется `alert fatigue`. - `Opus 4.5` ревьюит код лучше среднего человека и лишён негативных предубеждений; при правильно поданном контексте даже `Sonnet` даёт примерно те же замечания, что и человек, — после линтеров и тестов остаётся «сэничек здравомыслия». - Обсуждать языки программирования теперь имеет смысл не по синтаксису, а по `capabilities` (borrow checker, система типов) и тулингу — модель сама решит, как писать; TypeScript силён по скорости попадания с первого раза, Rust даёт гарантию «собралось — работает». - `Bitter Lesson`: масштаб вычислений бьёт хитрые алгоритмы, и узкое место сместилось с людей на деньги — грамотную команду инженеров всё чаще заменяют время и бюджет на токены и GPU. ### Главы - [00:00](https://apkhmv.xyz/podcast/episode-62/?t=0) Клауд-бот как личный ассистент - [00:41](https://apkhmv.xyz/podcast/episode-62/?t=41) Prompt injection и история OpenClaw - [02:43](https://apkhmv.xyz/podcast/episode-62/?t=163) Agent Swarm и автоматизация менеджмента - [08:11](https://apkhmv.xyz/podcast/episode-62/?t=491) GLM 4.7, дешёвые подписки и токеномика - [12:49](https://apkhmv.xyz/podcast/episode-62/?t=769) Кризис селекции: будущее наступило неравномерно - [15:19](https://apkhmv.xyz/podcast/episode-62/?t=919) Где юникорны и новые продукты? - [18:44](https://apkhmv.xyz/podcast/episode-62/?t=1124) iOS/Android и end-to-end тест как definition of done - [23:56](https://apkhmv.xyz/podcast/episode-62/?t=1436) Philosophy of Software Design и глубокие интерфейсы - [28:52](https://apkhmv.xyz/podcast/episode-62/?t=1732) Подписки за $200 и кто за них платит - [30:38](https://apkhmv.xyz/podcast/episode-62/?t=1838) Enterprise: как внедряли ИИ в Островке - [37:18](https://apkhmv.xyz/podcast/episode-62/?t=2238) Три риска безопасности: код ничего не стоит - [43:57](https://apkhmv.xyz/podcast/episode-62/?t=2637) Claude разблокировал среду: стек LiteLLM + OpenWebUI - [49:47](https://apkhmv.xyz/podcast/episode-62/?t=2987) Langfuse, трейсинг промптов и гардрейлы - [59:03](https://apkhmv.xyz/podcast/episode-62/?t=3543) Какие модели используют power users - [1:08:56](https://apkhmv.xyz/podcast/episode-62/?t=4136) Системные аналитики, легаси и цифровой бункер - [1:15:21](https://apkhmv.xyz/podcast/episode-62/?t=4521) Совет слушателям ### Ссылки - [The Bitter Lesson — Rich Sutton (2019)](http://www.incompleteideas.net/IncIdeas/BitterLesson.html) - [A Philosophy of Software Design — John Ousterhout](https://web.stanford.edu/~ouster/cgi-bin/aphilosophyofsoftwaredesign.php) - [LiteLLM — прокси для LLM](https://www.litellm.ai) - [Open WebUI](https://openwebui.com) - [Langfuse — трейсинг и телеметрия LLM](https://langfuse.com) - [Amazon Bedrock](https://aws.amazon.com/bedrock/) - [Ostrovok.ru](https://ostrovok.ru) ## #61: Лучший GC: Java и Go - Markdown: https://apkhmv.xyz/podcast/episode-61/index.md - Гости: [Александр Ланцов](https://apkhmv.xyz/people/alexander-lantsov/index.md) Александр Пахомов и Александр «Саша» Ланцов (Java-разработчик в финтехе, Мир Plat.Form) на примере двух рантаймов — HotSpot JVM и Go — прослеживают всю эволюцию сборщиков мусора: от фундаментальных алгоритмов (reference counting, mark-and-sweep, mark-compact, копирующий) и трёхцветной маркировки до `Serial`/`Parallel`, `CMS`, `G1`, `Shenandoah`, `ZGC` и нового `Green Tea` в Go. По пути — гипотеза о поколениях и почему её нет в Go, card table и GC-барьеры, фрагментация и спаны, указатели Брукса, цветные указатели и трюк с виртуальной памятью, спираль смерти. В финале — как осознанно выбрать GC под latency, пропускную способность и размер хипа. ### Главное - Трассирующие сборщики мусора ищут не мусор, а живые объекты: стоимость маркировки пропорциональна количеству достижимых объектов, а не общему размеру хипа. - `Mark-and-Sweep` прост и не двигает объекты (указатели не инвалидируются), но страдает от фрагментации; `Mark-Compact` и копирующий коллектор её решают ценой переноса объектов и позволяют дешёвую аллокацию через bumping pointer. - Гипотеза о поколениях работает только вместе с card table и write-барьером, отслеживающими редкие ссылки из старого поколения в молодое; в Go её нет, потому что escape-анализ и структуры уводят большинство короткоживущих объектов на стек. - Конкурентная маркировка требует барьеров: `SATB` (snapshot-at-the-beginning) ловит запись ссылки из чёрного объекта в белый и перекрашивает, сохраняя инвариант; барьеры дешевы за счёт цепочки ранних `if`. - `CMS` давал конкурентную маркировку, но без дефрагментации накапливал фрагментацию и падал в однопоточный `Full GC` с `Mark-Compact`; `G1` разбивает хип на регионы с remembered set и регулирует паузу, выбирая, сколько регионов собрать (garbage first). - `Shenandoah` сначала защищал перенос указателями Брукса (лишний указатель раздувал объект), в версии 2.0 переехал в `mark word`; поддерживает сжатые указатели, поэтому хорош для небольших хипов с низким latency. - `ZGC` хранит цвет прямо в 64-битном указателе и умеет переносить объекты силами мутаторов; из-за этого не поддерживает сжатые указатели, зато проектировался под гигантские хипы; трюк с мульти-маппингом виртуальной памяти из версии 1.0 в версии 2.0 убрали. - Единого «лучшего» GC нет: `Parallel` — под пропускную способность (Spark), `ZGC`/`Shenandoah` — под низкий latency, `G1` — гибрид и дефолт в Java; выбор нужно проверять профилированием на своей нагрузке, а не «астрологией». ### Главы - [00:00](https://apkhmv.xyz/podcast/episode-61/?t=0) Вступление: два рантайма — Java и Go - [06:03](https://apkhmv.xyz/podcast/episode-61/?t=363) Зачем это знать: собеседования и low-latency - [08:56](https://apkhmv.xyz/podcast/episode-61/?t=536) Фундамент: reference counting и трассирующие сборщики - [14:19](https://apkhmv.xyz/podcast/episode-61/?t=859) Маркировка и трёхцветный алгоритм - [22:56](https://apkhmv.xyz/podcast/episode-61/?t=1376) Mark and Sweep и фрагментация - [31:02](https://apkhmv.xyz/podcast/episode-61/?t=1862) Mark-Compact и копирующий коллектор - [46:14](https://apkhmv.xyz/podcast/episode-61/?t=2774) GC нужно место «дышать»: спираль смерти - [52:42](https://apkhmv.xyz/podcast/episode-61/?t=3162) Гипотеза о поколениях, card table и барьеры - [1:05:20](https://apkhmv.xyz/podcast/episode-61/?t=3920) Serial и Parallel GC в Java - [1:14:11](https://apkhmv.xyz/podcast/episode-61/?t=4451) Древний Go: спаны и классы размеров - [1:26:00](https://apkhmv.xyz/podcast/episode-61/?t=5160) Частично конкурентные сборщики и барьеры - [1:36:36](https://apkhmv.xyz/podcast/episode-61/?t=5796) Конкурентный Go и отказ от поколений - [1:43:20](https://apkhmv.xyz/podcast/episode-61/?t=6200) G1: регионы и remembered set - [1:55:39](https://apkhmv.xyz/podcast/episode-61/?t=6939) Shenandoah и указатели Брукса - [2:04:11](https://apkhmv.xyz/podcast/episode-61/?t=7451) ZGC: цветные указатели и виртуальная память - [2:23:32](https://apkhmv.xyz/podcast/episode-61/?t=8612) Green Tea в Go: маркировка спанов - [2:27:15](https://apkhmv.xyz/podcast/episode-61/?t=8835) Итоги: компактизация, поколения, выбор в Java и Go - [2:32:11](https://apkhmv.xyz/podcast/episode-61/?t=9131) Как выбрать GC под свою задачу - [2:47:39](https://apkhmv.xyz/podcast/episode-61/?t=10059) Заключение и где копнуть глубже ### Ссылки - [The Garbage Collection Handbook](https://gchandbook.org) - [The Green Tea Garbage Collector — блог Go](https://go.dev/blog/greenteagc) - [HotSpot JVM GC options cheat sheet — блог Алексея Рагозина](http://blog.ragozin.info/2011/09/hotspot-jvm-garbage-collection-options.html) - [TCMalloc — аллокатор от Google](https://github.com/google/tcmalloc) - [The Pragmatic Programmer, 20th Anniversary Edition](https://pragprog.com/titles/tpp20/the-pragmatic-programmer-20th-anniversary-edition/) ## #60: Claude Code и инженерная ответственность с Senior Software Vlogger - Markdown: https://apkhmv.xyz/podcast/episode-60/index.md - Гости: [Дмитрий Рожков](https://apkhmv.xyz/people/dmitry-rozhkov/index.md) Александр Пахомов и Дмитрий Рожков (менеджер и автор YouTube-канала «Senior Software Vlogger») разбирают, как `Claude Code` меняет работу инженера: Дмитрий, будучи менеджером и не Swift-программистом, полностью написал моделями Mac-приложение `Summit AI Notes` и продаёт его в App Store. Отсюда разговор уходит к главному тезису выпуска — «инженерной ответственности»: за код, который сгенерировала модель, отвечает не Anthropic, а инженер. По пути — почему важен строгий `harness` вокруг модели, чем `Opus 4.5` лучше `Sonnet 4`, почему классическое код-ревью упирается в бутылочное горлышко по Голдратту и как программирование с LLM превращается в менеджмент. ### Главное - Инженерная ответственность — ключевой тезис выпуска: Anthropic нельзя привлечь за плохой pull-request, а инженера можно, поэтому теперь ты отвечаешь не за свой код, а за код, который сгенерировала модель. - Менеджер, не будучи Swift-программистом, полностью написал моделями (`Claude Code`, `Gemini CLI`, `Codex`) Mac-приложение `Summit AI Notes` на ~50 тысяч строк Swift, продаёт его в App Store, и за всё время у приложения лишь два crash-репорта. - Качество сгенерированного кода на незнакомом стеке оценивается как чёрный ящик — работает, не течёт по памяти и CPU, проходит строгий линтер — а не построчным чтением; для Swift-приложения помогает и то, что компилятор сам себя верифицирует. - Модель по умолчанию срезает углы там же, где люди: не пишет тесты, валит всё в один файл без архитектуры — поэтому решают строгий `harness` (форматтер, самый строгий линтер, правила в `CLAUDE.md`) и сеньорское мышление, а не «сделай красиво». - `Opus 4.5` для многих стал водоразделом: он реже, чем `Sonnet 4`, ходит кругами и сам понимает, когда надо подумать, — то, что раньше приходилось вымучивать (запись двух аудиопотоков через `ScreenCaptureKit`), решается быстрее. - Классическое код-ревью умирает: под лавиной сгенерированных pull-request'ов оно становится бутылочным горлышком по Голдратту («Цель»), а три его функции — обмен знаниями, менторинг и ловля багов — можно раздать отдельным агентам (по требованиям, security, перформансу). - Программирование с LLM по сути превращается в менеджмент, только с быстрыми итерациями и без коммуникации с людьми; главное, чего не хватает агентам, — агентности и самостоятельного принятия решений, и именно этим человек их дополняет. - Инженерная ответственность требует не меньше, а больше: программировать надо лучше, чем раньше, проверять — ещё больше, потому что за два дня плотного кодирования с LLM создаётся объём контекста, который раньше нарастал два месяца. ### Главы - [00:00](https://apkhmv.xyz/podcast/episode-60/?t=0) Холодный старт: инженерная ответственность - [00:39](https://apkhmv.xyz/podcast/episode-60/?t=39) Summit AI Notes: локальная запись звонков на Mac - [03:06](https://apkhmv.xyz/podcast/episode-60/?t=186) Из Swift-любителя в менеджеры, а код пишет Claude - [05:15](https://apkhmv.xyz/podcast/episode-60/?t=315) Реальный продукт: продажи, установки, crash-репорты - [10:00](https://apkhmv.xyz/podcast/episode-60/?t=600) Почему Swift: мало open source, но выборка качественнее - [11:38](https://apkhmv.xyz/podcast/episode-60/?t=698) Оценка кода как чёрного ящика и ревью синьором - [17:37](https://apkhmv.xyz/podcast/episode-60/?t=1057) Sonnet 4 против Opus 4.5 и борьба со ScreenCaptureKit - [30:30](https://apkhmv.xyz/podcast/episode-60/?t=1830) Harness, срезание углов и контекст перед глазами - [36:44](https://apkhmv.xyz/podcast/episode-60/?t=2204) Мигающие курсоры, циклы и вайб-кодинг по Карпати - [43:55](https://apkhmv.xyz/podcast/episode-60/?t=2635) Менеджерская оптика и инженерная ответственность - [53:16](https://apkhmv.xyz/podcast/episode-60/?t=3196) Смерть код-ревью: Голдратт, bottleneck и мультиагенты - [1:07:20](https://apkhmv.xyz/podcast/episode-60/?t=4040) Конкретные тулы: Claude Code, Qoder, Cursor, голос - [1:14:00](https://apkhmv.xyz/podcast/episode-60/?t=4440) Заключение: относитесь к модели как к джуниору ### Ссылки - [Senior Software Vlogger — YouTube-канал Дмитрия Рожкова](https://www.youtube.com/@SeniorSoftwareVlogger) ## #59: Основы Web3: Blockchain и Ether - Markdown: https://apkhmv.xyz/podcast/episode-59/index.md - Гости: [Дима Королёв](https://apkhmv.xyz/people/dima-korolev/index.md) Александр Пахомов и Дима Королёв (инженер, несколько лет в Web3) разбирают блокчейн и Ethereum инженерным языком — без маркетингового буллшита. Как биткоин Сатоши стал первым leaderless-леджером с инвариантом no double spend через `proof of work`; почему у биткоина нет финалити, а балансы — это derived-вьюха поверх лога блоков; как Ethereum добавил EVM, смарт-контракты и `ERC-20`, а `proof of stake`, валидаторы со стейком и L2-шардинг сделали транзакции дешёвыми. Попутно — MEV-атаки, мосты и `WBTC`, CAP-теорема через partial order и аналогию с Kafka, DEX против CEX, и как идеи Web3 (доказуемые гарантии, secure chip, confidential compute) просачиваются в Web2. ### Главное - Биткоин — первая самоподдерживающаяся система, распределяющая ценность без доверия между участниками; её главный инвариант — no double spend (нельзя потратить больше, чем есть). - `Satoshi consensus` (он же `proof of work`) устроен так, что всем майнерам выгодно достраивать одну самую длинную цепь: максимальный reward получает тот, кого принял majority сети, а не тот, кто «первый» — физического времени в сети нет, только логическое. - У биткоина нет финалити: состояние вероятностно, и теоретически историю можно переписать — но каждый новый блок стоит астрономических вычислений, поэтому после ~5 блоков перезапись практически невозможна. - Балансы в леджере биткоина не хранятся — хранится лог блоков с транзакциями, а таблица балансов это derived materialized-вьюха; атака `50% + 1` даёт контроль заморозить/цензурировать транзакции, но не украсть чужие токены (нет валидной подписи). - Ethereum добавил EVM и смарт-контракты на `Solidity` с `gas fees`: правила зашиты не в протокол, а в код; стандарт `ERC-20` позволил хранить ненативные токены на леджере эфира и запустил DeFi (лендинг под `collateral`, `WBTC`, стейблкоины). - `Proof of stake` заменяет гонку всех майнеров на псевдослучайно выбранный небольшой набор валидаторов со «золочённым» стейком (слэшинг за читерство); это дёшево, но финалити всё ещё вероятностная — чекпоинт в эфире наступает примерно раз в полчаса. - L1-сети (`proof of work` Bitcoin, `proof of stake` Ethereum) дают total order и потому медленные и дорогие; L2 — это шардинг на независимые партиции (аналог партиций в Kafka) с периодическим settlement в L1, что роняет стоимость транзакции до десятков центов. - Идеи Web3 просачиваются в Web2: доказуемые криптографические гарантии вместо голого доверия провайдеру, `secure chip`/passkey в каждом устройстве и confidential compute (докер-образ на secure-чипе в облаке с подписью вендора) — движение к системам с меньшим baseline-доверием. ### Главы - [00:00](https://apkhmv.xyz/podcast/episode-59/?t=0) Вступление: блокчейн и эфир инженерным языком - [00:45](https://apkhmv.xyz/podcast/episode-59/?t=45) Что такое Web3: от Сатоши к сети без доверия - [04:12](https://apkhmv.xyz/podcast/episode-59/?t=252) Биткоин — не первая сеть: торренты и e-mail - [08:52](https://apkhmv.xyz/podcast/episode-59/?t=532) Как поднять ноду и Satoshi consensus - [10:45](https://apkhmv.xyz/podcast/episode-59/?t=645) У биткоина нет финалити - [16:19](https://apkhmv.xyz/podcast/episode-59/?t=979) Proof of work изнутри: хэши, mempool и MEV - [20:54](https://apkhmv.xyz/podcast/episode-59/?t=1254) Минусы биткоина: цена и доверие - [25:54](https://apkhmv.xyz/podcast/episode-59/?t=1554) Эфир: EVM, смарт-контракты и gas - [31:34](https://apkhmv.xyz/podcast/episode-59/?t=1894) DeFi: WBTC, залог и заём - [38:31](https://apkhmv.xyz/podcast/episode-59/?t=2311) Proof of stake, валидаторы и слэшинг - [46:41](https://apkhmv.xyz/podcast/episode-59/?t=2801) L1/L2, CAP-теорема и partial order - [50:09](https://apkhmv.xyz/podcast/episode-59/?t=3009) Шардинг L2 и settlement в L1 - [1:03:29](https://apkhmv.xyz/podcast/episode-59/?t=3809) Биллинг, ордербуки и трейдинг - [1:08:36](https://apkhmv.xyz/podcast/episode-59/?t=4116) DEX против CEX и кастомные сети - [1:13:39](https://apkhmv.xyz/podcast/episode-59/?t=4419) Как эфир катит апдейты; минусы эфира - [1:18:54](https://apkhmv.xyz/podcast/episode-59/?t=4734) Web3 влияет на Web2: secure chip и confidential compute - [1:29:58](https://apkhmv.xyz/podcast/episode-59/?t=5398) Совет слушателям и Stateful Compute ### Ссылки - [Stateful Compute — Substack Димы Королёва](https://dimakorolev.substack.com/p/stateful-compute) - [Substrate — фреймворк для блокчейнов (Polkadot SDK)](https://substrate.io) - [«Designing Data-Intensive Applications», Martin Kleppmann](https://dataintensive.net) - [Telegram-канал подкаста «Тысяча фичей»](https://t.me/tfeat) ## #58: Apache Cassandra, часть 3: читаем данные - Markdown: https://apkhmv.xyz/podcast/episode-58/index.md - Гости: [Дмитрий Константинов](https://apkhmv.xyz/people/dmitry-konstantinov/index.md) Заключительная, третья часть разбора Apache Cassandra: Александр Пахомов и Дмитрий Константинов (коммитер Apache Cassandra) прослеживают путь запроса на чтение от координатора до диска. По дороге — какие чтения Cassandra делает эффективно (по `partition`- и префиксу `clustering`-ключа) и почему это OLTP-, а не аналитическая база; кворумная математика `R + W > N` и `strong consistency`; выбор реплик через `Snitch`, спекулятивные ретраи и оптимизация «данные с одной реплики, digest с остальных»; `read-repair` и пагинация без `OFFSET`; а на нижнем уровне — `Bloom filter`, `primary index` с `index summary`, `key cache`, блочное сжатие с `compression metadata`, вынос метаданных в off-heap и, наконец, боль tombstones при чтении «очередей». ### Главное - API драйвера для чтения и записи одинаковый (те же `PreparedStatement`/`BoundStatement`); разница лишь в обработке результата — при чтении данные текут обратно от сервера, и почти всегда работает пагинация. - Cassandra — OLTP-, а не аналитическая база: эффективны чтения по полному `partition`-ключу плюс диапазону или префиксу `clustering`-ключа; запрос без полного `partition`-ключа вырождается в full scan по всем нодам, потому что хэш от части ключа не связан с хэшом целого. - Кворумное чтение опирается на неравенство `R + W > N`: если множество ответивших на запись реплик пересекается с множеством читаемых хотя бы в одной ноде, чтение увидит последнюю запись (в терминах Cassandra — `strong consistency`); `replication factor` при этом отвечает за долговечность, а не за консистентность. - Координатор выбирает реплики через `Snitch` (по умолчанию dynamic snitch — по медиане времени ответа), но такая обратная связь может входить в автоколебания; поэтому иногда выгоднее слать запрос сразу во все реплики ради предсказуемой нагрузки. - Голосования между репликами нет: ответы сливаются по «последний по таймстемпу побеждает»; в оптимизации Cassandra запрашивает полные данные лишь с одной (обычно локальной) реплики, а с остальных — `MD5`-digest, и сравнивает хэши (это ~3% CPU из-за неудачно выбранного `MD5`). - `read-repair`: если при чтении данные на репликах разошлись, координатор не только вернёт клиенту актуальную версию, но и запишет её обратно на устаревшие реплики — то есть чтение может породить запись. - Пагинация в Cassandra — только «вперёд» через закладку (курсор в партиции), без `OFFSET`/прыжков на произвольную страницу; консистентность гарантируется лишь в пределах одной страницы, а не всего запроса. - На чтении Cassandra отбрасывает лишние `SSTable` по min/max ключам и `Bloom filter`, находит позицию через `primary index` + `index summary` в памяти и `key cache`, а данные хранит блоками под сжатием (`LZ4` по умолчанию, `ZSTD`), что требует отдельного `compression metadata` для маппинга смещений. ### Главы - [00:00](https://apkhmv.xyz/podcast/episode-58/?t=0) Вступление: часть 3, читаем данные - [00:33](https://apkhmv.xyz/podcast/episode-58/?t=33) Краткий пересказ частей 1 и 2 - [06:15](https://apkhmv.xyz/podcast/episode-58/?t=375) Виды чтений: partition- и clustering-ключи - [14:57](https://apkhmv.xyz/podcast/episode-58/?t=897) Полное сканирование, DSBulk и токены - [21:14](https://apkhmv.xyz/podcast/episode-58/?t=1274) Координатор чтения и маскирование колонок - [26:42](https://apkhmv.xyz/podcast/episode-58/?t=1602) Consistency level и кворумная математика - [39:38](https://apkhmv.xyz/podcast/episode-58/?t=2378) Выбор реплик и Snitch - [50:02](https://apkhmv.xyz/podcast/episode-58/?t=3002) Спекулятивные ретраи и чтение со всех реплик - [58:49](https://apkhmv.xyz/podcast/episode-58/?t=3529) Слияние ответов: digest вместо данных - [1:08:52](https://apkhmv.xyz/podcast/episode-58/?t=4132) Read-repair: чтение чинит реплики - [1:12:44](https://apkhmv.xyz/podcast/episode-58/?t=4364) Пагинация и её особенности - [1:24:09](https://apkhmv.xyz/podcast/episode-58/?t=5049) Локальное чтение: memtable и SSTable - [1:31:31](https://apkhmv.xyz/podcast/episode-58/?t=5491) Bloom filter - [1:42:49](https://apkhmv.xyz/podcast/episode-58/?t=6169) Primary index, index summary и key cache - [1:54:54](https://apkhmv.xyz/podcast/episode-58/?t=6894) Сжатие и compression metadata - [2:06:05](https://apkhmv.xyz/podcast/episode-58/?t=7565) Off-heap, unsafe и эволюция JVM - [2:14:52](https://apkhmv.xyz/podcast/episode-58/?t=8092) Tombstones и антипаттерн очереди - [2:18:36](https://apkhmv.xyz/podcast/episode-58/?t=8316) Что осталось за кадром: LWT, Accord, SAI - [2:26:36](https://apkhmv.xyz/podcast/episode-58/?t=8796) Совет напоследок: затюньте, чтобы понять ### Ссылки - [Apache Cassandra](https://cassandra.apache.org) - [DataStax Bulk Loader (DSBulk)](https://github.com/datastax/dsbulk) - [Caffeine — кэш-библиотека для Java](https://github.com/ben-manes/caffeine) - [Amazon Corretto Crypto Provider](https://github.com/corretto/amazon-corretto-crypto-provider) - [Zstandard (ZSTD)](https://github.com/facebook/zstd) - [Accord — распределённые транзакции для Cassandra (CEP-15)](https://cwiki.apache.org/confluence/display/CASSANDRA/CEP-15%3A+General+Purpose+Transactions) ## #57: Apache Cassandra, часть 2: как работает запись - Markdown: https://apkhmv.xyz/podcast/episode-57/index.md - Гости: [Дмитрий Константинов](https://apkhmv.xyz/people/dmitry-konstantinov/index.md) Вторая часть разбора Apache Cassandra: Александр Пахомов и Дмитрий Константинов (коммитер Apache Cassandra) прослеживают путь одной операции записи от серверного сокета до диска. По дороге — серверный `Netty` с нативным `epoll`, flow control через TCP backpressure, аутентификация и авторизация, consistent hashing с виртуальными нодами, consistency level и кворумы, gossip-протокол и hinted handoff, а затем локальная запись: `commit log`, трёхуровневый memtable (`ConcurrentSkipListMap`/trie над `B-tree`), «last write wins» по таймстемпам, сброс в `SSTable`, компакция и, наконец, удаления через tombstones. ### Главное - Серверная сторона Cassandra на `Netty` симметрична клиентской и умеет включать нативный транспорт (`epoll` на Linux, `BoringSSL` для TLS) простой подкладкой JAR в classpath — прирост порядка 10–15% «за бесплатно». - Flow control на входе Cassandra ограничивает не число in-flight запросов, а их суммарный размер в байтах (по умолчанию ~10% от хипа); при перегрузке чаще всего просто перестаёт читать из сокета, опираясь на TCP backpressure. - Cassandra шардирует данные через consistent hashing: `Murmur3`-хэш ключа кладётся на кольцо, реплики находятся бинарным поиском по кольцу, а виртуальные ноды (`vnodes`) выравнивают распределение при добавлении/удалении нод. - `consistency level` (`ONE`, `QUORUM`, `LOCAL_QUORUM`, `ALL`, `ANY`) — параметр запроса, задающий число ответивших реплик; он двигает систему по CAP-треугольнику между доступностью и консистентностью. - Живость нод Cassandra отслеживает gossip — эпидемический протокол: нода шлёт heartbeat в seed-ноду и несколько случайных, и информация о `membership` расходится по кластеру, как инфекция. - Запись на реплике сначала идёт в `commit log`, но по умолчанию `fsync` не синхронный (раз в ~10 секунд) — Cassandra меняет надёжность одной ноды на скорость, полагаясь на репликацию; включение синхронного `fsync` роняет производительность примерно на порядок. - Memtable — это трёхуровневая структура «мапа мап»: `ConcurrentSkipListMap` или trie по partition-ключу, персистентное `B-tree` по clustering-ключу и `B-tree` по колонкам; слияние идёт по правилу «побеждает больший таймстемп», поэтому в Cassandra критична синхронизация часов клиентов. - Удаление в LSM — это вставка `tombstone` (могильной плиты) с таймстемпом; выкинуть его при компакции безопасно, только доказав отсутствие «затенённых» записей — по min/max таймстемпам и ключам SSTable и через `Bloom filter`, иначе старые данные воскресают. ### Главы - [00:00](https://apkhmv.xyz/podcast/episode-57/?t=0) Вступление: часть 2, погружаемся в сервер - [00:39](https://apkhmv.xyz/podcast/episode-57/?t=39) Серверный Netty и нативный транспорт - [08:59](https://apkhmv.xyz/podcast/episode-57/?t=539) Flow control: rate limiting и TCP backpressure - [23:37](https://apkhmv.xyz/podcast/episode-57/?t=1417) Обработка запроса: парсинг и авторизация - [29:52](https://apkhmv.xyz/podcast/episode-57/?t=1792) Координатор и задача шардирования - [39:48](https://apkhmv.xyz/podcast/episode-57/?t=2388) Consistent hashing, кольцо и виртуальные ноды - [55:29](https://apkhmv.xyz/podcast/episode-57/?t=3329) Consistency level и кворумы - [1:02:29](https://apkhmv.xyz/podcast/episode-57/?t=3749) CAP-треугольник и толерантность к отказам - [1:11:05](https://apkhmv.xyz/podcast/episode-57/?t=4265) Gossip, seed-ноды и определение живости - [1:22:16](https://apkhmv.xyz/podcast/episode-57/?t=4936) Мёртвые реплики и hinted handoff - [1:33:39](https://apkhmv.xyz/podcast/episode-57/?t=5619) Локальная запись: commit log и fsync - [1:54:33](https://apkhmv.xyz/podcast/episode-57/?t=6873) Memtable: мапа мап, trie и B-деревья - [2:09:50](https://apkhmv.xyz/podcast/episode-57/?t=7790) SSTable, сброс на диск и компакция - [2:14:39](https://apkhmv.xyz/podcast/episode-57/?t=8079) Удаление: tombstones и shadowing - [2:26:34](https://apkhmv.xyz/podcast/episode-57/?t=8794) Tombstones и консистентность реплик - [2:29:53](https://apkhmv.xyz/podcast/episode-57/?t=8993) Итог, книги и анонс третьей части ### Ссылки - [Apache Cassandra](https://cassandra.apache.org) - [Netty — асинхронный сетевой фреймворк](https://netty.io) - [Caffeine — кэш-библиотека для Java](https://github.com/ben-manes/caffeine) - [Wireshark](https://www.wireshark.org) - [«Designing Data-Intensive Applications», Martin Kleppmann](https://dataintensive.net) - [«Database Internals», Alex Petrov](https://www.databass.dev) ## #56: Apache Cassandra, часть 1: клиент, сервер - Markdown: https://apkhmv.xyz/podcast/episode-56/index.md - Гости: [Дмитрий Константинов](https://apkhmv.xyz/people/dmitry-konstantinov/index.md) Александр Пахомов и Дмитрий Константинов (коммитер Apache Cassandra) проходят путь запроса end-to-end со стороны клиента: как устроен драйвер Cassandra и как, поняв его, написать собственный. Разбирают contact points и service discovery, равноправные ноды и rolling upgrade, CQL и модель данных (keyspace, partition/clustering ключи, upsert без чтения), prepared statement с кэшем на сервере, кодеки-сериализацию, выбор ноды и локальность дата-центров, а на нижнем уровне — бинарный протокол поверх Netty: нарезку TCP-потока на фреймы, корреляцию ответов через stream id, таймауты на hash wheel timer, идемпотентные и спекулятивные ретраи, backpressure. Это первая часть трилогии; серверная сторона — в следующих выпусках. ### Главное - Cassandra — кластер равноправных нод без выделенного лидера: клиенту дают `contact points`, а полный список адресов драйвер вытягивает из служебных таблиц `system.local`/`system.peers` — это встроенный service discovery. - Модель данных задаётся на этапе `CREATE TABLE`: обязательный `PARTITION KEY` определяет шардирование (все строки одного ключа лежат вместе), а опциональный `CLUSTERING KEY` задаёт порядок внутри партиции — по сути двухуровневая распределённая хэш-таблица. - `INSERT` и `UPDATE` в Cassandra — это один и тот же upsert без чтения предыдущего значения (`read-before-write` отсутствует), поэтому нет `UNIQUE`-констрейнтов, зато запись быстрая и почти всегда идемпотентная. - `PREPARED STATEMENT` кэшируется на конкретной ноде под `MD5`-хэшем запроса; репликации нет — если нода не знает id, драйвер обязан переподготовить запрос, а сервер держит кэш ограниченного размера (Caffeine). - Драйвер выбирает ноду стратегией `load balancing policy`: отсекает мёртвые и удалённые дата-центры, предпочитает локальный DC и реплики партиции, учитывает загрузку и даже uptime ноды (JVM-прогрев). - Бинарный протокол работает поверх Netty: TCP — это поток, который надо res* нарезать на фреймы по длине из хедера; ответы коррелируются с запросами через `stream id`, что позволяет держать десятки тысяч запросов in-flight на одно соединение. - Таймауты реализованы через `hash wheel timer` — кольцевой массив-«циферблат» с хэшированием по остатку от деления, дешёвый на постановку и отмену тысяч одноразовых таймеров. - Идемпотентные запросы драйвер может ретраить; поверх обычных ретраев есть спекулятивные (hedged) запросы — по 90-му перцентилю латентности драйвер шлёт дубль в другую ноду и берёт ответ того, кто ответит первым, снижая хвостовые задержки. ### Главы - [00:00](https://apkhmv.xyz/podcast/episode-56/?t=0) Вступление: сквозной путь запроса в Cassandra - [02:00](https://apkhmv.xyz/podcast/episode-56/?t=120) Клиент-серверная модель и языковые драйверы - [05:47](https://apkhmv.xyz/podcast/episode-56/?t=347) Contact points: подключение к распределённому кластеру - [15:59](https://apkhmv.xyz/podcast/episode-56/?t=959) Равноправные ноды и rolling upgrade - [20:31](https://apkhmv.xyz/podcast/episode-56/?t=1231) Аутентификация и TLS - [32:36](https://apkhmv.xyz/podcast/episode-56/?t=1956) CQL, keyspace и создание таблицы - [41:52](https://apkhmv.xyz/podcast/episode-56/?t=2512) Primary, partition и clustering ключи - [49:53](https://apkhmv.xyz/podcast/episode-56/?t=2993) Upsert и три вида statement - [59:41](https://apkhmv.xyz/podcast/episode-56/?t=3581) Prepared statement, MD5-хэш и кэш - [1:15:58](https://apkhmv.xyz/podcast/episode-56/?t=4558) Кодеки: сериализация Java-объектов в байты - [1:30:42](https://apkhmv.xyz/podcast/episode-56/?t=5442) Дата-центры, локальность и выбор ноды - [1:49:00](https://apkhmv.xyz/podcast/episode-56/?t=6540) Протокол, хедеры и нарезка TCP-потока - [2:03:28](https://apkhmv.xyz/podcast/episode-56/?t=7408) Корреляция запросов и ответов: stream id - [2:13:19](https://apkhmv.xyz/podcast/episode-56/?t=7999) Таймауты и hash wheel timer - [2:27:34](https://apkhmv.xyz/podcast/episode-56/?t=8854) Ретраи, идемпотентность и спекулятивные запросы - [2:37:11](https://apkhmv.xyz/podcast/episode-56/?t=9431) Backpressure, rate limiting и итоги ### Ссылки - [Apache Cassandra](https://cassandra.apache.org) - [Netty — асинхронный сетевой фреймворк](https://netty.io) - [Caffeine — кэш-библиотека для Java](https://github.com/ben-manes/caffeine) - [ANTLR — генератор парсеров](https://www.antlr.org) - [Google SRE Book (глава про hedged requests)](https://sre.google/sre-book/table-of-contents/) ## #55: Как мыслит предприниматель - Markdown: https://apkhmv.xyz/podcast/episode-55/index.md - Гости: [Вова](https://apkhmv.xyz/people/vova/index.md) Александр Пахомов и Вова — основатель компании Unison и продукта yuchat, с которым Александр работает больше четырёх лет, — разбирают, как мыслит предприниматель: почему работа должна давать не только «плюшки», но и рост, зачем нанимать «под человека», а не «под вакансию», и что такое ламповый «социум», который плохо масштабируется. Во второй половине — про инструменты для живого удалённого общения (спонтанная коммуникация как в open space, возможность догнать пропущенный созвон на скорости), про вкус и креатив в профессии и про новую реальность, в которой всё труднее доверять коду и контенту, сгенерированному ИИ. ### Главное - Работа — большая часть жизни, поэтому «плюшек» (массажные кресла, психолог в офисе, завтраки) недостаточно: по пирамиде потребностей они внизу, а сверху человеку нужно понимать, к чему он растёт. - Выгорание — это потеря мотивации; личный рецепт против него — всегда держать следующую, чуть более высокую цель, чтобы мотивация не заканчивалась. - Главное требование к junior-специалисту — быть «оголтелым»: думать головой и искренне вовлекаться, а не присылать сгенерированный `буллшит` ради скорости. - Новый и ещё несформированный навык — фильтровать колоссальный поток информации и отделять важное; молодому поколению это даётся тяжелее, потому что объём растёт почти экспоненциально. - Ламповый «социум» единомышленников имеет ограниченную ёмкость (десятки-сотни, не тысячи) и плохо масштабируется — в большом enterprise ценности, спускаемые сверху вниз, обычно не работают. - Правильный найм — искать человека, с которым можешь работать, а не «закрывать вакансию под требования»; человеку нужно время присмотреться, в той ли он культуре. - Спонтанность и «услышать» разговор коллег важнее расписания: креатив и брейншторминг по календарю не букаются, а слух вовлекает, не перегружая и без того занятое зрение. - Удобство решает: если догнать пропущенный созвон неудобно (почта → Google Drive → плеер), этого просто не произойдёт; маленький шаг вроде прослушивания записи на `X2` разблокирует целую рабочую практику. ### Главы - [00:28](https://apkhmv.xyz/podcast/episode-55/?t=28) Вступление: кто такой Вова - [02:26](https://apkhmv.xyz/podcast/episode-55/?t=146) Работа, комфорт и «социум» - [06:33](https://apkhmv.xyz/podcast/episode-55/?t=393) Молодые специалисты и «оголтелый студент» - [11:36](https://apkhmv.xyz/podcast/episode-55/?t=696) Информационный шум и навык фильтрации - [20:06](https://apkhmv.xyz/podcast/episode-55/?t=1206) «Я начальник, ты дурак» и масштаб культуры - [24:34](https://apkhmv.xyz/podcast/episode-55/?t=1474) Искать человека, а не закрывать вакансию - [31:58](https://apkhmv.xyz/podcast/episode-55/?t=1918) Эйфория основателя и продуктовая трансформация - [40:42](https://apkhmv.xyz/podcast/episode-55/?t=2442) Спонтанность и разгрузка головы - [48:11](https://apkhmv.xyz/podcast/episode-55/?t=2891) Единственный, кто с тебя спросит, — ты сам - [54:31](https://apkhmv.xyz/podcast/episode-55/?t=3271) Инструменты для живого удалённого социума - [1:05:46](https://apkhmv.xyz/podcast/episode-55/?t=3946) Спонтанная коммуникация против асинхронной - [1:16:52](https://apkhmv.xyz/podcast/episode-55/?t=4612) Киллер-фича: догнать пропущенный созвон - [1:21:51](https://apkhmv.xyz/podcast/episode-55/?t=4911) AI-инструменты и кризис доверия к сгенерированному ### Ссылки - [yuchat — продукт компании Unison](https://yuchat.ai) ## #54: Вайбим с Иваном Ямщиковым - Markdown: https://apkhmv.xyz/podcast/episode-54/index.md - Гости: [Иван Ямщиков](https://apkhmv.xyz/people/ivan-yamshchikov/index.md) Александр Пахомов и Иван Ямщиков (сооснователь Pleias, профессор THWS) разбирают, как генеративные модели и «вайб-кодинг» меняют работу инженера в середине 2025 года: где модели реально полезны (быстрое прототипирование) и где буксуют (тестирование, валидация и дебаг сгенерированного кода). По пути — как из «восстановления пропусков в тексте» вырос reasoning, почему модель в чате не дообучается на вашем фидбэке, чем маленькие модели и RAG интересны бизнесу с чувствительными данными, и какой навык остаётся за человеком: придумывать тесты и удерживать «вкус» к задаче. ### Главное - Вайб-кодинг силён для прототипирования, но дебаг и тестирование сгенерированного кода — узкое место, и оно же сдерживает автономных агентов. - Баланс автономии агента и контроля человека похож на дилемму фрилансера с заказчиком: проверять слишком часто — делать лишнюю работу, слишком редко — рискнуть выдать нерабочий результат. - Reasoning сводится к восстановлению пропусков в цепочке рассуждений (chain of thought) плюс декомпозиции задачи на подзадачи и трате большего «компьюта» на ответ. - Модель в чате не дообучается на вашей обратной связи — она предобучена; непрерывное дообучение упирается в «катастрофическое забывание» (catastrophic forgetting). - Большая модель ценна не столько качеством на одной задаче, сколько гибкостью: её можно дообучать под много задач, а маленькую под каждую новую приходится радикально переучивать. - Стартап Pleias обучает маленькие (350M–1,2B) модели только на открытом датасете Common Corpus; они мультиязычны, сильны в RAG и умеют цитировать источники «из коробки». - Спрос enterprise — локальные и гибридные пайплайны: не отдавать чувствительные данные и код в OpenAI/Anthropic, а часть задач решать маленькой локальной моделью. - Главный навык программиста в эпоху агентов — придумывать тесты и удерживать «вкус» к задаче; написание кода всё больше делегируется модели. ### Главы - [00:00](https://apkhmv.xyz/podcast/episode-54/?t=0) Вступление - [00:42](https://apkhmv.xyz/podcast/episode-54/?t=42) Вайб-кодинг: прототипы против дебага - [05:14](https://apkhmv.xyz/podcast/episode-54/?t=314) Тестирование агентов и баланс с человеком - [13:12](https://apkhmv.xyz/podcast/episode-54/?t=792) Reasoning: chain of thought и декомпозиция - [18:11](https://apkhmv.xyz/podcast/episode-54/?t=1091) Дообучение и катастрофическое забывание - [27:43](https://apkhmv.xyz/podcast/episode-54/?t=1663) Маленькие модели, Common Corpus и RAG - [34:53](https://apkhmv.xyz/podcast/episode-54/?t=2093) Локальные модели и приватность данных в enterprise - [43:27](https://apkhmv.xyz/podcast/episode-54/?t=2607) Главный навык: придумывать тесты - [48:13](https://apkhmv.xyz/podcast/episode-54/?t=2893) Практический совет: завайб-кодить пет-проект - [55:12](https://apkhmv.xyz/podcast/episode-54/?t=3312) Заключение ### Ссылки - [Common Corpus — открытый датасет Pleias (Hugging Face)](https://huggingface.co/datasets/PleIAs/common_corpus) - [Pleias — лаборатория Ивана](https://pleias.fr) ## #53: Datomic: самая рок-н-рольная БД - Markdown: https://apkhmv.xyz/podcast/episode-53/index.md - Гости: [Никита Прокопов](https://apkhmv.xyz/people/nikita-prokopov/index.md) Александр Пахомов и Никита Прокопов (Nikitonsky — автор Fira Code, DataScript и телеграм-канала «Стой под стрелой») разбирают Datomic — базу данных, которая идёт против течения индустрии. Начав с боли, когда оптимизатор `Postgres` внезапно замедляет запрос в сто раз, они переходят к устройству Datomic: модель `Entity-Attribute-Value` вместо таблиц, язык запросов `Datalog` вместо `SQL`, разделение чтения и записи, однопоточный транзактор и иммутабельная база с путешествием во времени. Отдельная линия разговора — как маленькая команда за счёт радикальной простоты решает те же задачи минимальными средствами. ### Главное - Оптимизатор `Postgres` снимает головную боль в ~90% случаев, но когда инженер точно знает нужную последовательность операций, отсутствие прямого контроля над планом становится проблемой — добавление no-op-фильтра может замедлить запрос примерно в 100 раз. - Зависимость запроса от индекса в `SQL` неявная: запрос молча предполагает, что индекс есть, но нигде его не указывает — отсюда идея спустить абстракцию на уровень ниже, вплоть до `SELECT ... FROM table USING INDEX`. - Datomic хранит данные не таблицами, а тройками `Entity-Attribute-Value` (датомами); это делает разреженные поля, множественные значения и ссылки бесплатными по overhead, а обратные ссылки — такими же дешёвыми, как прямые. - Datomic использует `Datalog` — паттерн-матчинг по тройкам с автоматическим джойном и рекурсивными правилами; он эквивалентен `SQL` по мощности, но `order by`/`limit` в нём нет — их выносят в постобработку на клиенте. - Datomic «деконструирует» базу данных: чтение идёт напрямую из network-attached storage мимо сервера, а записи обслуживает единственный однопоточный транзактор, который просто линеаризует поток транзакций. - Однопоточного writer'а хватает для подавляющего большинства бизнес-приложений (порядка тысячи транзакций в секунду); отказ решать проблемы, которых у тебя нет, радикально упрощает систему. - Datomic — иммутабельная база: клиент держит ссылку на конкретную версию (эпоху) и видит консистентный снапшот всей базы, а также умеет запрашивать состояние на любой момент в прошлом — фантомные чтения как явление просто исчезают. - Радикальная простота Datomic родилась из ограничения маленькой команды; эта же модель `TripleStore` + `Datalog` реализуется в ~200 строк и легла в основу `DataScript` — in-memory клона, удобного даже без персистентности. ### Главы - [00:00](https://apkhmv.xyz/podcast/episode-53/?t=0) Вступление: гость Nikitonsky и рок-н-рольная БД - [01:06](https://apkhmv.xyz/podcast/episode-53/?t=66) История про Postgres: оптимизатор запросов подводит - [05:50](https://apkhmv.xyz/podcast/episode-53/?t=350) Контроль против оптимизатора: хочется управлять планом - [10:39](https://apkhmv.xyz/podcast/episode-53/?t=639) Datomic как альтернатива: другой взгляд на данные - [16:25](https://apkhmv.xyz/podcast/episode-53/?t=985) Триплы: Entity-Attribute-Value и датомы - [28:00](https://apkhmv.xyz/podcast/episode-53/?t=1680) Datalog: паттерн-матчинг вместо SQL и индексы - [38:58](https://apkhmv.xyz/podcast/episode-53/?t=2338) Транзакции: add/retract и деконструкция базы данных - [41:11](https://apkhmv.xyz/podcast/episode-53/?t=2471) Разделение чтения и записи, однопоточный транзактор - [46:12](https://apkhmv.xyz/podcast/episode-53/?t=2772) Рок-н-ролл: осознай свой масштаб - [51:00](https://apkhmv.xyz/podcast/episode-53/?t=3060) Чтение на клиенте и произвольные функции на Clojure - [58:28](https://apkhmv.xyz/podcast/episode-53/?t=3508) Только Clojure/Java: почему Datomic не взлетел широко - [1:01:18](https://apkhmv.xyz/podcast/episode-53/?t=3678) Storage и иммутабельность: путешествие во времени - [1:22:35](https://apkhmv.xyz/podcast/episode-53/?t=4955) DataScript: TripleStore как удобная структура данных ### Ссылки - [Datomic — база данных](https://www.datomic.com) - [DataScript — immutable database и Datalog для Clojure/Script](https://github.com/tonsky/datascript) - [Fira Code — шрифт с лигатурами для программистов](https://github.com/tonsky/FiraCode) - [PostgreSQL](https://www.postgresql.org) ## #52: Трансформация профессии разработчика в 2025 - Markdown: https://apkhmv.xyz/podcast/episode-52/index.md - Гости: [Андрей Володин](https://apkhmv.xyz/people/andrey-volodin/index.md) Александр Пахомов и Андрей Володин (сооснователь и CTO стартапа Gracia, ex-founding engineer Prisma и сооснователь NetMonet) разбирают, как вайб-кодинг и AI-агенты меняют профессию разработчика в середине 2025 года. Отправной точкой служит кейс Андрея: не будучи фронтендером, он с нуля собрал в Cursor комплексную админку (backend-driven UI, three.js, парсинг COLMAP) за ноль строк ручного кода. Отсюда — почему «попсовые» стеки (React, TypeScript) под наибольшим давлением, а low-level, робототехника и diptech пока «тихая гавань»; зачем разработчику смещаться в сторону бизнеса; и как экономическая конъюнктура (конец ZIRP, стагнация рынка смартфонов) переопределяет ценность кода — от «читабельности» к «нераспространению говнокода». ### Главное - Опытный разработчик без фронтенд-опыта собрал в `Cursor` комплексную админку (backend-driven UI, `three.js`, парсинг `COLMAP`) за ноль строк ручного кода — быстрее, дешевле и без усталости по сравнению с наймом фрилансера. - Ценность кода теперь не в читабельности, а в том, что он «не распространяет метастазы»: self-contained-модули не шерят общие утилиты, поэтому поломка в одном месте не ломает всё остальное. - Давление AI сильнее всего в «попсовых» стеках (`React`, `TypeScript`), потому что нейросети обучены на огромном объёме именно такого кода; асинхронные агенты первыми «выжрут» задачи джунов и мидлов. - Low-level computing (`CUDA`-кернелы, шейдеры, профайлинг), embedded, робототехника и research пока «тихая гавань»: мало открытых данных и сложно построить `reinforcement learning` feedback loop. - Университеты должны делать double down на фундаментал (алгоритмы, компиляторы, линейная алгебра, сети), а не гнаться за хайпом: fastfood-знания вроде «слайдер на React» и так выдаёт AI за секунду. - Почасовая оплата разработчика абсурдна и напрямую мотивирует работать хуже; платить надо за результат — «за сапог, а не за часы». - Код — это «ассемблер для документации и продуктовых задач»: если слить на торренты фронтенд крупного банка, `literally nothing will happen`, потому что вне своего бизнеса он ценности не несёт. - Целевая команда будущего — не соло-фаундер (его скопируют 50 тысяч таких же), а свитспот в 10–30 ультра-профессионалов, где роли смерживаются в «имплементаторов» и «бизнес-визионеров». ### Главы - [00:00](https://apkhmv.xyz/podcast/episode-52/?t=0) Холодный старт: тезисы Андрея - [02:09](https://apkhmv.xyz/podcast/episode-52/?t=129) Вступление - [03:10](https://apkhmv.xyz/podcast/episode-52/?t=190) Знакомство: Prisma, NetMonet, Gracia - [09:33](https://apkhmv.xyz/podcast/episode-52/?t=573) Кейс: админка в Cursor без фронтендера - [26:30](https://apkhmv.xyz/podcast/episode-52/?t=1590) AI-трансформация команды и метрики - [34:57](https://apkhmv.xyz/podcast/episode-52/?t=2097) Попсовые vs непопсовые сферы, джуны и сеньоры - [53:35](https://apkhmv.xyz/podcast/episode-52/?t=3215) Университеты и фундаментальные знания - [1:11:02](https://apkhmv.xyz/podcast/episode-52/?t=4262) Разработчик как «предатель»: нативка vs веб - [1:21:18](https://apkhmv.xyz/podcast/episode-52/?t=4878) Экономика: конец ZIRP и бума смартфонов - [1:25:58](https://apkhmv.xyz/podcast/episode-52/?t=5158) Код как «ассемблер для документации» - [1:37:58](https://apkhmv.xyz/podcast/episode-52/?t=5878) Инструменты: агенты, MCP, init.md, тестирование - [1:50:15](https://apkhmv.xyz/podcast/episode-52/?t=6615) Модели: не прыгать с модельки на модельку - [1:53:37](https://apkhmv.xyz/podcast/episode-52/?t=6817) Языки: попсовые побеждают, бан на breaking change - [2:06:37](https://apkhmv.xyz/podcast/episode-52/?t=7597) Соло-фаундер против команды-свитспота - [2:23:34](https://apkhmv.xyz/podcast/episode-52/?t=8614) Ламповое напутствие и финал ### Ссылки - [Gracia — объёмное 4D-видео (Gaussian Splatting)](https://gracia.ai) - [Cursor — AI-редактор кода](https://cursor.com) - [Aider — терминальный AI-агент для кода](https://aider.chat) - [Browserbase / Stagehand — AI-browser automation](https://www.browserbase.com) - [Repomix — упаковка репозитория для LLM](https://repomix.com) ## #51: Код ревью в Clickhouse - Markdown: https://apkhmv.xyz/podcast/episode-51/index.md - Гости: [Максим Кита](https://apkhmv.xyz/people/maxim-kita/index.md) Александр Пахомов и коммитер ClickHouse Максим Кита разбирают, как в большом open-source-проекте устроено код-ревью: почему оно неотделимо от мощного CI, от которого зависит, сколько ответственности можно снять с ревьюера, и от того, как сами контрибьюторы готовят свой код. По пути — какие тесты и санитайзеры гоняет ClickHouse, почему `code coverage` как хардстоп чаще вредит, какие пул-реквесты страшнее всего ревьюить (вероятностные алгоритмы), как «запал» автора и человеческая психология определяют судьбу PR, и почему изоляция кода через `factory`-паттерн и принцип open-closed так важна для контрибьютабельности. ### Главное - В ClickHouse код-ревью — обязательная часть перед мержем, и оно неотделимо от CI: чем сильнее CI, тем больше ответственности можно снять с ревьюера, чтобы внешний контрибьютор мог сам увидеть и починить проблему. - Главная задача ревьюера в большом open-source-проекте — не ловить опечатки, а задавать вектор: понимать мотивацию PR и то, как фичу правильно реализовать в духе проекта; если ревьюер сам не знает, как её сделать, полноценного ревью не получится. - Проблема форматирования решена «одной кнопкой» в Go (`gofmt`) и Rust, но не в C++ и не на JVM: почти у каждого C++-проекта свой конфиг `clang-format` поверх шаблона (Chromium, LLVM, WebKit), а вопрос `camelCase` vs `snake_case` в C++ так и не устоялся. - ClickHouse гоняет stateless-, stateful-, unit- и интеграционные тесты, стресс-тесты, фаззеры (в том числе SQL-фаззер) и перф-тесты под ARM и x86 — со всеми санитайзерами (address, thread, memory, UB); зелёный CI делает вероятность бага очень маленькой. - `code coverage` как хардстоп чаще вредит: 100% покрытия не гарантирует работоспособность, люди забивают его пустыми тестами, а такие тесты потом ломаются при рефакторинге и замедляют эволюцию кода. - Самые тяжёлые для ревью пул-реквесты — с хардкорным алгоритмическим кодом, особенно вероятностными алгоритмами: тут нужно понять код на 100%, потому что опечатка (например, в большом простом числе) может незаметно сломать алгоритм. - Судьбу PR во многом решает психология: у автора есть «запал», который с каждым днём падает, поэтому важно отвечать быстро и сразу давать максимум фидбэка; антипаттерн — ревьюить по верхам, гонять по нитпикам, а через несколько итераций сказать «тут всё архитектурно неправильно». - Изолируйте код: `factory`-паттерн и принцип open-closed позволяют добавлять функцию или парсер отдельным файлом, который ничего наружу не торчит и ничего не ломает; но паттернами (адаптеры, декораторы) легко упороться — обёртки оправданы, только когда оборачиваемый тип нельзя поменять. ### Главы - [00:00](https://apkhmv.xyz/podcast/episode-51/?t=0) Вступление: зачем говорить про код-ревью - [01:33](https://apkhmv.xyz/podcast/episode-51/?t=93) Что такое код-ревью и чем он отличается от проекта к проекту - [04:56](https://apkhmv.xyz/podcast/episode-51/?t=296) Главная задача ревьюера — задавать вектор - [11:58](https://apkhmv.xyz/podcast/episode-51/?t=718) CI как помощник ревьюера - [14:07](https://apkhmv.xyz/podcast/episode-51/?t=847) Форматирование: gofmt против clang-format - [24:41](https://apkhmv.xyz/podcast/episode-51/?t=1481) Тесты, санитайзеры и фаззеры в ClickHouse - [29:40](https://apkhmv.xyz/podcast/episode-51/?t=1780) Флэки-тесты и споры про code coverage - [36:53](https://apkhmv.xyz/podcast/episode-51/?t=2213) Самые тяжёлые PR: хардкорные и вероятностные алгоритмы - [43:02](https://apkhmv.xyz/podcast/episode-51/?t=2582) Взаимодействие ревьюера и автора: запал и психология - [50:53](https://apkhmv.xyz/podcast/episode-51/?t=3053) 99% мержа: как в ClickHouse доделывают чужие PR - [54:23](https://apkhmv.xyz/podcast/episode-51/?t=3263) Селф-ревью: как автору готовить код к ревью - [1:12:16](https://apkhmv.xyz/podcast/episode-51/?t=4336) Структура кода: factory-паттерн и изоляция - [1:26:03](https://apkhmv.xyz/podcast/episode-51/?t=5163) Паттерны, open-closed и итоги ### Ссылки - [ClickHouse — колоночная СУБД (GitHub)](https://github.com/ClickHouse/ClickHouse) ## #50: Как я повысил свою продуктивность за этот год - Markdown: https://apkhmv.xyz/podcast/episode-50/index.md - Гости: нет Сольный, юбилейный 50-й выпуск: Александр Пахомов возвращается к формату монолога и разбирает, что за год ощутимо подняло его продуктивность как программиста. Разговор идёт по четырём слоям — эргономика рабочего места (кресло `ErgoHuman`, кронштейн для ноутбука, ортолинейная сплит-клавиатура), софт (`Ghostty` + `tmux` + `Neovim` как единая среда, `fish`, единая тема во всех программах), пет-проект «база данных на Rust» и его влияние на уверенность в языке, и, наконец, здоровье — отказ от соцсетей и новостных каналов ради «свободного места в голове» плюс спорт как способ прокачать не тело, а майндсет времени и дисциплины. ### Главное - Эргономичное кресло надо выбирать не по цене и не по интернет-обзорам, а сидя в шоуруме по 10–15 минут на каждой модели: `Herman Miller Aeron` за ~2000$ подошёл автору хуже, чем `ErgoHuman Elite 2` за ~1000$ — под конкретное тело кресло подбирается индивидуально. - Кронштейн, поднимающий экран на уровень глаз, снимает постоянное напряжение задних мышц шеи: когда голова висит вперёд над ноутбуком, эти мышцы держат её всё время, что у автора доходило до пульсирующей боли и бессонницы. - Одного хорошего монитора достаточно почти всегда; два монитора реально нужны только под стриминг (один транслируется целиком, второй — под `OBS`), а постоянно крутить голову между экранами — неестественная нагрузка. - Ортолинейная сплит-клавиатура (клавиши строго друг под другом) резко снижает промахи слепой печати по спецсимволам и скобкам, а разведённые на ~30 см половины расправляют плечи и грудную клетку — 8 часов в день со сведёнными руками сгорбливают. - Связка `Ghostty` (терминал на Zig) + `tmux` + `Neovim` под единой темой `Gruvbox` стирает границу между терминалом, командной строкой и редактором — весь интеллектуальный труд, кроме Java (её автор оставляет в `IntelliJ IDEA` + IdeaVim), делается в одном окне. - Пет-проект «своя база данных на Rust» оказался без обозримого скоупа (у больших компаний первая версия — это ~5 лет), но именно он превратил формальное «знаю Rust» в реальное умение: автор смог по ходу дела написать на Rust веб-сервер, отдающий `200` для health-check `Traefik`. - Отказ от Twitter, новостных телеграм-каналов, TikTok и Instagram освободил «пространство в голове» и энергию: любое чтение таких лент запускает фоновое «думание», а без него у автора появились силы на второй сезон подкаста и другое творчество. - Спорт даёт не только здоровую спину и «промытую» кардио голову, но и переносимый на работу майндсет: как штангу в 100 кг не взять за пару тренировок, так и большую фичу или пет-проект берёт наложение времени и дисциплины на деятельность, а не только талант и желание. ### Главы - [00:13](https://apkhmv.xyz/podcast/episode-50/?t=13) Юбилейный монолог: без гостей и без технических деталей - [01:59](https://apkhmv.xyz/podcast/episode-50/?t=119) Эргономика: рабочее место и стол - [03:14](https://apkhmv.xyz/podcast/episode-50/?t=194) Как выбирать кресло: ErgoHuman против Herman Miller - [11:36](https://apkhmv.xyz/podcast/episode-50/?t=696) Кронштейн для ноутбука и осанка - [16:20](https://apkhmv.xyz/podcast/episode-50/?t=980) Один или два монитора; MacBook M3 Max - [21:17](https://apkhmv.xyz/podcast/episode-50/?t=1277) Сплит-клавиатура и ортолинейность - [30:10](https://apkhmv.xyz/podcast/episode-50/?t=1810) Софт: терминал Ghostty на Zig - [36:22](https://apkhmv.xyz/podcast/episode-50/?t=2182) tmux и Neovim как единая среда - [46:14](https://apkhmv.xyz/podcast/episode-50/?t=2774) База данных на Rust: пет-проект и уверенность в языке - [52:15](https://apkhmv.xyz/podcast/episode-50/?t=3135) Телеграм-бот и веб-сервер на Rust за 200 - [58:13](https://apkhmv.xyz/podcast/episode-50/?t=3493) Отказ от соцсетей и новостных каналов - [1:06:50](https://apkhmv.xyz/podcast/episode-50/?t=4010) Спорт: майндсет времени и дисциплины - [1:17:47](https://apkhmv.xyz/podcast/episode-50/?t=4667) Заключение: никаких фетишей ### Ссылки - [Ghostty — терминал на Zig](https://ghostty.org) - [Neovim](https://neovim.io) - [tmux](https://github.com/tmux/tmux) - [fish shell](https://fishshell.com) - [Gruvbox Material — цветовая схема](https://github.com/sainnhe/gruvbox-material) - [QMK Firmware — прошивка клавиатур](https://qmk.fm) - [Vial — конфигуратор клавиатур](https://get.vial.today) - [n8n — платформа автоматизации](https://n8n.io) - [Traefik — reverse proxy](https://traefik.io) ## #49: Serverless Postgres: как работает Neon Database - Markdown: https://apkhmv.xyz/podcast/episode-49/index.md - Гости: [Стас Кельвич](https://apkhmv.xyz/people/stas-kelvich/index.md) Александр Пахомов и Стас Кельвич (сооснователь Neon, где он сделал storage layer) разбирают внутреннее устройство serverless-Postgres. Как Neon отделяет compute от storage: `compute` — это чуть подхаченный Postgres, у которого чтение с диска заменено на чтение по сети, а `storage` — свои сервисы на Rust (Safekeeper — консенсусный `WAL` на модифицированном Raft/DiskPaxos, и PageServer — партиционированное LSM-дерево поверх S3). По пути — процессы Postgres-комьюнити (commit-fest'ы, пятилетние патчи, `TLA+`), branching через copy-on-write и запросы к истории по `LSN`, live-миграция виртуалок ради вертикального скейлинга без разрыва соединений, авторизация по `HTTP` для V8-isolate'ов, а также будущее многопоточного Postgres. Это вторая, глубоко техническая часть; обзорная — в выпуске 48. ### Главное - Neon разделяет `compute` и `storage`: compute — это Postgres, у которого чтение страниц с диска заменено чтением по сети, а запись `WAL` идёт в свой storage; storage выглядит для Postgres как реплика на запись и как диск на чтение. - Storage-слой multi-tenant и stateless-по-compute: `HA` и защита от split-brain живут в storage, поэтому compute-ноды (`stateless` Postgres) можно агрессивно перезапускать в Kubernetes — это резко упрощает эксплуатацию миллионов баз силами 10 человек. - Durability строится двумя тирами: Safekeeper коммитит `WAL` в 2 из 3 availability-зон (аналог quorum commit), затем PageServer материализует журнал в 8-килобайтные страницы и как можно быстрее сбрасывает их в S3 — «горячую картошку» отдают S3 как фундаменту durability. - Safekeeper реализует консенсус модифицированным Raft (по сути DiskPaxos): роли разделены — Postgres-compute только пропоузер/лидер, Safekeeper только фолловер; корректность части протокола проверяли на `TLA+` (это model checker, не доказательство — как property-based testing). - PageServer — партиционированное LSM-дерево, но append-only ради дешёвой выгрузки в S3 (S3 не даёт менять префикс); без garbage collection хранится вся история, поэтому запрос страницы на произвольном `LSN` дёшев — отсюда time-travel, дешёвые исторические запросы и восстановление до точного `LSN`. - Branching — это copy-on-write: бранч терабайтной базы создаётся мгновенно, данные копируются лишь при записи; это раскрывает preview-окружения на реальных данных, тест миграций против прода и (в разработке) анонимизацию/маскирование данных на бранче. - Вертикальный автоскейлинг делают live-миграцией виртуалки (QEMU/KVM, pre-copy/post-copy), утаскивая за собой IP через `VXLAN`: `TCP`-соединения, транзакции и контекст сессии переживают переезд с одной Kubernetes-ноды на другую — обычный HTTP-style rescheduling для Postgres не годится из-за долгоживущих запросов и сессионного состояния. - Форк Postgres у Neon крошечный (10–20k строк, адаптация новой версии — меньше месяца), потому что почти всё вынесено в расширения; будущее — многопоточный Postgres (thread-local вместо static-переменных), над которым команда работает в апстриме, а не в своём форке. ### Главы - [00:00](https://apkhmv.xyz/podcast/episode-49/?t=0) Вступление: вторая часть, погружаемся внутрь Neon - [01:10](https://apkhmv.xyz/podcast/episode-49/?t=70) Что такое Neon и экономика Postgres-комьюнити - [10:00](https://apkhmv.xyz/podcast/episode-49/?t=600) История Postgres: System R, Ingres, Lisp → C - [17:52](https://apkhmv.xyz/podcast/episode-49/?t=1072) Релиз-цикл, commit-fest'ы и пятилетние патчи - [23:45](https://apkhmv.xyz/podcast/episode-49/?t=1425) Тестирование Postgres: green trunk, фаззинг, MVCC - [29:51](https://apkhmv.xyz/podcast/episode-49/?t=1791) Язык C, Rust и надёжность через людей - [33:22](https://apkhmv.xyz/podcast/episode-49/?t=2002) Как основали Neon: команда и вижен - [37:08](https://apkhmv.xyz/podcast/episode-49/?t=2228) Разделение compute и storage, опыт Aurora - [42:38](https://apkhmv.xyz/podcast/episode-49/?t=2558) shared-everything против shared-nothing - [46:22](https://apkhmv.xyz/podcast/episode-49/?t=2782) compute как Postgres с сетевым чтением WAL и durability - [53:51](https://apkhmv.xyz/podcast/episode-49/?t=3231) System design: Safekeeper, PageServer и S3 - [1:03:56](https://apkhmv.xyz/podcast/episode-49/?t=3836) Консенсус: Paxos, Raft, DiskPaxos и TLA+ - [1:18:57](https://apkhmv.xyz/podcast/episode-49/?t=4737) PageServer: LSM, append-only и история по LSN - [1:27:55](https://apkhmv.xyz/podcast/episode-49/?t=5275) Branching: copy-on-write и preview-окружения - [1:40:39](https://apkhmv.xyz/podcast/episode-49/?t=6039) Маскирование данных, RLS и HTTP-авторизация - [1:44:52](https://apkhmv.xyz/podcast/episode-49/?t=6292) Автоскейлинг: live-миграция виртуалок - [1:57:41](https://apkhmv.xyz/podcast/episode-49/?t=7061) Перформанс в облаке: виртуализация, OLTP против OLAP - [2:05:55](https://apkhmv.xyz/podcast/episode-49/?t=7555) Open source, форк Postgres и многопоточность - [2:25:05](https://apkhmv.xyz/podcast/episode-49/?t=8705) Вопросы слушателей: реплики, конкуренты, Rust - [2:41:11](https://apkhmv.xyz/podcast/episode-49/?t=9671) Заключение: пробуйте себя в open source ### Ссылки - [Neon — serverless Postgres as a service](https://neon.tech) - [Socrates: The New SQL Server in the Cloud (Microsoft Research, SIGMOD 2019)](https://www.microsoft.com/en-us/research/publication/socrates-the-new-sql-server-in-the-cloud/) - [TLA+ — язык и model checker Лесли Лэмпорта](https://lamport.azurewebsites.net/tla/tla.html) - [pgrx — фреймворк для расширений Postgres на Rust](https://github.com/pgcentralfoundation/pgrx) - [Amazon Aurora](https://aws.amazon.com/rds/aurora/) - [Supabase — Postgres-платформа для приложений](https://supabase.com) - [Выпуск 48: обзор ландшафта баз данных с ко-фаундером Neon](https://apkhmv.xyz/podcast/episode-48/) ## #48: Реплицируем RDBMS с ко-фаундером Neon - Markdown: https://apkhmv.xyz/podcast/episode-48/index.md - Гости: [Стас Кельвич](https://apkhmv.xyz/people/stas-kelvich/index.md) Александр Пахомов и Стас Кельвич (сооснователь Neon — serverless Postgres as a service, где он сделал storage layer) с высоты птичьего полёта осматривают весь ландшафт баз данных: почему `SQL` пережил полвека и все попытки его заменить, что осталось от волны `NoSQL`, зачем Neon отдаёт Postgres по `HTTP` для edge-воркеров на V8, и где заканчивается один сервер. По пути — «константы скорости света» для пропускной способности (30–40k транзакций в секунду в одно соединение), инженерия шардирования и shuffle join, а также распределённые транзакции: двухфазный и трёхфазный коммит, Paxos Commit и подходы к изоляции. Это первая, обзорная часть; технические кишки Neon — в следующем выпуске. ### Главное - `SQL` — декларативный язык: ты описываешь желаемый результат, а система сама придумывает, как его получить; с рекурсивными запросами (`WITH RECURSIVE`) он формально Turing-полный. - Базу данных итерировать труднее, чем компилятор или язык: люди не прощают потерю данных, поэтому рынок ценит в СУБД в первую очередь надёжность и годы безотказной работы — это тормозит эксперименты и делает индустрию консервативной. - Волна `NoSQL` начала 2010-х в итоге эволюционировала обратно к классике: у той же MongoDB появились write-ahead log, B-деревья и buffer manager, и она стала похожа на обычную базу, просто с другим языком запросов. - В edge-средах (Cloudflare Workers, V8 isolates) нельзя открыть произвольный TCP-сокет, а долгоживущие соединения не переиспользуются между запросами — поэтому Neon отдаёт Postgres по `HTTP`: stateless-запросы V8 агрессивно переиспользует, экономя лишние round-trip'ы. - «Константа скорости света» для честного пинг-понга «запрос-ответ» в одно соединение — 30–40 тысяч транзакций в секунду в любой базе (Postgres, Redis, свой кэш на C++); упирается в CPU и планировщик ОС, а не в саму базу. Без сети и диска, батчами — миллионы (уровень Java `ConcurrentHashMap`). - Распределяют данные ради двух вещей: пропускной способности (масштабировать за предел одного сервера) и отказоустойчивости (реплики переживают сбой ноды) — но 10 машин отказывают чаще одной, выигрыш даёт только система, умеющая восстанавливаться от отказов. - Распределённый `JOIN` больших таблиц чаще всего сводится к shuffle join: перешардировать данные по ключу через сеть, локально сджойнить и смёржить; узкое место — не CPU, а бэкплейн сетевого свитча. - Атомарность распределённой транзакции обеспечивают двухфазным коммитом (блокирующий: нужна доступность всех участников), а корректный неблокирующий вариант — Paxos Commit; изоляцию делают либо кросс-нодовым snapshot isolation (Spanner, CockroachDB, TiDB), либо детерминированным реордерингом неинтерактивных транзакций (FaunaDB, YDB). ### Главы - [00:00](https://apkhmv.xyz/podcast/episode-48/?t=0) Вступление: в гостях ко-фаундер Neon - [00:39](https://apkhmv.xyz/podcast/episode-48/?t=39) SQL исполнилось 50 лет - [03:04](https://apkhmv.xyz/podcast/episode-48/?t=184) Почему SQL так живуч и консервативен - [13:00](https://apkhmv.xyz/podcast/episode-48/?t=780) NoSQL: что из волны прижилось - [16:01](https://apkhmv.xyz/podcast/episode-48/?t=961) Key-value, Redis и CRDT - [20:41](https://apkhmv.xyz/podcast/episode-48/?t=1241) Realm и SDK для мобилок - [23:29](https://apkhmv.xyz/podcast/episode-48/?t=1409) CRUD-сервисы, GraphQL и Facebook - [27:10](https://apkhmv.xyz/podcast/episode-48/?t=1630) Neon: branching и HTTP вместо Postgres-протокола - [36:29](https://apkhmv.xyz/podcast/episode-48/?t=2189) Datomic, Стоунбрейкер, векторный и полнотекстовый поиск - [44:44](https://apkhmv.xyz/podcast/episode-48/?t=2684) Какую базу выбрать: расчёты на салфетке и SQLite - [48:51](https://apkhmv.xyz/podcast/episode-48/?t=2931) «Скорость света»: константы производительности - [55:45](https://apkhmv.xyz/podcast/episode-48/?t=3345) Зачем распределять: пропускная способность и отказоустойчивость - [1:15:37](https://apkhmv.xyz/podcast/episode-48/?t=4537) Инженерия шардирования - [1:24:35](https://apkhmv.xyz/podcast/episode-48/?t=5075) Distributed execution и shuffle join - [1:40:44](https://apkhmv.xyz/podcast/episode-48/?t=6044) Распределённые транзакции: 2PC, Paxos Commit, изоляция - [1:53:56](https://apkhmv.xyz/podcast/episode-48/?t=6836) Итоги и анонс части про Neon ### Ссылки - [Neon — serverless Postgres as a service](https://neon.tech) - [Datomic — база данных с датолог-подобным языком запросов](https://www.datomic.com) - [pgvector — векторный поиск для Postgres](https://github.com/pgvector/pgvector) - [Google Cloud Spanner](https://cloud.google.com/spanner) - [CockroachDB — distributed SQL database](https://www.cockroachlabs.com) - [YDB — распределённая база данных (Яндекс)](https://ydb.tech) - [Выпуск про Qdrant и векторный поиск](https://apkhmv.xyz/podcast/episode-41/) ## #47: Fleet: редактор с оптимистичными транзакциями - Markdown: https://apkhmv.xyz/podcast/episode-47/index.md - Гости: [Андрей Зайцев](https://apkhmv.xyz/people/andrei-zaitsev/index.md), [Никита Прокопов](https://apkhmv.xyz/people/nikita-prokopov/index.md) Александр Пахомов и Андрей Зайцев (инженер JetBrains, архитектор редактора Fleet) разбирают внутреннее устройство Fleet как одновременно редактора кода и мутабельной базы данных. Разговор идёт от трёх исходных челленджей (remote development, коллаборация, полиглотность) через `React`-подобный UI, чистые функции и персистентные структуры данных к главной идее — распределённым оптимистичным транзакциям на механике «переписывания истории» в духе git-rebase, где всё состояние редактора это одно значение. По пути — параллели с `Datomic` и `MVCC`, детектор конфликтов на хэшах, нативный рендеринг через `Skia` и бюджет кадра при 120 FPS, а также роль garbage collector в функциональном коде. ### Главное - Всё состояние Fleet — это одно персистентное значение (мутабельная база данных в памяти в духе `React` + `Redux`/`Re-frame`); UI это чистые функции от этого значения, а транзакции меняют значение отдельно от отрисовки. - Fleet задумывался как ответ на три челленджа, которых не было у IntelliJ IDEA изначально: remote development, совместная разработка над одним workspace и полиглотность (быть редактором «для разработчиков», а не для конкретного стека). - Главная идея быстрого UI — computational avoidance: по максимуму не звать пользовательский код; движок знает, какие компоненты какие части базы читали, и перевызывает только те, чьи данные изменились. - Совместное редактирование реализовано не через `CRDT` и не через operational transformation, а через путешествие во времени и `git-rebase`: транзакции это чистые функции, которые можно переиграть поверх нового состояния. - Конфликт определяется не записью в одно место, а нарушением причинно-следственной связи — тем, что для решения о записи ты прочитал то, что записал другой; детектируется пересечением множеств хэшей (read/write set), почти как блокчейн. - Персистентность базы даёт чтение без блокировок (не нужен read-лог), позволяет гонять массу фоновых рутин против состояния и так борется с фризами; bottleneck остаётся единственный транзактор, применяющий функции по очереди. - Fleet рисуется как игра — каждый кадр весь экран заново: UI-фреймворк строит список draw-call'ов и одним махом отправляет их на GPU через `Skia`; бюджет кадра при 120 FPS около 8 мс, из них в userspace остаётся ~4–5 мс. - В функциональном коде аллокации происходят «как дыхание», поэтому GC с компактящим молодым поколением часто выигрывает у ручного `malloc`/`free`; а место, которое много аллоцирует, обычно и есть медленный код. ### Главы - [00:00](https://apkhmv.xyz/podcast/episode-47/?t=0) Вступление: зачем понадобился Fleet - [01:42](https://apkhmv.xyz/podcast/episode-47/?t=102) Три челленджа: remote, коллаборация, полиглотность - [13:12](https://apkhmv.xyz/podcast/episode-47/?t=792) React, Redux и облачная IDE - [23:01](https://apkhmv.xyz/podcast/episode-47/?t=1381) Плавность UI как архитектурная цель - [25:57](https://apkhmv.xyz/podcast/episode-47/?t=1557) Computational avoidance: не звать юзер-код - [30:48](https://apkhmv.xyz/podcast/episode-47/?t=1848) Функциональное программирование как освобождение - [41:32](https://apkhmv.xyz/podcast/episode-47/?t=2492) Datomic: база данных как значение - [48:44](https://apkhmv.xyz/podcast/episode-47/?t=2924) Наблюдатель всегда смотрит в прошлое - [55:26](https://apkhmv.xyz/podcast/episode-47/?t=3326) Оптимистичные транзакции Fleet и два таймстемпа - [1:00:58](https://apkhmv.xyz/podcast/episode-47/?t=3658) CRDT, operational transformation и путь ребейза - [1:06:01](https://apkhmv.xyz/podcast/episode-47/?t=3961) Конфликт как причинно-следственная связь и хэш-трюк - [1:11:19](https://apkhmv.xyz/podcast/episode-47/?t=4279) Персистентность против фризов - [1:22:56](https://apkhmv.xyz/podcast/episode-47/?t=4976) Fleet как продукт: полиглотный и лёгкий - [1:33:57](https://apkhmv.xyz/podcast/episode-47/?t=5637) Нативный рендеринг: Skia, draw calls, GPU - [1:43:04](https://apkhmv.xyz/podcast/episode-47/?t=6184) Garbage collector против ручной памяти - [2:03:29](https://apkhmv.xyz/podcast/episode-47/?t=7409) Совет: учить Clojure и больше писать ### Ссылки - [JetBrains Fleet](https://www.jetbrains.com/fleet/) - [Datomic — база данных как значение](https://www.datomic.com) - [Clojure](https://clojure.org) - [Skia — 2D graphics library](https://skia.org) - [Zed — редактор кода](https://zed.dev) ## #46: Nikitonsky про современные редакторы кода - Markdown: https://apkhmv.xyz/podcast/episode-46/index.md - Гости: [Никита Прокопов](https://apkhmv.xyz/people/nikita-prokopov/index.md) Александр Пахомов и Никита Прокопов (tonsky) — автор шрифта Fira Code, библиотеки DataScript и блога «Стой под стрелой» — разбирают, каким должен быть современный редактор кода. От эргономики (сплит-клавиатуры, home row, стрелки на `EJKL`) через спор о Vim, терминале и модальности к расширяемости и «шумности» IntelliJ IDEA. Никита объясняет, почему он много лет сидит в Sublime Text, почему «умный» редактор делает тебя тупее, и как маленькая команда без денег на nice-to-have фичи выигрывает у раздутых IDE. ### Главное - Раскладка со смещёнными рядами — исторический артефакт печатных машинок; эргономичнее ortho-linear колонки и сплит на ширину плеч, но всем good enough, поэтому индустрия не меняет стандарт. - Самое доступное улучшение для любого — перенести стрелки на home row (`EJKL`/`HJKL`) через системный ремап (Karabiner), а не только внутри Vim; тогда навигация одинакова во всех приложениях. - Навык сам по себе не растёт: человек находит локальный максимум и застревает — чтобы улучшиться, нужно сознательное усилие, а не просто «дольше вариться». - Никита ушёл с Vim из-за модальности (невидимый режим) и того, что редактирование в нём живёт по своим правилам, не совместимым с остальной системой; Sublime работает как весь macOS. - «Скорость терминала» — не свойство терминала: графический редактор можно написать таким же быстрым; Vim просто старый и рассчитан на слабое железо, а хорошая клавиатурность достижима и в GUI. - Расширяемость обязательна, но модель важна: Emacs/NeoVim дают хачить свой редактор (`init.lua`, одна строчка на плагин), а VS Code требует оформлять плагин и ограничивает API ради контроля экосистемы. - «Умная» IDE (`Go to Definition`, авто-рефакторинг) снижает, как ты интернализируешь код: перестаёшь помнить, где что лежит; в «тупом» редакторе понимаешь структуру плотнее и чувствуешь код своим. - Много денег вредит продукту: JetBrains и VS Code пихают nice-to-have фичи и нотификации, а команда Sublime из трёх человек делает только критичное — редактор целиком помещается в голове. ### Главы - [00:00](https://apkhmv.xyz/podcast/episode-46/?t=0) Вступление - [02:37](https://apkhmv.xyz/podcast/episode-46/?t=157) Эргономика клавиатуры: home row и сплит - [09:31](https://apkhmv.xyz/podcast/episode-46/?t=571) Стрелки на home row: хук Vim и EJKL - [15:08](https://apkhmv.xyz/podcast/episode-46/?t=908) Почему большинство не переходит на сплит - [26:32](https://apkhmv.xyz/podcast/episode-46/?t=1592) Переход к Vim и Neovim - [27:20](https://apkhmv.xyz/podcast/episode-46/?t=1640) Никита о Vim: модальность и система команд - [33:04](https://apkhmv.xyz/podcast/episode-46/?t=1984) Саша защищает Vim: visual mode, макросы, escape - [42:53](https://apkhmv.xyz/podcast/episode-46/?t=2573) Программирование в терминале в 2024-м - [47:07](https://apkhmv.xyz/podcast/episode-46/?t=2827) Скорость и клавиатурность — не свойство терминала - [53:17](https://apkhmv.xyz/podcast/episode-46/?t=3197) Расширяемость редактора и плагины - [1:00:19](https://apkhmv.xyz/podcast/episode-46/?t=3619) Copilot в одну строчку; Atom против VS Code - [1:04:01](https://apkhmv.xyz/podcast/episode-46/?t=3841) Шумность интерфейса IntelliJ IDEA - [1:10:41](https://apkhmv.xyz/podcast/episode-46/?t=4241) Много денег — много булшита; фокус Sublime - [1:17:56](https://apkhmv.xyz/podcast/episode-46/?t=4676) Sublime Text: почему он его выбрал - [1:27:46](https://apkhmv.xyz/podcast/episode-46/?t=5266) Умные IDE делают тебя тупее - [1:32:05](https://apkhmv.xyz/podcast/episode-46/?t=5525) Zed, языковые модели и Fleet - [1:39:14](https://apkhmv.xyz/podcast/episode-46/?t=5954) Fleet и заключение ### Ссылки - [Fira Code — моноширинный шрифт с лигатурами](https://github.com/tonsky/FiraCode) - [«Cursor keys belong at the center of your keyboard» — статья Никиты про EJKL](https://tonsky.me/blog/cursor-keys/) - [Karabiner-Elements — ремаппинг клавиш на macOS](https://karabiner-elements.pqrs.org) - [Neovim](https://neovim.io) - [Sublime Text](https://www.sublimetext.com) - [Zed — редактор на Rust](https://zed.dev) - [Helix — модальный редактор](https://helix-editor.com) ## #45: TigerBeetle: база данных не похожа на остальные - Markdown: https://apkhmv.xyz/podcast/episode-45/index.md - Гости: [Алексей Кладов](https://apkhmv.xyz/people/matklad/index.md) Александр Пахомов и Алексей Кладов (matklad — автор IntelliJ Rust и rust-analyzer, теперь разработчик TigerBeetle) подробно разбирают, чем TigerBeetle не похож на остальные СУБД: написана на `Zig`, без `SQL`-интерфейса, со статической аллокацией памяти и жёстко зашитой доменной моделью из аккаунтов и трансферов. По ходу — почему `OLTP` стоит вернуть к процессингу именно финансовых транзакций (а `SQL` назвать `OLGP`), как реплицированная state machine на консенсусе `VSR` переживает ненадёжные сеть и диск, как устроены чек-суммы, суперблок, батчинг и детерминированный компакшн `LSM`-деревьев, и почему системное программирование на самом деле простое — надо просто брать и писать код. ### Главное - TigerBeetle специализирован под `OLTP` в узком смысле — процессинг финансовых транзакций, где нужна строгая сериализуемость; остальное (аутентификация, скоринг, аватарки) выносится в обычную `OLGP`-базу вроде Postgres. - Проблема, которую решает TigerBeetle, — контеншен: задачи, которые фундаментально не параллелятся (перевод денег с одного популярного счёта банка), где `COST` из статьи Фрэнка Макшерри «Scalability! But at what COST?» фактически бесконечен. - Клиенты никогда не пишут в TigerBeetle напрямую — stateless `API Gateway` собирает запросы конечных пользователей в батчи (до 8000 трансферов) и шлёт их одним сообщением; вся бизнес-логика double-entry booking живёт в гейтвее. - Ядро TigerBeetle — реплицированная state machine (кластер из 6 машин на консенсусе `VSR`), параметризованная бизнес-логикой; в `Zig` это выражается функциями, которые принимают тип и возвращают тип, что даёт почти 100%-й code reuse в детерминированном симуляторе. - TigerBeetle предполагает почти византийский диск: он может вернуть мусор или записать данные не по тому адресу, поэтому чтение блока идёт по паре «адрес + чек-сумма», а битый блок прозрачно чинится копией с кворума других реплик. - На диске лежит функциональная (persistent) структура данных: ничего не перезаписывается in-place, а `superblock` в четырёх копиях с последовательной записью и `fsync` даёт атомарность чекпоинта поверх неатомарной записи. - Три уровня батчинга (8000 трансферов на консенсус, компакшн каждые 32 сообщения, чекпоинт каждые 1024) амортизируют работу; детерминированный компакшн достигается процедурой резервирования блоков, дающей byte-for-byte идентичный диск на всех репликах. - TigerBeetle не использует `malloc`/`free` — вся память аллоцируется на старте, что заставляет весь код работать с фиксированным бюджетом; главный совет гостя — не читать, а брать и писать код: системное программирование очень простое. ### Главы - [00:00](https://apkhmv.xyz/podcast/episode-45/?t=0) Вступление: чем TigerBeetle не похож на остальных - [02:47](https://apkhmv.xyz/podcast/episode-45/?t=167) Кто такой matklad и что такое TigerBeetle - [08:46](https://apkhmv.xyz/podcast/episode-45/?t=526) Какую базу выбрать для финансовой системы - [11:21](https://apkhmv.xyz/podcast/episode-45/?t=681) OLTP против OLGP: вернуть транзакции в транзакции - [17:47](https://apkhmv.xyz/podcast/episode-45/?t=1067) Conway's Law и два разных стора - [22:18](https://apkhmv.xyz/podcast/episode-45/?t=1338) Generic-код, Zig и state machine - [24:48](https://apkhmv.xyz/podcast/episode-45/?t=1488) Симулятор и code reuse для анимаций - [26:47](https://apkhmv.xyz/podcast/episode-45/?t=1607) Абстракции над сетью и диском - [34:48](https://apkhmv.xyz/podcast/episode-45/?t=2088) Свой каунтер, LSM и чекпоинты - [41:41](https://apkhmv.xyz/podcast/episode-45/?t=2501) Когда просто взять Postgres: контеншен и COST - [45:25](https://apkhmv.xyz/podcast/episode-45/?t=2725) Консенсус, ненадёжный диск и починка по кворуму - [59:52](https://apkhmv.xyz/podcast/episode-45/?t=3592) Суперблок в четырёх копиях и атомарность - [1:06:20](https://apkhmv.xyz/podcast/episode-45/?t=3980) Три уровня батчинга: автобус вместо машин - [1:11:53](https://apkhmv.xyz/podcast/episode-45/?t=4313) Throughput против latency и перформанс - [1:19:47](https://apkhmv.xyz/podcast/episode-45/?t=4787) Детерминированный компакшн и резервирование блоков - [1:24:10](https://apkhmv.xyz/podcast/episode-45/?t=5050) Устройство диска: один файл, грид, блок №0 - [1:30:52](https://apkhmv.xyz/podcast/episode-45/?t=5452) Статическая аллокация без malloc - [1:33:35](https://apkhmv.xyz/podcast/episode-45/?t=5615) Системное программирование — это просто - [1:38:24](https://apkhmv.xyz/podcast/episode-45/?t=5904) Главный совет: брать и писать код - [1:46:43](https://apkhmv.xyz/podcast/episode-45/?t=6403) Челлендж: TigerBeetle на Rust без аллокаций ### Ссылки - [TigerBeetle — база данных для финансовых транзакций](https://tigerbeetle.com) - [TigerBeetle на GitHub](https://github.com/tigerbeetle/tigerbeetle) - [Блог Алексея Кладова (matklad)](https://matklad.github.io) - [rust-analyzer](https://rust-analyzer.github.io) - [Frank McSherry — Scalability! But at what COST?](https://www.usenix.org/system/files/conference/hotos15/hotos15-paper-mcsherry.pdf) - [Zig — язык программирования](https://ziglang.org) ## #44: SIMD в базах данных - Markdown: https://apkhmv.xyz/podcast/episode-44/index.md - Гости: [Максим Кита](https://apkhmv.xyz/people/maxim-kita/index.md) Александр Пахомов и коммитер ClickHouse Максим Кита разбирают процессоры глазами системного инженера — от иерархии кэшей, стека и prefetch до суперскалярности, спекулятивного выполнения и протокола когерентности `MESI`. Во второй половине разговор уходит в модели памяти (`happens-before`, relaxed / acquire-release / sequential consistency), false sharing и лок-фри-примитивы, а затем — в главную тему: `SIMD`, автовекторизацию, `CPU dispatch` и хитрые SIMD-алгоритмы вроде гугловой Swiss-хеш-таблицы, которыми ClickHouse ускоряет обработку данных. ### Главное - Процессор в тысячу раз быстрее оперативной памяти, поэтому доступ идёт через иерархию кэшей (`L1`/`L2`/`L3`), которая подтягивает данные кэш-линиями (обычно 64 или 128 байт), эксплуатируя пространственную и временную локальность. - Итерация и копирование `ArrayList` быстрее `LinkedList`, потому что непрерывный массив читается кэш-линиями и хорошо предсказывается prefetch'ем, а связный список даёт кэш-промах почти на каждом элементе. - Транспонирование второй матрицы перед перемножением превращает обход «строка на столбец» в «строка на строку» и ускоряет наивный алгоритм в 3–10 раз — та же математика, но последовательный доступ к памяти. - На реальном железе `x86` тест «два потока пишут и читают» может выдать `0,0` из-за store-буфера; отсюда нужны модели памяти, которые отвечают, «какая запись видна какому чтению», не заставляя думать про внутренности процессора. - Три уровня гарантий атомиков: relaxed даёт только `modification order` (годится для счётчиков), acquire-release триггерит `happens-before`, а sequential consistency добавляет глобальный порядок — и позволяет рассуждать в модели чередования, если нет data race. - False sharing убивает производительность даже без data race: несколько потоков, пишущих в соседние переменные одной кэш-линии, гоняют её между ядрами — лечится паддингом (`hardware_destructive_interference_size`, 64 байта на `x86`). - `SIMD` (Single Instruction Multiple Data) — широкие регистры (`XMM`/`YMM`/`ZMM`, 128/256/512 бит) и инструкции над ними; вместе с автовекторизацией и loop-unrolling дают ускорение простых циклов в 2–4 раза, а в идеале до 16×. - Портируемость решается через `CPU dispatch`: одна функция компилируется под `SSE4.2`/`AVX2`/`AVX-512`, а на рантайме по `CPUID` выбирается доступная версия; `AVX-512` при этом опасен (нет на AMD, роняет частоту), поэтому Google и ClickHouse по умолчанию берут `SSE4.2`. ### Главы - [00:07](https://apkhmv.xyz/podcast/episode-44/?t=7) Вступление: процессоры глазами инженера - [01:41](https://apkhmv.xyz/podcast/episode-44/?t=101) Как работает процессор: инструкции, регистры, память - [04:34](https://apkhmv.xyz/podcast/episode-44/?t=274) Иерархия кэшей и кэш-линии - [12:36](https://apkhmv.xyz/podcast/episode-44/?t=756) Стек: почему память на нём всегда прогрета - [16:13](https://apkhmv.xyz/podcast/episode-44/?t=973) ArrayList против LinkedList и prefetch - [19:21](https://apkhmv.xyz/podcast/episode-44/?t=1161) Суперскалярность и спекулятивное выполнение - [23:47](https://apkhmv.xyz/podcast/episode-44/?t=1427) Протокол когерентности кэшей MESI - [25:32](https://apkhmv.xyz/podcast/episode-44/?t=1532) Пример с перемножением матриц - [33:16](https://apkhmv.xyz/podcast/episode-44/?t=1996) False sharing, барьеры и store-буфер на x86 - [38:57](https://apkhmv.xyz/podcast/episode-44/?t=2337) Модели памяти и happens-before - [44:27](https://apkhmv.xyz/podcast/episode-44/?t=2667) Relaxed, acquire-release, sequential consistency - [1:00:24](https://apkhmv.xyz/podcast/episode-44/?t=3624) Шардированный счётчик и паддинг кэш-линий - [1:07:45](https://apkhmv.xyz/podcast/episode-44/?t=4065) Лок-фри, wait-free и CAS - [1:14:20](https://apkhmv.xyz/podcast/episode-44/?t=4460) SIMD: широкие регистры, автовекторизация, история AVX - [1:32:53](https://apkhmv.xyz/podcast/episode-44/?t=5573) Портируемость и CPU dispatch - [1:57:08](https://apkhmv.xyz/podcast/episode-44/?t=7028) SIMD-алгоритмы: Swiss-хеш-таблица и финал ### Ссылки - [ClickHouse — колоночная СУБД (GitHub)](https://github.com/ClickHouse/ClickHouse) - [simdjson — парсинг JSON на SIMD](https://github.com/simdjson/simdjson) - [Agner Fog — оптимизация ПО и справочники по инструкциям](https://www.agner.org/optimize/) - [Andy Pavlo — курс по базам данных (CMU)](https://15445.courses.cs.cmu.edu/) ## #43: Как работает JIT в базах данных - Markdown: https://apkhmv.xyz/podcast/episode-43/index.md - Гости: [Максим Кита](https://apkhmv.xyz/people/maxim-kita/index.md) Александр Пахомов и Максим Кита (ментейнер LLVM, коммитер ClickHouse) разбирают Just-In-Time-компиляцию: сначала на классическом примере JVM, где JIT девиртуализирует вызовы, инлайнит `get` у `ArrayList` и убирает bound-check, а потом — как тот же приём работает в базах данных. На примере ClickHouse, Postgres и YDB они показывают, как выполнение выражений над `union`-типами компилируется в одну плотную функцию через `LLVM IR`, чем OLAP-компиляция отличается от OLTP и почему `JIT` — это ещё и постоянный источник проблем с безопасностью и падениями. ### Главное - `JIT` (just-in-time) компилирует горячий код в рантайме под конкретную машину: он знает `instruction set` процессора (вплоть до `AVX-512`) и потому может сгенерировать код лучше, чем заранее собранный `AOT`-бинарь в C/C++/Rust/Go. - Классический выигрыш в JVM: `get` у полиморфного `List` — виртуальный вызов через таблицу диспетчеризации; после того как JIT видит, что там всегда `ArrayList`, он девиртуализирует и инлайнит вызов, даёт `bound check elimination` и разворачивает цикл — ускорение в десятки-сотни раз. - В классической СУБД строка — это массив `union`-типов, а выполнение выражений идёт по дереву (точнее, `DAG`) через полиморфный `execute`; это куча виртуальных вызовов и распаковки типов, которая жутко тормозит на миллионах строк. - `JIT` в базе компилирует граф выражений в одну функцию с уже подставленными типами и константами (`id * 2` превращается в сдвиг), убирая виртуальные вызовы и промежуточные аллокации; руками покрыть все комбинации типов нереально — для `a + b + c` это тысячи функций. - OLAP-системы (ClickHouse) компилируют синхронно прямо в пайплайне — 15 мс на фоне 200 мс запроса терпимы; OLTP (Postgres, YDB) обязаны компилировать асинхронно, иначе один `row` вместо 5 мс даст пик, ломающий SLA. - На низком уровне `JIT` через `LLVM` строится из `LLVM IR` (`Module` → `Function` → basic-блоки) с помощью `IRBuilder`, компилируется в `binary object`, линкуется, кладётся в `mmap`-страницы с правами `read+execute` — права `write+execute` одновременно недопустимы, это прямой `RCE`. - `JIT` опасен: любой баг — это падение без стектрейса или порча памяти; даже валидные с виду `LLVM IR` могут ронять сам LLVM (баг в векторайзере), поэтому LLVM линкуют статически, а компиляцию форкают в отдельный процесс. - Прокачиваться в инженерии стоит от задач с понятным `definition of done` в виде кода, которые доводятся до работающего состояния за пару дней; лучше всего — в open-source-проектах, которые нравятся (ClickHouse, LLVM, Spring). ### Главы - [00:08](https://apkhmv.xyz/podcast/episode-43/?t=8) Вступление: JIT и гость Максим Кита - [01:05](https://apkhmv.xyz/podcast/episode-43/?t=65) JIT: что это и зачем, пример с List и ArrayList - [11:47](https://apkhmv.xyz/podcast/episode-43/?t=707) Bound check elimination - [13:28](https://apkhmv.xyz/podcast/episode-43/?t=808) Виртуальные вызовы и прогрев JVM - [16:51](https://apkhmv.xyz/podcast/episode-43/?t=1011) JIT против AOT-компиляции - [19:08](https://apkhmv.xyz/podcast/episode-43/?t=1148) Размер ссылки в Java против структур в Rust - [27:00](https://apkhmv.xyz/podcast/episode-43/?t=1620) Простой код против умного в ClickHouse - [27:55](https://apkhmv.xyz/podcast/episode-43/?t=1675) Страх linked list: баг с конфигом на Poco - [32:27](https://apkhmv.xyz/podcast/episode-43/?t=1947) Самый быстрый LRU-кэш в ClickHouse - [41:05](https://apkhmv.xyz/podcast/episode-43/?t=2465) Кейси Моратори против чистого кода - [55:23](https://apkhmv.xyz/podcast/episode-43/?t=3323) JIT в базах данных: Postgres - [57:16](https://apkhmv.xyz/podcast/episode-43/?t=3436) Union-типы, страницы и Volcano-модель - [1:06:01](https://apkhmv.xyz/podcast/episode-43/?t=3961) Инлайнинг констант и специализация функций - [1:17:19](https://apkhmv.xyz/podcast/episode-43/?t=4639) Когда компилировать: OLAP против OLTP - [1:26:11](https://apkhmv.xyz/podcast/episode-43/?t=5171) JIT по шагам: машинный код и LLVM IR - [1:39:43](https://apkhmv.xyz/podcast/episode-43/?t=5983) Безопасность и краши LLVM - [1:45:27](https://apkhmv.xyz/podcast/episode-43/?t=6327) Компиляция всего запроса и как стать инженером ### Ссылки - [LLVM — компиляторная инфраструктура](https://llvm.org) - [ClickHouse](https://clickhouse.com) - [PostgreSQL](https://www.postgresql.org) - [YDB](https://ydb.tech) - [asmjit — генерация машинного кода на C++](https://asmjit.com) - [Umbra — СУБД с data-centric code generation (TUM)](https://umbra-db.com) - [Amazon Redshift](https://aws.amazon.com/redshift/) ## #42: MrCyberSec: что нужно знать про безопасность - Markdown: https://apkhmv.xyz/podcast/episode-42/index.md - Гости: [Мекан Байрыев](https://apkhmv.xyz/people/mekan-bairyev/index.md) Александр Пахомов и Мекан Байрыев (специалист по безопасности веб-приложений в Mad Devs, автор YouTube-канала MrCyberSec) проходят путь атакующего от IP-адреса до `root`: сканирование портов `nmap`, перебор директорий и API-эндпоинтов, SQL-инъекции, хранение паролей и хеширование, reverse shell и эскалацию привилегий через SUID-биты, capabilities и cron. По ходу — типовые кейсы (утечка данных через незащищённую ручку, побайтовое чтение `id_rsa` через хеш-оракул, бэкдор в цепочке поставок и история с `xz`), подборка ресурсов для обучения (Hack The Box, TryHackMe, CTF) и чек-лист гигиены для бэкенд-разработчика, сводящийся к принципу минимальных привилегий. ### Главное - Разведка начинается с `nmap`: по открытым портам и баннерам сервисов (через `netcat`) видны версии ПО (`OpenSSH`, `Redis`, `nginx`, `Spring Boot`), а по ним — известные уязвимости; порт-нокинг прячет порт до правильной последовательности «стуков». - Перебор директорий и эндпоинтов (`GoBuster`, `ffuf`, `KiteRunner`) по словарям находит скрытые ручки по нестандартному ответу (`401`/`200` среди `404`); rate-limiting лишь замедляет атаку, но не спасает. - Найденная документация OpenAPI/Swagger или dev/QA-поддомен (через фаззинг субдоменов) — лучший подарок атакующему: учебный кейс — ручка без авторизации отдавала имена, хеши паролей и другие клиентские данные (broken access control). - SQL-инъекция через конкатенацию пользовательского ввода в запрос позволяет читать таблицы (`information_schema`), добавлять пользователей, а иногда выполнять код и читать файлы (`LOAD_EXTENSION` в SQLite, `LOAD_FILE` в MySQL); защита — prepared statements и валидация ввода. - `MD5` для паролей брутфорсится мгновенно; нужен медленный алгоритм (`bcrypt`) с солью и пароли от 12–16 символов, но утёкшие базы «хеш → пароль» обнуляют даже стойкий пароль, если он туда попал. - `RCE` реализуется через reverse shell: атакующий слушает `netcat` на открытом наружу порту (80/443), а на жертве перенаправляет `/bin/bash` в TCP-поток; без исходящего доступа команды гоняют по одной через саму уязвимость. - Эскалация до `root` — это цепочка: мисконфигурация `sudo`, SUID-бит на кастомной утилите, capabilities, перехват Python-импорта из writable-директории в cron; `LinPEAS`/`WinPEAS` автоматически подсвечивают такие векторы. - Базовая гигиена бэкендера сводится к принципу минимальных привилегий (least privilege): по умолчанию нет доступа ни к чему, права выдаются гранулярно; CI-боту нельзя давать `root`, а секреты и БД надо разграничивать между сервисами. ### Главы - [00:00](https://apkhmv.xyz/podcast/episode-42/?t=0) Вступление и знакомство с гостем - [03:16](https://apkhmv.xyz/podcast/episode-42/?t=196) Разведка: nmap, порты и баннеры сервисов - [08:24](https://apkhmv.xyz/podcast/episode-42/?t=504) Порт-нокинг и сокрытие сервисов - [13:06](https://apkhmv.xyz/podcast/episode-42/?t=786) Перебор директорий и API-эндпоинтов - [21:16](https://apkhmv.xyz/podcast/episode-42/?t=1276) OpenAPI/Swagger, dev- и QA-поддомены - [26:03](https://apkhmv.xyz/podcast/episode-42/?t=1563) Broken access control и утечки данных - [29:30](https://apkhmv.xyz/podcast/episode-42/?t=1770) SQL-инъекции: от sleep до дампа базы - [34:26](https://apkhmv.xyz/podcast/episode-42/?t=2066) Хеширование паролей: MD5, bcrypt, соль - [46:49](https://apkhmv.xyz/podcast/episode-42/?t=2809) RCE и reverse shell - [53:11](https://apkhmv.xyz/podcast/episode-42/?t=3191) Эскалация привилегий до root - [1:03:32](https://apkhmv.xyz/podcast/episode-42/?t=3812) SUID, capabilities и цепочки уязвимостей - [1:11:36](https://apkhmv.xyz/podcast/episode-42/?t=4296) Цепочка поставок и бэкдоры: история xz - [1:14:20](https://apkhmv.xyz/podcast/episode-42/?t=4460) Ресурсы, книги, Hack The Box и CTF - [1:21:51](https://apkhmv.xyz/podcast/episode-42/?t=4911) Чек-лист бэкендера и менеджмент секретов ### Ссылки - [MrCyberSec — YouTube-канал Мекана Байрыева](https://www.youtube.com/@MrCyberSec) - [Hack The Box](https://www.hackthebox.com) - [TryHackMe](https://tryhackme.com) - [Root Me](https://www.root-me.org) - [CTFtime — агрегатор CTF-соревнований](https://ctftime.org) - [picoCTF](https://picoctf.org) - [OWASP Top 10](https://owasp.org/www-project-top-ten/) - [Подкаст «Смени пароль» (Лаборатория Касперского)](https://podcast.smenipowl.ru) ## #41: Qdrant: Векторная база данных на Rust - Markdown: https://apkhmv.xyz/podcast/episode-41/index.md - Гости: [Андрей Васнецов](https://apkhmv.xyz/people/andrey-vasnetsov/index.md) Александр Пахомов и Андрей Васнецов (CTO и сооснователь Qdrant) разбирают, как устроен векторный поиск и почему Qdrant — это поисковый движок, а не «векторная база данных». По пути: откуда берутся эмбеддинги (word2vec, BERT, ONNX) и какими свойствами обладают векторы; почему точный индекс не работает в размерности полторы тысячи и как вместо него применяется приближённый `HNSW`; в чём киллер-фича Qdrant — фильтруемый `HNSW` со вторичными индексами; как всё это шардируется и реплицируется поверх `RAFT`; и большой финальный блок про Rust — от безопасного рефакторинга и `cargo` до вставок на ассемблере, квантизации и `io_uring`. ### Главное - Эмбеддинг — это машинно-читаемое представление объекта (текста, картинки, аудио): близость векторов по выбранной метрике означает семантическую близость, и сравнивать всегда нужно относительно (скор `0.7` интереснее `0.6`), а не по абсолютному значению. - Метрику (`cosine`, евклидово расстояние, `dot product`) выбирают под то, на чём обучалась нейросеть; на практике удобнее всего `dot product` — он самый дешёвый в вычислении. - Один эмбеддинг OpenAI — это ~1500 float'ов ≈ 6 КБ; на миллионе записей это уже ~6 ГБ, которые ради скорости приходится держать в RAM. - Точный индекс (`B-tree`, геохэш) ломается о «проклятие размерности», поэтому применяется приближённый поиск `ANN` на графе `HNSW` (Hierarchical Navigable Small Worlds) — жадный обход с несколькими лучами, сложность ~`O(log n)`. - Киллер-фича Qdrant — фильтруемый `HNSW`: векторный индекс знает про вторичные индексы (цена, локация) и достраивает дополнительные рёбра между отфильтрованными вершинами, что дешевле, чем join-индекс, и не ломается на низкой кардинальности (там просто `fullscan`). - Qdrant — поисковый движок, а не source-of-truth: его гарантии — скорость, масштабирование и отказоустойчивость (как у Elasticsearch), а в `RAFT`-консенсусе хранится только маленькая, но важная мета-информация о шардах, не сами векторы. - Rust выбран потому, что это system programming language для программ, которыми пользуются другие программы; компилятор даёт безопасный рефакторинг (паттерн-матчинг находит все места правки) и гарантии против data race и segfault ценой высокого порога входа и медленной компиляции. - Самый горячий код — вычисление `dot product` — написан на ассемблере под каждую архитектуру (даёт ~10× к наивной реализации); а `io_uring` позволяет на этапе рескоринга слать тысячи параллельных чтений к диску одним процессом, снижая latency одного запроса. ### Главы - [00:12](https://apkhmv.xyz/podcast/episode-41/?t=12) Вступление: гость и почему это не «векторная база» - [01:57](https://apkhmv.xyz/podcast/episode-41/?t=117) Что такое векторный поиск: Google Lens и эмбеддинги - [11:13](https://apkhmv.xyz/podcast/episode-41/?t=673) Векторы, метрики и косинусное расстояние - [19:29](https://apkhmv.xyz/podcast/episode-41/?t=1169) Слова в векторы: word2vec, BERT, ONNX - [27:58](https://apkhmv.xyz/podcast/episode-41/?t=1678) В чём проблема: 6 КБ на эмбеддинг и брутфорс - [35:22](https://apkhmv.xyz/podcast/episode-41/?t=2122) Проклятие размерности и приближённый поиск HNSW - [43:36](https://apkhmv.xyz/podcast/episode-41/?t=2616) Киллер-фича: фильтруемый HNSW и вторичные индексы - [58:02](https://apkhmv.xyz/podcast/episode-41/?t=3482) Распределённость: шарды, репликации и RAFT - [1:06:28](https://apkhmv.xyz/podcast/episode-41/?t=3988) Поисковый движок как вторичное хранилище - [1:11:21](https://apkhmv.xyz/podcast/episode-41/?t=4281) Тестирование распределёнки и local mode - [1:17:17](https://apkhmv.xyz/podcast/episode-41/?t=4637) REST против gRPC и боль генерации OpenAPI-клиентов - [1:30:28](https://apkhmv.xyz/podcast/episode-41/?t=5428) Производительность и бенчмарки - [1:38:39](https://apkhmv.xyz/podcast/episode-41/?t=5919) Почему Rust: рефакторинг, гарантии и порог входа - [2:08:51](https://apkhmv.xyz/podcast/episode-41/?t=7731) Ассемблер, квантизация, io_uring и latency памяти - [2:27:09](https://apkhmv.xyz/podcast/episode-41/?t=8829) Vision продукта и контрибьютинг в open source - [2:37:17](https://apkhmv.xyz/podcast/episode-41/?t=9437) Совет для карьеры: сначала проблема, потом демка ### Ссылки - [Qdrant — векторный поисковый движок на Rust](https://qdrant.tech) - [Qdrant на GitHub](https://github.com/qdrant/qdrant) - [ONNX — Open Neural Network Exchange](https://onnx.ai) - [Tokio — асинхронный рантайм для Rust](https://tokio.rs) - [Rayon — data-parallelism для Rust](https://github.com/rayon-rs/rayon) - [io_uring (эффективный асинхронный I/O в Linux)](https://en.wikipedia.org/wiki/Io_uring) ## #40: Спэшл: Эргономика, NeoVim и TDD - Markdown: https://apkhmv.xyz/podcast/episode-40/index.md - Гости: [Илья Ильиных](https://apkhmv.xyz/people/ilya-ilyinykh/index.md) Первый оффлайн-выпуск «Тысячи фичей»: в гостях у Александра Пахомова — Илья Ильиных, автор YouTube-канала «Куда войти?». Почти два часа они разбирают эргономику рабочего места (посадка, монитор, сплит-клавиатуры, механические свитчи, слепая печать), путь от IntelliJ IDEA через Emacs к `NeoVim` и то, почему модальность и Unix-философия редактора заставляют программиста по-настоящему познакомиться со своими инструментами. Во второй половине — большой разговор про TDD как способ проектирования и «обуздания» легаси, про моки и интеграционные тесты и про то, стоит ли программировать по выходным. ### Главное - Здоровый программист — тот, кто задумался о своём здоровье: важнее спорта сделать эргономичным само рабочее место, где ты проводишь 8+ часов (монитор на уровень глаз и подальше, один экран, подставка под кисти). - Сплит-клавиатура разводит половины под каждую руку, распрямляя плечи и открывая диафрагму, — говорить на созвонах становится легче. - Слепая печать нужна не ради скорости, а чтобы не перефокусировать глаза между монитором и клавиатурой (это как «челночный бег» для глазных мышц) и чтобы вообще сесть за сплит. - Модальность `Vim` переиспользует удобные клавиши home row (`h`, `j`, `k`, `l`) и для ввода текста, и для навигации; в немодальном редакторе навигации достаётся неудобное пространство под мизинец. - `NeoVim` устроен по Unix-философии: плагины на `Lua` композируются между собой и переиспользуют общий UX (`quickfix`-листы, `Telescope`); выделенный текст можно прогнать через любую bash-команду (`!`) без плагинов. - Конфиг-`dotfiles` лежат в git, версионируются и клонируются на сервер — и там разворачивается та же среда разработки; в Java нет консольного форматтера, а `gofmt`/`spotless` показывают, как это должно работать. - TDD помогает даже в жёстком легаси (по книге «Working Effectively with Legacy Code»): тесты изолируют изменения, формулируют требование как код и превращают разработку в индукцию — «рисуешь по одной линии», а не строишь весь замок в голове. - Хороший код с достаточными тестами и зелёным пайплайном самоценен, как авторский почерк: если чек-стайл и тесты проходят, придираться к стилю не стоит (так же льют код разработчики ClickHouse). ### Главы - [00:00](https://apkhmv.xyz/podcast/episode-40/?t=0) Холодный открывок и подводка - [01:52](https://apkhmv.xyz/podcast/episode-40/?t=112) Здоровье и эргономика программиста - [04:46](https://apkhmv.xyz/podcast/episode-40/?t=286) Монитор: высота, дистанция, один экран - [12:31](https://apkhmv.xyz/podcast/episode-40/?t=751) Сплит-клавиатуры и механические свитчи - [19:25](https://apkhmv.xyz/podcast/episode-40/?t=1165) Перерывы, спорт и «дать мозгу поварить» - [27:44](https://apkhmv.xyz/podcast/episode-40/?t=1664) Слепая печать как навык - [36:35](https://apkhmv.xyz/podcast/episode-40/?t=2195) Комбинации клавиш и страдающий мизинец - [41:20](https://apkhmv.xyz/podcast/episode-40/?t=2480) Emacs, Evil и путь к Vim - [48:57](https://apkhmv.xyz/podcast/episode-40/?t=2937) Что такое NeoVim: модальность - [55:52](https://apkhmv.xyz/podcast/episode-40/?t=3352) Unix-философия и композиция плагинов - [1:04:22](https://apkhmv.xyz/podcast/episode-40/?t=3862) dotfiles в git и переносимая среда - [1:06:14](https://apkhmv.xyz/podcast/episode-40/?t=3974) «Красноглазики»: споры вокруг Vim - [1:11:39](https://apkhmv.xyz/podcast/episode-40/?t=4299) Форматирование в Java и знакомство с инструментами - [1:21:05](https://apkhmv.xyz/podcast/episode-40/?t=4865) TDD: писать тесты вперёд даже в легаси - [1:29:43](https://apkhmv.xyz/podcast/episode-40/?t=5383) TDD как индукция и код как авторский почерк - [1:42:59](https://apkhmv.xyz/podcast/episode-40/?t=6179) Переработки, work-life balance и заключение ### Ссылки - [«Куда войти?» — YouTube-канал Ильи Ильиных](https://www.youtube.com/@kydavoiti) - [obs.nvim — Obsidian-подобный плагин Ильи для NeoVim](https://github.com/IlyasYOY/obs.nvim) - [MonkeyType — тренажёр скоростной печати](https://monkeytype.com) - [TypingClub — тренажёр слепой печати](https://www.typingclub.com) - [Better Display — High-DPI-масштабирование внешних мониторов на Mac](https://betterdisplay.pro) - [Spotless — форматтер и линтер для сборки (в т.ч. Java)](https://github.com/diffplug/spotless) - [«Working Effectively with Legacy Code», Michael Feathers](https://www.oreilly.com/library/view/working-effectively-with/0131177052/) - [«Test-Driven Development: By Example», Kent Beck](https://www.oreilly.com/library/view/test-driven-development/0321146530/) - [«Growing Object-Oriented Software, Guided by Tests»](http://www.growing-object-oriented-software.com/) ## #39: Иван Ямщиков: Наука, Образование и лайфхаки - Markdown: https://apkhmv.xyz/podcast/episode-39/index.md - Гости: [Иван Ямщиков](https://apkhmv.xyz/people/ivan-yamshchikov/index.md) Александр Пахомов и Иван Ямщиков (профессор ИИ в THWS, Вюрцбург) уходят от техники в сторону науки и образования: как устроена академическая карьера в Европе (аспирантура — постдок — профессура) и почему письмо незнакомому учёному способно изменить траекторию. Через эмпирический принцип POSIWID («смысл системы в том, что она делает») Иван разбирает, чему на самом деле учит школа, а в финале выводит систему профессионального роста программиста: любопытство джуна, пет-проекты мидла и менторство сеньора. ### Главное - Написать письмо практически любому учёному сегодня несложно, и по тому, как он отвечает, видно, выйдет ли совместная работа; это реальный способ сменить карьерную траекторию. - Академическая карьера в ЕС — это ступени аспирантура (≈4 года, зарплата выше медианной) → постдок (переезды каждые 1–2 года) → профессура как почти пожизненное трудоустройство с максимальной интеллектуальной свободой. - Принцип POSIWID Стаффорда Бира (`point of the system is what it does`) велит судить о системе по её результатам, а не по декларируемым целям: если школа отбивает желание учиться, значит в этом её фактический смысл. - Будущее наступает всегда и везде; каким будет ваше личное будущее, зависит от вас, а не от свойств места или времени — линейное «резюме-мышление» этому мешает. - Методика Монтессори растит агентность через три опоры: заниматься задачей столько, сколько нужно; самому выстраивать социальные связи; убирать за собой — дисциплина не инвазивная, а естественная. - Каждый человек на нелюбимой работе делает беднее всех вокруг: меньше создаёт ценности, медленнее растёт, платит меньше налогов и добавляет обществу проблем. - Система роста программиста: джуна отличает любопытство («глаза горят»), мидла — способность самому довести пет-проект от и до, сеньора — умение оценивать чужие проекты и собирать вокруг себя комьюнити. - Пет-проект стоит затевать не ради одного фреймворка, а когда рядом накопился целый кластер смежных тем, про каждую из которых знаешь шапочно, — тогда один проект закрывает сразу несколько лакун. ### Главы - [00:14](https://apkhmv.xyz/podcast/episode-39/?t=14) Вступление: не совсем технический выпуск - [01:11](https://apkhmv.xyz/podcast/episode-39/?t=71) Как Александр пришёл к подкастам и «Проветримся» - [06:54](https://apkhmv.xyz/podcast/episode-39/?t=414) «Нейронная оборона» и путь Ивана в генеративные сети - [12:50](https://apkhmv.xyz/podcast/episode-39/?t=770) Юрген Йост: как учёный видит горящих людей - [18:05](https://apkhmv.xyz/podcast/episode-39/?t=1085) Письмо незнакомому учёному как способ сменить траекторию - [18:49](https://apkhmv.xyz/podcast/episode-39/?t=1129) Академическая карьера в ЕС: аспирантура и постдок - [30:28](https://apkhmv.xyz/podcast/episode-39/?t=1828) Будущее есть везде: против линейного мышления - [36:56](https://apkhmv.xyz/podcast/episode-39/?t=2216) Школьная травма: чтение, зубрёжка дат - [40:54](https://apkhmv.xyz/podcast/episode-39/?t=2454) Принцип POSIWID: смысл системы в том, что она делает - [44:47](https://apkhmv.xyz/podcast/episode-39/?t=2687) Чему учит школьный звонок и «Отупляя нас» - [57:57](https://apkhmv.xyz/podcast/episode-39/?t=3477) Индия против Европы: ответы или вопросы - [1:00:31](https://apkhmv.xyz/podcast/episode-39/?t=3631) Монтессори и воспитание агентности - [1:08:15](https://apkhmv.xyz/podcast/episode-39/?t=4095) Технооптимизм и три совета, как учиться после вуза - [1:12:04](https://apkhmv.xyz/podcast/episode-39/?t=4324) Любопытство, пет-проекты, сообщество - [1:20:44](https://apkhmv.xyz/podcast/episode-39/?t=4844) Джун, мидл, сеньор: система роста - [1:30:24](https://apkhmv.xyz/podcast/episode-39/?t=5424) Спорт, дозирование нагрузки и прощание ### Ссылки - [Подкаст «Проветримся» (подкаст Ивана Ямщикова)](https://provetrimsya.mave.digital) - [Learn How to Learn — курс на Coursera](https://www.coursera.org/learn/learning-how-to-learn) - [Sir Ken Robinson: How to escape education's death valley (TED)](https://www.ted.com/talks/sir_ken_robinson_how_to_escape_education_s_death_valley) - [John Taylor Gatto — «Dumbing Us Down»](https://newsociety.com/books/d/dumbing-us-down-25th-anniversary-edition) ## #38: Почему ClickHouse не тормозит - Markdown: https://apkhmv.xyz/podcast/episode-38/index.md - Гости: [Максим Кита](https://apkhmv.xyz/people/maxim-kita/index.md) Александр Пахомов и коммитер ClickHouse Максим Кита разбирают, почему самая популярная аналитическая база данных не тормозит: от разницы OLAP и OLTP и колоночного хранения до движков семейства `MergeTree`, агрегатных функций, проекций и `FINAL`. Во второй половине — инженерная культура ClickHouse: stateless-тесты вместо моков, фаззинг, Jepsen и `TLA+`, интроспекция и профилирование запросов через flame graph, а также разбор инцидента с высокой конкурентностью у одного крупного клиента, где глобальный mutex в контексте заменили на read-write. ### Главное - OLAP-базы хранят данные колоночно (структура массивов вместо массива структур), поэтому читают только нужные колонки и на аналитических запросах бывают в сотни-тысячи раз быстрее строковых OLTP-баз. - Похожие данные в одной колонке сжимаются кратно лучше, чем разнородный профиль строки целиком, — это второй множитель производительности после сокращения объёма чтения. - ClickHouse сознательно отказывается от универсальности (не претендует на OLTP/HTAP): жёсткие рамки для пользователя дают движку больше пространства для оптимизации. - Движки семейства `MergeTree` (`ReplacingMergeTree`, `AggregatingMergeTree`, `SummingMergeTree`) применяют логику к строкам с одинаковым первичным ключом во время фонового merge; `FINAL` применяет её на лету при чтении. - Агрегатная функция в ClickHouse — это тип данных с методами `create`/`merge`/`finalize`; `merge` двух состояний позволяет агрегировать в много потоков и хранить преагрегаты как в `AggregatingMergeTree`. - Проекция отличается от материализованного представления тем, что консистентна и лежит в том же куске данных, поэтому оптимизатор может прозрачно читать запрос из неё вместо основной таблицы. - ClickHouse тестируют не юнит-тестами с моками, а stateless-тестами через SQL-интерфейс плюс интроспекция (сколько прочитано байт, строк, засечек); всё гоняется под санитайзерами и фаззерами. - Инцидент TinyBird (10 000 запросов/сек) — это `Critical Sections Bound`: глобальный mutex контекста упирался в шедулер; починили, разделив mutex на глобальный и локальный и заменив на read-write. ### Главы - [00:07](https://apkhmv.xyz/podcast/episode-38/?t=7) Вступление: вторая серия про ClickHouse - [01:30](https://apkhmv.xyz/podcast/episode-38/?t=90) История с тормозящей базой на проде - [02:52](https://apkhmv.xyz/podcast/episode-38/?t=172) OLAP против OLTP: колоночное хранение - [10:31](https://apkhmv.xyz/podcast/episode-38/?t=631) Сжатие данных и два множителя производительности - [17:15](https://apkhmv.xyz/podcast/episode-38/?t=1035) HTAP, single store и Change Data Capture - [26:31](https://apkhmv.xyz/podcast/episode-38/?t=1591) Философия ClickHouse: рамки ради оптимизации - [31:30](https://apkhmv.xyz/podcast/episode-38/?t=1890) Агрегатные функции как тип данных - [36:51](https://apkhmv.xyz/podcast/episode-38/?t=2211) MergeTree, sparse-индекс и FINAL - [51:12](https://apkhmv.xyz/podcast/episode-38/?t=3072) Кликстрим, топ-5 сайтов и преагрегаты - [51:45](https://apkhmv.xyz/podcast/episode-38/?t=3105) Проекции против материализованных представлений - [1:01:54](https://apkhmv.xyz/podcast/episode-38/?t=3714) Транзакции в ClickHouse: Jepsen и TLA+ - [1:16:08](https://apkhmv.xyz/podcast/episode-38/?t=4568) Баги в алгоритмах: компараторы и бинарный поиск - [1:20:08](https://apkhmv.xyz/podcast/episode-38/?t=4808) Тестирование: stateless-тесты вместо моков - [1:29:02](https://apkhmv.xyz/podcast/episode-38/?t=5342) Memory leak с логерами и интроспекция - [1:38:13](https://apkhmv.xyz/podcast/episode-38/?t=5893) Профилирование запросов и flame graph - [1:53:06](https://apkhmv.xyz/podcast/episode-38/?t=6786) Физический план, executor и work-stealing - [2:05:13](https://apkhmv.xyz/podcast/episode-38/?t=7513) Инцидент TinyBird: Critical Sections Bound - [2:20:41](https://apkhmv.xyz/podcast/episode-38/?t=8441) Инженерная культура ClickHouse и контрибьютинг ### Ссылки - [ClickHouse — колоночная аналитическая база данных](https://clickhouse.com) - [TinyBird — real-time аналитика на ClickHouse](https://www.tinybird.co) - [Jepsen — тестирование распределённых систем](https://jepsen.io) ## #37: vas3k: CEO OF HTMX - Markdown: https://apkhmv.xyz/podcast/episode-37/index.md - Гости: [Вастрик](https://apkhmv.xyz/people/vas3k/index.md) Александр Пахомов зовёт в гости Вастрика (vas3k) — технологического блогера и основателя Вастрик-клуба — чтобы разобрать, на каком стеке живут его pet-проекты и почему инженерная простота — это не тупость, а опыт. Гость рассказывает, как из ЖЖ вырос блог на `Django` с `Postgres` в `Docker`, деплоем по `SSH` и одной машиной на Hetzner под `Cloudflare`, и объясняет главный тезис: код для себя и код на работе решают противоположные задачи. Финал — манифест против SPA и ода `HTMX` как «расширенному HTML» для бэкендеров. ### Главное - Код для pet-проекта и код на работе преследуют противоположные цели: первый ты пишешь, чтобы его было удобно поддерживать тебе будущему, второй — чтобы он «бил по рукам» многим другим людям после тебя. - Инди-стек Вастрик-клуба намеренно примитивен: `Django` + `Postgres` в `Docker Compose` на одной машине Hetzner, деплой по `SSH` из GitHub Actions, `volume` с базой на том же диске и ежедневный бэкап. - `Cloudflare` перед сервером закрывает кэширование статики, защиту от DDoS, бесплатный SSL и мини-аналитику — так блог переживал сотни тысяч просмотров в сутки на самой маленькой машине. - Ошибки продакшена ловит `Sentry` как error tracker (глобальный «try-catch» поверх приложения), а не как логер; в Java-мире его реже используют из-за культа настраиваемых логеров. - Выбор технологии почти не влияет на успех pet-проекта, а вот навредить может: бери язык, на котором пишешь «не приходя в сознание», иначе утонешь в проблемах новичка и забросишь проект. - Большие системы почти никогда не проектируются с нуля — они вырастают из «одноклеточного» MVP, который сначала проверяет гипотезу, а потом переписывается командой набело. - Инди-хакинг — это компания одного человека, которая делает десятки дешёвых продуктов в год ради одного выстрелившего; деньги приносит решение чужих проблем, а не сложность инфраструктуры. - `HTMX` — это «расширенный HTML»: любой тег может слать любой HTTP-запрос и получать в ответ кусок HTML для замены, поэтому интерактивность живёт поверх честных страниц без SPA и «фестиваля спиннеров». ### Главы - [00:00](https://apkhmv.xyz/podcast/episode-37/?t=0) Холодный старт: я ненавижу SPA - [01:54](https://apkhmv.xyz/podcast/episode-37/?t=114) Вступление: гость — vas3k - [04:33](https://apkhmv.xyz/podcast/episode-37/?t=273) Первая версия Вастрик-блога: ЖЖ, CMS, Django - [06:04](https://apkhmv.xyz/podcast/episode-37/?t=364) Таймлайн и инди-веб - [08:36](https://apkhmv.xyz/podcast/episode-37/?t=516) Эншитификация платформ и закрытые API - [11:54](https://apkhmv.xyz/podcast/episode-37/?t=714) Стек блога: Django, Markdown, тексты через БД - [20:54](https://apkhmv.xyz/podcast/episode-37/?t=1254) Cloudflare: кэш, DDoS, SSL - [24:47](https://apkhmv.xyz/podcast/episode-37/?t=1487) Sentry: error tracker против логеров - [27:52](https://apkhmv.xyz/podcast/episode-37/?t=1672) Одна тачка, Docker Compose и деплой по SSH - [35:47](https://apkhmv.xyz/podcast/episode-37/?t=2147) Дисклеймер: pet-проект против работы - [38:55](https://apkhmv.xyz/podcast/episode-37/?t=2335) Managed Postgres, Supabase и аналитика - [48:03](https://apkhmv.xyz/podcast/episode-37/?t=2883) Redis, async.io и многопоточность в Python - [55:47](https://apkhmv.xyz/podcast/episode-37/?t=3347) Философия инди-хакинга - [1:08:53](https://apkhmv.xyz/podcast/episode-37/?t=4133) Скиллы инди-хакинга против работы - [1:21:35](https://apkhmv.xyz/podcast/episode-37/?t=4895) Django и Postgres: бери, что знаешь - [1:25:07](https://apkhmv.xyz/podcast/episode-37/?t=5107) Фронтенд без SPA: Vue поверх HTML и HTMX ### Ссылки - [Вастрик-блог](https://vas3k.blog) - [Вастрик-клуб](https://vas3k.club) - [HTMX](https://htmx.org) - [Supabase — self-hosted Postgres](https://supabase.com) ## #36: LLVM: Rust, современный C++, как законтрибьютить - Markdown: https://apkhmv.xyz/podcast/episode-36/index.md - Гости: [Максим Кита](https://apkhmv.xyz/people/maxim-kita/index.md) Первый «хардкорный» выпуск: Александр Пахомов и Максим Кита (разработчик ClickHouse, контрибьютор компилятора Swift, коммитер LLVM) разбирают, как устроен современный компилятор — фронтенд, middle-end и бэкенд, `LLVM IR` в `SSA`-форме, basic-блоки и phi-ноды. По пути — почему на C++ тяжело писать без санитайзеров и `clang-tidy`, чем силён `borrow checker` в Rust, что такое compile-time-полиморфизм и `if constexpr`, как деление превращается в умножение, и как реально законтрибьютить в LLVM и компилятор Swift. ### Главное - Компилятор состоит из трёх слоёв: фронтенд переводит язык в промежуточное представление, middle-end оптимизирует его backend-агностично, а бэкенд генерирует ассемблер под конкретную архитектуру; `LLVM` — это middle-end плюс бэкенд, а фронтенды (`clang`, Rust, Swift) отдают ему `LLVM IR`. - `LLVM IR` — это ассемблер в форме `SSA` (static single assignment) с бесконечным числом регистров: код разбит на basic-блоки, а phi-ноды выбирают значение регистра в зависимости от того, из какой ветки пришло управление. - На C++ трудно писать безопасно: нужны юнит-, интеграционные и стресс-тесты, фаззеры с покрытием и прогон под всеми санитайзерами (address, memory, thread, undefined behavior), плюс включённые ворнинги и `clang-tidy`. - Compile-time-полиморфизм (`if constexpr`, шаблонное метапрограммирование, `SFINAE`) генерирует специализации на этапе компиляции без runtime-оверхеда; в ClickHouse так диспетчеризуют операции над колонками разных типов. - Деление — дорогая операция (64-битное может занимать порядка сотни тактов), поэтому компилятор заменяет деление на константу умножением и сдвигом; почти все операции выражаются через `and` и `not`. - Перформанс-тесты надёжнее гонять, сравнивая версию «до» и «после» одновременно на одной машине, а не два прогона в разные дни: так исключаются шумы окружения, а нестабильные тесты видно сразу. - Alive (`alive2`) верифицирует, что оптимизация `LLVM IR` корректна для всех входов — это как `TLA+` для распределённых систем, только для трансформаций компилятора; к пул-реквестам в LLVM прикладывают alive-proof. - Контрибьютить в LLVM просто: вся разработка на GitHub, есть лейбл `good first issue` и теги вроде performance/vectorizer; недавно процесс переехал с Phabricator на pull-request'ы, а изменение в мастере тут же подтягивается сабмодулем в ClickHouse. ### Главы - [00:08](https://apkhmv.xyz/podcast/episode-36/?t=8) Вступление: хардкорный выпуск с Максимом Кита - [01:29](https://apkhmv.xyz/podcast/episode-36/?t=89) Векторные базы, RAG-агенты и borrow checker в Rust - [03:33](https://apkhmv.xyz/podcast/episode-36/?t=213) Рефакторинг мьютексов в ClickHouse и thread safety - [09:44](https://apkhmv.xyz/podcast/episode-36/?t=584) Почему на C++ тяжело: санитайзеры, coverage, clang-tidy - [14:00](https://apkhmv.xyz/podcast/episode-36/?t=840) if constexpr, SFINAE и compile-time-полиморфизм - [25:59](https://apkhmv.xyz/podcast/episode-36/?t=1559) JIT, портируемый бинарник и инструкции SSE/AVX - [28:56](https://apkhmv.xyz/podcast/episode-36/?t=1736) M-процессоры, ARM и модель стоимостей - [33:11](https://apkhmv.xyz/podcast/episode-36/?t=1991) Как правильно мерить перформанс: до и после - [39:06](https://apkhmv.xyz/podcast/episode-36/?t=2346) Устройство компилятора: frontend, middle-end, backend - [44:14](https://apkhmv.xyz/podcast/episode-36/?t=2654) LLVM IR, SSA, basic-блоки и phi-ноды - [1:00:30](https://apkhmv.xyz/podcast/episode-36/?t=3630) Как контрибьютить в компилятор Swift - [1:05:18](https://apkhmv.xyz/podcast/episode-36/?t=3918) Книги по компиляторостроению и код LLVM - [1:20:19](https://apkhmv.xyz/podcast/episode-36/?t=4819) Деление через умножение и трюки оптимизатора - [1:23:43](https://apkhmv.xyz/podcast/episode-36/?t=5023) Пакетные менеджеры C++, сабмодули и версионирование - [1:35:15](https://apkhmv.xyz/podcast/episode-36/?t=5715) Как законтрибьютить в LLVM и инструмент Alive - [1:49:24](https://apkhmv.xyz/podcast/episode-36/?t=6564) Зачем контрибьютить в сложные проекты ### Ссылки - [LLVM](https://llvm.org) - [ClickHouse](https://clickhouse.com) - [Swift](https://www.swift.org) - [Clang Thread Safety Analysis](https://clang.llvm.org/docs/ThreadSafetyAnalysis.html) - [LLVM Kaleidoscope: My First Language Frontend](https://llvm.org/docs/tutorial/MyFirstLanguageFrontend/) - [Alive2 — верификация оптимизаций LLVM](https://github.com/AliveToolkit/alive2) - [Agner Fog — оптимизационные мануалы](https://www.agner.org/optimize/) ## #35: IntelliJ IDEA: самый популярный редактор для Java - Markdown: https://apkhmv.xyz/podcast/episode-35/index.md - Гости: [Даниил Овчинников](https://apkhmv.xyz/people/daniil-ovchinnikov/index.md) Специальный выпуск про устройство IntelliJ IDEA: Александр Пахомов расспрашивает разработчика JetBrains Даниила Овчинникова о том, из чего собран IDE изнутри. Разбирают разделение на платформу и плагины (поддержка Java — тоже плагин), `PSI` как абстрактное синтаксическое дерево «на стероидах» и пайплайн его построения (`Lexer` → парсер → `AST` → `PSI`), устройство автодополнения через вставку скрытого идентификатора `IntelliJ IDEA RULES`, модель экшенов и гетерогенный контекст, инкрементальный репарсинг, многослойное тестирование (парсинг, инспекции, quick fix, completion, property-тесты на `JetCheck`), а также вечный спор о форматах конфигурации (`XML` против `JSON`/`YAML`/`HOCON`) и планы вынести UI на Compose Multiplatform. ### Главное - В IntelliJ IDEA всё поделено на платформу и плагины: платформа — это общая, языконезависимая логика (например, сам экшен «показать документацию»), а всё языкоспецифичное (включая поддержку Java) вынесено в плагины. - `PSI` (Program Structure Interface) — это абстрактное синтаксическое дерево «на стероидах»: параллельная структура над `AST`, обогащённая семантикой (ссылки с методом `resolve`, типы), по которой IDE подсвечивает ошибки несовместимости типов. - Пайплайн построения дерева в Java-плагине: рукописный `Lexer` регулярками бьёт текст на токены, рукописный парсер собирает из них `AST`-ноды, а поверх `AST` строится `PSI`. - Автодополнение работает через вставку скрытого идентификатора `IntelliJ IDEA RULES` в копию файла: он даёт в дереве ссылку, которую можно `resolve` и предложить все имена в текущем скоупе. - Репарсинг инкрементальный: при вводе перепарсивается не весь файл, а только ближайший блок кода до первых фигурных скобок, поэтому автодополнение и подсветка работают быстро даже в больших файлах. - Экшен — это объект, который знает, как выполниться (по сути лямбда) и как показать себя в UI; по нажатию шортката в keymap находятся все подходящие экшены, каждый решает, доступен ли он в текущем контексте (гетерогенной мапе), затем применяются промоутеры. - В IntelliJ почти нет чистых юнит-тестов: тесты поднимают приложение и проект в памяти; отдельные фикстуры тестируют парсинг (текст → дерево), инспекции и quick fix (`Alt+Enter`), completion, а `property`-тесты на своей библиотеке `JetCheck` проверяют, что репарс блока даёт тот же результат, что и парсинг файла целиком. - Текстовые форматы конфигурации (`XML`) выбирают, чтобы избежать class-loading: вынос всего class-loading из UI-потока в фон сделал стартап IDE почти мгновенным; `XML` предпочтён `Kotlin`-DSL (не требует загрузки классов) и `YAML` (где `no` — Норвегия — парсится как `false`). ### Главы - [00:33](https://apkhmv.xyz/podcast/episode-35/?t=33) Гость выпуска: Даня Овчинников - [01:00](https://apkhmv.xyz/podcast/episode-35/?t=60) Строчки кода как метрика и большие рефакторинги - [05:12](https://apkhmv.xyz/podcast/episode-35/?t=312) Платформа против плагинов - [07:37](https://apkhmv.xyz/podcast/episode-35/?t=457) Голосовые сообщения в inlay: протёкшая абстракция - [12:07](https://apkhmv.xyz/podcast/episode-35/?t=727) Что такое PSI - [15:52](https://apkhmv.xyz/podcast/episode-35/?t=952) Как PSI строится: Lexer, парсер, AST - [25:08](https://apkhmv.xyz/podcast/episode-35/?t=1508) Автодополнение и «IntelliJ IDEA RULES» - [30:13](https://apkhmv.xyz/podcast/episode-35/?t=1813) Экшены и гетерогенный контекст - [35:44](https://apkhmv.xyz/podcast/episode-35/?t=2144) Extension points, Lombok и бандлы - [37:51](https://apkhmv.xyz/podcast/episode-35/?t=2271) Kotlin против Java в IDEA, переезд на JDK - [40:56](https://apkhmv.xyz/podcast/episode-35/?t=2456) Как всё это тестируется - [48:37](https://apkhmv.xyz/podcast/episode-35/?t=2917) XML против JSON, YAML и HOCON - [52:19](https://apkhmv.xyz/podcast/episode-35/?t=3139) Будущее: Compose Multiplatform и удалённый UI ### Ссылки - [IntelliJ Platform — открытая платформа для разработки инструментов](https://www.jetbrains.com/opensource/intellij-platform/) - [IntelliJ Community — исходный код на GitHub](https://github.com/JetBrains/intellij-community) - [Grammar-Kit — генератор лексера, парсера и PSI по BNF](https://github.com/JetBrains/Grammar-Kit) - [jetCheck — property-based тестирование от JetBrains](https://github.com/jetbrains/jetCheck) ## #34: Спэшл: Подготовка к FAANG и важность алгоритмов - Markdown: https://apkhmv.xyz/podcast/episode-34/index.md - Гости: [Дмитрий Волыхин](https://apkhmv.xyz/people/dmitry-volyhin/index.md) Большой «спэшл» с гостем — Дмитрием Волыхиным, ведущим подкаста Java Swag и лидером комьюнити FAANG Talks, который получил оффер в Meta. Вместе с Александром они подробно разбирают весь путь подготовки к интервью в big tech: почему это лотерея и стоит ли платить за буткемпы, как устроены три части собеседования (алгоритмы, system design, behavioral), сколько готовиться и как выбрать между «спринтом» и «марафоном». Отдельно — про моки, про 7 шагов system design, про метод STAR, про грейды и деньги (`levels.fyi`), релокацию и главный инсайт: подготовка к FAANG делает тебя сильнее как инженера здесь и сейчас. ### Главное - Интервью в FAANG — это во многом лотерея: имеет смысл повышать вероятность прохождения, подаваясь сразу в пул компаний, а не целясь в одну «компанию мечты». - Буткемп оправдан только если вам нужен внешний график и комьюнити; свой «буткемп» можно собрать бесплатно — найти единомышленников и созваниваться, разбирая задачи с `LeetCode`. - Для алго-интервью нужно знать язык досконально (сложности операций у `HashMap`, `ArrayList`, `LinkedList`), чтобы синтаксис был «на кончиках пальцев» и всё мыслетопливо уходило на саму задачу. - Алгоритмический бэкграунд сильно решает и не забывается, как езда на велосипеде; при его отсутствии «марафон» (~час в день) выгоднее «спринта», потому что накопленная база служит и в следующем цикле. - Ключевой навык алго-интервью — не написать идеальный код молча, а провести интервьюера по его чек-листу: уточнить условия и ограничения, предложить brute-force и улучшение, покрыть тесты и дебаг; поэтому обязательны моки на английском. - System design строится по ~7 шагам (функциональные/нефункциональные требования, back-of-the-envelope, high-level, low-level, scaling); на low-level нужно предлагать варианты, но не называть `Kafka` без пометки «alternatives», чтобы не утонуть в деталях и уложиться в 40 минут. - Behavioral-интервью меряет ваш грейд по масштабу решённых проблем; истории пишут в Google Doc по методу STAR (Situation, Task, Action, Result), по 2 истории на вопрос, и они должны матчиться с CV. - Компенсацию в big tech смотрят на `levels.fyi` с учётом location; помимо base есть стоки и бонусы, зарплата считается в год (не в месяц), а сама подготовка к интервью прокачивает как инженера и на текущей работе. ### Главы - [01:00](https://apkhmv.xyz/podcast/episode-34/?t=60) Вступление и знакомство с Димой - [03:19](https://apkhmv.xyz/podcast/episode-34/?t=199) Что такое FAANG (и MANGO) - [06:39](https://apkhmv.xyz/podcast/episode-34/?t=399) Буткемпы, курсы или готовиться самому - [11:02](https://apkhmv.xyz/podcast/episode-34/?t=662) Собес как ЕГЭ? Формат алго-интервью - [13:49](https://apkhmv.xyz/podcast/episode-34/?t=829) Роль алгоритмического бэкграунда - [19:01](https://apkhmv.xyz/podcast/episode-34/?t=1141) Сколько готовиться: спринт против марафона - [24:29](https://apkhmv.xyz/podcast/episode-34/?t=1469) Курсы, чат единомышленников, топ-ресурсы - [28:56](https://apkhmv.xyz/podcast/episode-34/?t=1736) Кривая подготовки и переход к system design - [41:29](https://apkhmv.xyz/podcast/episode-34/?t=2489) System design: 7 шагов, high- и low-level - [1:03:33](https://apkhmv.xyz/podcast/episode-34/?t=3813) System design без опыта, моки и рисовалки - [1:08:34](https://apkhmv.xyz/podcast/episode-34/?t=4114) Behavioral-интервью и метод STAR - [1:18:01](https://apkhmv.xyz/podcast/episode-34/?t=4681) Грейд, деньги, levels.fyi и релокация - [1:41:39](https://apkhmv.xyz/podcast/episode-34/?t=6099) Кринж-истории и польза подготовки ### Ссылки - [LeetCode — платформа для подготовки к алго-интервью](https://leetcode.com) - [levels.fyi — зарплаты и грейды в IT-компаниях](https://www.levels.fyi) - [Java Swag — подкаст Дмитрия Волыхина](https://javaswag.github.io) - [Курс по алгоритмам Роберта Седжвика (Coursera)](https://www.coursera.org/learn/algorithms-part1) - [Курс по алгоритмам Павла Маврина (ИТМО)](https://www.youtube.com/@pavelmavrin) - [Cracking the Coding Interview — Gayle Laakmann McDowell](https://www.crackingthecodinginterview.com) - [System Design Interview — Alex Xu](https://www.amazon.com/System-Design-Interview-insiders-Second/dp/B08CMF2CQF) - [Excalidraw — доска для схем на system design интервью](https://excalidraw.com) ## #33: Query optimizations: эвристики и cost-based - Markdown: https://apkhmv.xyz/podcast/episode-33/index.md - Гости: нет Финал второго сезона про базы данных. Александр Пахомов разбирает один из самых сложных компонентов СУБД — оптимизатор запросов: как выглядит план запроса и как по нему текут данные, три модели обработки (итератор, материализация, векторизация), методы доступа к данным (`sequential scan` с его оптимизациями и `index scan`), Halloween Problem и JIT-компиляцию выражений. Вторая половина — параллелизм: модели воркеров (процесс на воркер, тред на воркер, embedded), горизонтальное распараллеливание плана и место самого оптимизатора в конвейере от парсера до физического плана, где он применяет эвристики и cost-based-оптимизации на основе статистик. ### Главное - План запроса — это дерево операторов, по которому данные текут снизу вверх: внизу методы доступа (`sequential scan`, `index scan`), выше — фильтры, `JOIN`, агрегации и проекция на вершине. - Есть три модели обработки: итераторная (`next` по одному тюплу, самая распространённая), материализации (оператор целиком собирает результат в память — хороша для маленьких таблиц) и векторизации (`next` возвращает вектор тюплов, к которому применяются SIMD-инструкции — типична для аналитических СУБД вроде Snowflake и ClickHouse). - `sequential scan` — худший, но иногда единственный способ доступа; его оптимизируют prefetch-ем страниц, buffer pool bypass, параллельным чтением, late materialization и data skipping (approximate queries и zone maps с предпосчитанными агрегатами в заголовке страницы). - Halloween Problem — это когда `UPDATE` (например, надбавка тем, кто получает меньше 100k) многократно находит и снова повышает одну и ту же запись; решается трекингом id уже обновлённых в текущем запросе строк. - Некоторые СУБД (Postgres) умеют JIT-компилировать выражения `WHERE` в нативную C-функцию вместо интерпретации дерева выражения для каждого тюпла. - Параллельное выполнение повышает throughput и снижает latency; в plan-driven-модели СУБД сама шедулит воркеров (SQL Server реализует собственный слой поверх ОС с кооперативным `yield`), что умнее, чем полагаться на планировщик операционной системы, как делает модель «процесс на воркер» в Postgres. - Поиск оптимального плана — NP-полная задача, поэтому ищут не идеальный, а «достаточно хороший» план; оптимизатор работает уже после парсера, байндера (имена → id из системного каталога) и tree-rewriter-а, превращая логический план в физический с конкретными методами доступа и реализациями `JOIN`. - Оптимизации делятся на эвристики (predicate/projection pushdown, разбиение и слияние предикатов, разворачивание подзапросов в `JOIN`, отсечение всегда-`false` условий) и cost-based, опирающиеся на статистику: гистограммы, скетчи (`HyperLogLog`), сэмплы и магические константы вроде «оперативка в 400 раз быстрее диска» в Postgres. ### Главы - [00:21](https://apkhmv.xyz/podcast/episode-33/?t=21) Вступление: оптимизатор запросов и финал сезона - [01:06](https://apkhmv.xyz/podcast/episode-33/?t=66) Что такое план запроса и как текут данные - [03:39](https://apkhmv.xyz/podcast/episode-33/?t=219) Три модели обработки: итератор, материализация, векторизация - [09:14](https://apkhmv.xyz/podcast/episode-33/?t=554) Методы доступа: sequential scan и его оптимизации - [14:43](https://apkhmv.xyz/podcast/episode-33/?t=883) index scan, Halloween Problem и JIT-компиляция - [19:19](https://apkhmv.xyz/podcast/episode-33/?t=1159) Параллельное выполнение: throughput и latency - [22:00](https://apkhmv.xyz/podcast/episode-33/?t=1320) Модели воркеров и свой слой поверх ОС - [25:40](https://apkhmv.xyz/podcast/episode-33/?t=1540) Как распараллелить план: горизонтальный параллелизм - [29:32](https://apkhmv.xyz/podcast/episode-33/?t=1772) Место оптимизатора: от парсера до физического плана - [33:47](https://apkhmv.xyz/podcast/episode-33/?t=2027) Эвристики: pushdown, подзапросы, переписывание предикатов - [39:47](https://apkhmv.xyz/podcast/episode-33/?t=2387) Cost-based: косты, статистики и магические константы - [45:48](https://apkhmv.xyz/podcast/episode-33/?t=2748) Итог сезона и анонс распределённых баз данных ### Ссылки - Нет. ## #32: Merge sort и hash join: соединяют и сортируют - Markdown: https://apkhmv.xyz/podcast/episode-32/index.md - Гости: нет Продолжение сезона про базы данных. Александр Пахомов разбирает, как СУБД сортируют и соединяют таблицы, когда данные не влезают в оперативную память. Сначала — алгоритмы сортировки (`quicksort`, top-N heap sort, external merge sort) и их оптимизации (early/late materialization, prefetch, кодогенерация под типы, сравнение бинарных префиксов), затем hash aggregate для `GROUP BY`, и наконец три способа соединения таблиц — nested loop join, sort-merge join и hash join — с выводом, почему hash join обычно самый эффективный. ### Главное - План запроса (query-план) — дерево операторов: снизу операторы доступа к данным (`sequential scan`, `index scan`), выше — соединения, фильтрации и агрегации, а в корне — `SELECT` с нужными полями. - Реляционная алгебра не знает про порядок строк, поэтому сортировка нужна отдельно — для `ORDER BY`, `DISTINCT`, эффективной вставки в B+-дерево и группировки в `GROUP BY`. - Если таблица влезает в память — сортируем `quicksort`; при `LIMIT N` — top-N heap sort (куча размера `N` за один full scan); иначе — external merge sort с фазами «нарезать и отсортировать чанки» и «слить отсортированные пробеги». - External merge sort упирается в диск, поэтому применяют prefetch: I/O в одном потоке подгружает следующие страницы в буфер, пока CPU сортирует текущую. - Сравнение ключей оптимизируют кодогенерацией под конкретные типы (`int sort`, `string sort`) вместо указателя на функцию, а строки сравнивают по бинарным префиксам байтов с fallback на медленное посимвольное сравнение. - `GROUP BY` считают через hash aggregate: строят хеш-таблицу «ключ → running-агрегат»; если она не влезает в память — external hash aggregate раскладывает данные по бакетам на диск, затем делает `rehash` каждого бакета. - Из трёх join-алгоритмов nested loop join (даже блочный или с индексом) почти всегда худший; sort-merge join окупается, когда данные уже отсортированы на диске или результат нужно сортировать дальше. - Hash join строит хеш-таблицу по первой таблице (`linear probing`) и пробивает её второй; при нехватке памяти переходит в Grace hash join с партиционированием на диск и рекурсивным партиционированием при перекосе; Bloom-фильтр отсекает лишние обращения к хеш-таблице. ### Главы - [00:20](https://apkhmv.xyz/podcast/episode-32/?t=20) Вступление - [01:05](https://apkhmv.xyz/podcast/episode-32/?t=65) Query-план: дерево операторов - [02:26](https://apkhmv.xyz/podcast/episode-32/?t=146) Диск, память и зачем нужны сортировки - [05:00](https://apkhmv.xyz/podcast/episode-32/?t=300) Сортировка в памяти: quicksort и top-N heap sort - [06:06](https://apkhmv.xyz/podcast/episode-32/?t=366) External merge sort и early/late materialization - [08:37](https://apkhmv.xyz/podcast/episode-32/?t=517) External merge sort пошагово и prefetch - [11:54](https://apkhmv.xyz/podcast/episode-32/?t=714) Оптимизации сравнения: кодогенерация и бинарные префиксы - [14:05](https://apkhmv.xyz/podcast/episode-32/?t=845) Сортировка через B+-дерево индекс - [15:46](https://apkhmv.xyz/podcast/episode-32/?t=946) Hash aggregate для GROUP BY - [18:45](https://apkhmv.xyz/podcast/episode-32/?t=1125) Join: постановка и метрика I/O - [20:38](https://apkhmv.xyz/podcast/episode-32/?t=1238) Nested loop, sort-merge и hash join ### Ссылки - [Grace hash join — Wikipedia](https://en.wikipedia.org/wiki/Hash_join) - [Bloom filter — Wikipedia](https://en.wikipedia.org/wiki/Bloom_filter) ## #31: WAL: сердце любой базы данных - Markdown: https://apkhmv.xyz/podcast/episode-31/index.md - Гости: нет Выпуск про Write-Ahead Log — механизм, который обеспечивает атомарность и долговечность транзакций и лежит в сердце почти любой базы данных. Александр объясняет, зачем логировать изменения, если оперативная память быстрая, но недолговечна, разбирает политики буферизации (`steal`/`no-steal`, `force`/`no-force`) и альтернативу в виде shadow paging, а затем на пальцах проходит устройство самого лога (append-only, immutable, log records, checkpoint) и семейство алгоритмов восстановления ARIES с его фазами analysis, redo и undo. ### Главное - WAL решает сразу две задачи — как откатывать незавершённые транзакции и как восстанавливаться после сбоя, — обеспечивая атомарность и долговечность (`durability`) из `ACID`. - Перед коммитом транзакции хвост лога обязан быть сброшен на диск (`fsync`), но дорогие грязные страницы с данными на диск не пишутся сразу — они дозаписываются асинхронно; это и есть выигрыш WAL перед подходом «писать всё на каждый коммит». - Правило write-ahead: любая модификация страницы сначала записывается в лог и только потом применяется к странице в буфере — сначала декларируем намерение, затем совершаем действие. - Большинство баз данных работают по политике `steal` + `no-force` (можно писать незакоммиченные страницы на диск и не ждать записи страниц на коммите); альтернатива `no-steal` + `force` — это shadow paging с быстрым восстановлением, но дорогими random writes. - Лог — это append-only и immutable структура: писать можно только в конец, а неизменяемость гарантирует, что читающие при восстановлении процессы не увидят подмены данных под ногами. - Checkpoint отсекает уже сброшенную на диск часть лога, чтобы не читать её при восстановлении; современные базы используют неблокирующий fuzzy checkpoint (`begin`/`end`) вместо stop-the-world. - ARIES (Algorithms for Recovery and Isolation Exploiting Semantics) восстанавливает базу в три фазы: analysis (наполнение `active transaction table` и `dirty page table` от последнего checkpoint), redo (проигрывание изменений до состояния на момент краха) и undo (откат незакоммиченных транзакций). - Log Sequence Number (`LSN`) — монотонно растущий идентификатор записи лога; вместе с `prev-LSN` и page LSN он задаёт порядок и цепочки, а во время undo пишутся compensation log records (`CLR`), чтобы повторный сбой не откатывал одно и то же дважды. ### Главы - [00:21](https://apkhmv.xyz/podcast/episode-31/?t=21) Вступление: WAL — сердце базы данных - [01:02](https://apkhmv.xyz/podcast/episode-31/?t=62) Какую проблему решаем: быстрая, но недолговечная память - [02:43](https://apkhmv.xyz/podcast/episode-31/?t=163) Две задачи: откат и восстановление, трейд-оффы - [03:37](https://apkhmv.xyz/podcast/episode-31/?t=217) Альтернатива: писать всё на диск на каждый коммит - [05:35](https://apkhmv.xyz/podcast/episode-31/?t=335) Политики буферизации: steal/no-steal, force/no-force - [07:23](https://apkhmv.xyz/podcast/episode-31/?t=443) shadow paging и почему побеждает steal/no-force - [08:38](https://apkhmv.xyz/podcast/episode-31/?t=518) Устройство лога: append-only, immutable, log records - [10:23](https://apkhmv.xyz/podcast/episode-31/?t=623) Буфер лога, два строгих правила и grouped commit - [13:28](https://apkhmv.xyz/podcast/episode-31/?t=808) Физическое и логическое логирование, checkpoints - [16:45](https://apkhmv.xyz/podcast/episode-31/?t=1005) Восстановление и ARIES: LSN, CLR, ATT и DPT - [22:52](https://apkhmv.xyz/podcast/episode-31/?t=1372) Три фазы ARIES: analysis, redo, undo - [27:13](https://apkhmv.xyz/podcast/episode-31/?t=1633) Итог ### Ссылки - [ARIES — оригинальная статья Mohan et al. (ACM)](https://dl.acm.org/doi/10.1145/128765.128770) ## #30: LSM Tree: структура данных взрывает мозг - Markdown: https://apkhmv.xyz/podcast/episode-30/index.md - Гости: нет Юбилейный тридцатый выпуск про Log-Structured Merge Tree — структуру данных, оптимизированную под запись и ставшую основной альтернативой `B+`-деревьям в современных key-value-хранилищах. Александр Пахомов объясняет RUM-трейд-офф (read-update-memory) и слабые места `B+`-дерева на записи, разбирает устройство двух- и многокомпонентного LSM (дерево в памяти + write-ahead log + иммутабельные `SSTable` на диске, compaction по уровням, tombstone-удаления), показывает, почему чтение в LSM платит за быструю запись, и связывает популярность LSM с физикой SSD, который тоже пишет и стирает блоками журналируемо. ### Главное - LSM-дерево (`Log-Structured Merge Tree`) — по сути единственная реальная альтернатива `B+`-деревьям как низкоуровневому key-value-хранилищу базы данных. - RUM-гипотеза (read-update-memory) гласит, что из трёх параметров — чтение, запись и занимаемое место — одновременно можно оптимизировать только два; `B+`-дерево оптимизировано под чтение, LSM — под запись. - В `B+`-дереве точечный апдейт стоит двух дисковых операций (считать страницу целиком, изменить, записать 4 КБ обратно), а страницы держат ~30% свободного места про запас — из-за этого оно проседает под интенсивной записью. - Данные внутри LSM строго иммутабельны и `append-only`: апдейт добавляет новую версию записи, а удаление — специальный маркер `tombstone`; за счёт этого на низком уровне не нужны блокировки (latch'и). - Двухкомпонентный LSM — это дерево в памяти (плюс `write-ahead log` для recovery) и одно дерево на диске; на практике почти не встречается, повсеместно используется многокомпонентный вариант с множеством иммутабельных деревьев на диске. - Compaction — фоновый процесс, сливающий мелкие иммутабельные таблицы в более крупные по уровням; размер уровней растёт геометрически, что математически минимизирует число дисковых операций при слиянии. - Чтение в LSM медленнее, чем в `B+`-дереве: чтобы получить актуальное значение ключа, приходится открыть итераторы по всем деревьям, где он может лежать, собрать все версии и по timestamp выбрать последнюю (в помощь идут `Bloom`-фильтры и проверка границ ключей). - Популярность LSM исторически связана с SSD: журналируемая запись блоками и иммутабельность ложатся на физику твердотельного накопителя лучше, чем постраничный in-place-апдейт `B+`-дерева. ### Главы - [00:20](https://apkhmv.xyz/podcast/episode-30/?t=20) Вступление: юбилейный выпуск про LSM - [01:10](https://apkhmv.xyz/podcast/episode-30/?t=70) Зачем нужна структура, отличная от B+ дерева - [01:48](https://apkhmv.xyz/podcast/episode-30/?t=108) RUM-трейд-офф и слабые места B+ на записи - [05:19](https://apkhmv.xyz/podcast/episode-30/?t=319) Чтение против записи: цена апдейта в B+ - [07:44](https://apkhmv.xyz/podcast/episode-30/?t=464) LSM: иммутабельность, append-only, tombstone - [09:38](https://apkhmv.xyz/podcast/episode-30/?t=578) Плюсы иммутабельности: нет блокировок, экономия места - [11:41](https://apkhmv.xyz/podcast/episode-30/?t=701) Двухкомпонентный LSM: память + диск + WAL - [15:34](https://apkhmv.xyz/podcast/episode-30/?t=934) Многокомпонентный LSM и compaction по уровням - [20:12](https://apkhmv.xyz/podcast/episode-30/?t=1212) Почему чтение платит за быструю запись - [24:37](https://apkhmv.xyz/podcast/episode-30/?t=1477) SSTable, Bloom-фильтры, проверка границ - [28:02](https://apkhmv.xyz/podcast/episode-30/?t=1682) Инсайты: LSM и физика SSD, сквозные журналы - [33:00](https://apkhmv.xyz/podcast/episode-30/?t=1980) Итог: как выбирать хранилище под нагрузку ### Ссылки - [Database Internals — книга Алекса Петрова](https://www.databass.dev) - [RocksDB — встраиваемое key-value-хранилище на LSM](https://rocksdb.org) ## #29: Concurrency control: 2PL, OCC, MVCC - Markdown: https://apkhmv.xyz/podcast/episode-29/index.md - Гости: нет Продолжение сезона про базы данных: как СУБД на самом деле гарантируют уровни изоляции. Александр разбирает три протокола управления конкурентностью — пессимистичную двухфазную блокировку (2PL) с её строгой версией, детекцией дедлоков по waits-for-graph, гранулярностью и intention locks; оптимистическое управление (OCC) с private workspace и фазами чтения/валидации/записи; и мультиверсионность (MVCC), которая хранит несколько версий объекта, даёт snapshot isolation почти бесплатно и лежит в основе большинства современных СУБД. Попутно — таймстемп-ординг как теоретический фундамент, аномалия write skew, дефолтные уровни изоляции в Postgres, Oracle и Google Spanner, а также хранение версий, сборка мусора и вторичные индексы в MVCC. ### Главное - Блокировки в базах данных (`shared`/`exclusive`) поддерживают уровни изоляции транзакций и управляются отдельной подсистемой Lock Manager — это не то же самое, что мьютексы в языках программирования. - Двухфазная блокировка (2PL) делит жизнь транзакции на growing phase (только захват блокировок) и shrinking phase (только освобождение); строгая версия (strong strict 2PL) отпускает все блокировки лишь на коммите, что убирает каскадный откат. - Дедлоки неизбежны под нагрузкой: Lock Manager строит waits-for-graph, и цикл в нём означает дедлок — его разрывают, выбирая транзакцию-жертву и откатывая её. - Intention locks (`IS`, `IX`, `SIX`) — это не блокировки, а маркеры на родительском узле иерархии, позволяющие не обходить все тюплы, чтобы понять, можно ли взять блокировку на всю таблицу. - Базовый timestamp ordering не использует блокировок, а сравнивает read/write-таймстемпы у объекта; в чистом виде он неприменим из-за контеншена на запись метаданных, но лежит в основе реальных алгоритмов OCC и MVCC. - Optimistic concurrency control работает через private workspace и три фазы (чтение → валидация → запись); он идеален для read-only и непересекающихся транзакций, но долгие транзакции под ним страдают — фейл случается только на валидации в самом конце. - Даже под 2PL возможна аномалия фантомной записи (phantom read), поэтому serializable требует дополнительных приёмов — повторного чтения датасета, предикатных блокировок или index locking. - MVCC хранит несколько физических версий одного логического объекта: писатели не блокируют читателей и наоборот, snapshot isolation достигается почти бесплатно, но остаётся аномалия write skew; расплата — хранение версий, сборка мусора и обновление вторичных индексов. ### Главы - [00:20](https://apkhmv.xyz/podcast/episode-29/?t=20) Вступление: как СУБД гарантируют изоляцию - [01:16](https://apkhmv.xyz/podcast/episode-29/?t=76) Блокировки в базах данных: shared и exclusive - [04:40](https://apkhmv.xyz/podcast/episode-29/?t=280) Двухфазная блокировка (2PL) - [06:33](https://apkhmv.xyz/podcast/episode-29/?t=393) Каскадный откат и strong strict 2PL - [08:39](https://apkhmv.xyz/podcast/episode-29/?t=519) Дедлоки и waits-for-graph - [11:36](https://apkhmv.xyz/podcast/episode-29/?t=696) Гранулярность блокировок и intention locks - [16:22](https://apkhmv.xyz/podcast/episode-29/?t=982) Таймстемп-ординг без блокировок - [21:20](https://apkhmv.xyz/podcast/episode-29/?t=1280) Optimistic concurrency control - [27:15](https://apkhmv.xyz/podcast/episode-29/?t=1635) Фантомные записи и предикатные блокировки - [30:31](https://apkhmv.xyz/podcast/episode-29/?t=1831) Уровни изоляции: Postgres, Oracle, Spanner - [35:05](https://apkhmv.xyz/podcast/episode-29/?t=2105) MVCC: мультиверсионность - [41:12](https://apkhmv.xyz/podcast/episode-29/?t=2472) Хранение версий, сборка мусора, индексы - [46:04](https://apkhmv.xyz/podcast/episode-29/?t=2764) Заключение и анонс LSM-деревьев ### Ссылки - [PostgreSQL — уровни изоляции транзакций](https://www.postgresql.org/docs/current/transaction-iso.html) - [Google Cloud Spanner](https://cloud.google.com/spanner) ## #28: ACID transactions: аномалии и сериализуемость - Markdown: https://apkhmv.xyz/podcast/episode-28/index.md - Гости: нет Сольный выпуск из серии про базы данных. Александр Пахомов разбирает ACID-транзакции: сначала «зазубренный» ответ на собеседовании (атомарность, консистентность, изоляция, долговечность) с комментариями к каждому свойству и упоминанием реализаций через write-ahead log и shadow paging, а затем — главную часть про изоляцию. На аналогии со складом он объясняет аномалии параллельного исполнения (грязное и неповторяемое чтение, фантомы, потерянное обновление, грязная запись, write skew), выстраивает из них уровни изоляции вплоть до `serializable` и разбирает, что вообще стоит за сериализуемостью — конфликты, граф зависимостей и разница между conflict- и view-serializable. ### Главное - Транзакция — последовательность операторов одного клиента над базой данных: `begin transaction` открывает её, а `commit` или `abort`/`rollback` завершает. - ACID = Atomicity, Consistency, Isolation, Durability; атомарность нужна прежде всего для удобства программиста — группу изменений хочется выполнять как один осмысленный юнит «всё или ничего». - Атомарность и долговечность база обеспечивает в основном через write-ahead log; альтернатива — shadow paging (теневые страницы), как в copy-on-write-хранилище LMDB из 26-го выпуска, но так делают немногие. - Consistency в ACID (сохранение инвариантов и констрейнтов) — это совсем не то же, что буква C в CAP-теореме; их постоянно путают. - Все аномалии сводятся к одному: одна или несколько транзакций производят запись, а дальше в зависимости от того, кто пишет и кто читает, получаются non-repeatable read, phantom read, lost update, dirty read/write или write skew. - Уровни изоляции отличаются друг от друга набором допускаемых аномалий: `read uncommitted` разрешает всё, `read committed` убирает грязные чтения/записи, `repeatable read` — неповторяемые и фантомные чтения, `serializable` — ещё и write skew. - `serializable` даёт гарантию, что результат параллельного исполнения транзакций доказуемо совпадает с результатом какого-то последовательного (serial) их выполнения. - Conflict-serializable = граф зависимостей между операциями транзакций не содержит циклов; view-serializable — более широкий класс планов, но считать его дорого по CPU, поэтому в 99% случаев на практике речь про conflict-serializable. ### Главы - [00:20](https://apkhmv.xyz/podcast/episode-28/?t=20) Вступление: ACID и сериализуемость - [02:14](https://apkhmv.xyz/podcast/episode-28/?t=134) Простой ответ про ACID на собеседовании - [03:43](https://apkhmv.xyz/podcast/episode-28/?t=223) Атомарность, WAL и shadow paging - [06:12](https://apkhmv.xyz/podcast/episode-28/?t=372) Консистентность и путаница с CAP-теоремой - [07:52](https://apkhmv.xyz/podcast/episode-28/?t=472) Долговечность - [08:49](https://apkhmv.xyz/podcast/episode-28/?t=529) Изоляция и склад из 21-го выпуска - [12:47](https://apkhmv.xyz/podcast/episode-28/?t=767) Аномалии: грязное, неповторяемое, фантомное чтение - [15:08](https://apkhmv.xyz/podcast/episode-28/?t=908) Lost update, dirty write и write skew - [18:27](https://apkhmv.xyz/podcast/episode-28/?t=1107) Уровни изоляции: от read uncommitted до serializable - [21:45](https://apkhmv.xyz/podcast/episode-28/?t=1305) Что стоит за serializable: конфликты, граф, conflict- и view-serializable - [29:02](https://apkhmv.xyz/podcast/episode-28/?t=1742) Итог и анонс двухфазных блокировок ### Ссылки - Нет. ## #27: Хэш таблицы: функции и схемы хэширования - Markdown: https://apkhmv.xyz/podcast/episode-27/index.md - Гости: нет Выпуск сезона про базы данных: почему хэш-таблицы проиграли `B+`-деревьям гонку за звание главной структуры данных для индексов. Александр Пахомов разбирает устройство хэш-таблицы и её два ключевых архитектурных решения — выбор хэш-функции (trade-off «скорость против collision rate», от `MurmurHash` и `CityHash` до state-of-the-art `xxHash`) и схему хэширования: статические (linear probe, Robin Hood, cuckoo) и динамические (chained, extendable, linear hashing). ### Главное - Хэш-таблица — неупорядоченный ассоциативный массив, отображающий ключ на значение; позицию в массиве задаёт хэш-функция, а сложность поиска обычно `O(1)`, в худшем случае `O(n)`. Обычный массив — её вырожденный случай: ключ = индекс, хэш-функция тождественна, а произвольный хэш приводят к диапазону индексов остатком от деления на длину массива. - «Идеальная» хэш-функция без коллизий на практике недостижима, поэтому коллизии (один хэш для разных ключей) приходится разрешать всегда. - Выбор хэш-функции — trade-off между скоростью и collision rate: константа быстра, но даёт максимум коллизий; `xxHash` от автора `zstd` — state of the art, по throughput в 2–3 раза быстрее `MurmurHash` и `CityHash`. - В ячейках хранят пару ключ-значение, а не только значение: после позиционирования по `hashCode` нужен ещё `equals`, чтобы убедиться, что найден именно нужный ключ. - Linear probe hashing разрешает коллизию переходом к следующей ячейке; при удалении обязателен маркер (tombstone), иначе пустота оборвёт линейный скан и живой ключ «потеряется». - Cuckoo hashing держит `N` таблиц с `N` хэш-функциями (различаются только сидом): коллизия в одной таблице разрешается вставкой в другую, что резко снижает число коллизий. - Extendable hashing навигирует по битам хэша через global counter и при переполнении сплитит только переполненный бакет, удваивая ассоциативный массив, — старые страницы на диске не трогаются. - Индексы почти всегда строят на `B+`-дереве, а не на хэш-таблицах: `B+` даёт сопоставимый перформанс даже при чтении по единственному ключу и вдобавок умеет быстрое построение индекса на отсортированных данных, чтение по диапазону и эффективное отсортированное сканирование. ### Главы - [00:20](https://apkhmv.xyz/podcast/episode-27/?t=20) Вступление: слон в комнате — хэш-таблицы - [01:00](https://apkhmv.xyz/podcast/episode-27/?t=60) Что такое хэш-таблица - [01:43](https://apkhmv.xyz/podcast/episode-27/?t=103) Массив как хэш-таблица и остаток от деления - [03:52](https://apkhmv.xyz/podcast/episode-27/?t=232) Условия наивной таблицы, коллизии - [04:36](https://apkhmv.xyz/podcast/episode-27/?t=276) Два архитектурных решения: функция и схема - [07:50](https://apkhmv.xyz/podcast/episode-27/?t=470) Хэш-функции: MurmurHash, CityHash, xxHash - [11:01](https://apkhmv.xyz/podcast/episode-27/?t=661) Linear probe hashing и маркер удаления - [15:53](https://apkhmv.xyz/podcast/episode-27/?t=953) Robin Hood и cuckoo hashing - [19:46](https://apkhmv.xyz/podcast/episode-27/?t=1186) Динамические схемы: chained hashing - [24:01](https://apkhmv.xyz/podcast/episode-27/?t=1441) Extendable hashing по битам хэша - [29:19](https://apkhmv.xyz/podcast/episode-27/?t=1759) Linear hashing и split pointer - [31:40](https://apkhmv.xyz/podcast/episode-27/?t=1900) Итог: почему индексы строят на B+ ### Ссылки - [xxHash — extremely fast hash algorithm](https://github.com/Cyan4973/xxHash) - [MurmurHash](https://github.com/aappleby/smhasher) - [Google CityHash](https://github.com/google/cityhash) - [CMU 15-445 Database Systems — Hash Tables (Andy Pavlo)](https://15445.courses.cs.cmu.edu/) ## #26: Оптимизируем B+tree: копирование, пакетирование - Markdown: https://apkhmv.xyz/podcast/episode-26/index.md - Гости: нет Продолжение сезона про базы данных: разбор проблем классического B+tree и инженерных приёмов их решения. Александр Пахомов объясняет, зачем деревьям нужны защёлки (latches) и почему в мире СУБД «блокировки» и «защёлки» значат не то же, что в языках программирования, показывает метод latch crabbing с оптимистичным спуском, а затем разбирает две продакшен-оптимизации записи — copy-on-write B+tree (движок LMDB в OpenLDAP) и буферизацию дельт в Lazy/Buffered B+tree (движок WiredTiger в MongoDB). ### Главное - В мире СУБД термины перевёрнуты относительно языков программирования: «защёлка» (latch) синхронизирует потоки (это `mutex` / `read-write lock` из кода), а «блокировка» (lock) синхронизирует пользовательские транзакции на более высоком уровне. - `read-write lock` пускает много читателей одновременно, но лишь одного писателя, и на время записи блокирует всех; `mutex` — эксклюзивная блокировка на один поток независимо от чтения или записи. - Наивная поэтажная блокировка B-дерева сверху вниз превращает корень в узкое место — каждый поток держит на нём защёлку, и дерево фактически становится однопоточной структурой; так не делает ни одна СУБД. - Latch crabbing («крабинг») отпускает защёлку родителя сразу, как только взята защёлка потомка, — как краб на двух ножках, — поэтому корень заблокирован лишь на миг принятия решения. - Крабинг спускается оптимистично с read-защёлками, а при необходимости структурных изменений (каскад сплитов до корня) возвращается наверх и повторяет спуск уже с write-защёлками; из-за указателей между листьями возможны deadlock'и, которые решаются таймаутами и retry. - В copy-on-write B+tree страницы иммутабельны: запись копирует нужную страницу с изменением и порождает новую версию дерева, поэтому читателям не нужны защёлки — но они могут прочитать устаревшую версию данных. - Copy-on-write B+tree — не только теория: движок `LMDB` (Lightning Memory-Mapped Database) на его основе используется в OpenLDAP. - Buffered/Lazy B+tree не мутирует страницы при записи, а складывает дельты (`+1`, `−1`, …) в маленький буфер на страницу: чтение платит применением дельт, зато фоновый демон редко схлопывает буферы на диск — так устроен движок `WiredTiger` в MongoDB. ### Главы - [00:58](https://apkhmv.xyz/podcast/episode-26/?t=58) Напоминание: B+tree из 24-го выпуска - [01:48](https://apkhmv.xyz/podcast/episode-26/?t=108) Проблема 1: блокировки и защёлки (путаница терминов) - [03:06](https://apkhmv.xyz/podcast/episode-26/?t=186) Реализация защёлок: mutex и read-write lock - [04:50](https://apkhmv.xyz/podcast/episode-26/?t=290) Защёлки в B-дереве и гонки данных - [08:24](https://apkhmv.xyz/podcast/episode-26/?t=504) Latch crabbing: спуск «крабиком» - [10:45](https://apkhmv.xyz/podcast/episode-26/?t=645) Оптимистичный подход и deadlock - [12:59](https://apkhmv.xyz/podcast/episode-26/?t=779) Проблема 2: структурные изменения при записи - [13:21](https://apkhmv.xyz/podcast/episode-26/?t=801) Copy-on-write B+tree и LMDB / OpenLDAP - [16:46](https://apkhmv.xyz/podcast/episode-26/?t=1006) WiredTiger в MongoDB: буферизация дельт - [21:28](https://apkhmv.xyz/podcast/episode-26/?t=1288) Заключение ### Ссылки - [LMDB — Lightning Memory-Mapped Database](https://www.symas.com/lmdb) - [OpenLDAP](https://www.openldap.org) - [WiredTiger — storage engine](https://source.wiredtiger.com) - [MongoDB — WiredTiger storage engine](https://www.mongodb.com/docs/manual/core/wiredtiger/) ## #25: Buffer pools: почему БД реализуют часть ОС - Markdown: https://apkhmv.xyz/podcast/episode-25/index.md - Гости: нет Продолжение сезона про базы данных. Александр разбирает, как СУБД управляют памятью: что такое buffer pool, зачем нужны dirty pages и отложенная запись, чем опасен `fsync` (включая почти двадцатилетний баг в Postgres, из-за которого ошибка `fsync` приводила к потере данных) и почему поэтому многие базы пишут собственный кэш в обход ОС через `O_DIRECT`, несмотря на знаменитую отповедь Линуса Торвальдса. Во второй половине — политики вытеснения страниц: FIFO, LRU, 2Q, Clock и TinyLFU из библиотеки Caffeine. ### Главное - Buffer pool кэширует страницы БД в оперативной памяти: запросы идут не на диск, а в пул, и получают указатель на страницу, подгружая её с диска только при промахе. - Изменённые страницы помечаются как dirty pages и сбрасываются на диск не сразу, а пачками, чтобы не ходить на диск при каждой модификации; это ускоряет запись, но само по себе не гарантирует долговечность при сбое питания. - Чтобы гарантировать долговечность в buffered I/O, после `write` нужно вызвать `fsync`, но `fsync` сбрасывает на диск все грязные страницы кэша, а не одну — поэтому паттерн неоптимален. - Почти 20 лет Postgres неверно обрабатывал ошибку `fsync`: делал retry, но после первой ошибки ОС уже очищала грязные страницы из памяти, и повторный `fsync` затирал данные на диске. - ОС очищает грязные страницы после ошибки `fsync`, чтобы избежать утечки памяти (например, если `fsync` шёл на выдернутую флешку), — из-за этой универсальности страдают разработчики БД. - Свой buffer pool с флагом `O_DIRECT` даёт БД контроль (пиннинг горячих страниц, знание, что это узлы `B+`-дерева) в обход кэша ОС, против которого в 2007 году резко высказывался Линус Торвальдс. - FIFO как политика вытеснения не учитывает частоту и вымывает из кэша горячие страницы (корень дерева); LRU это чинит переносом обращённых страниц в конец очереди, но создаёт contention на одной структуре под конкуренцией. - Clock (модификация используется в Linux) прост и CAS-friendly: стрелка обходит кольцо страниц, гася бит доступа, и вытесняет ту, чей бит остался нулём; TinyLFU из Caffeine, наоборот, ищет кандидатов на сохранение через частотный фильтр и очереди приёма/испытания/защиты. ### Главы - [00:21](https://apkhmv.xyz/podcast/episode-25/?t=21) Вступление - [00:59](https://apkhmv.xyz/podcast/episode-25/?t=59) Кэширование и buffer pool - [02:46](https://apkhmv.xyz/podcast/episode-25/?t=166) Грязные страницы и отложенная запись - [04:42](https://apkhmv.xyz/podcast/episode-25/?t=282) Вытеснение страниц из пула - [05:07](https://apkhmv.xyz/podcast/episode-25/?t=307) Buffer pool ОС и флаг O_DIRECT - [06:53](https://apkhmv.xyz/podcast/episode-25/?t=413) buffered I/O, write и fsync - [08:24](https://apkhmv.xyz/podcast/episode-25/?t=504) 20-летний баг с fsync в Postgres - [12:21](https://apkhmv.xyz/podcast/episode-25/?t=741) Пиннинг страниц и оптимизация ссылок - [14:08](https://apkhmv.xyz/podcast/episode-25/?t=848) Политики замещения: FIFO, LRU, 2Q - [19:11](https://apkhmv.xyz/podcast/episode-25/?t=1151) Clock, CAS и TinyLFU (Caffeine) - [25:43](https://apkhmv.xyz/podcast/episode-25/?t=1543) Итог и анонс ### Ссылки - [PostgreSQL — управление памятью и shared buffers](https://www.postgresql.org/docs/current/runtime-config-resource.html) - [Caffeine — high-performance caching library для Java](https://github.com/ben-manes/caffeine) ## #24: Лучшая структура данных: B-tree, B+tree - Markdown: https://apkhmv.xyz/podcast/episode-24/index.md - Гости: нет Продолжение сезона про базы данных. Александр Пахомов объясняет, почему главной структурой данных в индексах стало именно B-дерево: сначала на пальцах разбирает бинарное дерево поиска, его инвариант и вырождение в список, затем — балансировку и логарифмический поиск, и показывает, почему бинарные деревья не годятся для диска (большая высота → много случайных чтений). Дальше на примере библиотеки с указателями на стеллажах он раскрывает устройство `B+tree` (внутренние узлы-указатели, листовые узлы с данными, связанный список листьев для sequential scan) и объясняет, чем оно лучше классического `B-tree`. ### Главное - Бинарное дерево поиска держит инвариант «слева строго меньше, справа строго больше», что даёт бинарный поиск, но без балансировки может выродиться в список со сложностью `O(N)`. - Сбалансированное дерево (глубина левого и правого поддеревьев различается не более чем на единицу) даёт поиск за `O(log₂ N)`: в дереве из 1024 элементов — максимум 10 переходов по указателям. - Баланс не поддерживается сам собой — при каждой вставке и удалении структура проверяется и указатели при необходимости переставляются. - Бинарные деревья не годятся для диска: степень ветвления 2 делает дерево высоким, а множество переходов по указателям превращается в множество случайных чтений (random seek), которые на диске медленны. - Для диска нужна структура с высокой степенью ветвления и низкой высотой — этим и берёт `B-tree`; поэтому внутри индексов почти всегда лежит именно оно. - Когда говорят `B-tree`-индекс, почти всегда имеют в виду `B+tree`: внутренние узлы хранят только пары «указатель — ключ» (обычно в слотированной странице), а сами данные (пары ключ-значение) лежат только в листовых узлах. - Листовые узлы `B+tree` связаны в список (связанный список связанных списков), что даёт быстрый sequential/full scan без «американских горок» вверх-вниз по дереву, которыми страдает классический `B-tree`. - Инвариант заполнения гарантирует, что каждый узел занят не меньше чем наполовину: при переполнении узел разделяется или часть данных переливается в соседний, при недозаполнении узлы сливаются — всё ради минимизации числа страниц и случайных чтений. ### Главы - [00:21](https://apkhmv.xyz/podcast/episode-24/?t=21) Вступление: B-дерево в индексах - [01:04](https://apkhmv.xyz/podcast/episode-24/?t=64) Просьба поддержать подкаст - [01:50](https://apkhmv.xyz/podcast/episode-24/?t=110) Бинарное дерево поиска и его инвариант - [04:07](https://apkhmv.xyz/podcast/episode-24/?t=247) Вырождение в список и балансировка - [06:09](https://apkhmv.xyz/podcast/episode-24/?t=369) Поиск по ключу, а не «да/нет» - [06:57](https://apkhmv.xyz/podcast/episode-24/?t=417) Почему бинарные деревья не годятся для диска - [08:11](https://apkhmv.xyz/podcast/episode-24/?t=491) B+tree: аналогия с библиотекой - [09:41](https://apkhmv.xyz/podcast/episode-24/?t=581) Устройство внутренних узлов B+tree - [11:24](https://apkhmv.xyz/podcast/episode-24/?t=684) Листовые узлы и связанный список для scan - [13:57](https://apkhmv.xyz/podcast/episode-24/?t=837) Заполнение узлов, вставка и удаление - [16:24](https://apkhmv.xyz/podcast/episode-24/?t=984) B+tree против B-tree и итог ### Ссылки - [Andy Pavlo — CMU Intro to Database Systems](https://15445.courses.cs.cmu.edu) - [B+ Tree Visualization (David Galles, USF)](https://www.cs.usfca.edu/~galles/visualization/BPlusTree.html) ## #23: SSD и HDD: устройство дисков и слотированные страницы - Markdown: https://apkhmv.xyz/podcast/episode-23/index.md - Гости: нет Выпуск второго сезона про базы данных. Александр Пахомов объясняет, как внутреннее устройство накопителей — механическая головка HDD и блочная организация SSD (ячейка → строка → массив → страница → блок, где чтение и запись идут страницами, а удаление — блоками) — диктует примитивы, которыми оперируют хранилища. Разбирает иерархию памяти и таблицу задержек «Latency Numbers Every Programmer Should Know», а затем — устройство страницы в базе данных: заголовок и записи, фрагментацию с дефрагментацией и в итоге слотированные страницы (slotted pages) со слот-массивом, растущим навстречу данным. ### Главное - HDD — это магнитные пластины со считывающей головкой; перемещение головки (random seek) — медленная механическая операция, поэтому базы данных оптимизируют под последовательное чтение и запись и минимизируют случайные обращения. - В SSD головки нет, а память организована иерархически: ячейка → строка → массив → страница → блок; минимальная единица чтения и записи — страница (обычно 4 КБ), а минимальная единица удаления — блок. - Из-за поблочного удаления страницы часто лишь помечают как удалённые, а не стирают физически: соседняя страница в том же блоке может быть ещё не готова к удалению. - Иерархия хранилищ делится на volatile (регистры, CPU cache, RAM — быстрый побайтовый random access, но теряется при выключении) и non-volatile (SSD, HDD, сеть — блочный доступ, но данные сохраняются). - Таблица «Latency Numbers Every Programmer Should Know»: регистр ~1 нс, CPU cache ~4 нс, RAM ~100 нс, SSD ~16 000 нс, HDD ~2 000 000 нс, сеть ~50 000 000 нс — в человеческом масштабе это 1 с, 4 с, 100 с, 4,5 часа, 3,5 недели и полтора года. - Базы данных хранят данные в страницах фиксированного размера (обычно 4 КБ); страница идентифицируется id, который мапится на физическое смещение на диске, а страницы собираются в файлы — например, в `heap`-файл. - Страница состоит из заголовка (`header`, ~5–10%: размер, чек-сумма, версия формата, транзакционные данные) и записей-`tuple`; записи переменной длины при удалении из середины ведут к фрагментации, с которой борются дефрагментацией. - В слотированной странице (`slotted page`) сразу за заголовком идёт слот-массив смещений, растущий слева направо, а сами записи пишутся с конца страницы справа налево; клиенты ссылаются на записи через слоты, поэтому дефрагментация незаметна и не требует блокировок. ### Главы - [00:21](https://apkhmv.xyz/podcast/episode-23/?t=21) Вступление: как жёсткий диск сменился на SSD - [02:49](https://apkhmv.xyz/podcast/episode-23/?t=169) HDD: магнитный диск, головка и random seek - [04:20](https://apkhmv.xyz/podcast/episode-23/?t=260) SSD: ячейки, страницы и блоки - [05:37](https://apkhmv.xyz/podcast/episode-23/?t=337) Почему нам вообще приходится идти на диск - [06:49](https://apkhmv.xyz/podcast/episode-23/?t=409) Иерархия хранилищ: volatile и non-volatile - [08:39](https://apkhmv.xyz/podcast/episode-23/?t=519) Latency Numbers Every Programmer Should Know - [11:15](https://apkhmv.xyz/podcast/episode-23/?t=675) Как базы данных представляют данные: страницы - [13:34](https://apkhmv.xyz/podcast/episode-23/?t=814) Устройство страницы: заголовок и записи - [17:13](https://apkhmv.xyz/podcast/episode-23/?t=1033) Переменные записи, фрагментация и дефрагментация - [19:53](https://apkhmv.xyz/podcast/episode-23/?t=1193) Слотированные страницы (slotted pages) - [24:56](https://apkhmv.xyz/podcast/episode-23/?t=1496) Итог и не-хэппи-энд истории с диском ### Ссылки - [Latency Numbers Every Programmer Should Know](https://gist.github.com/jboner/2841832) - [CMU 15-445/645 — Intro to Database Systems (Andy Pavlo)](https://15445.courses.cs.cmu.edu/) - [Apache Ignite — распределённая база данных](https://ignite.apache.org) ## #22: Архитектура баз данных: компоненты и классификация - Markdown: https://apkhmv.xyz/podcast/episode-22/index.md - Гости: нет Второй выпуск сезона про базы данных. Через развёрнутую аналогию с сортировочным складом Александр Пахомов разбирает верхнеуровневую архитектуру почти любой СУБД — транспортный уровень, обработчик запросов с оптимизатором, подсистему выполнения и подсистему хранилища (диспетчеры транзакций, блокировок, буфера, восстановления и средства доступа), — а затем классифицирует базы данных по методам хранения: OLTP против OLAP, in-memory против дисковых, строковые против колоночных. В финале — идея композируемости: современные СУБД собираются из переиспользуемых блоков, но абстракции между слоями неизбежно текут ради скорости. ### Главное - Почти любая СУБД состоит из четырёх слоёв: транспортный уровень, обработчик запросов (парсер + оптимизатор), подсистема выполнения и подсистема хранилища. - Транспортный уровень двусторонний: одна подсистема общается с клиентом, другая — между нодами кластера, и они могут переиспользовать общий код. - Обработчик запросов сперва парсит и валидирует запрос (включая проверку доступа к объектам), а затем оптимизатор строит план запроса — дерево исполнения, которое видно через `EXPLAIN`. - Подсистема выполнения бывает локальной (`JOIN`-ы, сортировки, агрегации, чтение и запись данных) и удалённой (передать запрос или его часть на другую ноду). - Подсистема хранилища — самая сложная: диспетчер транзакций, диспетчер блокировок, средства доступа (`LSM`- или `B-Tree`-деревья), диспетчер буфера и диспетчер восстановления. - Большинство СУБД не полагаются на виртуальную память ОС для кэширования страниц, а реализуют собственный диспетчер буфера — это осознанное решение. - OLTP-базы (Postgres, Oracle) оптимизированы под частые одиночные чтения и записи и обычно строковые; OLAP-базы оптимизированы под редкие тяжёлые аналитические запросы и обычно колоночные. - Колоночное хранение выигрывает на агрегатах по одному полю (векторные `SIMD`-инструкции, лучшее сжатие однотипных данных), но проигрывает строковому на выборке всех полей одной записи. ### Главы - [00:20](https://apkhmv.xyz/podcast/episode-22/?t=20) Вступление: компоненты и классификация БД - [01:10](https://apkhmv.xyz/podcast/episode-22/?t=70) Аналогия со складом - [04:04](https://apkhmv.xyz/podcast/episode-22/?t=244) Склад как база данных: расшифровка аналогии - [05:53](https://apkhmv.xyz/podcast/episode-22/?t=353) Четыре слоя и транспортный уровень - [06:23](https://apkhmv.xyz/podcast/episode-22/?t=383) Обработчик запросов: парсер и оптимизатор - [08:04](https://apkhmv.xyz/podcast/episode-22/?t=484) Подсистема выполнения: локальная и удалённая - [08:44](https://apkhmv.xyz/podcast/episode-22/?t=524) Подсистема хранилища и её диспетчеры - [11:39](https://apkhmv.xyz/podcast/episode-22/?t=699) Чем различаются БД: OLTP и OLAP - [14:38](https://apkhmv.xyz/podcast/episode-22/?t=878) In-memory против дисковых баз данных - [16:07](https://apkhmv.xyz/podcast/episode-22/?t=967) Колоночные против строковых хранилищ - [20:20](https://apkhmv.xyz/podcast/episode-22/?t=1220) Композируемость: переиспользование блоков ### Ссылки - Нет. ## #21: Введение в базы данных: История и SQL - Markdown: https://apkhmv.xyz/podcast/episode-21/index.md - Гости: нет Первый выпуск второго сезона, посвящённого базам данных. Александр Пахомов объясняет, почему глубокое, а не поверхностное понимание баз данных важнее знания конкретного языка, фреймворка или СУБД, прослеживает историю от реляционных систем 70-х через NoSQL и NewSQL до облачных и shared-disk-решений, а затем освежает ключевые концепции SQL: `SELECT`/`WHERE`, агрегаты, `GROUP BY`/`HAVING`, `JOIN`, оконные функции и common table expressions. ### Главное - Глубокое понимание алгоритмов и внутреннего устройства баз данных ценнее знания конкретного языка, фреймворка или СУБД: подход language-agnostic масштабируется до framework-agnostic и database-agnostic. - Реляционные базы данных появились в середине 70-х, победили конкурентов к 80-м (Oracle, Ingres → Postgres, Informix, DB2), а в 90-х начался их бум (MS SQL Server, MySQL, Postgres, SQLite). - `NoSQL` расшифровывается как Not Only SQL; такие системы (документные, key-value) жертвовали схемой и `ACID`-транзакциями ради масштабируемости в эпоху интернет-бума 2000-х. - NewSQL-системы 2010-х (Google Spanner, CockroachDB, YugabyteDB, Apache Ignite 3) совмещают распределённость, `SQL` и полноценные транзакции. - В shared-disk-архитектуре (Spark, Snowflake, Redshift, Impala) файловая система (`HDFS`, `S3`) — общая абстракция, а масштабируется отдельный слой compute; это противопоставлено shared-nothing. - `SQL` — не язык программирования, а стандарт: базовый уровень совместимости — `SQL-92`, последний принятый стандарт — 2016 года, стандарт 2023 добавляет графовые запросы. - Без явных `DISTINCT` или `ORDER BY` результат `SQL`-запроса не является множеством и не отсортирован — в нём могут быть дубли; сортировка по умолчанию замедлила бы и чтение, и вставку. - `WHERE` фильтрует строки до агрегации, `HAVING` накладывает предикат уже на результат агрегации; рекурсивные CTE (`WITH RECURSIVE`) по сути задают рекурсивную функцию. ### Главы - [00:20](https://apkhmv.xyz/podcast/episode-21/?t=20) Вступление: второй сезон про базы данных - [01:48](https://apkhmv.xyz/podcast/episode-21/?t=108) Базы данных на собеседовании — сложный топик - [05:58](https://apkhmv.xyz/podcast/episode-21/?t=358) language-, framework- и database-agnostic - [11:50](https://apkhmv.xyz/podcast/episode-21/?t=710) История баз данных: 60-е — 90-е - [15:01](https://apkhmv.xyz/podcast/episode-21/?t=901) NoSQL и Not Only SQL - [16:12](https://apkhmv.xyz/podcast/episode-21/?t=972) NewSQL: распределённость плюс транзакции - [17:05](https://apkhmv.xyz/podcast/episode-21/?t=1025) Облако и shared-disk-системы - [20:05](https://apkhmv.xyz/podcast/episode-21/?t=1205) Графовые и time series базы данных - [22:04](https://apkhmv.xyz/podcast/episode-21/?t=1324) Что их объединяет: SQL - [23:20](https://apkhmv.xyz/podcast/episode-21/?t=1400) SQL как стандарт и основы запросов - [28:54](https://apkhmv.xyz/podcast/episode-21/?t=1734) GROUP BY, HAVING, функции и их причуды - [35:05](https://apkhmv.xyz/podcast/episode-21/?t=2105) ORDER BY, LIMIT, оконные функции, CTE - [38:42](https://apkhmv.xyz/podcast/episode-21/?t=2322) Итог и анонс следующего выпуска ### Ссылки - [Apache Ignite — распределённая база данных](https://ignite.apache.org) - [CockroachDB — distributed SQL database](https://www.cockroachlabs.com) - [Google Cloud Spanner](https://cloud.google.com/spanner) - [Neo4j — графовая база данных](https://neo4j.com) - [Apache Hadoop (HDFS)](https://hadoop.apache.org) ## #20: Выживает сильнейший: генетические алгоритмы - Markdown: https://apkhmv.xyz/podcast/episode-20/index.md - Гости: нет Юбилейный двадцатый выпуск без гостей. Александр Пахомов рассказывает про свой магистерский диплом — «мертворождённый» инструмент, который генетическим алгоритмом писал бы юнит-тесты на Java-код. По пути он даёт вводную в теорию тестирования (классы эквивалентности, критерии покрытия от строк до MC/DC, мутационное тестирование, фазинг и Search-Based Software Testing), разбирает устройство абстрактного генетического алгоритма и объясняет, как он спроецировал его понятия — популяцию, гены, функцию приспособленности, мутацию и скрещивание — на генерацию тестов, а в конце признаёт, что как продукт затею убил Copilot. ### Главное - Search-Based Software Testing сводит генерацию тестов к задаче оптимизации: тесты генерируются и уточняются, пока критерий покрытия не достигнет 100% или не выйдет тайм-аут. - Класс эквивалентности — это подмножество входных данных, приводящих к одному и тому же пути исполнения кода; для тест-кейсов берут по одному представителю из каждого класса плюс значения на границах. - Покрытие строк (line coverage) считать легче всего, но оно ломается при рефакторинге (тернарник → `if/else`); покрытие ветвлений и условий адекватнее, но требует экспоненциально больше входных данных. - Критерий MC/DC оставляет только значимые тесты: каждый следующий кейс меняет ровно один входной параметр так, чтобы поменялся результат, — генерация останавливается, когда такого изменения больше не найти. - Мутационное тестирование проверяет качество тестов, внося мелкие мутации в исходный код (например, меняя знак сравнения): если тест не «падает» на мутанте, он плохой. - В генетическом алгоритме мутация нужна, чтобы вырваться из локального максимума: без случайных изменений генов популяция застревает и никогда не достигает глобального оптимума. - При проекции генетического алгоритма на тесты особь — это тестовый класс, гены — его методы, помеченные `@Test`, а функция приспособленности — достигнутое тестами покрытие кода. - Как продукт идею убил Copilot: генетический алгоритм — «долгая фигня», а генеративные модели пишут тесты быстрее; как исследовательский проект диплом прокачал навык ресёрча и не был потрачен зря. ### Главы - [00:20](https://apkhmv.xyz/podcast/episode-20/?t=20) Вступление: юбилейный 20-й выпуск - [01:06](https://apkhmv.xyz/podcast/episode-20/?t=66) Идея диплома: тесты для legacy-кода - [06:05](https://apkhmv.xyz/podcast/episode-20/?t=365) Как я писал диплом: LaTeX, GitHub, без научрука - [10:37](https://apkhmv.xyz/podcast/episode-20/?t=637) Теория тестирования: классы эквивалентности - [15:08](https://apkhmv.xyz/podcast/episode-20/?t=908) Структурное тестирование и критерии покрытия - [19:51](https://apkhmv.xyz/podcast/episode-20/?t=1191) MC/DC: только значимые тесты - [22:30](https://apkhmv.xyz/podcast/episode-20/?t=1350) Тестирование с помощью ИИ: мутации и фазинг - [25:14](https://apkhmv.xyz/podcast/episode-20/?t=1514) Search-Based Software Testing - [26:32](https://apkhmv.xyz/podcast/episode-20/?t=1592) Как устроен генетический алгоритм - [30:53](https://apkhmv.xyz/podcast/episode-20/?t=1853) Генетический алгоритм для генерации Java-тестов - [38:41](https://apkhmv.xyz/podcast/episode-20/?t=2321) Выводы: стоило ли оно того, и олдскульная полезняшка ### Ссылки - [Kent Beck — Test-Driven Development: By Example](https://www.oreilly.com/library/view/test-driven-development/0321146530/) - [The Fuzzing Book — интерактивный учебник по фазингу и генерации тестов](https://www.fuzzingbook.org/) - [jqwik — property-based testing для JVM](https://jqwik.net/) - [Testcontainers (AtomicJar)](https://testcontainers.com/) - [Максим Ильяхов, Людмила Сарычева — «Пиши, сокращай»](https://sokratil.ru/) - [LanguageTool — проверка орфографии и грамматики](https://languagetool.org/) - [Алексей Шипилёв — «Fork/Join» (доклад, JEEConf 2012)](https://shipilev.net/talks/jeeconf-May2012-forkjoin.pdf) ## #19: Выдал базу: три важнейших вещи в разработке - Markdown: https://apkhmv.xyz/podcast/episode-19/index.md - Гости: нет Сольный выпуск по мотивам «Программиста-прагматика». Александр Пахомов размышляет об оптимальном размере команды (5–7 человек) и о пользе функциональных команд, способных выдавать end-to-end результат, разбирает происхождение термина «карго-культ» и его проявления в скраме, а затем формулирует три практики из Pragmatic Starter Kit, которые должны быть в любом проекте: система контроля версий, тестирование и полная автоматизация. В финале — идея, что инженер прежде всего problem solver, призыв «подписывать свою работу» и наводка на YouTube-канал Computerphile. ### Главное - Оптимальный размер команды — примерно 5–7 человек: столько контекстов реально удержать в голове, а сверх этого команда превращается в набор людей под общим названием. - Команда эффективнее всего, когда способна выдать end-to-end результат («трассирующий выстрел») — неполную, но работающую фичу, по которой сразу видно, туда ли идёт разработка. - Функциональная команда (бэкенд, фронтенд, мобилка в одном юните) минимизирует межкомандные зависимости; при разделении по слоям координация двух команд усложняет доставку. - Не нужно копировать процессы Netflix или Spotify (трайбы, гильдии): вы не они — практику надо выбирать под свой контекст и проверять экспериментом, а не по карго-культу. - Карго-культ — из реального «культа даров небесных» в Меланезии: островитяне строили аэродромы из соломы, копируя форму без понимания причин; так же слепое следование ритуалам скрама имитирует форму без результата. - Три обязательные практики любого проекта (Pragmatic Starter Kit): система контроля версий, регрессионное тестирование и полная автоматизация (CI/CD). - Тесты надо проверять: хороший тест обязан ловить баги, поэтому в код вносят багу и смотрят, что тест перешёл из красного в зелёный (как в TDD); мутационное тестирование автоматизирует это, разворачивая условия в `source code`. - Инженер — это problem solver, а не «кодер»: он доставляет value кодом, конфигом, ресёрчем или `kill -9`, а способ решения — деталь имплементации; свою работу стоит «подписывать». ### Главы - [00:20](https://apkhmv.xyz/podcast/episode-19/?t=20) Вступление и постановка тем - [00:53](https://apkhmv.xyz/podcast/episode-19/?t=53) Оптимальный размер команды - [02:56](https://apkhmv.xyz/podcast/episode-19/?t=176) Функциональные команды и трассирующий выстрел - [08:03](https://apkhmv.xyz/podcast/episode-19/?t=483) Айдентика команды: имена и символы - [10:21](https://apkhmv.xyz/podcast/episode-19/?t=621) Карго-культ: происхождение термина - [12:00](https://apkhmv.xyz/podcast/episode-19/?t=720) Карго-культ в разработке и критическое мышление - [14:35](https://apkhmv.xyz/podcast/episode-19/?t=875) Pragmatic Starter Kit и система контроля версий - [16:33](https://apkhmv.xyz/podcast/episode-19/?t=993) Тестирование и регрессионное тестирование - [17:33](https://apkhmv.xyz/podcast/episode-19/?t=1053) Тестирование тестов и мутационное тестирование - [21:39](https://apkhmv.xyz/podcast/episode-19/?t=1299) Автоматизация и CI/CD как источник кайфа - [26:58](https://apkhmv.xyz/podcast/episode-19/?t=1618) Инженер как problem solver - [29:17](https://apkhmv.xyz/podcast/episode-19/?t=1757) Sign your work и open source - [32:19](https://apkhmv.xyz/podcast/episode-19/?t=1939) Полезняшка: канал Computerphile ### Ссылки - [The Pragmatic Programmer — Andrew Hunt, David Thomas](https://pragprog.com/titles/tpp20/the-pragmatic-programmer-20th-anniversary-edition/) - [Computerphile — YouTube-канал](https://www.youtube.com/user/Computerphile) - [Testcontainers для Java](https://java.testcontainers.org) - [progressbar — библиотека прогресс-баров для терминала на Java](https://github.com/ctongfei/progressbar) ## #18: Спэшл: положение дел, YouTube - Markdown: https://apkhmv.xyz/podcast/episode-18/index.md - Гости: нет Спэшл-выпуск «положение дел»: Александр рассказывает, что подкаст не заканчивается, а он расширяет территорию — выходит на YouTube (первый видос будет про сам подкаст) и присматривается к TikTok. Большая часть выпуска — подробный дневник погружения дилетанта в видеопроизводство: камера Sony A7 III, микрофон, свет как самая важная часть кадра (схема из трёх источников: ключевой, контровый, подсветка фона), монтаж в DaVinci Resolve вместо тормозящего iMovie, музыка и авторские права, а также генерация обложек через Midjourney с промтами от GPT-4. ### Главное - Подкаст остаётся основным форматом (раз в две недели плюс спонтанные спэшлы), но параллельно запускается YouTube-канал, а первый ролик будет как раз про подкаст и его влияние на автора. - Для видео важнее хорошего оборудования грамотный свет: приличной камеры (или даже настроенного телефона) достаточно, потому что вся оптика по сути поглощает свет, а дешёвые офисные лампы дают низкий индекс цветопередачи и стробят. - Классическая схема освещения — три источника: ключевой светит на лицо под ~45° и чуть сверху для мягкого контраста, контровый бьёт сзади в затылок и отделяет «говорящую голову» от фона, третий цветом подсвечивает бэкграунд. - Белый подкастерский микрофон `Rode Podcaster` не годится для видео: он остаётся в кадре (нужен на расстоянии кулака) и бликует под светом, поэтому для съёмки нужен чёрный микрофон. - `DaVinci Resolve` — оптимальный редактор для старта: есть бесплатная версия, а `iMovie` начинает фризиться и тупить на длинных роликах (например, при монтаже 4K-видео с iPhone). - Обучаться ремеслу стоит через погружение в среду профессионалов: автор изучал монтаж по плейлистам канала «Хохлов Сабатовский» и смотрел стримы «Гарик Тарано» про Sony и свет. - Обложки к выпускам удобно генерировать нейросетью: `Midjourney` рисует картинку, а `GPT-4` превращает описание на обычном языке в качественный промт для неё. - На чужую музыку в видео на YouTube действуют авторские права: за трек правообладателя грозит страйк или принудительный шеринг монетизации, поэтому автор берёт биты у знакомого битмейкера и принципиально считает воровство недопустимым. ### Главы - [00:17](https://apkhmv.xyz/podcast/episode-18/?t=17) Вступление: расширение территории - [00:59](https://apkhmv.xyz/podcast/episode-18/?t=59) YouTube и первый видос — про подкаст - [02:02](https://apkhmv.xyz/podcast/episode-18/?t=122) Как я подхожу к новой сфере - [03:34](https://apkhmv.xyz/podcast/episode-18/?t=214) Камера: Sony A7 III - [05:11](https://apkhmv.xyz/podcast/episode-18/?t=311) Микрофон: почему подкастерский не подходит - [06:34](https://apkhmv.xyz/podcast/episode-18/?t=394) Свет — самое важное в кадре - [12:12](https://apkhmv.xyz/podcast/episode-18/?t=732) Сценарий и подход к монтажу - [14:21](https://apkhmv.xyz/podcast/episode-18/?t=861) DaVinci Resolve против iMovie - [19:29](https://apkhmv.xyz/podcast/episode-18/?t=1169) Генерация картинок: Midjourney и GPT-4 - [22:55](https://apkhmv.xyz/podcast/episode-18/?t=1375) TikTok как ещё одна платформа - [25:03](https://apkhmv.xyz/podcast/episode-18/?t=1503) Итог: положение дел ### Ссылки - [DaVinci Resolve — редактор видео (Blackmagic Design)](https://www.blackmagicdesign.com/products/davinciresolve) - [Хохлов Сабатовский — YouTube-канал про монтаж и DaVinci Resolve](https://www.youtube.com/@khs_yt) - [Гарик Тарано — YouTube-канал про съёмку, Sony и свет](https://www.youtube.com/channel/UC3XJcYENqqGmJhgXeL0TUmQ) - [Midjourney — генерация изображений нейросетью](https://www.midjourney.com) - [ChatGPT / GPT-4 (OpenAI)](https://chat.openai.com) ## #17: Гибкие требования: парное программирование, Agile - Markdown: https://apkhmv.xyz/podcast/episode-17/index.md - Гости: нет Выпуск по мотивам книги «Программист-прагматик». Александр Пахомов доказывает, что требования нужны в первую очередь самим разработчикам — чтобы уточнить, чего на самом деле хочет заказчик, и не писать лишний код, — и разводит требования с бизнес-политиками, которые нельзя зашивать в хардкод. Затем он разбирает приёмы решения запутанных задач (сузить проблему, загрузить данные в подсознание, найти «уточку»), делится своим взглядом на парное программирование и живое общение против асинхронного, а под конец разоблачает agile-коучей и спорит с культом спринтов. ### Главное - Требования нужны прежде всего разработчику: чтобы задать направление и не писать код, который не нужен или который придётся переделывать, — а не как спущенный сверху документ на исполнение. - Никто не знает на 100%, чего хочет; задача инженера — вопросами вытащить детали и корнер-кейсы из заказчика, а иногда и отговорить от фичи, ведь ненаписанный код — лучший код. - Требования разрабатываются в диалоге из верхнеуровневой `user story`: заказчика волнует результат, а низкоуровневые детали — забота разработчиков. - Требования (`requirements`) нужно отличать от политик (бизнес-правил вроде размера скидки): политики со временем меняются, поэтому их выносят в метаданные, конфиги или админку, а не зашивают в хардкод. - В документе с требованиями полезен словарь терминов: если `customer`, `client` и `user` означают разное, это стоит зафиксировать с примерами, чтобы не искажать смысл. - Озарение при решении сложной задачи не приходит из ниоткуда — подсознанию нужно скормить много сырых данных, фактов и экспериментов; параллельно проблему сужают и по возможности воспроизводят тестом. - Из парного программирования полезно брать совместное исследование кода вдвоём и обсуждение документа голосом в онлайне — так получаешь более включённый фидбэк, чем от асинхронной пересылки. - Agile — это про гибкость и ценности из манифеста (люди важнее процессов, работающий код важнее документации), а не про навязанные тулы и спринты; коуч, который насаждает процессы, agile как раз не понимает. ### Главы - [00:20](https://apkhmv.xyz/podcast/episode-17/?t=20) Вступление - [00:51](https://apkhmv.xyz/podcast/episode-17/?t=51) Что такое требования и откуда страх перед ними - [03:21](https://apkhmv.xyz/podcast/episode-17/?t=201) Зачем требования нужны разработчику - [03:57](https://apkhmv.xyz/podcast/episode-17/?t=237) Пример: бесплатная доставка от 50 долларов - [06:52](https://apkhmv.xyz/podcast/episode-17/?t=412) В каком виде представлять требования - [08:15](https://apkhmv.xyz/podcast/episode-17/?t=495) user story и уточнение деталей - [09:41](https://apkhmv.xyz/podcast/episode-17/?t=581) Требования против политик и словарь терминов - [12:24](https://apkhmv.xyz/podcast/episode-17/?t=744) Решение запутанных задач: советы из книги - [20:55](https://apkhmv.xyz/podcast/episode-17/?t=1255) Парное программирование и живое общение - [29:47](https://apkhmv.xyz/podcast/episode-17/?t=1787) Разоблачение agile-коучей и культ спринтов - [35:57](https://apkhmv.xyz/podcast/episode-17/?t=2157) Итог и полезняшка: Java Swag ### Ссылки - [«Программист-прагматик» (The Pragmatic Programmer)](https://pragprog.com/titles/tpp20/the-pragmatic-programmer-20th-anniversary-edition/) - [Manifesto for Agile Software Development](https://agilemanifesto.org) ## #16: Спэшл: RBAC - Markdown: https://apkhmv.xyz/podcast/episode-16/index.md - Гости: нет Первый «спэшл» — короткий тематический выпуск между основными. Александр разбирает модель управления доступом Role-Based Access Control (RBAC): три её кита (пользователи, роли, привилегии), надстройки в виде иерархии ролей и ограничений (разделение обязанностей и лимиты на назначение ролей), а затем на пальцах сравнивает реализации в Postgres (где путаются пользователи и роли) и ClickHouse (с хорошей иерархией привилегий, но возможностью выдавать их и пользователям напрямую — что ломает каноническую модель). ### Главное - RBAC строится на трёх сущностях — пользователи, роли, привилегии — и двух связях: «роль — привилегия» (permission assignment) и «пользователь — роль» (role assignment). - Главное преимущество RBAC — контроль доступа на уровне ролей: право выдаётся и отзывается один раз у роли, а не у каждого пользователя; один `REVOKE` на роль закрывает доступ всем её носителям. - Плоская модель (flat RBAC) расширяется иерархией: роли наследуют друг друга, поэтому вместо назначения нескольких ролей одному пользователю заводят агрегирующую роль (например, `Manager`). - Ограничения (constrained RBAC) дают разделение обязанностей — например, запрет совмещать роли `Admin` и `QA` у одного пользователя. - Ограничением может быть любой предикат, включая лимит на число носителей роли: если самую мощную роль разрешено выдать лишь двоим, при взломе злоумышленник не сможет её присвоить. - Ориентир «правильного» RBAC — модель из статей NIST (с 1996 года): реализация должна быть простой и не добавлять того, чего в стандарте нет. - В Postgres нет чёткого разделения пользователей и ролей (роль с `LOGIN`/`NOLOGIN`, `CREATE ROLE` в SQL против `createuser` в shell) — понятия смешиваются, хотя в остальном система гибкая, вплоть до row-level security. - ClickHouse хорошо иерархирует привилегии (`ALTER` → `ALTER TABLE` → `ALTER COLUMN` → …), но позволяет назначать привилегии и ролям, и пользователям напрямую — что нарушает каноническую RBAC-модель. ### Главы - [00:18](https://apkhmv.xyz/podcast/episode-16/?t=18) Вступление: новый формат «спэшл» - [01:21](https://apkhmv.xyz/podcast/episode-16/?t=81) Что такое RBAC - [02:42](https://apkhmv.xyz/podcast/episode-16/?t=162) Три кита: пользователи, роли, привилегии - [04:19](https://apkhmv.xyz/podcast/episode-16/?t=259) Пример: GRANT и контроль на уровне ролей - [06:06](https://apkhmv.xyz/podcast/episode-16/?t=366) flat RBAC и иерархия ролей - [06:58](https://apkhmv.xyz/podcast/episode-16/?t=418) Ограничения: разделение обязанностей и лимиты - [08:37](https://apkhmv.xyz/podcast/episode-16/?t=517) RBAC в СУБД: критерии и NIST - [09:21](https://apkhmv.xyz/podcast/episode-16/?t=561) Postgres: путаница пользователей и ролей - [10:50](https://apkhmv.xyz/podcast/episode-16/?t=650) ClickHouse: иерархия привилегий и её изъян - [12:38](https://apkhmv.xyz/podcast/episode-16/?t=758) Итог ### Ссылки - [NIST RBAC — модель управления доступом на основе ролей](https://csrc.nist.gov/projects/role-based-access-control) - [ClickHouse — управление доступом и привилегии](https://clickhouse.com/docs/en/operations/access-rights) - [PostgreSQL — роли базы данных](https://www.postgresql.org/docs/current/user-manag.html) ## #15: Fib.nth: о чем не думают инженеры - Markdown: https://apkhmv.xyz/podcast/episode-15/index.md - Гости: нет Глава «While You Are Coding» из «Программиста-прагматика» глазами Александра: как победить боязнь белого листа прототипом-игрой, почему нельзя коммитить код, который не понимаешь (история с незадокументированным бином Spring Shell), «мышление графиками» вместо зубрёжки О-большого, атомарный рефакторинг с точки зрения свежеиспечённого коммитера Apache-проекта, TDD без карго-культа, property-based testing для проверки инвариантов и капитанские, но забываемые правила security. И хохма про Fib.nth, давшая выпуску имя. ### Главное - Против боязни белого листа: начните с «прототипа-игры» без ответственности, получите end-to-end эффект — а потом сотрите всё и пишите нормальный продакшн-код. - Не коммитьте код, который не понимаете: «работает» на ваших данных — ещё не значит работает; обход контракта библиотеки (незадокументированный бин Spring Shell) рано или поздно ломается мажорным обновлением. - Документируйте вынужденные хаки максимально подробно — это тот случай, когда комментарии в коде необходимы, — и тестируйте сами предположения: assumeThat в JUnit 5 скипает тест, а не валит его. - О-большое — это «мышление графиками»: представьте кривую — и понятно, как время растёт от размера входа; лучший в теории алгоритм на маленьких данных может проигрывать простому линейному. - Рефакторинг — регулярная практика, но атомарная: не мешайте его с фичами в одном pull request — оставьте TODO со слинкованным джира-тикетом; ревьюеры скажут спасибо. - Тест, дизайн и кодинг — всё это программирование: оценивать имплементацию без тестов бессмысленно; а 100% покрытие — вообще не про TDD, это просто метрика. - Property-based testing проверяет инварианты (вероятность всегда от 0 до 1) на сотнях сгенерированных входов и находит кейсы, о которых вы не подумали. - Security капитанская, но забываемая: входные И выходные данные — векторы атаки («такой пароль уже используется» — подарок брутфорсеру), а аутентификация отсекает DoS-запросы до базы данных. ### Главы - [00:20](https://apkhmv.xyz/podcast/episode-15/?t=20) Вступление - [02:09](https://apkhmv.xyz/podcast/episode-15/?t=129) Боязнь белого листа - [05:09](https://apkhmv.xyz/podcast/episode-15/?t=309) Programming by coincidence - [09:36](https://apkhmv.xyz/podcast/episode-15/?t=576) Осознанное программирование - [13:10](https://apkhmv.xyz/podcast/episode-15/?t=790) Алгоритмы и мышление графиками - [18:58](https://apkhmv.xyz/podcast/episode-15/?t=1138) Рефакторинг: атомарные изменения - [23:07](https://apkhmv.xyz/podcast/episode-15/?t=1387) TDD без карго-культа - [28:22](https://apkhmv.xyz/podcast/episode-15/?t=1702) Property-based testing - [32:53](https://apkhmv.xyz/podcast/episode-15/?t=1973) Security: stay safe out there - [38:40](https://apkhmv.xyz/podcast/episode-15/?t=2320) Fib.nth: хохма про именование - [41:30](https://apkhmv.xyz/podcast/episode-15/?t=2490) Заключение ### Ссылки - [«The Pragmatic Programmer», 20th Anniversary Edition](https://pragprog.com/titles/tpp20/the-pragmatic-programmer-20th-anniversary-edition/) - [«Cracking the Coding Interview»](https://www.crackingthecodinginterview.com) - [LeetCode](https://leetcode.com) ## #14: Используем технологии по назначению - Markdown: https://apkhmv.xyz/podcast/episode-14/index.md - Гости: нет Взгляд прагматичного инженера на GPT-хайп весны 2023-го: как Александр реально использует ChatGPT в ежедневной работе — пишет гуглдоки и джира-тикеты «потоком сознания» с нативной редактурой, почему Copilot в коде чаще мешает, чем помогает, но отлично пишет JavaDoc и подсказывает забытые тест-кейсы. Плюс Copilot CLI, плагины ChatGPT через OpenAPI-спеку и проверенная руками (и отложенная) идея пайплайна Whisper → ChatGPT → телеграм-посты из выпусков подкаста. Полезняшка — браузер Arc. ### Главное - Смотрите на GPT-хайп как инженер: это генеративная лингвистическая модель — «генератор следующего слова», и именно из этого понимания рождаются рабочие юзкейсы. - Главный юзкейс — тексты: пишешь поток сознания на «своём» английском, ChatGPT с коротким контекст-промптом переписывает нативно; остаётся ~5% редактуры — так пишутся гуглдоки и джира-тикеты. - Copilot в коде чаще мешает: ложных срабатываний сильно больше полезных, проверка предложений съедает внимание, а сгенерированный код порой даже не компилируется — «сынок, хочешь помочь — не мешай». - Зато Copilot отлично пишет JavaDoc для публичного API (текст, а не код) и подсказывает забытые тест-кейсы — null, минус один и прочие краевые случаи. - Плагины ChatGPT интегрируются через OpenAPI-спецификацию — ещё одна причина писать спеки для своих сервисов. - Идею «Whisper → текст подкаста → ChatGPT → телеграм-посты» Александр проверил руками за полчаса вместо недель имплементации: модель не вытянула объём текста — идея спокойно отложена. Сначала проверка гипотезы, потом инженерия. - Ожидайте стабилизации и специализации инструментов — например, умный автокомплит в терминале, продолжающий команды «серым», как fish suggestions. - Бояться «потерять скилл» из-за инструментов — путь в никуда: пользуйтесь технологиями по назначению. ### Главы - [00:20](https://apkhmv.xyz/podcast/episode-14/?t=20) Вступление - [00:32](https://apkhmv.xyz/podcast/episode-14/?t=32) Хайп против прагматичного взгляда - [01:36](https://apkhmv.xyz/podcast/episode-14/?t=96) Как работают генеративные модели - [03:32](https://apkhmv.xyz/podcast/episode-14/?t=212) Юзкейс 1: гуглдоки - [07:33](https://apkhmv.xyz/podcast/episode-14/?t=453) Юзкейс 2: джира-тикеты - [09:01](https://apkhmv.xyz/podcast/episode-14/?t=541) Copilot: помощь или помеха - [10:56](https://apkhmv.xyz/podcast/episode-14/?t=656) Где Copilot хорош: JavaDoc и тесты - [13:52](https://apkhmv.xyz/podcast/episode-14/?t=832) Copilot CLI и плагины ChatGPT - [17:06](https://apkhmv.xyz/podcast/episode-14/?t=1026) Пэт-проект: Whisper + ChatGPT для подкаста - [21:36](https://apkhmv.xyz/podcast/episode-14/?t=1296) Выводы: пользуйтесь по назначению - [23:31](https://apkhmv.xyz/podcast/episode-14/?t=1411) Полезняшка: браузер Arc ### Ссылки - [OpenAI Whisper](https://github.com/openai/whisper) - [DeepL — переводчик](https://www.deepl.com) - [GitHub Copilot](https://github.com/features/copilot) - [Браузер Arc](https://arc.net) ## #13: Любимый паттерн: Builder, Concurrency, Actors - Markdown: https://apkhmv.xyz/podcast/episode-13/index.md - Гости: нет Любимый паттерн Александра — Builder: закрытый конструктор, immutable-объекты, валидации в сеттерах, именованные параметры, которых нет в Java, тестовые фикстуры — и как он пишет билдеры руками, без Lombok (а Copilot их отлично генерирует). Во второй части по мотивам «Программиста-прагматика» — конкурентность: чем она отличается от параллелизма, почему shared state is hard, как устроена модель акторов и почему её современное воплощение — микросервисы с Kafka-«мейлбоксом» и Kubernetes-«супервайзером». Полезняшки — плейлист про устройство баз данных и фичи новой Java. ### Главное - Builder — один из самых полезных паттернов в современной Java: закрытый конструктор плюс билдер-компаньон дают immutable-объекты, корректные по построению. - Билдер привносит в Java именованные параметры: вместо конструктора из одиннадцати null'ов — читаемые сеттеры, понятные и на ревью без подсветки IDE. - Валидации живут в сеттерах билдера: каждая проверка рядом со своим полем, тестируется отдельно — и если объект существует, он гарантированно провалидирован. - Билдер — не для всего: сервисы и контроллеры создаёт DI-фреймворк, а стихия билдера — дата-классы (Person, Configuration, Address) и тестовые фикстуры, достраиваемые в каждом тесте. - «Лишний код» — слабый контраргумент: написание билдера заставляет заранее продумать дефолты и инварианты объекта, а Copilot генерирует такой код почти без ошибок. - Конкурентность — выполнение кода «как будто параллельно», параллелизм — реально параллельно; любой поход по сети, в базу или файловую систему — кандидат на асинхронность. - Shared state is hard: гонки данных, дедлоки, а мьютекс — устная договорённость, которую компилятор не проверяет; предпочитайте узкие примитивы (атомики с CAS, CountDownLatch) широким блокировкам. - Модель акторов изящна и скейлится (Erlang), но её современное воплощение — микросервисы: Kafka как мейлбокс, Kubernetes как супервайзер; используйте там, где польза очевидна, а начинайте со здравого монолита. ### Главы - [00:20](https://apkhmv.xyz/podcast/episode-13/?t=20) Вступление - [00:47](https://apkhmv.xyz/podcast/episode-13/?t=47) Паттерн Builder: что это - [02:48](https://apkhmv.xyz/podcast/episode-13/?t=168) Плюсы: immutable, контроль, именованные параметры - [07:25](https://apkhmv.xyz/podcast/episode-13/?t=445) Этапы создания и тестовые фикстуры - [10:33](https://apkhmv.xyz/podcast/episode-13/?t=633) Как я пишу билдеры - [13:38](https://apkhmv.xyz/podcast/episode-13/?t=818) Когда билдер не нужен - [15:29](https://apkhmv.xyz/podcast/episode-13/?t=929) «Лишний код» и Copilot - [18:14](https://apkhmv.xyz/podcast/episode-13/?t=1094) Конкурентность ≠ параллелизм - [21:55](https://apkhmv.xyz/podcast/episode-13/?t=1315) Shared state is hard - [26:12](https://apkhmv.xyz/podcast/episode-13/?t=1572) Модель акторов - [30:56](https://apkhmv.xyz/podcast/episode-13/?t=1856) Микросервисы как актёры - [34:54](https://apkhmv.xyz/podcast/episode-13/?t=2094) Полезняшки: базы данных и новая Java ### Ссылки - [«The Pragmatic Programmer», 20th Anniversary Edition](https://pragprog.com/titles/tpp20/the-pragmatic-programmer-20th-anniversary-edition/) - [JDK 20 — список фичей релиза](https://openjdk.org/projects/jdk/20/) - [JDK 21 (LTS) — план релиза](https://openjdk.org/projects/jdk/21/) - [CMU Database Group — лекции об устройстве баз данных](https://www.youtube.com/@CMUDatabaseGroup) ## #12: Налог на наследование: конечные автоматы - Markdown: https://apkhmv.xyz/podcast/episode-12/index.md - Гости: нет Связность — враг изменений: по мотивам «Программиста-прагматика» Александр разбирает признаки высокого каплинга и способы его снижать — от инкапсуляции и отказа от глобального стейта до недооцененных конечных автоматов, observer-паттерна и pub-sub с реактивным программированием. Кульминация — «налог на наследование»: почему наследование классов — самый сильный способ связать код намертво и чем его заменить: интерфейсы, делегирование и миксины (даже в Java — через аннотации, как @Mixin в Picocli). Полезняшка — канал «500 дней геймдева». ### Главное - Связность — враг изменений: искусство инженерии не в том, чтобы написать работающий код (это сделает и нейросеть, и базовый джун), а в том, чтобы его потом было легко менять. - Знаки высокого каплинга: неочевидные зависимости между модулями, изменения расползаются по кодовой базе, разработчики боятся трогать код, а фичи согласуются митингами на много команд. - База декаплинга: инкапсулируйте стейт внутри объектов; глобальная переменная — это лишний параметр, добавленный каждому методу кодовой базы; синглтон — «паттерн-антипаттерн». - Конечные автоматы недооценены: состояния, ивенты и экшены разделены by design, система получается open-closed — и это тот случай, когда стоит написать свою простую реализацию, а не искать библиотеку. - Observer-паттерн прост, но синхронен и хрупок (упавший обзервер рвёт цепочку); pub-sub добавляет каналы и развязывает источники и слушателей — это и есть реактивное программирование: идеально для UI, на бэкенде — по необходимости. - Наследование классов — самый сильный способ увеличить связность: наследуются методы, данные и API, и контракт родителя железобетонно сковывает наследника (поменяли getPower у vehicle — рефакторишь весь код, использующий car). - Альтернативы: интерфейсы для типизации и контрактов, делегирование (композиция) для переиспользования кода, миксины/трейты для подмешивания поведения. - Базовый класс в тестах — то же наследование с теми же проблемами: extensions в JUnit 5 решают задачу чище. ### Главы - [00:20](https://apkhmv.xyz/podcast/episode-12/?t=20) Вступление - [00:49](https://apkhmv.xyz/podcast/episode-12/?t=49) Связность — враг изменений - [02:08](https://apkhmv.xyz/podcast/episode-12/?t=128) Знаки высокой связанности - [03:26](https://apkhmv.xyz/podcast/episode-12/?t=206) Инкапсуляция и глобальный стейт - [06:40](https://apkhmv.xyz/podcast/episode-12/?t=400) Конечные автоматы - [11:14](https://apkhmv.xyz/podcast/episode-12/?t=674) Observer и pub-sub: реактивщина - [14:42](https://apkhmv.xyz/podcast/episode-12/?t=882) Transformation thinking - [16:22](https://apkhmv.xyz/podcast/episode-12/?t=982) Налог на наследование - [22:42](https://apkhmv.xyz/podcast/episode-12/?t=1362) Альтернативы: интерфейсы, делегирование, миксины - [28:16](https://apkhmv.xyz/podcast/episode-12/?t=1696) Полезняшка: «500 дней геймдева» ### Ссылки - [«The Pragmatic Programmer», 20th Anniversary Edition](https://pragprog.com/titles/tpp20/the-pragmatic-programmer-20th-anniversary-edition/) - [ReactiveX — language-agnostic спецификация реактивного программирования](https://reactivex.io) ## #11: Горе-митап: опыт выступления, презентации - Markdown: https://apkhmv.xyz/podcast/episode-11/index.md - Гости: нет Эмоциональный выпуск про первый опыт Александра в роли докладчика на локальном IT-митапе: сорванные тайминги, слабая модерация и девять слушателей на докладе про GraalVM. Из этого — выводы: почему митапу нужна модерация докладов, сколько докладов выдерживает аудитория и когда «сделай сам» — единственный выход. Во второй части — как Александр готовит презентации: белые слайды, минимум текста, интерактивность, и связка iPad + Concepts + Google Slides. Полезняшка — доклад Вадима Макишвили «36». ### Главное - Не все митапы стоят внимания докладчика: коммитьтесь, только если знаете организаторов лично или проверили их прошлые мероприятия — зритель может уйти, докладчик заложник до конца. - Митап без модерации докладов — ошибка: непросмотренные доклады съедают время зрителей и размывают качество всего мероприятия. - Три-четыре доклада — потолок: дальше аудитория устаёт и расходится (из ~50 человек до седьмого доклада дожили девять). - Попутное открытие: DI-фреймворки задизайнены под серверы — в CLI-приложении Micronaut утроил время старта (400 мс → 1,5 с); для command-line лучше обойтись без DI. - Хороший доклад начинается с вопроса «зачем и для кого» — если ценности для аудитории нет, идею доклада стоит отмести ещё до слайдов. - Слайды вторичны и дополняют речь: белый фон, крупный шрифт, минимум текста, выводы появляются по одному — это управление вниманием зрителя. - Тайминги — уважение к другим докладчикам: 30 минут — идеальная длина, и обязателен хотя бы один прогон живому человеку. - Связка iPad + Concepts + Google Slides: фиксированная зона экспорта в Concepts даёт «дорисовывающиеся» от слайда к слайду схемы без прыжков картинки. ### Главы - [00:20](https://apkhmv.xyz/podcast/episode-11/?t=20) Вступление - [00:52](https://apkhmv.xyz/podcast/episode-11/?t=52) Как я вписался в митап - [03:45](https://apkhmv.xyz/podcast/episode-11/?t=225) Доклад про GraalVM и спин-офф про DI в CLI - [06:24](https://apkhmv.xyz/podcast/episode-11/?t=384) Как всё прошло: тайминги и модерация - [10:09](https://apkhmv.xyz/podcast/episode-11/?t=609) Единственный хороший доклад - [12:15](https://apkhmv.xyz/podcast/episode-11/?t=735) Мой доклад для девяти человек - [14:59](https://apkhmv.xyz/podcast/episode-11/?t=899) Выводы: модерация, лимит докладов, «сделай сам» - [21:47](https://apkhmv.xyz/podcast/episode-11/?t=1307) Какой я вижу хорошую презентацию - [29:17](https://apkhmv.xyz/podcast/episode-11/?t=1757) Инструменты: iPad, Concepts, Google Slides - [35:01](https://apkhmv.xyz/podcast/episode-11/?t=2101) Полезняшка: «36» Вадима Макишвили ### Ссылки - [Concepts — приложение для скетчей и диаграмм](https://concepts.app) - [Вадим Макишвили — доклад «36»](https://www.youtube.com/watch?v=FxljIvLxUqQ) ## #10: Design by contract: инварианты, Archunit - Markdown: https://apkhmv.xyz/podcast/episode-10/index.md - Гости: нет Юбилейный десятый выпуск, записанный в студии. Design by contract из «Программиста-прагматика»: предусловия, постусловия и инварианты через тройки Хоара, почему предусловия — не валидация пользовательского ввода, и спор с авторами о том, может ли TDD заменить контракты. Затем — практика: контракты в джавадоке, тесты в структуре given/when/then и ArchUnit — библиотека для тестирования архитектуры, которой Александр зафиксировал инвариант стартап-хуков прямо в build time. Полезняшка — 37signals. ### Главное - Design by contract — это предусловия, постусловия и инварианты, формально — тройки Хоара: выполнено предусловие P → команда C исполнима → гарантировано постусловие Q. - Инвариант — условие, соблюдающееся всю жизнь класса: классика — баланс банковского аккаунта не бывает отрицательным. - Предусловия — про коммуникацию классов и команд между собой, а не про валидацию пользовательского ввода: пользователи о контракте ничего не знают. - Авторы считают, что TDD тестирует только happy path и потому не заменяет контракты; Александр не согласен: разбиение входных данных на классы эквивалентности покрывает и нарушения контракта. - В Java встроенных контрактов нет: описывайте их в джавадоке больших публичных классов — DbC прежде всего техника мышления; ассерты в коде громоздки и отключаются флагом. - Структура тестов given/when/then (комментариями) помогает увидеть покрытые предусловия и постусловия — и тиммейты перенимают подход сами, без просьб: лучший знак, что он работает. - ArchUnit цементирует архитектуру юнит-тестами: зависимости между пакетами, слоистая архитектура, аннотации, наследование — выразительный DSL плюс вся сила рефлексии. - Кейс: инвариант «число стартап-хуков равно ожидаемому» проверяется ArchUnit в build time — нарушенный контракт ломает сборку с информативным сообщением, а не падает где-то в рантайме. ### Главы - [00:20](https://apkhmv.xyz/podcast/episode-10/?t=20) Вступление: юбилейный выпуск из студии - [01:02](https://apkhmv.xyz/podcast/episode-10/?t=62) Контракты и тройки Хоара - [03:17](https://apkhmv.xyz/podcast/episode-10/?t=197) Инварианты и где живут контракты - [05:19](https://apkhmv.xyz/podcast/episode-10/?t=319) TDD против design by contract - [08:28](https://apkhmv.xyz/podcast/episode-10/?t=508) Контракты в Java: джавадок и ассерты - [12:19](https://apkhmv.xyz/podcast/episode-10/?t=739) Тесты в стиле given/when/then - [16:27](https://apkhmv.xyz/podcast/episode-10/?t=987) ArchUnit: тестируем архитектуру - [22:15](https://apkhmv.xyz/podcast/episode-10/?t=1335) Кейс: инвариант стартап-хуков в build time - [28:18](https://apkhmv.xyz/podcast/episode-10/?t=1698) Заключение: 37signals ### Ссылки - [«The Pragmatic Programmer», 20th Anniversary Edition](https://pragprog.com/titles/tpp20/the-pragmatic-programmer-20th-anniversary-edition/) - [ArchUnit — тестирование архитектуры в Java](https://www.archunit.org) - [37signals](https://37signals.com) ## #9: Прагматичные тулы: plain text, git, shell - Markdown: https://apkhmv.xyz/podcast/episode-09/index.md - Гости: нет Глава «Программиста-прагматика» про ежедневные инструменты: почему plain text — самое живучее представление знаний, как сделать shell своей вотчиной (темы, prompt, алиасы, fish), чек-лист совершенства во владении редактором, зачем всегда нужна система контроля версий и философия дебаггинга — чинить проблему, а не искать виновных, воспроизводить багу тестом и читать чёртово сообщение об ошибке. Бонус: подкаст зафичерил Apple, и Александр рассказывает, на что это похоже. Полезняшка — лекция Джона Остерхаута «A Philosophy of Software Design». ### Главное - Plain text — самое живучее представление знаний: оно не устаревает вместе с софтом и из коробки дружит со всеми Unix-инструментами и git. - Используйте силу командной строки и сделайте shell своей вотчиной: тема, prompt с git-веткой, алиасы для SSH-серверов, автокомплиты — а fish продуман по UX прямо из коробки. - Добейтесь совершенства во владении редактором: пройдите чек-лист (выделение, навигация, мультикурсор, сортировка строк, поиск по regex) и доводите найденные пробелы до мышечной памяти, исключая «авторепит». - Всегда используйте систему контроля версий — и проведите мысленный эксперимент с пролитым на ноутбук кофе: сколько времени займёт восстановление рабочего окружения? - Дебаггинг — это problem solving, а не поиск виновных: «не имеет значения, чья это была ошибка, — это всё ещё ваша проблема». - Сначала тест, потом фикс: воспроизведённая юнит-тестом бага — это подтверждение находки, доказательство фикса и страховка от регрессии. - Читайте чёртово сообщение об ошибке; «ифы не сломались» — в 99% случаев проблема в вашем коде; а предположения ничего не значат, пока не доказаны тестом или скриптом. - После фикса рефлексируйте: почему о баге не узнали раньше и что изменить (статанализ, новые тесты), чтобы этот класс ошибок больше не доходил до продакшна. ### Главы - [00:19](https://apkhmv.xyz/podcast/episode-09/?t=19) Вступление: подкаст зафичерил Apple - [03:31](https://apkhmv.xyz/podcast/episode-09/?t=211) Сила plain text - [08:11](https://apkhmv.xyz/podcast/episode-09/?t=491) Shell: терминал как вотчина - [13:46](https://apkhmv.xyz/podcast/episode-09/?t=826) Power editing: чек-лист совершенства - [21:50](https://apkhmv.xyz/podcast/episode-09/?t=1310) Система контроля версий - [24:52](https://apkhmv.xyz/podcast/episode-09/?t=1492) Поиск багов: чините проблему, а не виновных - [31:05](https://apkhmv.xyz/podcast/episode-09/?t=1865) Сначала тест, потом фикс - [41:22](https://apkhmv.xyz/podcast/episode-09/?t=2482) Управление текстом: awk, sed, Python - [43:42](https://apkhmv.xyz/podcast/episode-09/?t=2622) Инженерные ежедневники - [45:40](https://apkhmv.xyz/podcast/episode-09/?t=2740) Полезняшка: A Philosophy of Software Design ### Ссылки - [«The Pragmatic Programmer», 20th Anniversary Edition](https://pragprog.com/titles/tpp20/the-pragmatic-programmer-20th-anniversary-edition/) - [oh-my-zsh](https://ohmyz.sh) - [fish shell](https://fishshell.com) - [Todoist](https://todoist.com) - [Джон Остерхаут — лекция «A Philosophy of Software Design»](https://www.youtube.com/watch?v=bmSAYlu0NcY) ## #8: Медленная Java: GraalVM, Mockito - Markdown: https://apkhmv.xyz/podcast/episode-08/index.md - Гости: нет Почему Java стартует медленно — класс-лоадинг, интерпретация, прогрев JIT — и как GraalVM native image ускорил command-line-приложение Александра с 3,5 секунд до 40 миллисекунд: closed-world assumption, инициализация классов в build time и цена в виде ручных метаданных для рефлексии. Плюс обзор альтернатив — AppCDS и CRaC от Azul. Во второй части — расследование флэки-тестов: как Mockito записывает вызовы в глобальный shared-state стек внутри when/thenReturn, почему это ломается в многопоточности и когда вместо мока нужен стаб, фейк или интеграционный тест. Полезняшка — «Распределённые данные» Алекса Петрова. ### Главное - Java-старт дорог из-за класс-лоадинга и интерпретации до прогрева JIT: Hello World — около 800 мс на Java 17 против 5 мс у скомпилированного Go. - GraalVM native image переносит класс-лоадинг и компиляцию в build time (closed-world assumption) — старт CLI-приложения ускорился с 3,5 секунд до 40 миллисекунд, на два порядка. - Graal меняет привычную семантику: статические блоки исполняются при сборке (значение env, прочитанное в build time, «зашьётся» и в проде), а рефлексия, ресурсы и динамическая загрузка требуют явных метаданных — иначе ClassNotFound в рантайме. - Альтернативы: AppCDS — дамп загруженных классов приложения (примерно вдвое быстрее старт), и CRaC от Azul — восстановление уже прогретого приложения за десятки миллисекунд, но с очень узкой нишей. - Всегда спрашивайте, является ли проблема проблемой: микросервису за лоад-балансером с хелс-чеками скорость старта почти не важна, а вот для CLI-утилиты на Java это фактически бизнес-требование — идеальная ниша GraalVM. - Флэки-тесты от Mockito: конструкция when(...).thenReturn(...) пишет вызовы в глобальный shared-state стек, и конкурентный вызов мока из другого потока вклинивается между push и pop — отсюда «несовпадение типов». - Моки — для тестирования поведения (Фаулер, «Mocks Aren't Stubs»); если мок — просто затычка для конструктора из семи сервисов, это запах: подойдут стаб, фейк или дамми, а лучше — интеграционный тест с реальным кодом. - Мок оправдан на крайней точке системы — например, mock-сервер для вендорного REST API, к которому нет тестовых серверов. ### Главы - [00:20](https://apkhmv.xyz/podcast/episode-08/?t=20) Вступление - [01:01](https://apkhmv.xyz/podcast/episode-08/?t=61) Затравка: с 3,5 секунд до 40 миллисекунд - [01:57](https://apkhmv.xyz/podcast/episode-08/?t=117) Как стартует Hello World на Java - [06:21](https://apkhmv.xyz/podcast/episode-08/?t=381) Сравнение с Go - [07:58](https://apkhmv.xyz/podcast/episode-08/?t=478) GraalVM: native image и closed world - [13:03](https://apkhmv.xyz/podcast/episode-08/?t=783) Приседания: метаданные, рефлексия, агент - [20:06](https://apkhmv.xyz/podcast/episode-08/?t=1206) CDS и AppCDS - [22:33](https://apkhmv.xyz/podcast/episode-08/?t=1353) CRaC от Azul - [25:02](https://apkhmv.xyz/podcast/episode-08/?t=1502) А нужно ли это вам? - [27:58](https://apkhmv.xyz/podcast/episode-08/?t=1678) Mockito: флэки-тесты и shared state - [34:57](https://apkhmv.xyz/podcast/episode-08/?t=2097) Моки, стабы, фейки — и когда мок не нужен - [41:32](https://apkhmv.xyz/podcast/episode-08/?t=2492) Заключение: Database Internals ### Ссылки - [GraalVM](https://www.graalvm.org) - [Проект CRaC (Coordinated Restore at Checkpoint)](https://openjdk.org/projects/crac) - [Мартин Фаулер — «Mocks Aren't Stubs»](https://martinfowler.com/articles/mocksArentStubs.html) - [Алекс Петров — «Database Internals» («Распределённые данные»)](https://www.databass.dev) ## #7: Трассирующий код: прототипы, оценки - Markdown: https://apkhmv.xyz/podcast/episode-07/index.md - Гости: нет Продолжение второй главы «Программиста-прагматика»: чем трассирующий код отличается от прототипа и почему первый — это продакшн-скелет с урезанной функциональностью, а второй всегда выкидывается. Затем — предметно-ориентированные языки (DSL): внутренние и внешние, и почему тесты — идеальное место для первого собственного DSL. И большая тема оценивания: как точность оценки задаёт ожидания, техника PERT с тремя сценариями, модель с критическими параметрами и лучший ответ на просьбу об оценке — «я к тебе вернусь». Полезняшка — игра Vim Adventures. ### Главное - Трассирующий код — не прототип: это полноценный продакшн-скелет (база, CI/CD, интеграции) с урезанной функциональностью, который быстро доставляет пользователю работающий end-to-end сценарий. - Преимущества трассирующего кода: ранняя обратная связь, продуктивные разработчики (цикл доставки уже настроен) и всегда есть что показать заказчику. - Промах трассирующего выстрела — нормально: скелет и пайплайн остаются, следующая итерация корректирует направление. - Прототип, наоборот, всегда выкидывается: прототипируйте, чтобы учиться, а не чтобы кого-то убедить; валидацию, полноту и устойчивость к ошибкам можно смело игнорировать. - Главная ошибка прототипирования — позволить воспринять прототип как почти готовый продукт; если донести это не получается, пишите трассирующий код. - DSL приближает код к предметной области: внутренние DSL (Spock, RSpec) ограничены языком-хостом, внешние (Cucumber) — только своим парсером; самое безопасное место для первого DSL — тестовая инфраструктура. - Точность оценки задаёт ожидания: «130 дней» провоцирует планирование день в день — скажите «около полугода»; до 15 дней оценивайте в днях, до 6 недель — в неделях, до 20 недель — в месяцах, дальше — подумайте дважды. - Оценивайте через модель (компоненты → критические параметры → сценарии) и PERT (оптимистичная/вероятная/пессимистичная оценки со сценариями); итерируйте оценки вместе с кодом, а лучший ответ на просьбу об оценке — «я к тебе вернусь». ### Главы - [00:20](https://apkhmv.xyz/podcast/episode-07/?t=20) Вступление - [01:02](https://apkhmv.xyz/podcast/episode-07/?t=62) Стрельба трассирующими - [04:25](https://apkhmv.xyz/podcast/episode-07/?t=265) Преимущества трассирующего кода - [06:19](https://apkhmv.xyz/podcast/episode-07/?t=379) Когда выстрел мимо: итерации - [08:56](https://apkhmv.xyz/podcast/episode-07/?t=536) Прототипы: учиться малой кровью - [12:32](https://apkhmv.xyz/podcast/episode-07/?t=752) Прототип архитектуры и опасность недопонимания - [16:13](https://apkhmv.xyz/podcast/episode-07/?t=973) DSL: предметно-ориентированные языки - [22:51](https://apkhmv.xyz/podcast/episode-07/?t=1371) Оценивание: точность задаёт ожидания - [28:59](https://apkhmv.xyz/podcast/episode-07/?t=1739) Модель, критические параметры, PERT - [34:32](https://apkhmv.xyz/podcast/episode-07/?t=2072) Слона едят по частям - [36:11](https://apkhmv.xyz/podcast/episode-07/?t=2171) Заключение: Vim Adventures ### Ссылки - [«The Pragmatic Programmer», 20th Anniversary Edition](https://pragprog.com/titles/tpp20/the-pragmatic-programmer-20th-anniversary-edition/) - [Vim Adventures — игра для прокачки навигации в Vim](https://vim-adventures.com) ## #6: Прагматичный Golang: design, dry, Go - Markdown: https://apkhmv.xyz/podcast/episode-06/index.md - Гости: нет Разбор второй главы «Программиста-прагматика»: хороший дизайн — тот, который легче изменить, DRY — про знания, а не только про код, ортогональные системы и обратимость решений. Во второй части Александр Пахомов делится первыми впечатлениями Java-разработчика от Go: почему не Kotlin, не Rust и не Python, как Advent of Code стал полигоном для нового языка и чем подкупают gofmt, go mod и простота вместо вопроса «как реализован HashSet». Рекомендация выпуска — «Чистая архитектура» Роберта Мартина. ### Главное - Хороший дизайн — тот, который легче изменить: все принципы проектирования (SRP, DRY, open-closed) в конечном счёте служат лёгкости изменений. - Лёгкость изменений — это ценность, а не правило: для одноразового скрипта «хороший дизайн» может быть оверкилом. - DRY — про знания, а не только про код: не дублируйте документацию, описание API и схемы данных — генерируйте их из единственного источника правды (OpenAPI, генераторы клиентов). - Не всякое дублирование — зло: одинаковые сегодня валидации двух разных бизнес-правил (18+ для покупки вина и для брака) объединять не стоит — завтра правила разойдутся, и общий код станет проблемой. - Ортогональность — изменения в одной части не трогают другие: это локализует баги, позволяет собирать компоненты как кубики и прячет вендора в одном месте. - Золотое правило: лёгкость написания юнит-тестов — отличный признак ортогональности системы. - Не существует окончательных решений: AWS завтра сменится на bare metal — проектируйте большие изменения обратимыми и разбивайте даже монолит на компоненты. - Go подкупает прагматизмом: единый gofmt и модули из коробки убирают холивары, язык читается без вопросов, порог входа — пара часов; Advent of Code — идеальный полигон для изучения нового языка. ### Главы - [00:20](https://apkhmv.xyz/podcast/episode-06/?t=20) Вступление - [02:21](https://apkhmv.xyz/podcast/episode-06/?t=141) Важность дизайна: хороший дизайн легче изменить - [07:41](https://apkhmv.xyz/podcast/episode-06/?t=461) DRY: не дублируйте знания - [16:47](https://apkhmv.xyz/podcast/episode-06/?t=1007) Ортогональные системы - [21:53](https://apkhmv.xyz/podcast/episode-06/?t=1313) Обратимость изменений - [23:46](https://apkhmv.xyz/podcast/episode-06/?t=1426) Go: почему именно он - [28:18](https://apkhmv.xyz/podcast/episode-06/?t=1698) Advent of Code как полигон - [30:25](https://apkhmv.xyz/podcast/episode-06/?t=1825) Первые впечатления: gofmt, модули, простота - [33:53](https://apkhmv.xyz/podcast/episode-06/?t=2033) Set из мапы и независимость от IDE - [38:17](https://apkhmv.xyz/podcast/episode-06/?t=2297) Заключение: «Чистая архитектура» ### Ссылки - [«The Pragmatic Programmer», 20th Anniversary Edition](https://pragprog.com/titles/tpp20/the-pragmatic-programmer-20th-anniversary-edition/) - [Go by Example](https://gobyexample.com) - [A Tour of Go](https://go.dev/tour/) - [Advent of Code](https://adventofcode.com) - [Роберт Мартин — «Чистая архитектура»](https://www.oreilly.com/library/view/clean-architecture-a/9780134494272/) ## #5: Солидные скиллы: soft skills, SOLID - Markdown: https://apkhmv.xyz/podcast/episode-05/index.md - Гости: нет Продолжение разбора «Программиста-прагматика»: каша из топора и сваренная лягушка, good enough software, портфель знаний, техники критического мышления и почему коммуникация — половина работы инженера. Во второй части Александр Пахомов разбирает SOLID не по учебнику, а по практике: какие принципы он применяет каждый день (single responsibility, open-closed), к каким относится скептически (interface segregation) и почему главное в принципах — разумность, а не догма. Рекомендация выпуска — книга «Пиши, сокращай». ### Главное - Будьте катализатором изменений: не просите у людей готовый результат — услышите «нет»; начните сами, как странник с кашей из топора, и люди подтянутся со своими «ингредиентами». - Не сваритесь как лягушка: держите «градусник» — следите за большой картиной, чтобы вовремя заметить, что проект (или вы сами) движется не туда. - Good enough software сегодня чаще всего лучше фантазий об идеальном завтра: выпускайте раньше, собирайте фидбэк — и, как художник у картины, знайте, когда остановиться. - Знания — это инвестиционный портфель: вкладывайтесь регулярно, диверсифицируйте, управляйте рисками (узкая экспертиза может «сгореть» вместе с технологией) и периодически ребалансируйте. - Софт-скиллы — harder than hard: софт мы пишем для людей, поэтому нетехническая литература не менее важна технической. - Критическое мышление по авторам: пять «почему», кто выгодоприобретатель, каков контекст (best practices — best для кого?), своевременно ли это и почему это вообще проблема. - Одинаково важно, что вы говорите и как: плохая презентация нивелирует гениальную идею; формулируйте мысль до документа и доклада и подбирайте язык под аудиторию. - SOLID — не догма: SRP и OCP делают код проще и расширяемым, LSP — базовая гигиена контрактов, а ISP и DIP легко довести до абсурда; соблюдайте разумность. ### Главы - [00:19](https://apkhmv.xyz/podcast/episode-05/?t=19) Вступление - [00:47](https://apkhmv.xyz/podcast/episode-05/?t=47) Каша из топора: будьте катализатором изменений - [03:01](https://apkhmv.xyz/podcast/episode-05/?t=181) Сваренная лягушка: помните о большой картине - [05:25](https://apkhmv.xyz/podcast/episode-05/?t=325) Good enough software - [09:34](https://apkhmv.xyz/podcast/episode-05/?t=574) Портфель знаний - [17:01](https://apkhmv.xyz/podcast/episode-05/?t=1021) Челленджи: что и как учить - [22:19](https://apkhmv.xyz/podcast/episode-05/?t=1339) Критическое мышление - [28:09](https://apkhmv.xyz/podcast/episode-05/?t=1689) Communicate: говорите и пишите хорошо - [40:47](https://apkhmv.xyz/podcast/episode-05/?t=2447) SOLID на практике - [50:13](https://apkhmv.xyz/podcast/episode-05/?t=3013) Заключение: «Пиши, сокращай» ### Ссылки - [«The Pragmatic Programmer», 20th Anniversary Edition](https://pragprog.com/titles/tpp20/the-pragmatic-programmer-20th-anniversary-edition/) - [Максим Ильяхов, Людмила Сарычева — «Пиши, сокращай»](https://book.glvrd.ru) ## #4: Прагматичные тесты: TDD, техдолг - Markdown: https://apkhmv.xyz/podcast/episode-04/index.md - Гости: нет Новая рубрика подкаста: разбор тем книги «Программист-прагматик» — топики It's Your Life, The Cat Ate My Source Code и Software Entropy, про ответственность, отговорки и теорию разбитых окон в коде. Во второй части Александр Пахомов признаётся, что пишет тесты до реализации: как устроен цикл TDD, почему он работает даже в легаси-системах, какие плюсы даёт — от тестов-спецификаций до крепкого сна — и лайфхак с красным тестом как чекпоинтом для выхода из состояния потока. ### Главное - It's Your Life: у программистов редкая свобода выбора; как говорил Мартин Фаулер — «вы можете изменить свою организацию или сменить организацию». Сначала попытайтесь улучшить, и только потом уходите. - The Cat Ate My Source Code: доверие в команде строится на ответственности за свою работу — предоставляйте решения, а не отговорки. - Software Entropy: техдолг распространяется по проекту как разбитые окна по району — одна допущенная небрежность легитимизирует следующие. Не живите с разбитыми окнами: чините сразу или прикрывайте тикетом. - Цикл TDD: красный тест → минимально достаточная реализация → зелёный тест → следующий тест; повторять, пока не покрыты все значимые кейсы. - TDD работает и в легаси: не рефакторьте всё подряд — выносите новую логику в отдельную сущность, разрабатывайте её через тесты и интегрируйте уже проверенной. - Тесты, написанные до кода, читаются как спецификация, а тестовая инфраструктура и DSL появляются сами: тестом вы формулируете требование, а мысль плохим кодом не выразишь. - TDD улучшает дизайн продакшн-кода: компоненты становятся инкапсулированными «чёрными ящиками», код — более компонуемым и гибким, а уверенность в нём даёт спокойный сон. - Лайфхак: красный тест — чекпоинт для выхода из потока; на следующий день запускаешь упавший тест и мгновенно возвращаешься в контекст. ### Главы - [00:20](https://apkhmv.xyz/podcast/episode-04/?t=20) Вступление - [01:11](https://apkhmv.xyz/podcast/episode-04/?t=71) «Программист-прагматик»: новая рубрика - [03:27](https://apkhmv.xyz/podcast/episode-04/?t=207) Топик 1: It's Your Life - [06:10](https://apkhmv.xyz/podcast/episode-04/?t=370) Топик 2: The Cat Ate My Source Code - [08:35](https://apkhmv.xyz/podcast/episode-04/?t=515) Топик 3: Software Entropy и разбитые окна - [13:27](https://apkhmv.xyz/podcast/episode-04/?t=807) TDD: признание и история про ETL - [15:44](https://apkhmv.xyz/podcast/episode-04/?t=944) Как работает цикл red–green - [18:30](https://apkhmv.xyz/podcast/episode-04/?t=1110) TDD в реальных проектах с легаси - [20:17](https://apkhmv.xyz/podcast/episode-04/?t=1217) Плюсы: спецификация, инфраструктура, дизайн - [26:38](https://apkhmv.xyz/podcast/episode-04/?t=1598) Лайфхак: красный тест как чекпоинт - [28:39](https://apkhmv.xyz/podcast/episode-04/?t=1719) Заключение и цитата Кента Бека ### Ссылки - [«The Pragmatic Programmer», 20th Anniversary Edition](https://pragprog.com/titles/tpp20/the-pragmatic-programmer-20th-anniversary-edition/) - [Кент Бек — «Экстремальное программирование. Разработка через тестирование»](https://www.oreilly.com/library/view/test-driven-development/0321146530/) ## #3: Пакетный менеджер: Homebrew, self-review - Markdown: https://apkhmv.xyz/podcast/episode-03/index.md - Гости: нет Александр Пахомов делится практикой селф-ревью: как отстраниться от собственного кода и отревьюить свой pull request так, будто его прислал незнакомый человек. А затем разбирает Homebrew: почему в macOS нет родного пакетного менеджера, что такое формулы, кеги и краны, как написать собственную формулу — на примере базы данных Ignite 3 — и отправить её в homebrew-core. ### Главное - Селф-ревью: прежде чем просить ревью у коллег, отревьюй свой pull request сам — глазами человека со стороны, который не писал ни строчки этого кода. - Отстраниться помогает пауза: отправить PR драфтом вечером и отревьюить утром со свежей головой — или закоммитить до обеда и посмотреть после. - Homebrew — «недостающий пакетный менеджер macOS»: из коробки его нет, потому что Apple продвигает App Store. - Терминология Homebrew — из пивоварения: формула (рецепт пакета на Ruby), кега, Cellar (/usr/local/Cellar), tap (git-репозиторий с формулами), bottle (предсобранный пакет), cask (GUI-приложения). - Homebrew — это программа на Ruby поверх git: формулы лежат в репозитории homebrew-core, а brew update — по сути git pull, поэтому его важно выполнять перед каждой установкой. - Своя формула: brew search — проверить имя, brew create — создать Ruby-файл, описать метод install на DSL и отправить pull request в homebrew-core; open-source с адекватной лицензией обычно принимают. - Доставка обновления — это просто pull request с новой ссылкой на дистрибутив и обновлённой чек-суммой. - Если в основной репозиторий нельзя — создайте собственный tap: пользователи подключат его командой brew tap. ### Главы - [00:21](https://apkhmv.xyz/podcast/episode-03/?t=21) Вступление - [01:09](https://apkhmv.xyz/podcast/episode-03/?t=69) Селф-ревью: сделай ревью себе сам - [04:14](https://apkhmv.xyz/podcast/episode-03/?t=254) Homebrew: зачем macOS пакетный менеджер - [05:01](https://apkhmv.xyz/podcast/episode-03/?t=301) Терминология: формулы, кеги, краны - [06:29](https://apkhmv.xyz/podcast/episode-03/?t=389) Как работает установка - [07:44](https://apkhmv.xyz/podcast/episode-03/?t=464) Пишем собственную формулу - [09:39](https://apkhmv.xyz/podcast/episode-03/?t=579) Pull request в homebrew-core и обновления - [10:21](https://apkhmv.xyz/podcast/episode-03/?t=621) Аналитика и собственные tap'ы - [11:06](https://apkhmv.xyz/podcast/episode-03/?t=666) Заключение: книга с кабанчиком ### Ссылки - [Homebrew — The Missing Package Manager for macOS](https://brew.sh) - [Репозиторий homebrew-core](https://github.com/Homebrew/homebrew-core) - [«Designing Data-Intensive Applications» — та самая книга с кабанчиком](https://dataintensive.net) - [Плейлист Distributed Systems от Мартина Клеппмана](https://www.youtube.com/playlist?list=PLeKd45zvjcDFUEv_ohr_HdUFe97RItdiB) ## #2: Гундосая спека: комменты, Open API - Markdown: https://apkhmv.xyz/podcast/episode-02/index.md - Гости: нет Александр Пахомов разбирает, почему коммит-месседж — это история проекта, а не формальность: правила оформления заголовка и тела, conventional commits, атомарные коммиты и главное правило — договориться о формате со всей командой. Во второй части — OpenAPI-спецификация: подходы code-first и design-first, генерация документации и всегда актуального клиента, сервисы, которые продают API без спеки, и история о том, как несовершенный туллинг съел два дня работы из-за стёртых при компиляции имён параметров. ### Главное - Коммит-месседж должен отвечать на вопросы «что» и «почему»: что поменялось, видно в диффе, а вот почему — только из сообщения коммита. - Базовые правила: заголовок до 50 символов, с большой буквы, без точки, в imperative mood (add, fix, improve); строки тела до 72 символов; тело отделяется пустой строкой. - Правило №0 — формат коммитов должен быть единым: о нём надо договориться со всей командой, иначе git log превращается в помойку, по которой невозможно искать. - Если коммит трудно описать — вы либо сделали лишнее, либо слишком много за раз: это сигнал разбить изменение на более атомарные коммиты. - Conventional commits добавляют scope и структуру, чтобы поверх git-лога автоматизировать релиз-ноуты и версионирование. - OpenAPI-спецификация — описание HTTP API, читаемое и человеком, и машиной: из неё генерируются документация и всегда up-to-date клиент. - Выбор между code-first и design-first — это выбор single source of truth: либо код определяет спецификацию, либо спецификация — код. - Туллинг несовершенен: Java стирает имена параметров интерфейсов при компиляции (arg0, arg1), из-за чего Micronaut-плагин терял связь @PathVariable с path — два дня на «бинарный поиск» причины. ### Главы - [00:21](https://apkhmv.xyz/podcast/episode-02/?t=21) Вступление - [01:10](https://apkhmv.xyz/podcast/episode-02/?t=70) Комментарии к коммитам: пишем историю проекта - [02:57](https://apkhmv.xyz/podcast/episode-02/?t=177) Правила коммит-месседжа - [05:25](https://apkhmv.xyz/podcast/episode-02/?t=325) Метаданные, conventional commits, атомарность - [07:44](https://apkhmv.xyz/podcast/episode-02/?t=464) OpenAPI: что это и зачем - [09:43](https://apkhmv.xyz/podcast/episode-02/?t=583) Code-first против design-first - [10:47](https://apkhmv.xyz/podcast/episode-02/?t=647) Single source of truth - [12:17](https://apkhmv.xyz/podcast/episode-02/?t=737) Кодогенерация, валидация, документация - [13:56](https://apkhmv.xyz/podcast/episode-02/?t=836) Сервисы без спеки - [15:08](https://apkhmv.xyz/podcast/episode-02/?t=908) Несовершенный туллинг: история на два дня - [21:34](https://apkhmv.xyz/podcast/episode-02/?t=1294) Заключение ### Ссылки - [Conventional Commits — спецификация](https://www.conventionalcommits.org) - [OpenAPI Initiative](https://www.openapis.org) - [Подкаст «Запуск завтра»](https://libolibo.ru/zapuskzavtra) ## #1: Пилот: слепая печать, коды ошибок - Markdown: https://apkhmv.xyz/podcast/episode-01/index.md - Гости: нет Пилотный выпуск без гостей. Александр Пахомов рассказывает, почему десятипальцевая (слепая) печать — важный навык для программиста и где её освоить, а затем разбирает проектирование ошибок публичного REST API: какие HTTP-коды возвращать и почему тело ошибки стоит отдавать в формате RFC 7807 (problem+json). ### Главное - Слепая (десятипальцевая) печать ценна не столько скоростью, сколько лёгкостью входа в состояние потока и комфортом работы без подсказок IDE. - Осваивать слепую печать удобно короткими подходами на тренажёрах TypingClub и Clava; Clava умеет тренировать символы языков программирования. - Для внутреннего API достаточно команде договориться о формате ошибок; публичный API обязан следовать внешним конвенциям HTTP. - Коды 4xx сигнализируют об ошибке клиента и требуют понятного тела с объяснением, что не так и что делать; коды 5xx означают ошибку на стороне сервера. - В ответах 5xx нельзя раскрывать детали (stack trace, версии библиотек) — это security-антипаттерн; возвращайте абстрактный «internal server error». - Коды 503 и 504 обычно возвращает инфраструктура (например, Kubernetes), а не код приложения. - Стандарт RFC 7807 (медиатайп application/problem+json) задаёт единое тело ошибки с полями type, title, status, detail и instance. - В экосистеме Spring формат problem+json даёт библиотека Zalando Problem; на Micronaut обёртку легко написать самостоятельно. ### Главы - [00:19](https://apkhmv.xyz/podcast/episode-01/?t=19) Вступление - [00:56](https://apkhmv.xyz/podcast/episode-01/?t=56) Слепая печать: зачем она программисту - [03:43](https://apkhmv.xyz/podcast/episode-01/?t=223) Как и где освоить слепую печать - [05:31](https://apkhmv.xyz/podcast/episode-01/?t=331) Ошибки REST API: постановка задачи - [05:52](https://apkhmv.xyz/podcast/episode-01/?t=352) Что такое REST и требования к ошибкам - [07:47](https://apkhmv.xyz/podcast/episode-01/?t=467) HTTP-коды по группам (1xx–5xx) - [16:00](https://apkhmv.xyz/podcast/episode-01/?t=960) Тело ошибки и RFC 7807 (problem+json) - [21:49](https://apkhmv.xyz/podcast/episode-01/?t=1309) Заключение и ссылки ### Ссылки - [TypingClub — тренажёр слепой печати](https://www.typingclub.com) - [Clava — тренажёр печати для программистов](https://clava.org) - [RFC 7807 — Problem Details for HTTP APIs](https://www.rfc-editor.org/rfc/rfc7807) - [Zalando Problem — библиотека problem+json для Spring](https://github.com/zalando/problem)