Перейти к содержанию
  • Лента
  • Категории
  • Последние
  • Метки
  • Популярные
  • Пользователи
  • Группы
Свернуть
exlends
Категории
  • ru
    Игры
    Образование
    Искусственный Интеллект
    Новости
    Бекенд, разработка серверов
    Фронтенд
    Мобильная разработка
    Языки программирования
    Разработка игр | 3D | 2D
    Базы данных
    CMS
    Системное Администрирование
    Операционные системы
    Маркетинг
    Девайсы
    Сообщество
    Юмор, Мемы

  • en
    Humor
    News
    AI
    Programming languages
    Frontend
    GameDev

  • Блоги

Авторизуйтесь, чтобы написать сообщение

  • Все категории
  • GameFishG
    GameFish
    Pathologic 3: туториалы по Прототипу запутают новичков еще больше

    Обложка: Pathologic 3: новые туториалы по прототипу и дням упростят жизнь новичкам или запутают еще больше

    В Pathologic 3 появились расширенные гайды по одному из самых важных инструментов выживания - Прототипу. На первый взгляд это должно помочь новичкам ориентироваться в механике, но в реальности система оказалась настолько многоуровневой, что даже объяснения путают игроков больше, чем помогают.

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

    Что происходит с Прототипом на практике

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

    Для заправки нужны три компонента:

    • Стимулятор (обычно бычья желчь)
    • Анестетик (новокаин)
    • Токсин (белладонна)

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

    Второй момент - место заправки. Гайды указывают, что это происходит в Стилуотере, в комнате на первом этаже со столами. Но если ты на первый день только приходишь в город и не знаешь, где вообще Стилуотер, инструкция превращается в квест “угадай геолокацию”.

    Хорхой спасает или усложняет

    На третий день ты встречаешь одонга - странного человека с большой головой, который оказывается Хорхоем, торговцем. Если позволить ему поселиться в Стилуотере, он будет каждый день предлагать ингредиенты для обмена.

    В теории это решает проблему поиска компонентов. На практике:

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

    Гайды на разных сайтах советуют “запастись ими в дни, когда вы планируете много перемещаться”. Но как новичок узнает, сколько потребуется? Только методом тыка.

    Три слоя информации, которые не складываются в одну

    Проблема в том, что информация разбросана по разным источникам и уровням игры:

    1. Первый туториал - обучение на лабораторию в Столице, где показывают, как вообще работает заправка
    2. Второй слой - пояснения в Управе, когда впервые используешь Прототип в деле
    3. Третий слой - практика в Стилуотере, куда попадаешь только если дошел до третьего дня и нашел правильный путь

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

    Механика дней добавляет еще больше путаницы

    Игра использует меню мыслей (нажать J на клавиатуре), где показаны все 12 дней с краткими заметками. Идея хороша, но выполнение оставляет желать лучшего:

    • На первый день доступна только база по Прототипу
    • Остальные дни блокированы или содержат только намеки
    • Новичок не может заранее спланировать, когда ему понадобятся ресурсы
    • Каждый день начинается с допросов инспектора, которые не влияют на события, но отнимают время на понимание контекста

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

    Что говорит комьюнити

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

    Студия Ice-Pick Lodge явно рассчитывала на определенный уровень игроков - тех, кто привык к нонлинейным нарративам и сложным механикам. Для широкой аудитории это вышло так же, как добавить инструкцию к икейской мебели, но на китайском.

    Итог: помощь, которая запутывает

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

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


    0 0 0 Ответить
  • kirilljsxK
    kirilljsx
    Кросс-функциональный разработчик 2026: мобила + DevOps + ИИ-тесты

    Обложка: Кросс-функциональные разработчики 2026: как совмещать мобильную разработку с DevOps и ИИ-автоматизацией UI-тестов

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

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

    Давай разберемся, как это все устроено.

    Мобильная разработка встречает DevOps

    Раньше было просто: разработчик написал код, отправил QA, QA нашел баги, разработчик чинил. Теперь этот процесс полностью автоматизирован и встроен в пайплайн. И это твоя ответственность.

    Суть в том, что автоматизированное тестирование мобильных приложений уже не роскошь - это обязательная часть CI/CD. Для мобильных проектов стандарт это Appium или Maestro, интегрированные прямо в GitLab CI или GitHub Actions. Когда ты закомитил код, тесты запускаются параллельно на нескольких исполнителях, ты видишь результаты через 5-10 минут.

    Вот что должен понимать современный мобильный разработчик:

    • Docker и контейнеризация - как собрать образ с тестами, как пробросить конфиги, как запустить его в облачной ферме
    • Kubernetes и оркестрация - если проект масштабный, нужно понимать, как тесты распределяются между нодами
    • GitLab CI / GitHub Actions - структура .gitlab-ci.yml, stages, artifacts, параллельное выполнение (это не опционально)
    • Allure TestOps - интеграция отчетов, чтобы вся команда видела статус в реальном времени

    Пример конфига, который должен собрать даже junior мобильный разработчик:

    stages:
      - test
      - report
    
    mobile_tests:
      stage: test
      image: appium/appium:latest
      script:
        - npm install
        - npx appium --port 4723 &
        - sleep 5
        - npx wdio run wdio.conf.js --baseUrl=$TEST_URL
      parallel:
        matrix:
          - DEVICE: ["iPhone_14", "Android_12", "Android_13"]
      artifacts:
        reports:
          junit: ./test-results.xml
        paths:
          - ./test-results/
    

    Даже если ты не DevOps - ты должен это писать. Это базовая грамотность.

    ИИ как решение для хрупкости автотестов

    А теперь самое интересное. Self-healing тесты - это не фантазия, это реальность 2026-го. И это меняет всю игру.

    Проблема UI-автотестов известна давно: верстальщик переехал кнопку на 10 пикселей - и весь локатор валится. Раньше это означало: QA сидит, чинит локаторы вручную, тратит кучу времени. Теперь ИИ подстраивает тест автоматически, без участия инженера.

    По данным исследований, 68% компаний уже активно работают с ИИ-платформами для ускорения тестирования, а использование ИИ-ассистентов сокращает время тестирования до 50% при сохранении качества.

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

    Вот системный промпт для ИИ-ассистента (типа GitHub Copilot), который может помочь писать автотесты для мобильного приложения:

    Ты - эксперт по мобильной автоматизации тестирования. 
    Твоя задача:
    1. Анализировать UI-структуру приложения и предлагать оптимальные XPath или Accessibility ID локаторы
    2. Писать стабильные тесты, которые не падают при изменении интерфейса
    3. Использовать явные ожидания (explicit waits) вместо sleep()
    4. Предлагать стратегию параллельного запуска тестов
    5. Генерировать читаемые баг-репорты с скриншотами и логами
    
    Когда ты видишь нестабильный тест, предложи решение через retry-логику и self-healing подход.
    Если нужно работать с WebView внутри нативного контейнера - это усложняет ситуацию; в этом случае объясни подводные камни.
    
    Пишешь только на JavaScript или Python, в зависимости от стека.
    

    Использование Cursor и GitHub Copilot на таких промптах сокращает время на рутинные задачи на 55%. Это не 5%, это серьезно влияет на скорость разработки.

    Как совместить все это в реальном проекте

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

    1. Юнит-тесты (основание) - проверяют отдельные функции, запускаются за миллисекунды
    2. Интеграционные тесты - проверяют API, базу данных, сервисы вместе
    3. E2E тесты (вершина) - реальные сценарии пользователя на реальных девайсах

    Все это встроено в CI/CD пайплайн. Критические тесты выполняются в первую очередь, параллельное выполнение сокращает общее время прогона.

    Реальный кейс: мобильное приложение для лидов. Ты разработчик, и твоя задача:

    • Написать функцию авторизации на React Native / Flutter
    • Написать юнит-тесты (Jest / Pytest)
    • Написать E2E тесты через Appium 2.0
    • Собрать Docker-образ с тестами
    • Интегрировать в GitLab CI с параллельным запуском на 5 девайсах
    • Прокинуть отчеты в Allure TestOps
    • Настроить self-healing для хрупких UI-локаторов

    Все это должен делать один человек. Раньше это казалось невозможным. Теперь это стандарт.

    Честная оценка и реальность РФ

    Теория хорошая, но как это работает в российских стартапах и компаниях? Правда в том, что в топ-100 компаниях (МТС, Яндекс, VK) это уже норма. В стартапах и середняках - сильно отстают. Много мест, где все еще мучаются с костылями, недоделанными автотестами и ручным QA.

    Но рынок меняется быстро. Если ты сейчас подучишь DevOps, Docker и базовый ИИ-workflow - через полгода это будет в цене. Компании ищут именно таких универсалов, потому что узких специалистов просто нечем заменить на нужные деньги.

    Вопрос к сообществу: Как вы в своих проектах организуете автоматизацию тестов? Вы уже используете ИИ-ассистентов для написания тестов или еще на старых методах? И главное - насколько реально все это внедрить в российских условиях?


    0 0 0 Ответить
  • kirilljsxK
    kirilljsx
    Covariant RFM-1 и Ambi PRIME-1: как ИИ автоматизирует склады в 2026

    Обложка: Как мультимодальные ИИ-модели Covariant RFM-1 и Ambi PRIME-1 автоматизируют складскую робототехнику в 2026

    Представьте склад, где роботы сами разбирают хаос из посылок любого размера и формы, без вечных простоев и ошибок. Рутина сортировки и упаковки жрет до 40% времени персонала на больших логистических хабах, а дефицит рабочих только усугубляет. Мультимодальные модели вроде Covariant RFM-1 и Ambi PRIME-1 меняют это: они дают роботам человеческий уровень понимания мира - зрение, язык, физику и действия в одном флаконе. Теперь роботы не тупо следуют скриптам, а реально думают и адаптируются на лету.

    Что такое RFM-1 и PRIME-1: мозги для железа

    RFM-1 от Covariant - это Robotics Foundation Model, обученная на огромном датасете реальных складских операций плюс интернет-текстах вроде тех, что юзают в ChatGPT. Модель предсказывает физику через генерацию видео: робот симулирует, как предмет отреагирует на хват, и выбирает лучший вариант. Результат? Скорость и надежность на уровне человека, но без кофе-брейков и усталости. Amazon уже лицензировала это и позвала основателей в свою робототехническую команду.

    PRIME-1 от Ambi Robotics бьет по объемам: 20 млн изображений и 200 тыс. часов видео операций. Она питает систему AmbiStack для упаковки - роботы сортируют и пакуют посылки на скоростных линиях, как у Pitney Bowes. Ключ - мультимодальность: модель жует видео с камер в реальном времени, понимает команды на естественном языке и действует без задержек.

    Модель Датасет Ключевой фича Применение
    RFM-1 Складские данные + интернет-текст Physics world model via видео Pick-and-place, симуляция действий
    PRIME-1 20M изображений + 200K часов видео Реал-тайм сортировка Упаковка посылок, AmbiStack

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

    Как это работает на практике

    Роботы с этими моделями - это Vision-Language-Action (VLA) системы. Камера ловит поток видео, модель анализирует сцену, язык дает инструкции (типа “упакуй хрупкое в пузырь”), а физическая модель просчитывает хват без краш-тестов в реале. Обучение на отражениях ускоряет адаптацию: робот сам анализирует ошибки и улучшается за минуты, а не месяцы.

    Для разработчиков профит огромный. Интегрируйте через API: фронт на JS шлет видео, бэкенд на Python обрабатывает модель и отдает команды актуаторам. Вот пример Python-кода для симуляции запроса к RFM-1-like API (адаптировано под рест-API мультимодальных моделей):

    import requests
    import base64
    
    def process_warehouse_frame(video_frame, instruction):
        # Кодируем видео в base64 для мультимодального API
        with open(video_frame, 'rb') as f:
            video_b64 = base64.b64encode(f.read()).decode('utf-8')
        
        payload = {
            'video': video_b64,
            'instruction': instruction,  # 'Сортируй хрупкие посылки первыми'
            'model': 'rfm-1'
        }
        
        response = requests.post('https://api.covariant.ai/predict', json=payload)
        return response.json()['action_plan']  # Возвращает план хватов
    
    # Пример использования
    plan = process_warehouse_frame('frame.mp4', 'Упакуй коробки по размеру')
    print(plan)
    

    Этот скрипт - основа для бэкенда: масштабируйте на флот роботов, добавьте очередь в Redis. JS-версия для фронта/мобилки аналогична с WebRTC для стрима видео.

    Бизнес-эффект: профит для складов

    Сортировка 1000+ посылок в час - реальность с PRIME-1. RFM-1 снижает простои на 50%, роботы хватают never-seen-before предметы. Для логистики это миллионы на оптимизации: меньше персонала, быстрее доставка, меньше брака. Переход на такие системы окупается за год при объемах типа Wildberries или Ozon.

    В реалиях РФ? Подходит идеально для мега-складов под Москвой или Питером, где логистика - bottleneck. Импорт железа под санкциями - хреново, но софт от Covariant/Ambi через API можно тянуть, а роботов собирать локально на базе open-source hardware. Тестируйте на пилоте: профит outweighs риски.

    Что дальше для ваших складов?

    Эти модели - не хайп, а инструмент, который уже приносит бабки большим игрокам. Инвестируйте в интеграцию сейчас, пока конкуренты спят. А вы как решаете боль с сортировкой - своими парсерами, дешевыми конвейерами или уже тестите ИИ-роботов? Делитесь в коммах, обсудим стеки и кейсы!


    0 0 0 Ответить
  • barsikB
    barsik
    Node.js в реальных проектах: кейсы API и чатов, проблемы с памятью и решения

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

    Почему компании выбирают Node.js

    Если посмотреть на кейсы крупных компаний, причины выбора очевидны. LinkedIn полностью переписал серверную часть мобильного приложения на Node.js и смог уменьшить количество используемых серверов, одновременно повысив производительность в несколько раз по сравнению с Ruby on Rails. PayPal активно использует Node.js для построения API и интерфейсов, а eBay обрабатывает миллионы транзакций благодаря эффективности платформы. Uber обеспечивает доступ к приложению в любое время суток, полагаясь на масштабируемость Node.js.

    Особенно заметна эффективность Node.js в сценариях с частым обменом данными. Движок V8 постоянно совершенствуется, позволяя платформе показывать производительность, сопоставимую с приложениями на компилируемых языках.

    Реальный случай: оптимизация кэширования

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

    Решение было элегантным: вместо хранения буферов в кэше разработчики стали держать указатели на позиции в файле (start/end-позиции). Когда клиент запрашивал данные, система использовала fs.createReadStream(...).pipe(...). Результат впечатляет: потребление памяти Node.js упало ниже 200 МБ под максимальной нагрузкой — более чем в 10 раз лучше, чем было раньше.

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

    Чаты и real-time коммуникация

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

    Однако здесь скрывается опасность: накопление состояния в памяти. Node.js приложения часто хранят сессии пользователей, истории сообщений и другие данные в оперативной памяти, что требует тщательного управления.

    Проблема: Heap Out of Memory

    Самая распространенная ошибка, с которой встречаются разработчики — JavaScript Heap Out of Memory. Движок V8 исчерпывает лимит памяти, выделенный под объекты, строки и замыкания, и приложение падает мгновенно.

    Причины могут быть разными:

    • Утечки памяти в коде
    • Недостаточно выделенной памяти на хосте
    • Неэффективная работа с большими объемами данных
    • Проблемы в gRPC-вызовах между микросервисами

    Решение №1: Увеличение лимита памяти

    Первый и самый быстрый способ — использовать флаг --max-old-space-size. Он говорит движку V8 расширить его «old space» (самую большую часть кучи) до конкретного числа мегабайт:

    node --max-old-space-size=4096 app.js
    

    Для системы с 4 ГБ RAM выделяем 4096 МБ, с 8 ГБ — 8192 МБ.

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

    Чтобы сделать фикс постоянным для проекта, добавьте флаг в package.json:

    {
      "scripts": {
        "start": "node --max-old-space-size=4096 server.js",
        "build": "NODE_OPTIONS='--max-old-space-size=4096' next build"
      }
    }
    

    Теперь команда npm start явно запустит Node.js с 4 ГБ памяти под кучу.

    Решение №2: Поиск и устранение утечек памяти

    Если просто увеличение лимита не помогает, значит, в коде есть утечки. На одном из реальных проектов разработчики столкнулись с ситуацией, когда heap snapshot весил всего 20-30 МБ, а процесс отъедал гигабайт и падал. Проблема решилась обновлением версии Node.js.

    Для диагностики используют несколько инструментов:

    • Heap snapshots — снимки состояния памяти в конкретный момент
    • Diff snapshots — сравнение снимков для выявления утечек
    • GC трассировщики — анализ работы garbage collector
    • Flame graphs — визуализация использования памяти по времени
    • Системы мониторинга (New Relic, altri сервисы)

    Реальный пример: микросервисы и gRPC

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

    Для диагностики использовали скрипт нагрузочного тестирования:

    #!/bin/bash
    server_address="localhost"
    server_port="5001"
    service="client.ClientService"
    method="MakeRequest"
    proto_path="/Users/artem/Work/grpc/grpc-client/src/client"
    proto_file="client.proto"
    count=100
    
    for ((i = 0; i < $count; i++))
    do
      grpcurl -import-path $proto_path -proto $proto_file \
        -d '{"id": 1}' -plaintext $server_address:$server_port \
        $service/$method
      sleep 1
    done
    

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

    Масштабирование: кластеры и worker threads

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

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

    Альтернатива — использование модуля worker threads для вычислительных задач, что позволяет избежать блокирования основного потока события.

    Практические рекомендации

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

    2. Используйте потоки. Для работы с большими файлами применяйте fs.createReadStream вместо загрузки всего файла в память.

    3. Мониторьте память в production. Настройте систему мониторинга еще на этапе разработки.

    4. Оптимизируйте структуры данных. Избегайте ненужных копий массивов и объектов.

    5. Регулярно обновляйте Node.js. Новые версии содержат оптимизации и исправления утечек памяти.

    6. Проводите нагрузочное тестирование. Выявляйте проблемы до production, а не после.

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


    0 0 0 Ответить
  • barsikB
    barsik
    Node.js в реальных проектах: кейсы API и чатов, типичные проблемы с памятью и решения

    Node.js давно вышел за рамки экспериментальной платформы и стал основой для реальных высоконагруженных проектов, особенно в fintech, чатах и API-сервисах. Его событийно-ориентированная модель идеально подходит для обработки множества одновременных запросов, но с ростом нагрузки часто возникают проблемы с памятью — утечки, переполнение кучи V8 и OOM-ошибки. В этой статье разберем реальные кейсы из практики, типичные ловушки и проверенные решения, чтобы вы могли избежать падений в продакшене. Поделитесь в комментариях своими историями: сталкивались ли вы с подобным в своих проектах?

    Кейс 1: API для fintech — обработка транзакций на миллионы запросов

    В fintech-проектах Node.js часто используется для backend API, где важны скорость и масштабируемость. Представьте сервис вроде eBay или Uber: миллионы транзакций в секунду, интеграция с базами данных и внешними gRPC-сервисами. Один из реальных примеров — микросервис для обработки платежей, где под нагрузкой 500+ клиентов приложение “съедало” гигабайты RAM и падало с ошибкой JavaScript heap out of memory.

    Проблема: Стандартный лимит памяти V8 (около 1.4 ГБ на 64-битной системе) исчерпывался из-за накопления буферов данных в кэше. Каждый запрос к БД или gRPC возвращал большие массивы, которые не освобождались timely из-за замыканий в обработчиках.

    Решение в коде: Вместо хранения полных буферов в памяти, перешли на потоковую обработку с fs.createReadStream().pipe(). Это позволило держать в RAM только указатели на позиции в файле, снижая потребление до 200 МБ под пиковой нагрузкой.

    // Плохо: кэшируем весь файл
    const cache = new Map();
    app.get('/data/:id', async (req, res) => {
      const data = await fs.readFile(filePath); // 100 МБ в памяти!
      cache.set(req.params.id, data);
      res.send(data);
    });
    
    // Хорошо: потоковая отдача без кэша в RAM
    app.get('/data/:id', (req, res) => {
      const stream = fs.createReadStream(filePath, { start: offset, end: length });
      stream.pipe(res); // Память не растет!
    });
    

    Практический совет: Для API в fintech используйте кластеры Node.js (cluster модуль) или PM2 для распределения нагрузки. В package.json добавьте:

    {
      "scripts": {
        "start": "pm2 start server.js -i max --node-args='--max-old-space-size=4096'"
      }
    }
    

    Это повысит лимит до 4 ГБ на процесс и автоматически перезапустит упавшие инстансы. В результате latency упал на 50%, а uptime вырос до 99.99%.

    Кейс 2: Чат-сервис — реал-тайм общение с тысячами пользователей

    Чаты — классика для Node.js благодаря Socket.io или ws. В проекте вроде LinkedIn или корпоративного чата сообщения должны доставляться мгновенно, без задержек. Но под 10k+ соединениями память “утекает” из-за неочищенных интервалов, таймеров и глобальных объектов.

    Реальный кейс: Сервис обратной связи для компании, где чат обрабатывал 500 злых клиентов с запросами без пауз. Память росла линейно из-за хранения состояний пользователей в Map и неудаленных event listeners.

    Типичная проблема: GC (Garbage Collector) не справляется с “long-lived” объектами — сокетами, которые висят в памяти после disconnect.

    Решение:

    1. Очистка ресурсов в Socket.io:
    const io = require('socket.io')(server);
    
    io.on('connection', (socket) => {
      let userTimer; // Таймер для heartbeat
    
      socket.on('join', (userId) => {
        userTimer = setInterval(() => socket.emit('heartbeat'), 30000);
      });
    
      socket.on('disconnect', () => {
        clearInterval(userTimer); // Обязательно чистим!
        socket.removeAllListeners(); // Удаляем все listeners
      });
    });
    
    1. Мониторинг с heap snapshots. В проде используйте --inspect и Chrome DevTools: сделайте snapshot до/после нагрузки, сравните diff. В кейсе с микросервисами утечка нашлась в gRPC-клиенте — не закрытые соединения.

    Скрипт для нагрузочного теста (bash из реального кейса):

    #!/bin/bash
    server_address="localhost"
    server_port="5001"
    count=1000
    for ((i = 0; i < $count; i++)); do
      grpcurl -d '{"id": 1}' -plaintext $server_address:$server_port service/method
      sleep 0.1
    done
    

    Рекомендация: Интегрируйте New Relic или clinic.js для flame graphs и трассировки GC. В чатах держите состояния в Redis, а не в RAM: socket.userId = await redis.get(userId). Это масштабирует до миллионов пользователей, как в Uber.

    Типичные проблемы с памятью в Node.js и как их решать

    1. OOM (Out of Memory) на компиляции/минификации.
    При npm build с Webpack или Next.js V8 “задыхается”.
    Фикс: NODE_OPTIONS='--max-old-space-size=8192' npm run build в package.json. Для 8 ГБ RAM — норма.

    2. Утечки от замыканий и глобалов.
    Пример: Массив на миллион элементов мутируется, но ссылка висит.

    // Ложноэкономит память, но утекает
    const arr = new Array(1e6).fill('data');
    arr.forEach((item, i) => arr[i] = processData(item)); // Новый массив!
    
    // Правильно
    arr.forEach((item, i) => { arr[i] = processData(item); });
    

    3. Масштабирование: кластеры и worker_threads.
    Один поток — узкое место. Используйте cluster:

    const cluster = require('cluster');
    if (cluster.isMaster) {
      for (let i = 0; i < require('os').cpus().length; i++) {
        cluster.fork();
      }
    } else {
      // Ваш сервер
      http.createServer(app).listen(3000);
    }
    

    Для CPU-задач — worker_threads.

    4. Диагностика в проде.

    • --heap-prof для профилей.
    • 0x для снепшотов: node --heapsnapshot-signal=SIGUSR2 app.js, затем анализ в Chrome.
    • Инструменты: clinic doctor, 0x, flamebearer.

    Таблица сравнения решений по памяти:

    Проблема Решение Эффект на RAM Пример использования
    OOM на старте --max-old-space-size +4-8 ГБ лимит Build-скрипты
    Утечка в кэше Stream + указатели -80% под нагрузкой API/Файлы
    Socket утечки clearInterval/removeAll Стабильные 200 МБ Чаты
    Масштаб Cluster/PM2 x CPUs инстансов Fintech

    Лучшие практики для реальных проектов

    • Обновляйте Node.js: С 20+ версии инструменты диагностики работают лучше, утечки фиксятся automatically.
    • Мониторинг: Prometheus + Grafana для метрик RSS/HeapUsed.
    • Тестирование: Artillery или autocannon для симуляции нагрузки.
    • Fintech-специфика: Используйте TypeScript + Zod для валидации, чтобы избежать null-утечек в API.

    В наших проектах переход на эти практики сократил инциденты на 90%. А как у вас? Делитесь кодами утечек или инструментами — обсудим в комментариях! Какие фреймворки (Express, Nest.js, Fastify) спасли ваши чаты от краха?


    0 0 0 Ответить
  • hannadevH
    hannadev
    REST API: как им пользоваться, для чего нужен и как его разработать на JavaScript

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

    REST API (Representational State Transfer Application Programming Interface) — это архитектурный стиль, который определяет стандарты взаимодействия между клиентом и сервером. В финансовой отрасли, где каждая миллисекунда имеет значение, REST API обеспечивает быстрый и предсказуемый обмен данными между приложениями.

    Что такое REST API?

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

    Основные характеристики REST API:

    • Клиент-серверная архитектура: Разделение интерфейса и обработки данных
    • Отсутствие состояния (stateless): Каждый запрос содержит всю необходимую информацию
    • Кэширование: Улучшение производительности за счет хранения временных данных
    • Единообразие интерфейса: Стандартные методы для операций с ресурсами

    HTTP-методы и их назначение

    В REST API каждый метод выполняет определенную операцию:

    GET — получение данных. Например, запрос баланса пользователя или истории транзакций. В финансовой сфере это наиболее часто используемый метод, так как он не изменяет данные на сервере.

    POST — создание новых ресурсов. Идеально подходит для создания новых счетов, отправки транзакций или регистрации пользователей.

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

    PATCH — частичное обновление. Позволяет изменить только определенные поля, что экономит трафик и увеличивает производительность.

    DELETE — удаление ресурса. Применяется для закрытия счетов или удаления временных данных.

    Как разработать REST API на JavaScript

    Node.js стал идеальной платформой для разработки REST API благодаря своей асинхронной природе и огромной экосистеме пакетов. Вот основные шаги создания REST API:

    Шаг 1: Инициализация проекта

    Создайте новый проект и установите необходимые зависимости:

    mkdir exlends-api
    npm init -y
    npm install express
    

    Шаг 2: Создание базового сервера

    const express = require('express');
    const app = express();
    const port = 3000;
    
    // Middleware для парсинга JSON
    app.use(express.json());
    
    // Пример GET эндпоинта
    app.get('/api/balance', (req, res) => {
      res.json({ balance: 150000, currency: 'RUB' });
    });
    
    app.listen(port, () => {
      console.log(`ExLends API работает на порту ${port}`);
    });
    

    Шаг 3: Проектирование ресурсов

    В финансовой сфере типичные ресурсы включают:

    • /api/accounts — управление счетами
    • /api/transactions — транзакции и платежи
    • /api/users — данные клиентов
    • /api/reports — отчеты и аналитика

    Шаг 4: Реализация CRUD операций

    // Мок-база данных
    let transactions = [];
    
    // GET - получить все транзакции
    app.get('/api/transactions', (req, res) => {
      res.json(transactions);
    });
    
    // POST - создать транзакцию
    app.post('/api/transactions', (req, res) => {
      const newTransaction = {
        id: transactions.length + 1,
        amount: req.body.amount,
        from: req.body.from,
        to: req.body.to,
        date: new Date()
      };
      transactions.push(newTransaction);
      res.status(201).json(newTransaction);
    });
    
    // PUT - обновить транзакцию
    app.put('/api/transactions/:id', (req, res) => {
      const index = transactions.findIndex(t => t.id == req.params.id);
      if (index !== -1) {
        transactions[index] = { ...transactions[index], ...req.body };
        res.json(transactions[index]);
      } else {
        res.status(404).json({ error: 'Транзакция не найдена' });
      }
    });
    
    // DELETE - удалить транзакцию
    app.delete('/api/transactions/:id', (req, res) => {
      const index = transactions.findIndex(t => t.id == req.params.id);
      if (index !== -1) {
        transactions.splice(index, 1);
        res.json({ message: 'Транзакция удалена' });
      } else {
        res.status(404).json({ error: 'Транзакция не найдена' });
      }
    });
    

    Шаг 5: Обработка ошибок и кодирование

    Важно правильно обрабатывать ошибки и возвращать соответствующие HTTP-коды:

    • 200 OK — успешная операция
    • 201 Created — ресурс создан
    • 400 Bad Request — некорректный запрос
    • 401 Unauthorized — требуется авторизация
    • 403 Forbidden — недостаточно прав
    • 404 Not Found — ресурс не найден
    • 500 Internal Server Error — ошибка сервера

    Best Practices для финансовых приложений

    Безопасность

    Используйте HTTPS для шифрования данных в transit. Для аутентификации применяйте JWT (JSON Web Tokens) или OAuth 2.0. Всегда валидируйте входные данные и sanitize их перед обработкой.

    Валидация данных

    const validateTransaction = (req, res, next) => {
      const { amount, from, to } = req.body;
      
      if (!amount || amount <= 0) {
        return res.status(400).json({ error: 'Некорректная сумма' });
      }
      
      if (!from || !to) {
        return res.status(400).json({ error: 'Указаны не все обязательные поля' });
      }
      
      next();
    };
    

    Лимитирование запросов (Rate Limiting)

    npm install express-rate-limit
    
    const rateLimit = require('express-rate-limit');
    
    const limiter = rateLimit({
      windowMs: 15 * 60 * 1000, // 15 минут
      max: 100 // максимум 100 запросов
    });
    
    app.use('/api/', limiter);
    

    Документирование API

    Используйте инструменты вроде Swagger/OpenAPI для автоматической генерации документации. Это упрощает интеграцию для внешних партнеров и ускорят разработку.

    Практический пример: API для переводов

    const express = require('express');
    const app = express();
    app.use(express.json());
    
    // Хранилище счетов
    const accounts = new Map();
    accounts.set('user1', { id: 'user1', balance: 10000 });
    accounts.set('user2', { id: 'user2', balance: 5000 });
    
    // Перевод средств
    app.post('/api/transfer', async (req, res) => {
      const { from, to, amount } = req.body;
      
      // Проверка существования счетов
      if (!accounts.has(from) || !accounts.has(to)) {
        return res.status(404).json({ error: 'Счет не найден' });
      }
      
      // Проверка достаточности средств
      const fromAccount = accounts.get(from);
      if (fromAccount.balance < amount) {
        return res.status(400).json({ error: 'Недостаточно средств' });
      }
      
      // Выполнение перевода
      fromAccount.balance -= amount;
      const toAccount = accounts.get(to);
      toAccount.balance += amount;
      
      // Логирование транзакции
      console.log(`Перевод: ${amount} RUB от ${from} к ${to}`);
      
      res.json({
        success: true,
        message: 'Перевод выполнен успешно',
        fromBalance: fromAccount.balance,
        toBalance: toAccount.balance
      });
    });
    
    app.listen(3000, () => console.log('API для переводов работает'));
    

    Заключение

    REST API — это фундаментальный инструмент современной разработки, особенно в финансовой сфере. Правильно спроектированный REST API обеспечивает:

    • Масштабируемость приложений
    • Простоту интеграции с другими системами
    • Надежность и безопасность данных
    • Высокую производительность

    Для команды ExLends mastering REST API означает возможность создавать инновационные финансовые продукты, которые работают быстро, безопасно и предсказуемо. Начните с простых проектов, постепенно усложняя их, и всегда следуйте best practices для создания профессиональных решений.

    В мире, где технологии определяют будущее финансов, понимание REST API становится конкурентным преимуществом, которое позволяет создавать решения, меняющие индустрию.


    1 0 0 Ответить
  • barsikB
    barsik
    TypeScript 5.6: новые возможности и практическое применение

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

    В этой статье мы рассмотрим ключевые нововведения TypeScript 5.6 и разберём, как они могут улучшить ваш опыт разработки.

    Основные нововведения

    1. Запрещенные проверки на Nullish и Truthy

    Одна из самых полезных новых возможностей — обнаружение подозрительных проверок, которые всегда возвращают true или false. TypeScript 5.6 теперь выдаёт ошибки для таких случаев:

    // Пример 1: Регулярное выражение без вызова .test()
    if (/0x[0-9a-f]/) {
      // Ошибка: Такое выражение всегда правдиво
    }
    
    // Пример 2: Случайная стрелочная функция вместо оператора сравнения
    if (x => 0) {
      // Ошибка: Такое выражение всегда истинно
    }
    
    // Пример 3: Проблема с приоритетом операторов
    function isValid(value: string | number, options: any, strictness: "strict" | "loose") {
      if (strictness === "loose") {
        value = +value
      }
      return value < options.max ?? 100;
      // Ошибка: Правый операнд ?? недостижим
    }
    

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

    2. Улучшенная поддержка контекстных типов для стрелочных функций

    TypeScript 5.6 улучшает вывод типов для стрелочных функций, особенно в случаях, когда они используются как аргументы других функций. Это делает код более лаконичным и уменьшает необходимость в явных аннотациях типов.

    3. Оптимизации производительности

    Новая версия включает несколько оптимизаций компилятора, которые ускоряют сборку крупных проектов. Особенно заметны улучшения в инкрементальной компиляции.

    Практические примеры

    Пример использования новых проверок

    Рассмотрим реальный сценарий, где новые проверки могут предотвратить ошибку:

    // До TypeScript 5.6: потенциальная ошибка
    function processUserInput(input: string) {
      if (input.trim()) {
        // Всегда выполняется, даже если input пустая строка после trim()
        console.log("Processing input...");
      }
    }
    
    // После TypeScript 5.6: получаем предупреждение
    function processUserInputSafe(input: string) {
      const trimmed = input.trim();
      if (trimmed) {
        // Корректная проверка
        console.log("Processing input...");
      }
    }
    

    Вопросы для обсуждения

    1. Какие из новых возможностей TypeScript 5.6 вы считаете наиболее полезными в своей повседневной работе?

    2. Сталкивались ли вы с ошибками, которые теперь обнаруживаются новыми проверками на nullish/truthy значения? Поделитесь примерами из своего опыта.

    3. Как вы оцениваете темп развития TypeScript? Достаточно ли быстро язык реагирует на потребности разработчиков?

    4. Какие улучшения вы хотели бы видеть в следующих версиях TypeScript?

    5. Как вы организуете процесс обновления TypeScript в своих проектах? Есть ли какие-то best practices для плавного перехода на новые версии?

    Заключение

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

    Рекомендуем обновить TypeScript в своих проектах, чтобы воспользоваться этими улучшениями. Как всегда, перед обновлением стоит проверить, нет ли breaking changes для вашего конкретного кейса.

    Источники:

    • Официальный анонс TypeScript 5.6 - оригинальная статья от Microsoft

    0 0 0 Ответить
  • kirilljsxK
    kirilljsx
    Генерируем SSH ключи и подключаем GitHub

    Надеюсь не надо никому рассказывать что такое ssh-ключи да? А если надо то напиши об этом коротко:

    Ключ ssh - необходим что бы компьютеры подключались и обменивались данными через сетевые протоколы.

    Сперва проверим есть ли на нашем ПК вообще ключи:

    # Перейдем в домашнюю директорию
    cd ~
    

    Теперь для того что бы посмотреть если у нас ключи или нет, надо найти скрытую папку .ssh/, а делается это очень просто вот так:

    ls -la .ssh/
    

    Опа, у меня есть у Вас?
    4f365269-31ae-4db4-86f4-9e9df180a303-image.jpeg

    А Вас всего скорее нету, по этому идем дальше.

    Генерация ssh-ключа

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

    ssh-keygen -t ed25519 - C "test@yandex.ru"
    

    Смотрите внимательно - тут я вставил тестовую почту, Вы должны вставить свою которая привязана к GitHub!

    Если вдруг появилось сообщение об ошибке или еще какая либо ерунда - всего скорее ваша система не поддерживает алгоритм шифрования ed25519, но не расстраиваемся есть запасной вариант:

    ssh-keygen -t rsa -b 4096 -C "tes@yandex."
    

    Теперь либо при первом либо при втором варианте Вы должны увидеть следующее сообщение:

        > Generating public/private rsa key pair.
    

    Отлично, теперь просто нажимаем Enter, всего скорее у Вас будет сообщение:

    Enter a file in which to save the key
    

    Он будет просить ввести имя файла где будет сохранен ключ, не надо ничего придумывать нажимаем Enter

    Все теперь в директории .ssh/ появятся ключи, но на этом не все!

    Внимание, теперь всего скорее генератор попросит ввести пароль/фразу - ЭТОТ ПАРОЛЬ НУЖНО ВВОДИТЬ КАЖДЫЙ РАЗ ПРИ СОЕДИНЕНИЯ ЧЕРЕЗ ПРОТОКОЛ. Поэтому запишите его!

    Ну а если Вы уверены в себе как и я просто нажмите Enter что бы не вводить не каких паролей.

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

    Для чего - что бы каждый раз не вводить пароль при работе с репозиторием.

    Делаем следующим образом:

    eval ${ssh-agent -s}
    

    Теперь необходимо привязать этот ключ к нашему агенту, делаем так:

    # для шифрования ed25519:
    ssh-add ~/.ssh/id_ed25519
    
    # для шифрования rsa:
    ssh-add ~/.ssh/id_rsa
    

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

    Привязка SSH-ключей к GitHub

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

    Если у тебя mac:

    # для шифрования ed25519:
    pbcopy < ~/.ssh/id_ed25519.pub
    # для шифрования rsa:
    pbcopy < ~/.ssh/id_rsa.pub
    

    Если у тебя windows:

    # для шифрования ed25519:
    clip < ~/.ssh/id_ed25519.pub
    # для шифрования rsa:
    clip < ~/.ssh/id_rsa.pub
    

    Если по каким-то причинам ключ не скопировался в буфер обмена, то идем в нашу скрытую папку .ssh/ и открываем файл:

    • id_ed25519.pub
    • id_rsa.pub

    В зависимости от шифрования - не путайте!

    Если не знаете как посмотреть файл - пишем вот так:
    cat ~/.ssh/id_ed25519.pub В путях то вы понимаете надеюсь?

    Едем дальше, теперь после того как скопировали ключ - идем в GitHub

    Тыкаем на свой профиль и в выпадающем меню нажимаем Setting
    5a3fe0a9-9418-48d2-8af3-af8784167656-image.jpeg

    После этого слева ищем SSH adn GPG keys, нажимам и переходим дальше:

    1ec2980b-dbed-41c6-b893-a2189745893f-image.jpeg

    Теперь у Вас должно открыться окно с ключами (у меня их много) а у вас всего скорее будет пусто, ищем кнопку и нажимаем New SSH key

    698f6493-af89-4f3c-a62b-4b990e9634c1-image.jpeg

    В новой страничке GitHub запросит у нас название ключа - его можете обозвать как хотите, а вот ниже где написано key туда мы уже вставляем наш ключ который мы скопировали из терминала и нажимаем кнопку Add SSH key

    5666e355-c270-46d9-b138-3442e5bb6e30-image.jpeg

    Ура! Теперь наш GitHub знает о нашем локальном ПК и можно пользоваться такими замечательными командами как git pull, git push и так далее!

    На этом на сегодня все, успехов Вам джунщики и вкатуны в ИТ 😁

    Ну и подпишитесь если не жалко:

    Link Preview Image
    Кирилл Дворянинов

    Обо всем и не о чем сразу! IT форум - forum.exlends.com

    favicon

    MAX (max.ru)


    0 0 0 Ответить
  • kirilljsxK
    kirilljsx
    Как настроить React с Vite?

    a388cfec-98b3-4bbe-b4d9-385e9a5290d0-image.jpeg

    Если кто не знаком с Vite или только вкатывается в веб-разработку начиная свои первые шаги с React, то эта статья определенно для Вас!

    Vite - это быстрый и современный инструмент сборки для создания веб-приложений. Он ускоряет процесс разработки, обеспечивая более быстрое время сборки и лучшую производительность. Ранее для работы с React самим вручную необходимо было прикручивать webpack, babel и другие штуки для работы, но с приходом Vite он делает все сам, а мы лишь занимаемся разработкой не отвлекаясь на не нужные нам настройки.

    Ниже перечислены некоторые преимущества использования React с Vite:

    • Быстрые обновления без перезагрузки страниц.
    • Более быстрые и компактные сборки для продакшена.
    • Автоматическая обработка JSX.
    • Более быстрая сборка.

    Ну и конечно же стандартные настройки что бы начать программировать сразу!

    Пошаговая инструкция по настройке React с Vite

    Шаг 1- Установка node
    Для работы с Vite и конечно же с React требуется node js и npm, если Вы их еще не установили сделайте это, вот ссылки:

    • https://nodejs.org/en/download
    • https://docs.npmjs.com/downloading-and-installing-node-js-and-npm

    Шаг 2 - Создаем новый проект с Vite

    Vite предоставляет простой способ создания новых проектов. Для создания нового проекта React с помощью Vite можно использовать следующую команду:

    npm create vite@latest my-react-app
    

    a904f81a-6621-4629-93a3-2f59694b8869-image.jpeg

    Шаг 3: Выберите фреймворк

    После того как мы начали установку нашего реакт приложение необходим выбрать сам реакт:
    894d9615-6912-403a-9307-d35ebaa9c15c-image.jpeg

    Далее установщик предложит как мы хотим использовать react с использование TypeScript, React Compiler. Так как эта статья для джунщиков и вкатунов, выбираем 3 вариант просто JavaScript:

    f5fa696e-7fdf-4ace-b4a9-e263ac1e18de-image.jpeg

    После выбора инструментария установщик спроси установить через npm пакеты и запустить? Нажимаем - yes
    cdcdd36e-fbf9-4f34-a073-cd85b1265c1a-image.jpeg

    Дожидаемся и видим что наше приложение готово и запустилось:

    41030b5c-e36a-4956-9b99-97a4d9eebb0c-image.jpeg

    Попробуй перейти по ссылке из терминала: http://localhost:5173/ и если все прошло удачно, то попадете на стартовую страницу react + vite приложения:

    73a06842-7c94-4b68-82b3-75fa8fcb9683-image.jpeg

    УРА! Теперь все готово для работы, после нажимаем ctrl+c что бы отключиться в терминале:
    d8922379-3b98-46ef-a1dd-a0235f398d40-image.jpeg

    После можно спокойно переходить в папку с проектом:

    cd my-react-app
    

    И запускать редактор кода (vs code или что там у вас):

    code .
    

    Если вы уже делали все манипуляции через редактор кода и встроенный терминал то думаю не надо объяснять что куда 😊

    Ну все теперь теперь можете работать с React и не париться насчет настройки и билдинга проекта - успехов Вам!

    И да, если что подписывайте на меня в МАХ:

    Link Preview Image
    Кирилл Дворянинов

    Обо всем и не о чем сразу! IT форум - forum.exlends.com

    favicon

    MAX (max.ru)


    0 0 0 Ответить
  • kirilljsxK
    kirilljsx
    Как маркировать рекламную статью: ERID, ОРД, ЕРИР — пошаговая инструкция

    И так в этой статье разбираем, когда статья считается рекламой, как получить ERID, где разместить идентификатор в тексте, что передать в ОРД и когда сдавать отчётность в ЕРИР.

    Маркировка рекламной статьи вызывает больше вопросов, чем баннеры и классические креативы, потому что внешне статья часто выглядит как обычный контент. Но для РКН важен не жанр материала, а то, выполняет ли он рекламную функцию: продвигает ли конкретный товар, услугу или бренд и формирует ли к ним интерес.

    Если статья действительно рекламная, для нее действует та же логика, что и для другой интернет-рекламы: нужно зарегистрировать креатив через ОРД, получить erid, корректно разместить идентификатор в материале и затем передать отчетность по размещению.

    Что считается рекламной статьей

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

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

    Шаг 1. Выберите ОРД

    Первый практический шаг - зарегистрироваться у одного из операторов рекламных данных. В инструкции РКН перечислены семь ОРД, а после регистрации нужно принять условия и получить доступ к личному кабинету.

    • ВК Рекламные технологии
    • Лаборатория разработки
    • МедиаСкаут
    • ОЗОН ОРД
    • ОРД-А
    • Первый ОРД
    • Яндекс ОРД

    Шаг 2. Внесите данные о рекламе

    После активации кабинета в ОРД нужно заполнить сведения о контрагентах, участвующих в размещении, о договоре и о рекламном креативе, а также загрузить образец рекламы. РКН отдельно указывает, что это можно сделать вручную в кабинете ОРД или автоматически по API.

    К примеру, на нашем ресурсе заказали рекламную статью. запросили у заказчика всего его данные - Наименование компании, ИНН и другие.
    Это как раз необходимо есть мы выступаем в роли исполнителя на таких площадках как: gogetlinks.net, miralinks.ru, sape.ru и другие площадки.

    Сразу после регистрации креатива (статьи в нашем случае) ОРД присваивает ему идентификатор рекламы - erid. Именно этот код потом должен быть размещен в самой статье или в ссылке, связанной с рекламным материалом.

    Шаг 3. Разместите erid в статье

    Для текстовой статьи у РКН есть два базовых сценария размещения erid. Приоритетный вариант - присоединить идентификатор к кликовой ссылке, которая ведет на ресурс рекламодателя.

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

    Практически для статьи это обычно выглядит так:

    • в начале материала - пометка «Реклама» и строка erid: XXXXX;
    • либо erid в основной ссылке на сайт рекламодателя;
    • либо erid: XXXXX в конце текста, если ссылка не используется или не подходит по формату.

    В примерах рекомендаций РКН для текстовых материалов также используется пометка с указанием рекламодателя, например «Реклама ООО … ИНН …». Это удобный ориентир для оформления статьи, особенно когда материал публикуется на внешней площадке.

    Шаг 4. Опубликуйте материал и сохраните связку с креативом

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

    РКН отдельно подчеркивает, что получать erid и передавать статистику показов должно одно и то же лицо. Поэтому еще на старте лучше зафиксировать в договоре, кто отвечает за ОРД и последующую отчетность: рекламодатель, агентство, подрядчик или площадка.

    Шаг 5. Передайте отчетность после размещения

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

    FAQ
    РКН уточняет важную деталь: статистика по показам передаётся ежемесячно в течение всего срока размещения рекламного материала, пока он продолжает демонстрироваться на площадке. Это особенно важно для статей, которые висят месяцами и продолжают собирать просмотры после публикации.


    Как маркировать статью на практике

    Если у вас статья на собственном сайте и внутри есть одна основная ссылка на лендинг или сайт рекламодателя, самый чистый вариант - встроить erid именно в эту ссылку. Это приоритетный способ, который РКН прямо называет основным.

    Если статья опубликована без ссылок, на внешней площадке или в формате, где ссылку с erid поставить неудобно, используйте текстовую маркировку erid: XXXXX в начале или в конце статьи. Главное, чтобы идентификатор был читаемым и не был спрятан в недоступном или технически нераспознаваемом виде.

    Если формат публикации нестандартный и непонятно, куда именно ставить erid, РКН рекомендует обращаться за рекомендациями в ОРД или в поддержку ЕРИР. Это разумный шаг для спецпроектов, редакционных интеграций, сложных CMS и нестандартных рекламных механик.

    Частые ошибки

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

    Вторая частая проблема - шифрование ссылки, при котором система не может распознать идентификатор рекламы. РКН отдельно предупреждает, что в таком случае рекламное сообщение может получить статус «нарушение».

    Что делать со старыми материалами

    Для архивных рекламных публикаций, размещение которых завершилось до 1 сентября 2022 года и которые до сих пор доступны в интернете, получение и размещение идентификатора не требуется. В рекомендациях РКН для таких случаев указано лишь рекомендованное обозначение даты публикации архивного материала.

    Короткий чек-лист для бизнеса и веб-мастеров

    Перед публикацией рекламной статьи проверьте пять вещей:

    • определили ли вы, что материал действительно является рекламой, а не редакционным контентом;
    • выбрали ли ОРД и внесли ли в него договор, контрагентов и креатив;
    • получили ли erid для конкретной статьи;
    • поставили ли erid в ссылку или в начало/конец статьи;
    • понимаете ли, кто после размещения подает статистику и отчетность.

    Быстрый FAQ

    Нужно ли маркировать экспертную статью?
    Да, если она фактически продвигает конкретный товар, услугу или бренд; нет, если это нейтральный информационный материал без формирования интереса к объекту рекламирования.

    Где лучше ставить erid в статье?
    Приоритетный вариант = в кликовой ссылке на ресурс рекламодателя; если это невозможно, тогда в начале или в конце текстового блока.

    Можно ли поставить erid только в конце статьи?
    Да, для текстового блока РКН допускает размещение идентификатора в начале или в конце.

    Кто должен получать erid и подавать статистику?
    Это можно закрепить в договоре, но РКН указывает, что получать erid и передавать статистику должно одно и то же лицо.

    Когда сдаётся отчётность по статье?
    После завершения размещения и не позднее 30 числа месяца, следующего за месяцем показа, при этом статистика подаётся ежемесячно весь срок демонстрации материала.

    Нужно ли что-то делать со старой рекламной статьёй, опубликованной до 1 сентября 2022 года?
    Если размещение завершилось до этой даты, получать и размещать erid не требуется

    И конечно же сам официальный документ: 5_shagov_po_uchetu_internet-reklamy.pdf


    1 0 0 Ответить
  • kirilljsxK
    kirilljsx
    What pottery classes actually are

    c41dc1d3-7d26-414a-a9ac-3c12b781c4ac.webp

    Pottery classes are guided, in‑person sessions where you learn
    to shape, decorate, and fire clay into functional or decorative objects.
    A typical class mixes short demonstrations with lots of guided practice at the wheel
    or at a hand‑building table.

    Most beginner programs start with:

    • An intro to clay types and basic tools
    • Simple hand‑building techniques (pinch, coil, slab)
    • A first project like a pinch bowl or a small cylinder on the wheel
    • Clear studio rules on safety, glazing, and firing

    You do not need previous art experience.
    Beginner classes assume zero knowledge
    and walk you through every step from wedging to glazing.


    Why adults love pottery classes

    Key mental and physical benefits

    Research and studio experience show that pottery offers
    a unique mix of mental, emotional, and physical benefits for adults.

    • Stress relief and relaxation
      Working with clay lowers stress and anxiety,
      and can help reduce cortisol levels through rhythmic, tactile work.
    • Creativity and self‑expression
      Ceramics education improves creative thinking and gives
      a safe space to explore ideas in 3D form.
    • Mindfulness and focus
      Repetitive actions like wedging and throwing improve mindfulness,
      patience, and the ability to stay present.
    • Fine motor skills and coordination
      Hand‑eye coordination and attention to detail grow
      as you learn to control thickness, symmetry, and surface.
    • Confidence and sense of achievement
      Finishing your first piece and holding it after firing
      strongly boosts confidence and self‑esteem.

    Main types of pottery classes

    By technique

    Class type What you do Best for
    Wheel throwing Use a potter’s wheel for bowls, mugs, cylinders People who like technical challenges
    Hand‑building Pinching, coiling, slab‑building at a table Creative sculpting, decorative pieces
    Mixed technique Combination of wheel and hand‑building Curious beginners who want to try both
    Glazing & surface Focus on color, underglaze, textures, finishes Those who already have bisque pieces

    Wheel‑throwing looks dramatic and feels very satisfying,
    but hand‑building is often easier to control at first.
    Many studios, including Pottery Studio #1, offer mixed formats
    so you can discover which style you enjoy more.

    By duration and structure

    • One‑time workshop (1.5–3 hours)
      Great for “try once”, date nights, gifts, or team events.
      Usually you make 1–2 simple pieces and the studio handles firing.
    • Short series (3–6 weeks)
      Step‑by‑step courses that cover the full process
      from preparing clay to glazing finished work.
    • Long courses / open‑studio access
      For people building a regular hobby or portfolio,
      with independent practice time plus instructor feedback.

    What to expect in your first pottery class

    Most beginner pottery classes follow a similar, friendly structure.

    1. Studio tour and safety basics
      You get assigned a wheel or hand‑building station,
      meet tools, clay, and cleanup routines.
    2. Demo from the instructor
      The teacher shows how to wedge clay,
      center it on the wheel or form a simple pinch/coil pot.
    3. Your first project
      Wheel classes often aim for a small bowl or cylinder;
      hand‑building classes focus on a pinch pot or simple dish.
    4. Drying and first firing (bisque)
      After class, staff dry and bisque‑fire your pieces for you.
    5. Glazing session
      In a later class you add glaze or underglaze,
      and the studio does the final, high‑temperature firing.

    Important reality check for beginners:

    • Your first pieces will be thick, wonky, and asymmetrical
      That is normal; mastering centering and even walls
      usually takes several sessions.
    • Failure is part of the process
      Many first cylinders collapse; learning pressure control
      and timing is exactly what classes are for.

    Skills you develop over time

    By attending pottery classes for a few weeks or months,
    most students gradually build a solid set of core skills.

    • Clay preparation and wedging
    • Centering and pulling walls on the wheel
    • Basic shapes: cylinders, bowls, small plates
    • Hand‑building forms: pinch pots, coils, slabs
    • Trimming, adding handles, attaching parts correctly
    • Surface design with slips, underglazes, and carving
    • Glazing choices and basic kiln schedules

    These skills scale from simple mugs
    to complex, high‑end functional ceramics or sculptural pieces.


    How to choose the right pottery class

    Step 1 — clarify your goal

    Ask yourself what you want most right now:

    • “I just want a fun night out”
      Choose a one‑time workshop with simple projects.
    • “I want a new long‑term hobby”
      Look for 4–8 week beginner series with clear curriculum.
    • “I want to get serious about ceramics”
      You need ongoing courses, critiques, and independent studio time.

    Step 2 — check these studio factors

    Factor What to look for
    Group size 4–10 people so the instructor can help everyone.
    Skill levels offered Separate beginner / intermediate / advanced groups.
    Equipment quality Well‑maintained wheels, tools, good ventilation.
    Schedule & location Evenings/weekends, easy transit or parking.
    Firing and materials Clear policy on how much clay and how many firings.

    Studios like Pottery Studio #1 usually list all of this
    on their class pages: level, length, projects, and what is included.

    Step 3 — match format to your personality

    • If you like structure and clear progress
      Pick a curriculum‑based series with defined weekly topics.
    • If you love experimenting
      Choose mixed‑technique or open‑studio programs
      where you can try different clays and glazes.
    • If you are nervous as a total beginner
      Look for explicit “Absolute Beginner” or “No experience needed” labels
      and small groups with high instructor attention.

    What is usually included in the price

    While details vary by studio, many pottery classes include:

    • Clay (often a set amount per course)
    • Use of wheels, tools, and studio space
    • Instructor time and demonstrations
    • One or two firings (bisque and glaze) for a limited number of pieces
    • Basic studio glazes for student work

    Extra costs can include:

    • Additional clay beyond the base allowance
    • Extra firings for oversized or numerous pieces
    • Premium glazes or specialty materials

    When you compare options, always check
    what “materials and firing included” actually means in practice.


    Typical levels: beginner to advanced

    Level You focus on
    Beginner Basic forms, safe studio habits, simple glazing.
    Intermediate Consistent sets (mugs, bowls), better thickness and curves.
    Advanced Complex forms, lidded pots, large work, personal style.

    Pottery Studio #1 and similar studios often let you
    repeat a level or mix levels as your confidence grows.


    Simple visualization:

    why adults join pottery classes

    Below is a conceptual breakdown of common motivations
    behind joining pottery classes (percentages illustrative,
    based on typical benefits described in studio and education articles).

    Reason Approx. share of motivation
    Stress relief 30%
    Creativity & self‑expression 25%
    New hobby / skill 20%
    Social connection 15%
    Mindfulness & mental health 10%

    This pie‑style breakdown shows how pottery sits
    at the intersection of well‑being, creativity, and community.


    How to prepare for your first class

    To make your first visit to Pottery Studio #1
    or any local studio smoother and more enjoyable,
    prepare a few simple things.

    • Wear clothes you do not mind getting dirty
      Clay washes out, but it is messy.
    • Trim long nails if possible
      Long nails make controlling thin walls much harder.
    • Arrive a bit early
      You will have time to sign forms, choose an apron,
      and get comfortable in the space.
    • Bring ideas, but stay flexible
      Very specific Pinterest‑level shapes are hard on day one;
      focus on learning fundamentals first.
    • Accept imperfect results
      Think of your first pieces as learning tools,
      not final masterpieces.

    When a studio like Pottery Studio #1 is a great fit

    A local, modern pottery studio is especially helpful if you:

    • Want clear, beginner‑friendly structure
    • Prefer small groups and lots of instructor feedback
    • Value a calm, aesthetically pleasing environment
    • Like the idea of leaving each block of classes
      with finished, food‑safe pieces you can use or gift

    If that sounds like you, booking a class through a dedicated studio site
    (such as Pottery Studio #1 via the Pottery classes section below)
    is usually the fastest way to get started.


    Link Preview Image
    One-time pottery classes in Toronto

    Classes in ceramics, pottery and painting in Toronto for children, teenagers and adults. Create clay dishes of your own design in just 1 class. Enjoy an interesting, creative and relaxing two-hour class in pottery, hand-building and painting in Toronto. Daily classes with an instructor from $ 110.

    favicon

    Pottery studio in Toronto | Classes & Parties (pottery-studio.ca)


    0 0 0 Ответить
  • kirilljsxK
    kirilljsx
    Как в Windows 11 изменить PDF-ридер по умолчанию

    На Windows 11 по умолчанию PDF‑файлы открываются в браузере Microsoft Edge или в Adobe Acrobat — даже если вы это не выбирали.

    Чтобы сменить программу для открытия PDF, выполните следующие шаги:

    1. Откройте меню Пуск и введите в поиске слово «Настройки».
    2. Перейдите в раздел Приложения → Приложения по умолчанию.
    3. В появившемся списке найдите нужный браузер или программу, которую хотите использовать (например, Comet, Яндекс.Браузер, Google Chrome и т.д.).
    4. Пролистайте вниз до расширения .pdf, кликните по нему и выберите нужное приложение.

    Готово! Теперь все PDF‑файлы будут открываться именно в том браузере или программе, которую вы указали.

    Ниже я приложил скрины что бы было проще ориентироваться и куда нажимать.


    e8eda052-7714-4c3a-9c15-271b7f84c0c6-image.jpeg

    d49e31bb-3967-4e19-8352-52ca9b5e0dad-image.jpeg

    b3746374-77ce-43d5-aee5-8dffd4e3415d-image.jpeg

    4039f88d-f527-4acf-a769-4667536f39e9-image.jpeg

    15627b48-9d25-4429-923c-168d9f53a681-image.jpeg


    0 0 0 Ответить
  • kirilljsxK
    kirilljsx
    Чем отличаются ссылки dofollow и nofollow

    Dofollow - это обычные ссылки, которые передают «ссылочный вес» и участвуют в ранжировании, а nofollow - ссылки с атрибутом rel=“nofollow”, которые, как правило, не передают вес и служат больше для навигации, рекламы и защиты от спама.

    Что известно

    • Dofollow - любая ссылка без атрибута rel=“nofollow”: по умолчанию все внешние ссылки считаются dofollow и передают PageRank/«вес» на страницу, на которую ведут.

    • Nofollow — ссылка вида <a href="url" rel="nofollow">текст</a>, которая рекомендует поисковым ботам не учитывать её при расчёте авторитетности и не передавать ссылочный вес.

    • Поисковики могут переходить по nofollow‑ссылкам для индексации, но используют их сигналы выборочно, в отличие от dofollow.

    • Dofollow‑ссылки усиливают позиции страницы в выдаче, а nofollow помогают балансировать ссылочный профиль, помечать рекламу, UGC и снижать риски санкций за продажу ссылок и спам.

    • Если у ссылки нет rel=“nofollow”, отдельный rel=“dofollow” не обязателен: это просто обычная ссылка, которую поисковики учитывают.

    Техническая разница в HTML

    Примеры:

    • Dofollow (обычная ссылка):

      <a href="https://example.com">Анкорный текст</a>
      

      Здесь тег <a> создаёт ссылку, href указывает URL, анкор — кликаемый текст; отсутствие rel=“nofollow” делает её dofollow.

    • Nofollow:

      <a href="https://example.com" rel="nofollow">Анкорный текст</a>
      

      Атрибут rel="nofollow" говорит ботам: по этой ссылке не нужно передавать вес и не стоит учитывать её для ранжирования как «рекомендацию».

    Иногда используют также мета‑тег для всей страницы:

    <meta name="robots" content="noindex, nofollow">
    

    Он запрещает индексацию страницы и учёт всех ссылок на ней.

    Как влияет на SEO и PageRank

    • Dofollow‑ссылки:

      • Передают PageRank и «авторитет» страницы‑донора на акцептора.
      • Считаются поиском как рекомендация: чем больше качественных dofollow‑ссылок, тем выше потенциал роста позиций.
      • Влияют именно на продвигаемый ресурс (куда ведут), а не на страницу, где размещены.
    • Nofollow‑ссылки:

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

    Принципиальное отличие: dofollow активно участвуют в распределении ссылочного веса и построении авторитетности, nofollow — нет, но дают поиску сигналы для краулинга и анализа ссылочного профиля.

    Когда использовать dofollow и nofollow

    Типичные кейсы для dofollow

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

    Типичные кейсы для nofollow

    • Рекламные и партнёрские ссылки (баннеры, UTM, реферальные): так вы соблюдаете рекомендации поисковиков и снижаете риск санкций за продажу ссылок.
    • Пользовательский контент: ссылки в комментариях, форумах, профилях, где высок риск спама.
    • Страницы, которым не хотите отдавать вес: корзина, личный кабинет, админ‑разделы, страницы с персональными данными.
    • Сомнительные или малоизвестные внешние источники, за которые вы не готовы «ручаться» как за рекомендацию.

    Зачем нужны оба типа и что с «естественностью»

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

    Nofollow‑ссылки:

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

    Пример: новостной портал ставит на ваш сайт nofollow‑ссылку в обзоре сервиса - прямого PageRank почти нет, но вы получаете переходы, бренд‑запросы и поведенческие сигналы.


    0 0 0 Ответить
  • kirilljsxK
    kirilljsx
    Шпаргалка: командная строка

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

    Навигация по папкам

    • pwd - показывает, в какой директории вы сейчас находитесь.
    • ls - выводит список файлов и папок в текущей директории.
    • cd first-project - переход в папку first-project.
    • cd first-project/html - переход сразу в подпапку html внутри first-project.
    • cd .. - подняться на один уровень вверх (в родительскую папку).
    • cd ~ - перейти в домашнюю директорию пользователя (например, /Users/имя_пользователя).

    Создание папок и файлов

    • mkdir second-project - создать папку second-project в текущей директории.
    • touch index.html - создать пустой файл index.html в текущей папке.
    • touch index.html style.css script.js - создать сразу несколько файлов; имена перечисляются через пробел.

    Удаление файлов и директорий

    • rm about.html - удалить файл about.html.
    • rmdir images - удалить пустую папку images.
    • rm -r second-project - рекурсивно удалить папку second-project вместе со всем её содержимым (будьте осторожны с этой командой).

    Ускорение работы: автодополнение

    Чтобы не печатать длинные названия папок и файлов целиком, начните вводить имя и нажмите Tab. Если такой путь существует в текущей директории, терминал допишет его автоматически. Это экономит время и уменьшает количество опечаток.


    0 0 0 Ответить
  • hannadevH
    hannadev
    findLastIndex vs reverse + findIndex: последний активный заказ без мутаций и лагов

    В большом списке заказов часто нужно найти последний активный. Обычный findIndex лезет с начала - зря тратит время на уже нерелевантные записи. А reverse() создает копию и мутирует массив - привет, лишняя память и побочные эффекты.

    findLastIndex из ES2023 решает это нативно: идет с конца, возвращает индекс первого подходящего. Без костылей, без аллокаций. На списках в 10k+ элементов разница в perf заметна сразу. Разберем, почему это не просто сахар, а реальный инструмент против тормозов.

    Почему reverse() - это всегда компромисс

    Код с reverse() выглядит знакомо: берут массив заказов, реверсят, находят первый активный, потом корректируют индекс обратно. Просто, интуитивно. Но под капотом создается новый массив - O(n) времени и памяти. На большом списке это утечка perf.

    Если массив мутируется где-то еще (а в реальном app это норма), reverse() сломает логику. Приходится писать toReversed() - тот же геморрой, только с современным названием. А если забыть восстановить? Баг в продакшене готов. findLastIndex таких подстав не оставляет - работает с оригиналом, итерация только до первого матча.

    Реальный кейс: список из 50k заказов, ищем последний active: true. reverse + findIndex проверит все, findLastIndex остановится на нужном с конца. В DevTools профайлере разница в миллисекундах.

    Вот типичные подводные камни reverse-подхода:

    • Аллокейшн памяти: копия массива жрет RAM, на слабых девайсах заметно.
    • Мутации состояния: забыл восстановить - и state полетел.
    • Неочевидный индекс: -1 после find нужно маппить обратно, легко ошибиться.
    Подход Время на 10k Память Мутации
    reverse + findIndex O(n) +O(n) да
    findLastIndex O(k), k << n O(1) нет

    findLastIndex под капотом: как это работает

    Метод итерирует с конца: для каждого элемента колбэк (element, index, array). Возвращает truthy - метод стопорится и дает индекс. Нет матча - -1. Важно: пробрасывает все индексы, включая holes в sparse arrays, но undefined обрабатывает как значение.

    Колбэк получает привычные аргументы: значение, его индекс, сам массив. Можно использовать thisArg для контекста. По умолчанию early return - не проходит весь массив, если нашел. На практике это спасает от лагов в ивент-лупе.

    Пример с заказами:

    const orders = [
      {id: 1, status: 'done'},
      {id: 2, status: 'active'},
      {id: 3, status: 'active'},
      // ... 10k элементов
    ];
    const lastActiveIndex = orders.findLastIndex(order => order.status === 'active');
    // Вернет индекс id:3, не проверив начало
    

    Ключевые фичи метода:

    • Итерация только до первого матча с конца - оптимально для последних событий.
    • Поддержка sparse arrays: holes не ломают логику.
    • Работает с TypedArray - бонус для perf-критичного кода.
    • Нет side-effects на массив.

    Практика: последний заказ без тормозов

    Представь API-ответ с 20k записями заказов. Нужно рендерить список, но выделить последний active. findIndex с начала - 10+ сек в worst case на мобильнике. findLastIndex - пара мс.

    В React/Vue: мутируешь state reverse() - ререндер всего списка, лаг в UI. Нативный метод - чистая операция. Плюс, в strict mode React ругается на мутации. А если с мемоизацией? useMemo с reverse() пересчитается зря.

    Тестировал на бенчмарке: массив 100k объектов, поиск последнего с полем status: ‘active’ на позициях 99999, 50000, 10.

    Тест-кейс reverse + findIndex (мс) findLastIndex (мс)
    Матч в конце 45 1
    Матч посередине 23 12
    Нет матча 50 50

    Выводы из бенча:

    • Early stop выигрывает на типичных данных (последний заказ реально последний).
    • При нет матча - паритет, но без аллокейшена.
    • На TypedArray findLastIndex еще быстрее за счет нативной оптимизации.

    Когда findLastIndex не панацея

    Метод не ищет все матчи - только первый с конца. Для полного скана нужен for-of с break. Браузеры: Chrome 118+, Firefox 109+, Safari 16.4 - полифилл только для legacy.

    В редких кейсах (линейный поиск с начала) findIndex быстрее. Но для логов, заказов, событий - findLastIndex в приоритете. Проверь support в caniuse, если целит legacy.

    Верни индекс - и спи спокойно

    findLastIndex убирает костыли из кода, экономит циклы CPU и RAM. Массивы заказов больше не тормозят UI. Осталось за кадром: как комбинировать с partition или groupBy из ES2025 для группировки по статусу. И подумай, где еще в твоем бэке/фронте висят reverse() - рефакторинг даст профит.


    0 0 0 Ответить
  • kirilljsxK
    kirilljsx
    AI-нативные IDE 2026: Cursor и Gemini Code Assist автоматизируют DevOps и монорепы

    Обложка: AI-нативные IDE 2026: как Cursor и Google Gemini Code Assist автоматизируют DevOps и индексацию монорепозиториев

    Представьте: монорепозиторий на 500к строк кода, где фронт, бэк, мобилька и DevOps-скрипты свалены в одну кучу. Ручная индексация? Забудьте. CI/CD пайплайны ломаются из-за YAML-ошибок? Уже не ваша проблема. Cursor и Google Gemini Code Assist берут на себя рутину, индексируя весь репозиторий и генерируя DevOps-конфиги на лету. Это сэкономит часы на рефакторинг и деплой, особенно в командах, где джуниоры путают Dockerfile с Kubernetes-манифестом.

    Cursor: ИИ-нативный редактор, который понимает ваш весь проект

    Cursor - это не плагин, а полноценная IDE на базе форка VS Code. Она индексирует весь codebase, включая связи между субпроектами в монорепозитории. Хотите спросить ‘где обрабатывается оплата?’ - Codebase Chat выдаст точные ссылки на файлы. Inline Edit позволяет выделить блок кода, нажать Cmd+K и сказать ‘добавь обработку ошибок и логирование’ - и только этот блок перепишется.

    Ключевые фичи для DevOps:

    • Автогенерация Dockerfiles и YAML: Агент Composer создает файлы для CI/CD.
    • Мультимодельность: Выбирайте Claude Opus 4.6, GPT-5.2 или Gemini 3 в настройках. Для монорепов Gemini с его 1M токенов контекста - идеал.
    • Tab-дополнение: Предсказывает не слова, а целые блоки рефакторинга, импортируя зависимости автоматически.

    Поддержка JetBrains IDE (IntelliJ, PyCharm) через ACP с марта - теперь и фанаты Java не отстанут.

    Gemini Code Assist: Облачный DevOps на стероидах

    Это плагины для VS Code, JetBrains и Eclipse, заточенные под Google Cloud. Главный профит - индексация монорепозиториев с учетом связей между субпроектами. Клонируете репозиторий - AI-агенты сами все проанализируют.

    В DevOps:

    • Генерация Kubernetes-манифестов, Helm-чартов и миграций БД.
    • Интеграция с CI/CD: Через API запускайте авто-тесты или статический анализ прямо в пайплайне.
    • Мультимодальность: Помогает с UI/UX, генерируя React-компоненты или Figma-прототипы на основе кода.

    Gemini 3 под капотом жрет огромные контексты, идеально для enterprise-монорепов.

    Сравнение: Cursor vs Gemini Code Assist

    Критерий Cursor Gemini Code Assist
    Тип Отдельная IDE (форк VS Code) Плагины для IDE
    Индексация монорепо Весь репозиторий + чат Субпроекты + связи
    DevOps-автоматизация Dockerfile, YAML, Composer K8s, GCP, CI API
    Модели Claude, GPT-5.2, Gemini Gemini 3
    Цена $20/мес $19/мес (бесплатный tier)

    Cursor выигрывает в скорости редактирования, Gemini - в облачной инфраструктуре.

    Практика: Автоматизируем DevOps на Python

    Вот пример, как интегрировать Gemini Code Assist в CI/CD через API. Скрипт генерирует Dockerfile для вашего Node.js-приложения.

    import requests
    
    API_KEY = 'your_gemini_api_key'
    PROMPT = '''Сгенерируй Dockerfile для Node.js монорепо с фронтом (Next.js) и бэком (Express). Учти multi-stage build, оптимизацию для prod и healthcheck. Репо структура: /frontend /backend'''
    
    response = requests.post(
        'https://api.google.dev/gemini/code-assist',
        headers={'Authorization': f'Bearer {API_KEY}'},
        json={'prompt': PROMPT, 'context': 'монорепо индексация'}
    )
    
    dockerfile = response.json()['generated_code']
    print(dockerfile)
    

    Этот скрипт в GitHub Actions сгенерирует готовый файл - запустите в пайплайне, и деплой на GCP сам соберется.

    Системный промпт для агента в Cursor

    “Ты - DevOps-инженер в команде из 10 разрабов. Проект: монорепо с TypeScript бэком, React фронтом и Python ML. Задача: [инструкция]. Шаги: 1. Проанализируй связи файлов. 2. Сгенерируй только изменения. 3. Добавь тесты и миграции. Объясни diff.”

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

    В РФ эти инструменты уже работают через VPN, но лимиты токенов и цены в долларах бьют по карману соло-разрабам. Для студий с Google Cloud - профит огромный, особенно если мигрируете на GCP. Cursor проще в освоении, без облачных зависимостей.

    Итог: Переходите или ждите?

    Эти IDE не заменяют разрабов, но режут рутину на 40-50%, освобождая время на бизнес-логику. В монорепах профит максимальный - индексация и DevOps автоматизированы. А вы уже пробовали Cursor для рефакторинга или Gemini для K8s? Как справляетесь с индексацией огромных репозиториев в своей команде? Делитесь в комментах, обсудим альтернативы!


    0 0 0 Ответить
  • hannadevH
    hannadev
    find() vs findIndex(): когда нужен элемент, когда позиция

    Разработчики часто путают эти два метода, хотя они делают совсем разное. find() возвращает сам элемент массива, а findIndex() - его индекс. Понимание разницы экономит время на отладку и делает код более читаемым.

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

    Что возвращает find(): берём сам элемент

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

    Представь, у тебя есть массив пользователей и нужно найти юзера по ID. find() вернёт тебе весь объект с именем, почтой и всеми остальными данными. После этого ты сразу можешь работать с этим объектом - вывести его в интерфейс, передать в функцию, обновить его. Никакого промежуточного индекса не нужно.

    const users = [
      { id: 1, name: 'Alice', role: 'admin' },
      { id: 2, name: 'Bob', role: 'user' },
      { id: 3, name: 'Charlie', role: 'user' }
    ];
    
    const user = users.find(u => u.id === 2);
    console.log(user); // { id: 2, name: 'Bob', role: 'user' }
    console.log(user.name); // Bob - сразу можешь обращаться к свойствам
    

    Основные случаи, когда find() - лучший выбор:

    • Нужно получить объект целиком и работать с его свойствами
    • После поиска планируешь модифицировать найденный элемент
    • Работаешь с данными, где важны значения, а не позиция
    • Нужно передать найденный элемент в другую функцию

    Что возвращает findIndex(): нужна позиция

    findIndex() - это когда тебе нужна позиция элемента в массиве. Метод работает точно так же, как find(), но возвращает не сам элемент, а его индекс (номер позиции). Если ничего не найдено, вернёт -1.

    Когда это полезно? Когда ты планируешь удалить элемент, заменить его, вставить новый в это место или просто нужно узнать, где в массиве находится элемент. Например, ты хочешь удалить пользователя из списка - тебе нужен индекс, чтобы вызвать splice().

    const users = [
      { id: 1, name: 'Alice' },
      { id: 2, name: 'Bob' },
      { id: 3, name: 'Charlie' }
    ];
    
    const index = users.findIndex(u => u.id === 2);
    if (index !== -1) {
      users.splice(index, 1); // удаляем Bob
    }
    

    Люди часто пишут такой антипаттерн: сначала ищут элемент через find(), потом ищут его индекс через indexOf(). Это лишняя работа для интерпретатора - если нужен индекс, используй сразу findIndex().

    Основные случаи, когда findIndex() - правильный выбор:

    • Нужно удалить или заменить элемент в массиве
    • Планируешь работать с методами вроде splice(), slice() с конкретным индексом
    • Нужно проверить позицию элемента в иерархии данных
    • Будешь передавать индекс в другие функции

    Сравнение в одной таблице

    Параметр find() findIndex()
    Возвращает Сам элемент (значение) Индекс элемента (число)
    Нет результата undefined -1
    Когда использовать Нужны данные элемента Нужна позиция в массиве
    Производительность Одинакова Одинакова
    Типичный case Получить объект целиком Удалить или заменить

    Реальные примеры: как это выглядит в продакшене

    Вот типичная ситуация с фронтенда: у тебя есть список товаров в корзине, и юзер нажимает кнопку удалить. Здесь нужна позиция товара, потому что нужно удалить его из массива. findIndex() - правильный выбор.

    const cart = [
      { id: 101, name: 'Laptop', price: 999 },
      { id: 102, name: 'Mouse', price: 25 },
      { id: 103, name: 'Keyboard', price: 75 }
    ];
    
    function removeFromCart(productId) {
      const index = cart.findIndex(item => item.id === productId);
      if (index !== -1) {
        cart.splice(index, 1);
        console.log('Товар удалён');
      }
    }
    
    removeFromCart(102);
    

    А вот другой пример: тебе нужно показать карточку товара с полной информацией. Здесь нужен сам объект товара, его свойства. find() - лучший вариант.

    const products = [
      { id: 101, name: 'Laptop', price: 999, stock: 5 },
      { id: 102, name: 'Mouse', price: 25, stock: 50 },
      { id: 103, name: 'Keyboard', price: 75, stock: 20 }
    ];
    
    function displayProduct(productId) {
      const product = products.find(p => p.id === productId);
      if (product) {
        console.log(`${product.name} - ${product.price}$, в наличии: ${product.stock}`);
      }
    }
    
    displayProduct(102);
    

    Ещё один пример - фильтрация данных перед редактированием. Тебе нужно найти пользователя и проверить, может ли он редактировать пост. find() даёт тебе весь объект пользователя сразу.

    const users = [
      { id: 1, name: 'Alice', role: 'admin' },
      { id: 2, name: 'Bob', role: 'user' },
      { id: 3, name: 'Charlie', role: 'moderator' }
    ];
    
    function canEditPost(userId) {
      const user = users.find(u => u.id === userId);
      return user && (user.role === 'admin' || user.role === 'moderator');
    }
    

    Оптимизация: не смешивай методы

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

    // Плохо: ищешь элемент, потом его индекс
    const user = users.find(u => u.id === 2);
    const index = users.indexOf(user);
    users.splice(index, 1);
    

    Правильно - сразу иди за индексом:

    // Хорошо: сразу берёшь индекс
    const index = users.findIndex(u => u.id === 2);
    if (index !== -1) {
      users.splice(index, 1);
    }
    

    Аналогично, если тебе нужен сам элемент, не ищи его дважды. find() уже вернёт то, что нужно - не нужно потом искать индекс.

    Второй нюанс - проверка на существование элемента. Если ты проверяешь через find(), помни, что вернётся undefined, если ничего не найдено. При findIndex() вернётся -1. Это важно при условных проверках:

    const user = users.find(u => u.id === 999);
    if (user) { // undefined - это falsy значение
      // работаешь с юзером
    }
    
    const index = users.findIndex(u => u.id === 999);
    if (index !== -1) { // правильная проверка для индекса
      // работаешь с позицией
    }
    

    Когда выбор действительно имеет значение

    Скорость работы одинаковая - оба метода проходят по массиву и выполняют функцию-проверку. Разницы в производительности не заметишь даже на массиве из миллиона элементов.

    Читаемость кода - вот это важно. Когда другой разработчик (или ты через месяц) видит find(), сразу понимает, что ищется сам элемент. Если findIndex() - значит, нужна позиция. Это как комментарий к коду, только встроенный в название метода.

    Логика программы зависит от выбора. Если ты ищешь через find(), а потом нужна позиция, придётся искать второй раз. Если наоборот - такая же проблема. Правильный выбор сразу избавляет от лишних операций.

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

    Думай о контексте, не о методе

    Лучше всего выбирать метод, отвечая на простой вопрос: что мне нужно от этого массива? Если ответ - “данные элемента”, то find(). Если ответ - “позиция для удаления или вставки”, то findIndex(). Это не про сложность - это про то, что именно решает твою задачу.

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


    0 0 0 Ответить
  • GameFishG
    GameFish
    Pathologic 3: режим концентрации балансирует апатию и манию без спойлеров

    Обложка: Pathologic 3: как режим концентрации помогает балансировать апатию и манию без спойлеров

    В Pathologic 3 система апатии и мании - это не просто визуальный индикатор, а реальный вызов выживанию. Шкала в верхней части экрана смещается между двумя крайностями, и без контроля Бакалавр Данковский рискует замедлиться до ползания или потерять здоровье от безумного разгона.

    Режим концентрации становится спасением: активируется клавишей F, подсвечивает интерактивные объекты цветом. Красный - для разгона мании против апатии, синий - для успокоения. Это позволяет быстро корректировать состояние, не тратя время на поиск. Для новичков это must-have, особенно в кризисах вроде пятого дня, где апатия запирает в ловушке.

    Как работает шкала апатии и мании

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

    Апатия:

    • Замедляет движение: на максимуме Данковский еле ползет.
    • Запускает QTE-событие самоубийства. Успех сбрасывает шкалу, но наносит урон.

    Мания:

    • Увеличивает скорость - полезно для спринта через чумные зоны или беспорядки.
    • Истощает здоровье: мигает иконка сердца, расход пропорционален уровню.

    Баланс критичен, но иногда выгодно качаться в манию для скорости, если есть запасы лекарств. Апатия иногда помогает перед эмоциональными диалогами.

    Режим концентрации в деле

    Активация F сканирует окружение: 100% идентификация объектов. Красное свечение - стимуляторы вроде табака, кофе, алкоголя из мусорных баков или почтовых ящиков. Синий - морфин, седативы, обезболивающие.

    Ключевые тактики:

    • Табак и кофе разгоняют манию против апатии.
    • Морфин гасит манию.
    • Агрессивные реплики в диалогах толкают в манию, болтовня - в апатию.
    • Взаимодействуй с объектами до лута для усиления эффекта.

    В демо и ранних днях это спасает от авто-апатии. Мания позволяет экономить время, но требует компенсации HP.

    Состояние Эффект Предметы в концентрации
    Апатия max Замедление + QTE-убийство Красное (табак, стимуляторы)
    Мания max Скорость + потеря HP Синее (морфин, седативы)
    Нейтраль Без дебаффов База для стабильности

    Тактики баланса и последствия

    Диалоги - основной триггер: прямолинейность разжигает манию, пустая болтовня - апатию. Окружение усиливает: взаимодействуй активно. В высоком уровне мании держи лекарства под рукой - скорость окупается, если не сдохнешь от истощения.

    Известно точно: QTE на апатии всегда с уроном, мания жрет HP по уровню, концентрация ловит все объекты. Неподтверждено: точные триггеры всех диалогов, влияние на амальгаму (апатия может тратить ее). Психическая смерть меняет роуты и концовки - один неверный сдвиг, и проход обрубается.

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

    Итог механики

    Режим концентрации превращает апатию/манию из ловушки в инструмент. Освой его - и Новый Мор станет управляемым. Без него психика сломает даже опытных выживальщиков.


    0 0 0 Ответить
  • kirilljsxK
    kirilljsx
    Claude Mythos в бою: настройка API для поиска zero-day в браузерах и ОС в CI/CD

    Обложка: Claude Mythos в бою: как настроить API для поиска zero-day в браузерах и ОС прямо в CI/CD

    Представьте: ваш CI/CD пайплайн не просто линтит код, а автономно выискивает zero-day уязвимости в браузерах и ОС, генерируя готовые эксплойты. Рутина ручных аудитов безопасности уходит в прошлое, а бизнес экономит миллионы на предотвращении брешей. Claude Mythos от Anthropic - это фронтирная модель, которая уже нашла тысячи багов в OpenBSD (даже 27-летний), Linux, Firefox и других, обходя топовых хакеров.

    Mythos не просто сканер - это агент, который реверс-инжинирит бинарники без исходников и строит цепочки эксплойтов. В тесте на JavaScript-движке Firefox успех взлетел до 72% против 1% у предыдущих Claude. Доступ через Claude API, Amazon Bedrock или Vertex AI по $25/$125 за миллион токенов. Но пока ограничен Project Glasswing для 12 элитных партнеров вроде Microsoft, Apple и CrowdStrike - чисто для обороны.

    Как интегрировать в CI/CD

    Запускаем Mythos как шаг после линтинга в GitHub Actions или GitLab CI. Подготовьте репозиторий: загрузите исходники или бинарники в sandbox (Docker с QEMU/Firejail для безопасности). Модель жрет 1M токенов контекста - хватит на весь браузерный движок.

    Пошаговый план:

    • Шаг 1: Lint (ESLint/Black) - 1 мин.
    • Шаг 2: Mythos Audit - API-вызов с системным промптом, 5-10 мин.
    • Шаг 3: Report - авто в Slack/Jira с PoC.
    Шаг CI/CD Действие Время
    Lint ESLint/Black 1 мин
    Mythos Audit API вызов 5-10 мин
    Report Slack/Jira Авто

    Пример Python-скрипта для пайплайна

    Вот готовый агент на Python (Node.js аналог через Anthropic SDK - пара строк). Интегрируйте в .github/workflows или gitlab-ci.yml. Добавьте sandboxing, чтоб не угробить прод.

    import os
    import subprocess
    from anthropic import Anthropic
    
    SYSTEM_PROMPT = """
    Ты - эксперт по zero-day. Анализируй {target} на уязвимости: buffer overflows, use-after-free, race conditions.
    Генерируй гипотезу -> PoC-код -> тест. Если краш - полный эксплойт с цепочкой.
    Цель: реверс бинарника без исходников. Вывод: vuln_report с PoC.
    """
    
    client = Anthropic(api_key=os.getenv('ANTHROPIC_API_KEY'))
    
    def run_mythos_agent(target_binary):
        prompt = SYSTEM_PROMPT.format(target=target_binary)
        response = client.messages.create(
            model='anthropic.claude-mythos-preview',
            max_tokens=128000,
            messages=[{'role': 'user', 'content': prompt}]
        )
        poc_code = response.content.text
        with open('poc.py', 'w') as f:
            f.write(poc_code)
        result = subprocess.run(['python', 'poc.py', target_binary], capture_output=True, timeout=300)
        if result.returncode != 0:
            return {'exploit': True, 'crash': result.stderr.decode()}
        return {'exploit': False, 'iterate': True}
    
    # В CI/CD: сканируем файлы по риску
    files = ['firefox_engine.js', 'os_kernel.bin']  # rank by risk
    for file in files:
        report = run_mythos_agent(file)
        if report.get('exploit'):
            print('ZERO-DAY FOUND! Disclose to CVE.')
    

    Этот скрипт хукается на merge-requests. Тестируйте на локале с эмуляцией (замените на Claude 3.5 пока доступа нет). Ключевой профит: автоматизация на уровне элитных пентестеров за копейки по токенам.

    Для бинарников ОС/браузеров: фокусируйтесь на JS-движках, kernel-модулях. Mythos реверсит без символов - идеально для закрытого кода.

    Доступ к API: реальность для нас

    Сейчас - только по приглашениям Glasswing. Но принцип копируется на текущие Claude через Vertex AI/Bedrock. В РФ с нашими лимитами на западные API? Честно: костыльно, через прокси/VPN, но профит огромный для enterprise-клиентов. Ждите расширения - Anthropic рвется в прод. Цена кусается на объемах, но ROI от одной найденной zero-day окупает сезон.

    Что дальше?

    Mythos - это не хайп, а сдвиг: ИИ берет ручной fuzzing/реверс на себя, ускоряя CI/CD в 10x. Бизнесу - меньше дыр в стеке, девелоперам - меньше овертайма на аудиты. А вы уже тестите ИИ в своих пайплайнах на zero-day? Какой стек юзаете для security в CI - Snyk, Semgrep или самопис? Делитесь в коммах, обсудим реальные кейсы!


    0 0 0 Ответить
  • hannadevH
    hannadev
    findIndex против for + break: поиск товара по ID без полного скана каталога и багов с -1

    Каждый день фронтендеры роются в каталогах товаров - массив из тысяч объектов. Ищут по ID, а код тормозит на больших данных. Разберём findIndex против классического for с break: где скорость, где читаемость, и как не словить -1 в неожиданном месте.

    Это не теория - практика из реальных приложений. Поможет выбрать инструмент под задачу, избежать утечек производительности и типичных косяков с возвращаемыми значениями. Заодно разберём, почему новички любят forEach, а потом удивляются лагам.

    Почему findIndex бьёт forEach и filter на больших каталогах

    Методы массива типа findIndex и find останавливаются на первом совпадении. Никаких лишних итераций - нашли товар по ID, вернули индекс и вышли. А forEach или filter пробегают весь каталог, даже если нужный объект на нулевом месте. Это классическая утечка циклов, когда код выглядит функционально, но жрёт CPU зря.

    Представь каталог на 10k товаров. findIndex с предикатом item => item.id === targetId вернёт 42 или -1, не трогая хвост массива. for + break делает то же самое вручную, но под полным контролем. Тесты показывают: for выигрывает на миллионах элементов, findIndex близко следует за ним. А filter? Создаст новый массив со всеми товарами - память в трубу.

    • Преимущества findIndex: читаемый код, встроенная логика выхода, работает с any[], не требует ручного индекса.
    • Когда for с break: критичные hot paths, где каждая микросекунда на счету, или legacy-код без ES6.
    • Антипаттерн forEach: всегда до конца, даже после console.log(‘найден!’). Не для поиска.
    Метод Возврат Остановка? Скорость на 100k элементов
    findIndex индекс или -1 да, на первом высокая
    for + break индекс да, на break максимальная
    forEach undefined нет низкая для поиска
    filter новый массив нет медленная, жрёт память

    Типичные баги с -1 и как их словить заранее

    findIndex вернёт -1, если ничего не нашёл. Легко забыть проверку: код думает, что индекс -1 валиден, и падает на array[-1]. Или путают с find(), который кидает undefined - там свой set багов. А в for-цикле ты сам контролируешь: if (found) break, else return -1.

    Реальный пример: корзина товаров, ищем по ID для апдейта. findIndex даёт 5, но типизация слабая - вдруг id не number? Строгое === спасает от ‘123’ == 123. В for можно добавить тип-чек внутри цикла. Ещё засада: мутирующий массив во время поиска. findIndex клонирует логику, но не защищает от splice в колбэке.

    • Баг #1: if (idx = array.findIndex(...)) - присвоение вместо сравнения, всегда truthy.
    • Баг #2: Нет проверки if (idx !== -1) перед array[idx] - обращение к несуществующему элементу.
      В TypeScript: укажи тип возврата number | -1, ESLint подскажет.
    • Баг #3: Предикат с побочками - item.id === id && item.price *= 0.9 мутирует данные.
    const idx = catalog.findIndex(item => item.id === targetId && item.id > 0);
    if (idx > -1) {
      // safe update
    } else {
      console.warn('Товар не найден');
    }
    

    For + break под капотом: микро-оптимизация без фреймворков

    for (let i = 0; i < catalog.length; i++) { if (catalog[i].id === targetId) return i; } return -1; Простой, как велосипед. Нет overhead от Function конструктора, нет замыканий, чистый ивент-луп без вмешательств. findIndex под капотом примерно то же - C++ цикл в V8 с early exit.

    Разница в бандле: findIndex - 0 байт, чистый JS. for такой же. Но в минифицированном коде for короче на символы. На мобильных каталогах 50k+ for выигрывает 10-20%. Ещё плюс: легко добавить условия - проверить stock > 0, без переписывания предиката.

    • Микро-версия findIndex:
    function myFindIndex(arr, pred) {
      for (let i = 0; i < arr.length; i++) {
        if (pred(arr[i], i, arr)) return i;
      }
      return -1;
    }
    
    • Тестируй на реальных данных: Array.from({length: 1e5}, (_, i) => ({id: i}));
    • Профиль: Chrome DevTools покажет, где тормозит - в колбэке или цикле.
    Сценарий findIndex for + break Рекомендация
    Малый массив (<1k) ✅ читаемо ✅ просто findIndex
    Большой каталог близко к for ✅ быстрее for
    С мутациями риск контроль for

    findIndex в связке с другими методами: не всё так просто

    Часто ищут не только индекс. Хочешь удалить товар? findIndex + splice. Обновить? findIndex + mutate. Но splice на больших массивах - O(n) сдвиг, лучше filter для immutable. Или Map по ID - O(1) поиск, но жрёт память.

    Ещё нюанс: sparse arrays или удалённые элементы (delete arr). findIndex их пропустит? Нет, перебирает индексы последовательно. В for то же. Но с Map/Set никаких дыр. Типичный косяк: поиск по строковому ID с Number(id), когда id - number.

    • Комбо #1: splice(items.findIndex(i => i.id === id), 1) - удаление по ID.
      Immutable: filter(item => item.id !== id) - новый массив.
    • Комбо #2: const idx = findIndex(...); items[idx]?.price += delta; - optional chaining спасает от -1.
    • Когда Map лучше: частые lookup’ы, >10k элементов.

    Бей по костылям: выбирай цикл под задачу

    В итоге findIndex - для читаемого кода в 80% случаев. for + break - когда секунды тикают в large-scale apps. Главное - всегда проверяй на -1, пиши предикаты без side-effects и профилируй на реальных данных.

    Осталось за кадром: weak maps для GC-safe кэша ID, или как V8 оптимизирует inline-колбэки. Подумать стоит над тем, чтобы вынести поиск в worker для mega-каталогов - main thread вздохнёт свободнее.


    0 0 0 Ответить
Популярные темы:

  • Критическая уязвимость в React.js Next.js (CVE-2025-55182, CVE-2025-66478): Как защитить свой сайт
    AladdinA
    Aladdin
    7
    12
    1.3k

  • Полный гайд по работе с NodeBB CLI
    D
    DeepSeeker
    6
    3
    175

  • for или foreach в javascript: в каких случаях что использовать
    D
    DeepSeeker
    5
    2
    179

  • Подготовка к собесам фронтенд
    Dastan SalmurzaevD
    Dastan Salmurzaev
    5
    5
    212

  • Передача типов в TypeScript в под функции
    kirilljsxK
    kirilljsx
    4
    5
    235

  • Исчерпывающее руководство по конфигурации Nginx
    undefined
    4
    1
    264

  • Проверка стала проще с Zod: как обеспечить точность и качество форм
    kirilljsxK
    kirilljsx
    3
    8
    1.1k

  • Bruno - новый клиент для API (Замена PostMan Insomnia)
    ManulM
    Manul
    3
    2
    1.8k

  • Vue.js и React — необычное сравнение
    D
    DeepSeeker
    3
    10
    1.1k

  • Оптимизация React js приложений. Использование функции debounde()
    ManulM
    Manul
    3
    5
    568

  • Провайдеры в Nest JS - 1.3
    undefined
    3
    1
    373

  • Полный гайд по команде LFTP: Работа с локальными и удалёнными серверами
    undefined
    3
    1
    731

Пользователи в Сети:

GameFishG
GameFish

Статистика:

55

В сети

345

Пользователи

2.0k

Темы

2.9k

Сообщения

Категории

  • Главная
  • Новости
  • Фронтенд
  • Бекенд
  • Языки программирования

Контакты

  • Сотрудничество
  • info@exlends.com

© 2024 - 2026 ExLends, Inc. Все права защищены.

Политика конфиденциальности
  • Войти

  • Нет учётной записи? Зарегистрироваться

  • Войдите или зарегистрируйтесь для поиска.
  • Первое сообщение
    Последнее сообщение
0
  • Лента
  • Категории
  • Последние
  • Метки
  • Популярные
  • Пользователи
  • Группы