Обновить

Бэкенд

Сначала показывать
Порог рейтинга

Зелёные тесты ≠ хорошие тесты

Впервые в истории писать тесты стало легко и совсем не страшно. Вокруг теперь у всех покрытие 80%, 90%, а то и вовсе 100%. И вот тут начинается проблема: зелёные тесты ≠ хорошие тесты.

Проблема в метрике, которой мы все привыкли доверять. Code coverage считает строку протестированной, если она выполнилась во время теста. Всё. Не «поймает ли тест баг в этой строке», не «проверяет ли он правильность результата» — просто выполнилась. Можно написать тест без единого assert, и покрытие вырастет. 500 тестов, 90% coverage, а пользы ноль.

Мутационное тестирование — это совершенно другой путь. В простейшей реализации этот инструмент тупо берёт твой код и намеренно ломает его: меняет > на >=, + на ‑, True на False. Каждая такая поломка — мутант. Если после мутации все тесты по‑прежнему зелёные — значит они ничего не проверяют. Покрытие есть, защиты нет.

Почему это важно именно сейчас?

Потому что нейронка любит зелёненькое. Чем больше зелёных тестов — тем субъективно лучше. 100 тестов внушают больше доверия, чем 10, правда? А внутри там assert response.status_code == 200. assert result is not None. assert len(items) > 0. Тест проверяет, что функция вернула хоть что‑то — и радостно зеленеет. Поменяй логику условия, перепутай знак, сломай граничный случай — тест всё равно зелёный. Потому что он проверяет не правильность, а наличие.

Мутационное тестирование — единственный автоматический способ это поймать. Метрика называется mutation score: процент убитых мутантов. 60% — плохо. 90%+ — тесты реально что‑то защищают.

Кое‑какие инструменты для такого тестирования уже есть: mutmut и cosmic‑ray для Python, Stryker для JS/TS, PIT для Java. Медленно? Да, значительно медленнее обычного тест‑рана. Но запускать его не нужно на каждый коммит — достаточно на PR в критические модули.

Но есть нюансы. А где их нет, правда?

Первый: мутации рандомные. Замена > на >= — это не баг, который кто‑то реально допустит. Это синтетическая поломка. Половина мутантов генерирует код, который в реальности никогда не появится. Ты тратишь время на убийство мутантов, которые не имеют отношения к настоящим ошибкам. Это как тестировать замок, ковыряя его вилкой — формально проверка, по факту мимо.

Второй — ещё хуже. Чтобы убить мутанта, тест должен зафиксировать конкретное поведение. Каждую ветку, каждое значение, каждый edge case. Доведи mutation score до 100% — и ты прибил гвоздями каждую строчку кода. Буквально. Теперь попробуй отрефакторить. Переименовал внутренний метод — 40 тестов красные. Поменял порядок полей в ответе — ещё 20. Тесты превращаются из страховки в кандалы: код работает правильно, но тесты падают, потому что они проверяют не поведение, а реализацию.

Это реально ловушка. Слишком гонишься за mutation score — получаешь хрупкие тесты. Не гонишься — получаешь видимость тестирования.

Перемены — впереди!

И вот тут становится по‑настоящему интересно. Представь, что мутации генерирует не тупой набор правил «замени плюс на минус», а нейронка, которая понимает контекст. Которая знает, какие баги реально встречаются в таком коде. Которая мутирует не синтаксис, а логику: меняет порядок проверок, путает граничные условия, забывает обработать edge case — ровно так, как ошибается человек. Или другая нейронка.

Сейчас есть явный сдвиг в сторону таких инструментов, но всё еще ничего достойного не вышло. Но уже скоро точно появится. И это будет совсем другой уровень. Не «выжили ли тесты после рандомной поломки», а «выжили ли тесты после правдоподобной ошибки».

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

Ждём, когда мутанты станут умнее.

Теги:
Всего голосов 5: ↑5 и ↓0+7
Комментарии3

«Просто добавь кнопку» и недели работы

Однажды заказчик пришёл с задачей, которая звучала как пара часов работы «Просто добавь кнопку — нажал, выгрузил данные, всё». Я открыла код и поняла, что эта кнопка стоит не пару дней, а недель — и это если повезёт..

Сложнее всего оказалось не сделать, а объяснить так, чтобы услышали.

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

Архитектурное объяснение я попробовала и оно не зашло. Слои, связи, зависимости: всё правильно, всё мимо.

Что работает вместо «красивого кода»

Я перестала объяснять как устроено и начала объяснять что произойдёт. Не «тут монолитная структура без инверсии зависимостей», а конкретно: — эта кнопка затрагивает три модуля, которые никто не трогал два года — если что‑то сломается, то мы не узнаем сразу, потому что тестов нет — следующая фича после этой будет стоить столько же в лучшем случае.

Заказчик услышал третий пункт. Именно его.

Нетехнический человек воспринимает разработку примерно так: «нажал кнопку → произошла магия → получил результат». Это не незнание — просто другая роль. Заказчик и не должен думать об архитектуре, это моя работа. Значит, говорить на его языке — тоже моя.

Как я считаю стоимость следующей фичи

Со временем сложился свой фреймворк. Не из учебника, а из разговоров, где меня не понимали, пока я не поменяла подход.

Три вещи, которые я оцениваю перед тем, как называть сроки: 1. Базовая сложность: сколько займёт в идеальных условиях, на нормальной архитектуре. 2. Архитектурный коэффициент — во сколько раз реальность дороже идеала. Код без тестов, с жёсткими связями между модулями — это 2-4× к оценке. Не абстракция: вот здесь нельзя менять, не затронув вот это. Рисую буквально на бумаге. 3. Риск‑налог — что может пойти не так. Что сломается, насколько быстро заметят, сколько займёт починка. Не чтобы напугать, а чтобы показать, что «быстро» и «надёжно» здесь в противоречии.

Когда эти три числа стоят рядом — разговор меняется. Заказчик видит, что не «разработчик тормозит», а «вот цена, вот риск, вот выбор».

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

Что осталось в голове

Техдолг — это не технический вопрос. Это финансовый.

Пока объясняешь его как технический — тебя не услышат. Как только переводишь в деньги, сроки и риски — начинают слышать.

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

А вы как объясняете техдолг тем, кому важен результат, а не архитектура? Есть формулировка, которая сработала лучше всего?

Теги:
Всего голосов 7: ↑5 и ↓2+3
Комментарии3

Валидация полей форм в Joomla 6

У каждого поля в форме Joomla есть поле type, но за валидацию значения отвечает атрибут validate.

Например: number — очевидно что значение должно быть числом.

<field
	name="count"
	type="number"
	label="MOD_ARTICLES_FIELD_COUNT_LABEL"
	description="MOD_ARTICLES_FIELD_COUNT_DESC"
	default="5"
	filter="integer"
	min="0"
	validate="number"
/>

Или UserId — тут сложнее, значение должно быть реальным id сужествующего пользователя.

<field
    name="default_value"
    type="user"
    label="PLG_FIELDS_USER_DEFAULT_VALUE_LABEL"
    validate="UserId"
/>

А в моём компоненте нужна валидация id компании.

Добавляем в поле атрибут validate="CompanyId":

<field
    name="company_id"
    type="text"
    label="COM_WISHBOXBONUSSYSTEM_FIELD_COMPANY_LABEL"
    required="true"
    validate="CompanyId"
/>

Добавляем класс правила (в моём случае по сути копия правила UserId):

<?php
/**
 * @copyright   (c) 2013-2026 Nekrasov Vitaliy <nekrasov_vitaliy@list.ru>
 * @license     GNU General Public License version 2 or later;
 */
namespace Joomla\Component\WishboxBonusSystem\Administrator\Form\Rule;

use Joomla\CMS\Form\Form;
use Joomla\CMS\Form\FormRule;
use Joomla\Database\DatabaseAwareInterface;
use Joomla\Database\DatabaseAwareTrait;
use Joomla\Database\ParameterType;
use Joomla\Registry\Registry;
use SimpleXMLElement;
use function defined;

// phpcs:disable PSR1.Files.SideEffects
defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects

/**
 * Form Rule class for the Joomla Platform.
 *
 * @since  1.0.0
 */
class CompanyIdRule extends FormRule implements DatabaseAwareInterface
{
    use DatabaseAwareTrait;

    /**
     * Method to test the validity of a Joomla User.
     *
     * @param   SimpleXMLElement  $element  The SimpleXMLElement object representing the `<field>` tag for the form field object.
     * @param   mixed              $value    The form field value to validate.
     * @param   ?string            $group    The field name group control value. This acts as an array container for the field.
     *                                       For example if the field has name="foo" and the group value is set to "bar" then the
     *                                       full field name would end up being "bar[foo]".
     * @param   ?Registry          $input    An optional Registry object with the entire data set to validate against the entire form.
     * @param   ?Form              $form     The form object for which the field is being tested.
     *
     * @return  boolean  True if the value is valid, false otherwise.
     *
     * @since   1.0.0
     *
     * @noinspection PhpMissingReturnTypeInspection
     */
    public function test(SimpleXMLElement $element, $value, $group = null, ?Registry $input = null, ?Form $form = null)
    {
        // Check if the field is required.
        $required = ((string) $element['required'] === 'true' || (string) $element['required'] === 'required');

        // If the value is empty, null or has the value 0 and the field is not required return true else return false
        if (($value === '' || $value === null || (string) $value === '0')) {
            return !$required;
        }

        // Get the database object and a new query object.
        $db    = $this->getDatabase();
        $query = $db->createQuery();

        // Build the query.
        $query->select('COUNT(*)')
            ->from($db->qn('#__wishboxbonussystem_companies'))
            ->where($db->qn('id') . ' = :companyId')
            ->bind(':companyId', $value, ParameterType::INTEGER);

        // Set and query the database.
        return (bool) $db->setQuery($query)->loadResult();
    }
}

И в модели нашей сущности (в моём случае OperationModel) подключаем префикс класса:

	public function getForm($data = [], $loadData = true)
	{
		FormHelper::addRulePrefix("\\Joomla\\Component\\WishboxBonusSystem\\Administrator\\Form\\Rule");

		return parent::getForm($data, $loadData);
	}
Теги:
Всего голосов 1: ↑1 и ↓0+2
Комментарии0

Два факта об int в Python

Один забавный факт привел меня к открытию другого :)

Читал Fluent Python и наткнулся на пример кода, который меня заинтересовал (помимо миллиона других, книга – топ). В главе про конкурентность и работу GIL была константа NUMBERS с необычным значением:

NUMBERS = 5_000_111_000_222_021

Нижние подчеркивания

Если не встречали в работе или документации, то вряд ли знаете (как и я): в числах можно использовать _ для читаемости. Интерпретатор их игнорирует:

>>> x = 1_2
>>> y = 12
>>> x == y
True
>>> x is y
True

Особенно удобно в высокоразрядных числах. Согласитесь 5_000_111_000_222_021 куда проще читать, чем 5000111000222021

Кеш малых чисел

Примеры ниже разбирал на домашнем ноуте с Cpython 3.13.11 и 3.14.3.

Пока игрался, меня заинтересовал один прикол. Я попробовал тот же пример с большими числами:

>>> x = 100_500
>>> y = 100500
>>> x == y
True
>>> x is y
False # Но ведь в примере выше было True..

Почему переменные больше не ссылаются на один объект?

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

Ответ на вопрос: «где граница, до которой числа закешированы?» я решил не гуглить, проверил небольшим скриптом:

>>> x = 0
>>> y = 0
>>> for n in range(1000):
...     print(f'If {x=} and {y=}, x is y: {x is y}')
...     x += 1
...     y += 1

# Пропустим часть строк
If x=254 and y=254, x is y: True
If x=255 and y=255, x is y: True
If x=256 and y=256, x is y: True
If x=257 and y=257, x is y: False # Вот и граница
If x=258 and y=258, x is y: False 
...

Сначала я сделал эмпирически вывод, что закеширован диапазон 0 – 256. Но после самопроверки с гуглом узнал, что также в амортизированный диапазон входят числа от -5 до -1. Итого : от -5 до 256 включительно.

UPD 15.03.2026. Добрый дядя в комментах принес ссылку на pr в Cpython 3.15, где кеш малых чисел увеличен до 1024 :). Ух, заживем..

Для присвоения переменным чисел вне диапазона, интерпретатор начнет выделять уже раздельные области памяти и is станет возвращать False.

Так то. В оптимизации пригодится вряд ли, но удивить друзей в баре сможете.

Теги:
Всего голосов 11: ↑10 и ↓1+9
Комментарии15

Неудобные вопросы про бэкап PostgreSQL: открытый разбор на вебинаре

Вокруг бэкапа PostgreSQL легко создать иллюзию, что все уже решено. Достаточно добавить в текст WAL, PITR, пару слов про консистентность и назвать агент «умным». Проблема в том, что в проде такие формулировки мало что гарантируют.

Можно ли вообще считать решение PostgreSQL-aware, если оно не живет внутри логики самой СУБД? Где проходит граница между нативными механизмами PostgreSQL и внешней платформой? Что происходит, если не доехал WAL-сегмент, не завершился post-script или восстанавливать нужно не весь инстанс, а один объект?

Из таких вопросов и вырос отдельный вебинар про PostgreSQL в Акуре, в формате открытого инженерного разбора: что здесь должна делать сама СУБД, что имеет смысл выносить во внешний слой, где начинаются реальные эксплуатационные проблемы и какие ограничения в таком подходе нельзя замалчивать.

План такой:

  • отдельно пройтись по WAL, PITR и консистентности;

  • обсудить, где файловый агент уместен, а где уже нет;

  • разобрать сценарии с ошибками pre/post-скриптов;

  • поговорить про восстановление в безопасную локацию и ручной recovery;

  • отдельно затронуть вопрос масштаба: почему на двух базах хватает shell-скриптов, а на пятидесяти уже начинается совсем другая жизнь.

26 марта 2026, 11:00 (МСК) Регистрация по ссылке. Приносите в комментарии вопросы, которые особенно хочется поднять в эфире.

Теги:
Всего голосов 4: ↑4 и ↓0+4
Комментарии0

ai_query() в StarRocks 4.1: вызываем LLM прямо из SQL. Разбор результатов тестов.

Зачем это нужно аналитику и как вписывается в архитектуру, я описал в своем Telegram-канале Selena (powered by StarRocks). Здесь — технические детали и результаты тестирования.

Архитектура StarRocks 4.x: два направления интеграции с языковыми моделями
Архитектура StarRocks 4.x: два направления интеграции с языковыми моделями

На схеме два потока данных между языковой моделью и базой данных:

Синий (вверху) — LLM → База через MCP (4.0). Пользователь задаёт вопрос на обычном языке. Агент сам формулирует SQL-запрос, отправляет его в StarRocks через MCP-протокол и возвращает ответ. Об этом я также подробно писал в нашем сообществе.

Зелёный (внизу) — База → LLM через ai_query() (4.1). Аналитик пишет SELECT с вызовом ai_query(). StarRocks на каждом сервере кластера отправляет запрос к языковой модели и возвращает её ответ как обычную текстовую колонку.

В версии 4.0 появилось первое направление, в 4.1 — второе. Полный цикл.

Что такое ai_query()

Функция принимает два аргумента: текстовый промпт и JSON с параметрами модели. Возвращает текстовую колонку — результат можно фильтровать, группировать и соединять с другими таблицами.

Обязательные параметры: model (название модели) и api_key (ключ доступа). Дополнительно можно указать адрес сервера модели, температуру, максимальную длину ответа и таймаут.

Функция работает с любым сервисом, совместимым с протоколом OpenAI: это и сам OpenAI, и локальные модели через Ollama, и DeepSeek, и vLLM.

Как тестировали:

Функция планируется к релизу в версии 4.1. Когда пришло время её проверить, привычный способ — развернуть готовый образ в Docker — не сработал. В образе обнаружился небольшой баг: функция была скомпилирована и лежала внутри сервера, но сервер о ней не знал. Исправление заняло одну строку в исходном коде. Но чтобы её применить, пришлось собирать BE из исходников.

Среда тестирования: виртуальная машина (8 CPU, 32 ГБ RAM), StarRocks 4.1.0-rc01 (собранный из исходников), языковая модель Ollama gemma3:1b (работает локально на процессоре). Тестовые данные — шесть отзывов о товарах.

Тест 1. Анализ тональности

Задача: определить, позитивный отзыв или негативный.

(SQL код по каждому тестированию я напишу в комментариях)

Вывод: четыре из шести точных.

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

Время: ~три секунды на шесть строк.

Не тот объем данных, чтобы экстраполировать на большие продакшн системы, но я тестировал не производительность, а работоспособность.

Тест 2. Суммаризация

Задача: сжать отзыв в одно предложение.
Вывод: адекватные резюме на русском языке. Длину ответа стоит контролировать параметром max_tokens.
Время: ~одна секунда на строку.

Тест 3. Извлечение характеристик

Задача: вытащить из текста ключевые свойства товара.
Вывод: характеристики извлекаются
Время: ~1 секунда на строку.

Тест 4. Классификация

Задача: определить категорию товара по тексту отзыва.
Вывод: категории определены верно. MacBook, монитор, наушники — «Электроника», мышь — «Периферия».
Время: ~0.5 секунды на строку.

Тест 5. Перевод

Задача: перевести отзыв с русского на английский.
Вывод: качественный перевод даже на модели в один миллиард параметров.
Время: ~1 секунда на строку.

Ограничения:

  1. Нельзя задать роль модели (нет системного промпта) — только сообщение от пользователя

  2. Нет повторных попыток при ошибке — если сервис модели вернул ошибку, это сразу ошибка SQL-запроса

  3. Кеш хранится на каждом сервере отдельно и теряется при перезапуске

Итого:

ai_query() — простая обёртка над протоколом языковых моделей с кешем и дедупликацией. Не революция, но именно такие простые интеграции оказываются самыми полезными.

Функция появится в StarRocks 4.1.

Теги:
Всего голосов 3: ↑2 и ↓1+1
Комментарии1

JEP 524 в JDK 26 — второй preview PEM API

Наконец-то работа с PEM в Java становится похожа на API, а не на набор ручного парсинга, Base64 и странных телодвижений.

Справка: PEM или Privacy-Enhanced Mail - это текстовый контейнер для криптографических данных. Проще говоря – это способ хранить или передавать ключ, сертификат или другой crypto-объект не в бинарном виде, а в текстовом.

Раньше с PEM работали так:

String pem = "-----BEGIN PUBLIC KEY-----\n"
        + Base64.getMimeEncoder(64, "\n".getBytes())
                .encodeToString(publicKey.getEncoded())
        + "\n-----END PUBLIC KEY-----";

А в обратную сторону, но уже с ручной нормализацией PEM, Base64-декодированием и KeyFactory:

String normalized = pem
        .replace("-----BEGIN PUBLIC KEY-----", "")
        .replace("-----END PUBLIC KEY-----", "")
        .replaceAll("\\s", "");

byte[] der = Base64.getDecoder().decode(normalized);

PublicKey key = KeyFactory.getInstance("EC")
        .generatePublic(new X509EncodedKeySpec(der));

По факту PEM в Java долгое время был не отдельным API, а набором низкоуровневых шагов, которые разработчик собирал руками.

А теперь это выглядит так:

var encoder = PEMEncoder.of();
String pem = encoder.encodeToString(keyPair);

var decoder = PEMDecoder.of();
KeyPair decoded = decoder.decode(pem, KeyPair.class);

То есть ключевую пару можно закодировать в PEM и декодировать обратно буквально в несколько строк.

Во втором preview:

  • PEMRecord переименовали в PEM

  • добавили decode()

  • расширили поддержку KeyPair и PKCS8EncodedKeySpec

  • упростили шифрование через EncryptedPrivateKeyInfo

А так, как все это дело еще в preview, не забываем использовать --enable-preview.

❓ Минус еще один кусок криптографической копипасты из Java-кода. PEM в Java постепенно перестает быть унылым?

Присоединяйтесь к русскоязычному сообществу разработчиков на Spring Boot в телеграм — Spring АйО, чтобы быть в курсе последних новостей из мира разработки на Spring Boot и всего, что с ним связано.

Теги:
Всего голосов 4: ↑4 и ↓0+4
Комментарии0

Что нас ждёт в StarRocks 4.1

В документации StarRocks появились release notes для 4.1 с пометкой RC (release candidate) — это предварительная версия перед финальным релизом. Посмотреть, куда движется проект, самое время. Я изучил release notes, связанные issues и PR, и выбрал четыре самых значимых изменения.

Ссылка на описание релиза: https://docs.starrocks.io/releasenotes/release-4.1/

Актуальные версии на сегодня: Stable — 3.5.14, Latest — 4.0.6.

1. Автоматическое управление распределением данных

Раньше при создании таблицы в shared-data кластере нужно было вручную выбирать ключ распределения и рассчитывать количество бакетов. Если ошибся — часть узлов перегружена, а часть простаивает, и исправление требует пересоздания таблицы.

В 4.1 для shared-data кластеров появляется range-based распределение: таблеты содержат метаданные диапазонов ключей, и система сама следит за их размером — автоматически разделяет слишком большие или объединяет недоиспользуемые. Без изменения схемы и без перезагрузки данных.

На практике: меньше ручной настройки при создании таблиц, меньше проблем с неравномерной нагрузкой. Issue #64986 (https://github.com/StarRocks/starrocks/issues/64986)

2. DELETE для Iceberg-таблиц

До 4.1 StarRocks мог только читать данные из Iceberg и добавлять новые (INSERT). Удалять было нельзя. А это серьёзное ограничение: удаление персональных данных по требованиям регуляторов, исправление ошибочных записей, очистка устаревших данных — всё приходилось делать через Spark или Trino.

Теперь DELETE FROM (механизм Iceberg position delete) работает напрямую из StarRocks. При этом delete-файлы совместимы с другими движками — Spark, Trino и Flink корректно их прочитают. StarRocks становится ещё более полноценным SQL-движком для Iceberg: SELECT + INSERT + DELETE. Issue #66944 (https://github.com/StarRocks/starrocks/issues/66944)

3. Рекурсивные CTE (WITH RECURSIVE)

Одна из самых запрашиваемых фич — сообщество просило с 2023 года. Рекурсивные CTE позволяют писать запросы, которые ссылаются сами на себя — это нужно для обхода иерархий (оргструктуры, категории товаров, вложенные комментарии), заполнения пропусков во временных рядах и графовых задач. Если вы мигрируете с PostgreSQL, MySQL или Trino — больше не нужно переписывать рекурсивные запросы. PR #65932 (https://github.com/StarRocks/starrocks/pull/65932)

4. Инкрементальное обновление Materialized Views на Iceberg

До 4.1 materialized views на Iceberg-таблицах обновлялись полным пересчётом — даже если в источнике добавилось несколько строк. Теперь StarRocks умеет обновлять MV инкрементально — обрабатывается только новая порция данных. Особенно заметно на append-heavy сценариях: логи, события, IoT-данные. Ограничение первой версии — работает только с таблицами, в которые данные добавляются, но не обновляются. Issue #61789 (https://github.com/StarRocks/starrocks/issues/61789)

Что ещё интересного: 

  • Полнотекстовый поиск в shared-data кластерах (inverted index, beta)

  • Таблеты до 100 ГБ

  • Меньше мелких файлов, проще эксплуатация

  • Поддержка Iceberg V3 и тип VARIANT для полуструктурированных данных

  • ai_query()

  • вызов LLM-моделей прямо из SQL-запроса

  • sum_map() — нативная агрегация MAP по ключам

  • Мониторинг потоков FE через SQL без внешних инструментов

Больше постов про StarRocks и Lakehouse — в Telegram-канале @starrocks_selena

Теги:
Всего голосов 3: ↑2 и ↓1+1
Комментарии0

Разворачиваем приватную LLM в кластере Kubernetes в прямом эфире

Начинаем через 30 минут, в 12:00 мск. Эксперты вместе с вами пройдут весь путь от подготовки кластера до готового интерфейса: настроят мониторинг, распределенные модели, интеграции и даже автоматизацию инфраструктуры.

Подключиться к трансляции →

Будет полезно DevOps- и SRE- и ML-инженерам, архитекторам и продакт-менеджерам.

О чем поговорим

— Почему клиенты все чаще выбирают приватные LLM.

— Как выделенные GPU-серверы решают задачи безопасности, производительности и стоимости. 

— Сравним стоимость владения облаком и физическими серверами на реальных кейсах. 

— Почему Kubernetes — идеальная платформа для управления LLM в проде.

— Воркшоп: разворачиваем приватную LLM от подготовки кластера до удобного интерфейса.

Подключайтесь к трансляции в VK и на YouTube.

Теги:
Всего голосов 3: ↑3 и ↓0+8
Комментарии0

Как проверить HTTP-запросы на Backend

Разрабатываете VK Mini Apps и хотите быть уверены, что HTTP-запросы на backend приходят именно из приложения VK, а не откуда угодно? Для этого нужна корректная проверка Init Data.

Наш backend-разработчик @dmvasiliev выложил Open Source-проект, который упрощает эту задачу. Это Python-пакет с готовыми алгоритмами проверки подлинности данных, передаваемых из VK Mini Apps. Он помогает быстро и безопасно настроить авторизацию и аутентификацию на backend-стороне приложения.

👉 Репозиторий
📘
Документация с примерами интеграции для Django и FastAPI.

Когда мы только начинали работать с VK Mini Apps, информации было немного: редкие кейсы, почти не у кого было спросить совета. За это время мы запустили несколько приложений, разобрались в нюансах платформы и накопили собственную экспертизу. Теперь делимся ею с сообществом через Open Source-проекты и вносим вклад в развитие технологии.

Репозиторий открыт — берите в работу, делитесь постом с коллегами. 

А если вам нужен VK, Telegram Mini App или спецпроект на другой платформе — команда Doubletapp поможет пройти путь от идеи до работающего продукта.
Примеры наших проектов — на сайте.

Теги:
Всего голосов 2: ↑1 и ↓10
Комментарии0

22 открытых урока марта для бэкенд-разработчиков

Привет, Хабр. Делимся подборкой бесплатных демо-уроков, которые проведут в марте преподаватели Otus. Это не предзаписанные, а живые онлайн-встречи — сможете узнать больше о формате обучения и задать вопросы экспертам. Выбирайте свою тему и присоединяйтесь!

Полный список бесплатных уроков марта по всем ИТ-направлениям (разработка, тестирование, архитиктура, инфраструктура, аналитика, ИИ, управление) смотрите в дайджесте.

Для начинающих рекомендуем обратить внимание на короткие видеокурсы, которые помогут закрепить основы, сейчас всего за 10 рублей:

Теги:
Всего голосов 2: ↑2 и ↓0+3
Комментарии0

Учимся писать промпты правильно

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

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

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

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

Вдруг меня осенило, слишком сильное обдумывание до начала работы в агентской разработке (последние полгода), стало чем-то сродни преждевременной оптимизации. Поработав с большим числом моделей и агентов, могу сказать, что если вы будете сами все продумывать, то заставите работать более менее нормально даже самые тупые модели, но вы никогда не поймете границы их возможностей, где они могут еще больше взять на себя освободив вас от рутины. А модели и агенты постоянно развиваются, там где раньше надо было подсказывать, теперь они могут сами. Плюс если вы работаете над AGENTS.md, скилами и mcp, то и тут мы ловим буст.

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

Для упавшего ci это выглядит так:

  1. Поправь тесты

  2. Прошу посмотреть последний запущенный билд на github actions

Баг в браузере:

  1. прошу открыть страницу (он это делает через mcp chrome) и самому изучить

Для рефакторинга:

  1. Переводим вот это на это

  2. Вот эталон (тут ссылка на файл)

Для фичи:

  1. Нужно реализовать такую фичу

  2. Даю пример или говорю с помощью какого инструмента

И все. Самые продвинутые модели типа opus 4.6 или codex 5.3 справятся самостоятельно с большинством острых углов. Сами спросят объем, посмотрят разные варианты, изучат доку и так далее. Модели по тупее, не сделают глубокого анализа и ничего особо не спросят, но именно тут вы поймете где их надо вести и включать свой мозг чаще. Хотя хорошие модели настолько сильно помогают, что я физически не могу использовать более простые для задач планирования. Они хороши в авторежиме только для работы по аналогии, рефакторинг, написание тестов и так далее.

Даже если вы что-то забудете или пропустите сразу, все это можно будет доуточнить, попросить показать примеры кода, сходить открыть браузер. Если в процессе появляются вещи, которые агент делает из раза в раз, например, пытается выяснить где что-то лежит, как работать с какой-то частью системы, то постепенно это выносится в AGENTS.md и с определенного размера и уровни сложности (когда уже нужны скрипты например и команды) выносится в skill.

Теги:
Всего голосов 2: ↑2 и ↓0+2
Комментарии0

Что только в коде не увидишь, когда делаешь код-ревью или просто изучаешь проект, встречаются разные забавные артефакты.

Опасный код
Опасный код

Все NDA разорваны. Проект не подлежит нарушению прав

Теги:
Всего голосов 1: ↑1 и ↓0+1
Комментарии1

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

Ответьте на три вопроса и получите 3 000 ₽ на хранение данных

Хранить данные можно по-разному: в S3, базах данных, аппаратных СХД. К тому же способы можно комбинировать и даже для самых тривиальных задач получить сотни вариантов решения. А если вы работаете с чувствительными данными, то подход к способу хранения данных становится еще ответственнее.

Чтобы было легче определиться, мы предлагаем новым клиентам тест-драйв наших хранилищ и 3 000 бонусных рублей на него. Ответьте на три вопроса, получите рекомендацию по хранению и протестируйте их.

Теги:
Всего голосов 3: ↑3 и ↓0+5
Комментарии0

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

Курс «Проектирование высокопроизводительных приложений» (ARC-008) для тех, кто пишет код и хочет строить системы, которые выдерживают нагрузку.

Вы научитесь:

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

✔️ Проектировать систему, чтобы она не тормозила с самого старта.

✔️ Понимать, что делают нагрузочные тесты, и как взаимодействовать с тестировщиками.

✔️ Видеть узкие места и знать, каким инструментом их лечить.

В программе: паттерны GoF, Lambda-архитектура, MapReduce, методология SPE (Performance Engineering).

🔥 Цена: 53 900 26 950 ₽ (для физических лиц). Скидка 50% действует только 5 марта.

🎁 Бонус: в рамках акции «Мартовский апгрейд» — селф-модуль из программы «Архитектор ПО. Путь к мастерству» в подарок!

👉 Записаться

Теги:
Всего голосов 1: ↑0 и ↓1-1
Комментарии0

Блоки, файлы или объекты? Шпаргалка ИТ-архитектора

Универсального способа хранить данные не существует — это всегда компромисс между скоростью (IOPS), потенциалом масштабирования и ИТ-бюджетом. Часто именно выбор СХД диктует, как будет работать ваша инфраструктура и во сколько она обойдется бизнесу.

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

Типы хранилищ/Хайстекс
Типы хранилищ/Хайстекс
Теги:
Всего голосов 1: ↑1 и ↓0+1
Комментарии0

Как выучить английский язык?

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

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

На Хабр Карьере мы собрали курсы по английскому, которые бьют точно в цель и экономят ваше время — заглядывайте:

Английский для IT. Документация, созвоны и Code Review.

Английский для менеджеров. Переговоры, презентации и управление.

Юридический английский. Контракты и международное право.

Разговорный английский. Живое общение без барьеров.

Английский для собеседований. Самопрезентация и каверзные вопросы.

Подготовка к экзаменам. Стратегии для IELTS и TOEFL.

Еще больше курсов на нашей витрине

Теги:
Всего голосов 2: ↑2 и ↓0+2
Комментарии0

Сейчас в очередной раз увидел новость от Антропика, что разработчики доживают свой последний год. И снова эти "эксперты" путают карту с местностью. Но у нас же с вами есть голова на плечах? Так что давайте сами и подумаем.

Типичный менеджер/аналитик - человек очень далёкий от кода и архитектуры. Да, двигает задачки, общается с бизнесом, делает красивые таблички, НО В КОДЕ НИЧЕРТА НЕ ПОНИМАЕТ. И не поймёт, даже если попросит ChatGPT объяснить. Почему? Да потому что даже если человек знает синтаксис - у него нет самого главного. Нужное мышление нарабатывается годами. Разработка это вообще не про "писать код", вот так открытие!

По какой-то необъяснимой для меня причине каждый раз упускается из вида самое главное. Рабочее приложение != "кнопочки жмутся, всё работает". Это верхушка айсберга, которую видно. Всё на самом деле сильно-сильно глубже. Все эти красивые сервисы, где ты натыкал в графе приложение и оно задеплоилось не применимы ни для одной серьезной компании. Это хорошо работает для стартапа или MVP, у которого трафик 1,5 колеки. И естественно, у человека "не из разработки" нет даже примерного понимания того, как это устроено изнутри. Чёрный ящик. Он не объяснит, почему выбрал тот или иной подход. Не заметит, что он был ошибочным. И это на проектах, в которых дай бог 2-3 сервиса, БД и nginx. Может ли такой человек довести проект до зрелого, стабильного состояния, который сможет развиваться годами? Сомневаюсь. Даже если допустить, что какой-нибудь Claude 5.7 будет в 10 раз умнее нынешнего - проблема не в этом.

Хороший инженер с хорошим инструментом может написать в 10 раз больше хорошего кода. Плохой инженер - напишет в 10 раз больше плохого кода. Пока что я не видел ни одного кейса, который мог бы опровергнуть это утверждение. Ты должен понимать, как работает твоё приложение и почему оно так работает. Это еще один скилл, который каждый разработчик приобретает годами. Это та самая "карта проекта" в голове, которая помогает тебе быстро и эффективно решать задачи. И это понимание спасает от многих проблем и ошибок, которые с ростом проекта становится нереально дорого исправлять. Даже с нейронками.

Еще свежи в памяти падения Cloudflare, AWS и десятка других сервисов. Почему? Потому что инженеры дали слишком много прав агенту, либо невнимательно проверили сгенерированный конфиг или код. НАСТОЯЩИЕ ИНЖЕНЕРЫ, КОТОРЫЕ ПОНИМАЛИ, ЧТО ДЕЛАЮТ. Лицо менеджера-вайбкодера, когда у него упал целый датацентр представили?) Сможет ли медсестра поставить диагноз с ChatGPT точнее, чем опытный врач, который использует тот же инструмент? Нет. Получается, что сам "инструмент" - не решающий фактор. Почему все сравнивают "вот я с гпт такооое могу, увольняйте всех бэкендеров"? И что, я с тем же ГПТ могу больше и быстрее.

На самом деле именно разработчики выигрывают больше всех с развитием ИИ. Сделать нормальное приложение сложнее, чем оформить табличку в аналитике. И уж явно сложнее 99% задач, которые выполняют менеджеры. Думаю Клод с этим справится на ура. Всё потихоньку движется к концепции software-инженера, который сам отвечает за аналитику, сроки выполнения и разработку. Ну и конечно же акцент больше сместится на проектирование архитектуры. Мы просто будем тратить меньше времени на код. И этот подход будет в десятки раз эффективнее любого "менеджера-аналитика-вайбкодера".

Что думаете?

Теги:
Всего голосов 4: ↑4 и ↓0+4
Комментарии2

Сейчас в очередной раз увидел новость от Антропика, что разработчики доживают свой последний год. И снова эти "эксперты" путают карту с местностью. Но у нас же с вами есть голова на плечах? Так что давайте сами и подумаем.

Типичный менеджер/аналитик - человек очень далёкий от кода и архитектуры. Да, двигает задачки, общается с бизнесом, делает красивые таблички, НО В КОДЕ НИЧЕРТА НЕ ПОНИМАЕТ. И не поймёт, даже если попросит ChatGPT объяснить. Почему? Да потому что даже если человек знает синтаксис - у него нет самого главного. Нужное мышление нарабатывается годами. Разработка это вообще не про "писать код", вот так открытие!

По какой-то необъяснимой для меня причине каждый раз упускается из вида самое главное. Рабочее приложение != "кнопочки жмутся, всё работает". Это верхушка айсберга, которую видно. Всё на самом деле сильно-сильно глубже. Все эти красивые сервисы, где ты натыкал в графе приложение и оно задеплоилось не применимы ни для одной серьезной компании. Это хорошо работает для стартапа или MVP, у которого трафик 1,5 колеки. И естественно, у человека "не из разработки" нет даже примерного понимания того, как это устроено изнутри. Чёрный ящик. Он не объяснит, почему выбрал тот или иной подход. Не заметит, что он был ошибочным. И это на проектах, в которых дай бог 2-3 сервиса, БД и nginx. Может ли такой человек довести проект до зрелого, стабильного состояния, который сможет развиваться годами? Сомневаюсь. Даже если допустить, что какой-нибудь Claude 5.7 будет в 10 раз умнее нынешнего - проблема не в этом.

Хороший инженер с хорошим инструментом может написать в 10 раз больше хорошего кода. Плохой инженер - напишет в 10 раз больше плохого кода. Пока что я не видел ни одного кейса, который мог бы опровергнуть это утверждение. Ты должен понимать, как работает твоё приложение и почему оно так работает. Это еще один скилл, который каждый разработчик приобретает годами. Это та самая "карта проекта" в голове, которая помогает тебе быстро и эффективно решать задачи. И это понимание спасает от многих проблем и ошибок, которые с ростом проекта становится нереально дорого исправлять. Даже с нейронками.

Еще свежи в памяти падения Cloudflare, AWS и десятка других сервисов. Почему? Потому что инженеры дали слишком много прав агенту, либо невнимательно проверили сгенерированный конфиг или код. НАСТОЯЩИЕ ИНЖЕНЕРЫ, КОТОРЫЕ ПОНИМАЛИ, ЧТО ДЕЛАЮТ. Лицо менеджера-вайбкодера, когда у него упал целый датацентр представили?) Сможет ли медсестра поставить диагноз с ChatGPT точнее, чем опытный врач, который использует тот же инструмент? Нет. Получается, что сам "инструмент" - не решающий фактор. Почему все сравнивают "вот я с гпт такооое могу, увольняйте всех бэкендеров"? И что, я с тем же ГПТ могу больше и быстрее.

На самом деле именно разработчики выигрывают больше всех с развитием ИИ. Сделать нормальное приложение сложнее, чем оформить табличку в аналитике. И уж явно сложнее 99% задач, которые выполняют менеджеры. Думаю Клод с этим справится на ура. Всё потихоньку движется к концепции software-инженера, который сам отвечает за аналитику, сроки выполнения и разработку. Ну и конечно же акцент больше сместится на проектирование архитектуры. Мы просто будем тратить меньше времени на код. И этот подход будет в десятки раз эффективнее любого "менеджера-аналитика-вайбкодера".

Что думаете?

Теги:
Рейтинг0
Комментарии0

Русский язык программирования.


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


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


Если вы начинающий автор или уже имеете хороший ЯП, пишите в комментарии и оставляйте ваш GitHub\GitFlip и название вашего языка.

Каждый ЯП посмотрю, проверю, изучу.

Теги:
Всего голосов 9: ↑2 и ↓7-5
Комментарии8