Обновить
1024K+

Программирование *

Искусство создания компьютерных программ

1 354,93
Рейтинг
Сначала показывать
Порог рейтинга
Уровень сложности

Работает ли Caveman? Тестируем модный скилл для экономии токенов

Уровень сложностиПростой
Время на прочтение4 мин
Охват и читатели9.2K

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

Что он обещает? Идея простая — скилл указывает нейронке говорить, как пещерный человек, убирать артикли, говорить коротко и думать лаконично. На первых строках README обещается экономия до 75%. При этом без потери качества!

Но работает ли все это на самом деле? Ведь 75 000 звёзд на репозитории не могут ошибаться?

Читать далее

YaFF в опенсорсе: как и зачем мы сделали zero‑copy представление для Protobuf

Уровень сложностиСредний
Время на прочтение40 мин
Охват и читатели24K

Чтение сериализованных данных — это инфраструктурный налог, который платит каждый сервис при получении информации из внешних источников, например по сети или с диска. В индустрии для схематизированных данных стандартом де‑факто стал Protobuf, и чаще всего этот налог выражается в существенных затратах CPU на его парсинг. В продвинутых случаях парсинг пытаются заменить на значительно более дешёвую, но при этом куда менее удобную работу с zero‑copy представлением FlatBuffers.

Мы открыли исходники YaFF (Yet Another Flat Format) — формата, который убирает этот налог, не заставляя отказываться от Protobuf. На масштабе Яндекса это особенно важно, потому что менять такие базовые вещи, как формат, дорого и больно. Поэтому YaFF изначально спроектирован как альтернативный wire format для существующих экосистем Protobuf (и в перспективе FlatBuffers). Это позволяет дёшево и бесшовно встраиваться в существующие проекты, не переписывая десятки тысяч строк кода.

Как это работает на практике, мы покажем на примере Яндекс Рекламы: в рекомендательной системе, где каждый из сотен тысяч запросов обрабатывает десятки тысяч объектов, нужно особое внимание к представлению данных. Благодаря YaFF мы смогли постепенно, шаг за шагом, оптимизировать систему и без дорогих рефакторингов сэкономить 10–20% CPU в масштабах крупных рантаймов.

Читать далее

Skill of the Week: Spring Data JPA. Никто не знает JPA, даже AI

Уровень сложностиПростой
Время на прочтение6 мин
Охват и читатели7.8K

Знание и умение разрабатывать на Spring Data JPA — это обязательный навык для разработчика, если он хочет заниматься разработкой приложений на Spring. Этого мы ожидаем и от AI-агента.

Удовлетворяют ли наши AI-агента этому условию? Во многом зависит от того, насколько продвинутую модель вы используете. Значит ли это, что Opus 4.8 не совершает ошибок? Совсем нет. Более того, иногда удивляешься, почему еще вчера он настроил связь правильно, а уже сегодня сделал ту же работу, но добавил CascadeType.ALL.

В сегодняшнем эпизоде еженедельной рубрики Skill of the Week разберёмся, как, используя Spring Data JPA Skill, научить своего агента важным навыкам при работе со Spring Data JPA.

Читать далее

Интеграционные тесты в Java: ускоряем Testcontainers через tmpfs и прединициализацию

Уровень сложностиСредний
Время на прочтение6 мин
Охват и читатели7.3K

Testcontainers - Java-библиотека, которая управляет Docker-контейнерами прямо из тестового кода. Во время выполнения тестов она запускает нужный контейнер - базу данных, брокер сообщений, поисковый движок и т.д. - а по завершении останавливает и удаляет контейнер.

Зачем это нужно? Для интеграционных тестов на реальном ПО, а не на in-memory эмуляторах. Тест работает с тем же движком, что и в продакшене.

В этой статье я разберу, как можно оптимизировать работу с Testcontainers:

tmpfs - перенос файлов в оперативную память.

Прединициализация - перенос тяжёлой инициализацию в отдельный Docker-образ.

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

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

Читать далее

Будущее разработки в эпоху ИИ: уволят ли нас и что с этим делать

Время на прочтение16 мин
Охват и читатели9.2K

Уволят ли завтра половину разработчиков? Нужны ли ещё джуны, когда приложение собирается за вечер? И как входить в профессию, если ИИ пишет код быстрее тебя? Отвечаю как senior-разработчик, который сам каждый день работает с этими инструментами: на цифрах со ссылками и на четырёх историях из практики, без хайпа и без паники.

Читать далее

Динамический полиморфизм против std::variant с указателями: Разрушаем мифы о скорости std::visit (v.2*)

Время на прочтение23 мин
Охват и читатели12K

В экосистеме современного C++ прочно укоренилось мнение: классический динамический полиморфизм через виртуальные функции (vtable) и наследование — это устаревший, медленный и недружелюбный к кэшу процессора механизм. В качестве «серебряной пули» модно предлагать связку std::variant и std::visit. Если вы спросите любого виртуального умника (ИИ) он до последнего будет убеждать вас что std::variant и std::visit всегда(!) лучше чем виртуальные функции, даже не сомневайтесь. Проблема в том что с таким отношением вы во многих случаях просто лишаете себя выбора адекватного технического решения. Решения адекватного условиям конкретной задачи с необходимостью диспетчеризации вызовов. По интернету кочуют статьи, утверждающие, что std::visit выполняет диспетчеризацию за фиксированное время O(1) и полностью уничтожает старый добрый ООП-подход, но вы должны понимать что не существует универсальных решений на все случаи жизни.

А что если мы попробуем уравнять начальные условия использования обеих техник диспетчеризации и будем использовать вариант с указателями, а не с эмплейс-объектами: std::vector<std::unique_ptr <BaseClass>> и std::vector<std::variantstd::unique_ptr<TypeA>, std::unique_ptr<TypeB>,std::unique_ptr<TypeC>>> в условиях раздельной компиляции классов и кода который делает вызовы (зачем это надо?).

Читать далее

Почему +0.3% к ROC‑AUC почти всегда шум, и как это проверить

Уровень сложностиСредний
Время на прочтение6 мин
Охват и читатели13K

ROC‑AUC вырос с 0,871 до 0,874 — модель стала лучше или вам просто повезло с разбиением?

Разберём, почему прирост на третьем знаке часто оказывается шумом, как измерить разброс метрики и сравнивать модели так, чтобы «улучшение» не исчезло на свежих данных.

Читать далее

ID, token, UUID и slug: в чём разница и почему их нельзя мешать

Уровень сложностиСредний
Время на прочтение9 мин
Охват и читатели20K

В каждом бэкенде рано или поздно рядом появляются id, UUID, slug, token и request_id. Все они выглядят как строки, но отвечают за разные вещи.

Когда это забывают, UUID становится защитой, slug — вечной айдишкой, а token — просто ещё одним идентификатором.

Читать далее

Новые возможности Hibernate 7.4

Уровень сложностиПростой
Время на прочтение5 мин
Охват и читатели13K

Hibernate 7.4 исправляет старую проблему с пагинацией и fetch join.

Раньше запрос на первые 10 Order вместе с OrderItem не мог безопасно ограничиться на уровне SQL. Из-за join один заказ превращался в несколько строк, и limit мог обрезать коллекцию. Поэтому Hibernate загружал все подходящие строки, а страницу выбирал уже в памяти. На больших данных это било по памяти и могло закончиться OutOfMemoryException.

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

Еще в 7.4 появились history и audit tables. @Temporal хранит версии строк и позволяет читать сущность на конкретный момент времени. @Audited пишет изменения ADD/MOD/DEL в audit-таблицу без Envers.

Читать далее

Единый оркестратор инфраструктуры: что происходит под капотом Digital Q.AppServer

Время на прочтение5 мин
Охват и читатели10K

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

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

Digital Q.AppServer как раз закрывает эту задачу: платформа дает единый интерфейс для работы с серверами приложений Digital Q.TomEE и Digital Q.WildFly и собирает в одном месте основные операции сопровождения. В центре внимания здесь – уже не сам по себе выбор между серверами, а то, что ими можно управлять как частью одного эксплуатационного процесса, а не как набором разрозненных систем.

Читать далее

Как я написал «Обратную змейку» на чистом Canvas

Уровень сложностиПростой
Время на прочтение7 мин
Охват и читатели22K

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

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

Читать далее

Как я ускорил dependency injection в Python в 130 раз: от рефлексии до компиляции графа

Уровень сложностиСредний
Время на прочтение4 мин
Охват и читатели9.1K

«Контейнер для DI — это лишний оверхед, передай зависимость руками и не выдумывай». Я тоже так считал, пока не замерил: наивный контейнер резолвил типичный сервис-граф примерно в 200 раз медленнее ручной сборки.

Рассказываю, как тремя шагами — кэш плана, удаление проверки, которая всё равно не срабатывает, и компиляция графа в одну плоскую функцию — довёл резолв с 52.9 до 0.40 мкс/оп, почти как руками. И как при этом не дал exec-кодогенерации тихо собирать не те объекты в проде.

Приёмы переносимые: профилирование микрооверхеда, выкидывание мёртвой защиты, фаззинг на эквивалентность.

Читать разбор

Property-based testing на практике: как находить баги, о которых вы не подумали

Уровень сложностиСредний
Время на прочтение8 мин
Охват и читатели7.8K

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

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

Читать далее

Ближайшие события

Hazard pointers на пальцах

Уровень сложностиСредний
Время на прочтение5 мин
Охват и читатели9.2K

Привет, Хабр.

Сегодня я постараюсь максимально понятным языком объяснить Hazard pointers, с схемой и примерами.

Читать далее

Как я писал генератор TypeScript-биндингов для Tauri

Уровень сложностиСредний
Время на прочтение5 мин
Охват и читатели7.1K

В Tauri фронтенд дёргает Rust-команды через invoke("get_user", { userId: 42 }) — строка, объект, никакой проверки типов. После очередного вечера, убитого на расхождение snake_case и camelCase, я написал генератор, который превращает Rust-команды и serde-типы в готовые TypeScript-файлы — без аннотаций и правок в коде приложения.

Под катом — почему генерировать надо не то, что написано в коде, а то, что serde реально шлёт по проводу; как я выпустил три релиза за один день, воюя с макросами; и при чём тут юникод-эскейпы в TOML на Windows.

Читать далее

Claude Code убрал из моей работы рутину и почему я этому не долго радовался

Уровень сложностиПростой
Время на прочтение3 мин
Охват и читатели17K

Долгое время вижу одно и то же в новостях и обзорах: ИИ уберет рутину, снимет трение, даст крылья и вообще панацея от всех болячек. Я поставил Claude Code — и да, трение исчезло. Рутина схлопнулась. Идею теперь можно проверить за вечер, а не за месяц.

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

Открыть ящик с идеями

Ааа, всё пропало! AI создаёт дырявый код! Что же делать?

Уровень сложностиПростой
Время на прочтение3 мин
Охват и читатели7.5K

Сегодня за утренним кофе прочитал статью “70% разработчиков считают ИИ-код дырявым, при этом 30% всех опрошенных деплоят его в прод”. Внезапного для меня в этом нет. Я уже писал, что ожидания завышены, а к сгенерированному коду есть избыточное доверие (как и к текстам в целом). Неожиданно другое: проблематику некачественного и ненадёжного ИИ-кода начинают обсуждать как нечто новое. Уже встречал размышления, мол, как теперь строить процессы разработки, чтобы достичь необходимое качество.

Читать далее

Создаём простого ИИ-агента с нуля. Часть 2

Время на прочтение9 мин
Охват и читатели7.9K

Что произойдёт, если дать языковой модели доступ к терминалу, файловой системе и интернету? Она перестанет быть болтливым ассистентом и превратится в агента, который сам читает код, правит файлы и запускает команды — примерно так под капотом и работают Claude Code и Codex. В этой части добавляем нашему агенту семь базовых инструментов и разбираемся, как модель сама решает, какой из них вызвать.

Читать далее

MCP vs CLI + Skill: что выгоднее для ИИ‑агента при работе с внутренними API

Время на прочтение17 мин
Охват и читатели12K

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

Для этого мы сравнили два способа «подружить» ИИ‑агента с внутренними API — MCP и CLI + Skill. Взяли гипотезу из внешних исследований, собрали бенчмарк на 14 сценариях и двух моделях, прогнали больше 400 запросов на реальных внутренних инструментах. И в какой‑то момент всё, что работало, сломалось — и это оказалось самым интересным. Пришлось разбираться почему.

Привет, меня зовут Даниил Михайлов, я из команды разработки партнёрских продуктов Городских сервисов Яндекса. В статье расскажу, что именно мы измеряли, как ломали свои же результаты и к каким выводам в итоге пришли. В конце статьи — дерево решений: когда какой подход использовать.

Читать далее

Generic Repository<T> обещал три вещи — не сдержал ни одной и забрал доменную модель

Уровень сложностиСредний
Время на прочтение9 мин
Охват и читатели12K

Сколько раз вы реально меняли базу под приложением? Generic Repository – первое, что тащат в проект, и последнее, в чём сомневаются, – держат ровно ради этого. У меня за карьеру смена базы случилась дважды, и оба раза репозиторий полетел в корзину вместе со всем слоем. Это лишь первое из трёх обещаний, которое он не сдержал, а по дороге тихо забрал доменную модель. Как именно – на реальном кейсе с Mongo, и чем мы его заменили.

Читать далее