StringConcat - разработка без боли и сожалений – Telegram
StringConcat - разработка без боли и сожалений
3.42K subscribers
87 photos
9 videos
3 files
208 links
Полезный блог от разработчиков для разработчиков. Наш сайт: howto.stringconcat.ru
Download Telegram
Недавно наткнулся на codecrafters.io — прикольный сервис, где можно с нуля реализовать всякие штуки вроде Redis, Git, SQLite и прочее непотребство.

По нашей классификации это пет-проекты класса «Минимализм» — когда ты не строишь продукт, а воссоздаёшь готовую технологию, чтобы понять, как она устроена внутри.

Каждое задание там — это разбор под капотом: сетевые протоколы, файловые форматы, системы хранения, парсеры и всё то, что обычно «просто работает».

Есть бесплатный тариф, так что можно попробовать без вложений.
Мы сами пока не юзали, но выглядит интересно
👍21🔥72
Forwarded from Artem Brannt
Я юзал с целью "освоить незнакомый язык на реальном проекте", мне понравилось. Из прикольного - все проекты делаются по baby steps (например, Redis начинается с задания "сделайте TCP-сервер, который отвечает PONG на PING на нужном порте), это сильно помогает постепенно въехать в новую технологию. Из не очень прикольного, но по-своему полезного - в заданиях обычно пишут, что делает, но практически не дают пояснений, как; если непонятно, приходится лезть в документацию, в другие решения, которые там же можно посмотреть, или спрашивать у ChatGPT). Бесплатно дают доступ к одному проекту, который меняется каждый месяц, плюс, когда они добавляют новый проект, у него есть период бета-тестирования, когда он тоже бесплатен.
🔥12👍1
Когда-то давно мне приспичило разобраться как работает Linux. Нашёл Linux From Scratch — проект, где ты буквально собираешь систему с нуля. Но это упоротый вариант.

В итоге я остановился на Arch Linux — почти как Gentoo, только без бесконечной пересборки мира.
Поднимал сети вручную, вкорячивал модули ядра, правил grub.cfg, шаманил с udev и драйверами.
Естественно, сейчас я уже всё это забыл и зову админа чтобы подключить сетевой кабель. Но тогда, когда я занимался прошивками и разрабатывал под Linux, это дало мне дикий буст к пониманию того, как система устроена изнутри. И вот это как раз пет-проект класса «Минимализм» — когда ты воссоздаёшь базовый слой, чтобы прочувствовать механику. Но есть опасность — после таких экспериментов у вас может прорасти свитер
🔥25
🔧 Немного закулисья нашей разработки

Редко удаётся рассказать — и тем более показать — детали рабочих процессов. Обычно всё покрыто коммерческой тайной. Но сегодня хочу приоткрыть занавес и поделиться тем, над чем мы работаем.

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

И честно говоря, я не разделяю всеобщих восторгов по поводу ИИ-тулзов общего назначения: да, в части случаев они экономят время, но количество допилок напильником там порой слишком велико (в последнее время я прям таки заставляю себя ими пользоваться, чтобы понять ограничения). Иногда проще вручную запилить, нежели объяснять электронному болвану что от него требуется. А ещё есть важная проблема — многие из этих агентов отправляют данные непонятно куда, а далеко не каждая компания может позволить себе делиться внутренней информацией с внешними сервисами.

Поэтому мы делаем ставку на другое: узкоспециализированную систему, заточенную под конкретный фреймворк и конкретные задачи интеграции. Вот, даже лендос склепали.

Наш подход — максимально декомпозировать каждый шаг, а то что можно сделать обычными алгоритмами — сделать ими и не выпендриваться. Так можно выжать максимум даже из относительно слабых моделей, которые легко развернуть на своей инфраструктуре. Но чтобы заставить модель уверенно решать даже узкую задачу, приходится серьёзно повозиться: продумывать промпты, писать на них тесты и т.д.

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

Система у нас состоит из двух ключевых модулей:
1. Генератор кода
2. Фреймворк с четкой структурой, в который этот код встраивается
На вход подается описание желаемого выхлопа, а так же документация целевых систем. На выходе — код, который реализует желаемую интеграцию, встроенную в фреймворк.

Сейчас я работаю над промптами, тестирую разные подходы и собираю первые результаты. И — что приятно — кое-что уже начинает работать (по крайней мере мне так кажется).

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

Продолжение следует 👇
🔥333👍1
Смотрел код — и заметил прекрасное. Зацените, как там проверяется время:

event.createdAt.truncatedTo(ChronoUnit.SECONDS) shouldBe OffsetDateTime.now().truncatedTo(ChronoUnit.SECONDS)

То есть просто отрезают миллисекунды в надежде, что тест «успеет» в ту же секунду. А если через миллисекунду тикнет новая? Ну да, можно же начать резать минуты… или часы…
Так и рождаются моргающие тесты, которые то проходят, то падают — чистое веселье.

Что с этим делать?

Нормальный путь — зафиксировать время через Clock.fixed() или Clock.offset() и передавать этот Clock внутрь всего, что генерирует OffsetDateTime.now(clock).
Красоты мало, зато:
• время контролируется снаружи;
• тесты становятся предсказуемыми;
• и никто больше не бегает от внезапно наступившей секунды.

Если же душа просит простых и понятных решений, в JUnit можно тупо повторять тест несколько раз. Прокатило один раз — и ладно, галочка зелёная.

Ещё вариант: не сравнивать даты напрямую, а мерить Duration.between(…) и проверять, что разница в пределах пары миллисекунд. А когда CI сервер начнет тормозить и тесты снова станут моргать — добавите еще пару секунд, делов то.

Ну и последний способ — попробовать замокать статический метод now(), если сможете конечно.

P.S.: Если понадобятся дополнительные лайфхаки по созданию говнокода — зовите, всегда рад помочь.
😁34👌6👍1👾1
Media is too big
VIEW IN TELEGRAM
Типичная разработка
😁32💯5👍31😭1
Видео vs текст

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

Но в последнее время ловлю себя на мысли, что иногда видосы всё же выигрывают. Формат текста ограничен: схемы, которые автору кажутся очевидными, читателю часто выглядят как «угадай что я имел в виду». В видео же можно рассмотреть детали, которые в тексте либо опускают («да это же капитанщина»), либо запихивают в такой формат, что толком ничего не разобрать.
👍3
А вы что выбираете, когда приходится изучать душные и не очень темы? (можно выбрать несколько вариантов)
Anonymous Poll
53%
Книги
73%
Текст (статьи, лонгриды, блоги)
60%
Видео
7%
Аудио/подкасты
3%
Другое (напишу в комментах)
👍2
Мы тут периодически прокачиваем наши курсы — и настало время небольшой калибровки. Для этого нам нужны примерно 5-10 добровольцев, которые готовы поучаствовать в коротком созвоне (30-40 минут).

Что будет на созвоне:
Мы позадаём несколько простых вопросов о наших продуктах - что актуально прямо сейчас, где болит и т.д. Это помогает нам держать курс в тонусе и развивать его туда, где он действительно полезен.

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

Условия:
1. Вы не проходили наш тренинг «Разработка без боли и сожалений»
2. Вы занимаетесь коммерческой разработкой бекенда 3+ лет

Созвон короткий, формат дружелюбный, польза — взаимная. Если хотите присоединиться — перейдите по ссылке и оставьте контакты с описанием проблемы, мы всё организуем.
🔥4👌1
Недавно на подлодке рассказывал о том, как выстраивать обработку ошибок, чтобы потом не было мучительно больно. И вот намедни снова наткнулся на эту же проблему. Пытался оставить заявку на сайте провайдера, но рукожопые разрабы не удосужились нормально проработать ошибки. В итоге потратил пару часов своей жизни — и столько же времени техподдержки (и наверняка не только моего). Ну подумаешь, с кем не бывает. Мы же тут высокопроизводительный код пишем и играем во фреймворки, а не пользователю делаем удобно.
🔥11👍6😁21
Тот неловкий момент, когда ты банк с 15 млн клиентов, а тебя френдзонит стартап.

Операция на открытом сердце: как мы искали движок для банка
Дано: Jago Bank. Представьте себе Тинькофф на третьем году жизни, только в Индонезии, в жаре и с дикими амбициями.

Приходит к нам бизнес и с порога заявляет: — Ребята, мы тут планируем скромный рост. Было 15 миллионов пользователей, станет 30. Ну вы там подготовьтесь по-быстрому.

Мы, как порядочные инженеры, пошли к нашему текущему провайдеру Core-системы: — Сдюжите? — Пфф, легко! — отвечают. — Мы вам просто второй инстанс рядом поставим. А вы уж там сами как-нибудь трафик между ними маршрутизируйте. И отчеты склеивайте руками. И вообще, крутитесь как хотите.

В переводе с вендорского на человеческий это означало: «Fuck you».

Мы намёк поняли. Осознали, что придется писать свою Core-систему (потому что кто, если не мы?). Самая мякотка там — это Ledger. Место, где живут все бухгалтерские проводки. Нам нужно переваривать около 1000 операций в секунду и не подавиться.

Но прежде чем садиться кодить велосипед, решили глянуть на рынок. Вдруг можно что-то укра... кхм, купить?

Натыкаемся на TigerBeetle. Это молодой стартап, который запилил не базу данных, а какой-то звездолёт на стероидах. Ребята дистиллировали саму суть финансовых проводок и выдали решение с космической надежностью и скоростью. Читаешь документацию и плачешь от счастья — видно, что люди знают домен лучше, чем свои пять пальцев.

Мы загорелись. Пишем им письмо, полное надежды и уважения:
«Привет! Мы банк, у нас 15 млн юзеров, растем до 30. Ваше решение — пушка. Мы почти готовы его ставить. Давайте знакомиться и работать!»
Ответ от стартапа приходит такой, будто мы у них мелочь у метро попросили:
«"Почти готовы" не считается. Вот когда решите на 100% — тогда и пишите. До связи».
Мы слегка офигели, но виду не подали. Пишем еще раз: «Ребят, ну скажите хоть сколько стоит? Бюджет-то планировать надо». Ответ:
«Сначала поклянитесь на крови, что берете нас, а потом мы вам ценник выкатим».
А теперь следите за руками. В это же самое время Google, у которого денег больше, чем у Бога, водит вокруг нас хороводы. Кормит бесплатными обедами, поит спешелти-кофе и присылает десант из Solution Architect’ов, которые в красках расписывают, как их Spanner идеально нам подходит.

Google прямым текстом говорит: «Пацаны, мы сделаем всё, лишь бы ваш financial ledger крутился на наших технологиях. Хотите массаж стоп? Только скажите».

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

З.Ы. «На самом деле, поведение стартапа — это отличный стресс-тест, который они провалили. Если они так ведут себя на этапе продажи, когда все обычно улыбаются и машут, то представьте, что будет, когда у нас в 3 часа ночи ляжет прод? Google, может, и не "звездолет", но у них хотя бы есть телефон, по которому можно наорать на живого человека».
😁22🔥1410👍9
Sergey Bukharov
Тот неловкий момент, когда ты банк с 15 млн клиентов, а тебя френдзонит стартап. Операция на открытом сердце: как мы искали движок для банка Дано: Jago Bank. Представьте себе Тинькофф на третьем году жизни, только в Индонезии, в жаре и с дикими амбициями.…
Мы в Satori тоже регулярно сталкиваемся с вендорами ПО. Раньше я как-то не особо обращал на это внимание… но теперь я просто в восхищении от того, как изящно устроен этот рынок. Узнал потрясающие вещи:

- Оказывается, API можно смело поставлять без документации — вы же умные, сами разберетесь.
- При этом часть API будет отвечать Not Implemented
- Можно брать деньги за доработки, а потом бодро сообщать: «Ну… не получилось».
- На вопрос «почему столько багов и есть ли у вас тесты?» присылать набор юнит-тестов, сгенерированный вчера ИИ, причём таких, что они не проверяют вообще ничего.
- Спокойно тестировать прямо на проде клиента — идеально же, всё под рукой.
- Игнорировать вопросы даже в платной техпододдержке — бережём энергию.
- На срочные запросы отвечать: «Единственный человек, который в теме, у нас сейчас в отпуске».
- Требовать оплату за работы, которых в природе не существовало.
- На просьбу о функциональности говорить: «Этого нет в нашем беклоге и никогда не появится».
- Продавать «коробочное решение», которое по факту — франкенштейн из копролита, костыля и поделия джуна после курсов.
- Обвинять заказчика, в том что он нормально задачу не ставит и не проверяет
- И главное, абсолютный шедевр: подсадить клиента на «бесплатное решение», а потом элегантно выкручивать ему руки за доработки.

Вот это я понимаю, бизнес-модель!
😁20🔥7💯5😢4🤷‍♂21
DIY для банка: выбираем базу данных, когда стартап нас отшил

В предыдущей серии я рассказывал, как TigerBeetle — стартап нашей мечты — отправил нас во френдзону. Пришлось засучить рукава и делать «сердце» банка самим.

Но на чем писать? Чтобы не было мучительно больно за бесцельно прожитые спринты, мы сформулировали требования.

Задача:

- 1000 TPS (транзакций в секунду) на рандомных аккаунтах.
- 100 TPS на одного «жирного» клиента.

С первым пунктом всё понятно: если руки растут из плеч, любая современная БД это вывезет. А вот второй пункт — это боль. Нужно заблокировать аккаунт, посчитать баланс, записать проводку и разблокировать. Арифметика беспощадна: 1 секунда / 100 транзакций = 10 мс на всё про всё. Тут уже на Python не попишешь, тут думать надо.

В кастинг на роль «сердца» попали четыре кандидата:

1. Postgres (Классика)
Старый добрый слон. Чтобы уложиться в 10 мс, всю логику придется зашивать в хранимки (Stored Procedures). Гонять данные туда-сюда между приложением и БД — непозволительная роскошь. Сомнения: Наша текущая система на MySQL выдает жалкие 7 TPS. Вендор клянется мамой, что это предел физики. Мы, конечно, умнее, но сможем ли мы быть умнее на порядок? Вопрос открытый.

2. Redis + Postgres (Безумный Макс)
Идея для смелых: ставим Redis перед Постгресом. — «Но это же просто кэш!» — кричат пуристы. — «Подержите мое пиво», — отвечаем мы.

Почему это круто:

- Single-threaded: Редис однопоточный. Никаких гонок (race conditions). Атомарность из коробки.

- Lua noscripts: Логику можно исполнять прямо внутри памяти. Быстро, дерзко.

- Надежность: У Редиса есть стримы. Можно реализовать Transaction Outbox паттерн без танцев с бубном, Kafka и Debezium. Данные льются в Postgres в фоне.

- Персистенс: Да, вся база должна лезть в RAM. Но Редис умеет сбрасывать данные на диск и реплицировать на слейвы. Если настроить прямыми руками — надежно, как швейцарские часы.

3. TigerBeetle (Бывшая)
Те самые ребята, которые нас отшили. Заявляют 1 000 000 TPS. Даже на один аккаунт. Звучит как сказка, но проверить надо. Вдруг врут? А если не врут — будем кусать локти (или снова проситься к ним).

4. Google Spanner (Швейцарский нож)
Самый загадочный зверь. Спрашиваешь у Гугла, что такое Spanner, и тебе отвечают: «ЭТО ВСЁ».
Хочешь SQL? Spanner.

Хочешь Key-Value? Spanner.

Графы? Spanner.

AI? Разумеется, Spanner! Там скоро можно будет писать запросы в духе: «AI, проверь, хватит ли у юзера 123 денег на пиво, и если да — переведи».
На презентации меня сдержало только хорошее воспитание, чтобы не спросить: «А блокчейн вы туда еще не впихнули?». Похоже, это единственное, чего там нет.

Проблема: Это распределенная БД. Она сама решает, где хранить данные. Скорее всего, она раскидает счета по разным нодам, и каждый перевод превратится в multi-node transaction. А это медленно. Но Гугл так настойчиво поил нас кофе и водил по виски-барам, что мы решили дать Спаннеру шанс. Из вежливости.

------

Результаты эпичной битвы и реальные цифры нагрузочного тестирования — в следующем посте.

А пока вангуем в комментариях. В каком порядке тулзы пришли к финишу (от лучшей производительности к худшей). И какую технологию выбрали бы лично вы?

Кто будет ближе всех — тот настоящий HighLoad архитектор.
🔥38
Финал: Битва баз данных. Кто стал сердцем банка?
[В прошлых сериях]: нас отшил дерзкий стартап, мы обиделись и пошли пилить своё решение. Задача была простая, как кирпич: найти хранилище, которое выдержит наши амбиции. 🎯 Цель: — 100 TPS (транзакций в секунду) на один аккаунт (с блокировками). — 1000 TPS на рандомные аккаунты.

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


1. Postgres (Старый конь борозды не портит)
Взяли его чисто как baseline, чтобы было с чем сравнивать. Вся логика строго на хранимках (Stored Procedures), один поход из приложения в базу.

Результат:
Один аккаунт: 1 300 TPS (В 13 раз больше требуемого! Мы слегка присели).
Много аккаунтов: 9 000 TPS.

Внезапно «скучный» SQL показал, что списывать его со счетов рановато.


2. Redis + Postgres (Форсаж)
Схема: Редис считает математику в памяти, а потом стримами (Streams) скидывает данные в Постгрес на вечное хранение.

Результат:
Один аккаунт: 23 000 TPS.
Много аккаунтов: 23 000 TPS.

Ему вообще плевать. Редис однопоточный, ему все равно хоть один аккаунт, хоть много. Скорость света.


3. TigerBeetle (Тот самый стартап)

Результат:
Один аккаунт: 27 000 TPS.
Много аккаунтов: 77 000 TPS.

Обещанного миллиона мы не увидели, но цифры всё равно мощные. Правда, прямо посреди теста мы словили эксепшн:
Whoops, there is a bug in SDK…

Мелочь, а неприятно. Представили, как ловим этот «Whoops» в продакшене в «Черную пятницу», и перекрестились.


4. Google Spanner (Боль и унижение)
Напомню, Гугл продавал нам это как «Решение Всех Проблем Человечества».

Результат:
Один аккаунт: 78 TPS. (Нет, я не забыл букву «K». Просто 78).
Много аккаунтов: 870 TPS. (Тоже просто 870).

Мы протерли глаза. Перезагрузили серверы. Цифры не изменились. Звоним в Гугл: «Ребята, что за фигня? Где обещанная магия?»

Нам вежливо посочувствовали и выдали гениальные советы:
- «А вы поставьте перед Спаннером Redis». (Спасибо, Кэп! А Спаннер тогда зачем?).
- Скинули статью на Medium: «Какие костыли прикрутить, чтобы базы данных хоть как-то работало с hot accounts».
- Рассказали вдохновляющую историю, как один банк реализовал на Спаннере... фичу кэшбека. (Кэшбека, Карл! Не леджера).

Когда мы наконец прорвались через продажников к суровым технарям, те вздохнули и признались: «Ну да, сотню TPS выжмете, больше — вряд ли. Архитектура такая».

Занавес.

------

Итоговое решение
Мы выбрали Postgres.

Почему:
- Запас прочности: Он выдал 1300 TPS на один аккаунт при требовании в 100. Этого нам хватит на годы.
- Надежность: Это скучная, предсказуемая технология. Никаких «Whoops» в SDK.
- Архитектура: Мы спроектировали систему так, чтобы оставить перед Постгресом «Redis-shaped hole» (дырку в форме Редиса).
- Если (или когда) мы вырастем до космических масштабов, мы просто вставим туда Redis, как деталь пазла. А пока — зачем платить сложностью за то, что старый добрый SQL делает бесплатно?

А теперь предлагаю погуглить "Spanners British slang". В общем, хорошую штуку Спаннером не назовут
🔥51👍5😱43