<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/">
  <channel>
    <language>ru</language>
    <title>Отладка</title>
    <description/>
    <link>https://tproger.ru/tag/debugging</link>
    <atom:link href="https://tproger.ru/tag/debugging/feed" rel="self" type="application/rss+xml"/>
    <lastBuildDate>Sat, 03 Oct 2026 15:34:36 GMT</lastBuildDate>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>12</sy:updateFrequency>
    <image>
      <title>Отладка</title>
      <link>https://tproger.ru</link>
      <url>https://tproger.ru/apple-touch-icon.png</url>
    </image>
    <item>
      <title>Баги, которые не ловятся тестами: три расследования и общая методика</title>
      <link>https://tproger.ru/articles/bagi-kotorye-ne-lovyatsya-testami-tri-rassledovaniya-i-obshhaya-meto</link>
      <comments>https://tproger.ru/articles/bagi-kotorye-ne-lovyatsya-testami-tri-rassledovaniya-i-obshhaya-meto?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Tproger]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/bagi-kotorye-ne-lovyatsya-testami-tri-rassledovaniya-i-obshhaya-meto</guid>
      <description><![CDATA[<p>Три расследования редких дефектов: гонка в SQLite, потеря сообщений в TCP и гонки в биллинге. Разбираем общую методику поиска невоспроизводимых багов.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/bagi-kotorye-ne-lovyatsya-testami-tri-rassledovaniya-i-obshhaya-meto">Баги, которые не ловятся тестами: три расследования и общая методика</a>»</p>]]></description>
      <category><![CDATA[Тестирование]]></category>
      <category><![CDATA[Сетевые протоколы]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[Базы данных]]></category>
      <category><![CDATA[Баги и ошибки]]></category>
      <category><![CDATA[PostgreSQL]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 09 Sep 2026 09:00:45 GMT</pubDate>
      <content:encoded><![CDATA[<p>Есть класс дефектов, которые проходят весь конвейер проверок и всплывают только в продакшене. Объединяет их не сложность кода. В двух случаях виновата форма проверки, написанной вежливой там, где реальность к сервису вежлива не бывает; в третьем проверка не поймала бы дефект вообще.</p><p>Разбираем три расследования — пропавшую запись в базе, три процента сообщений, терявшихся только на чистой машине, и гонки в биллинге, которые видит одна поддержка. У всех трёх разные предметные области и одна общая методика поиска невоспроизводимых багов.</p><p>Отсутствие закономерности само по себе является находкой: если сбой не привязан ни к шарду, ни к клиенту, ни к времени суток, это указывает на гонку, а не на данные.</p><p>Когда воспроизвести дефект синтетически нельзя, остаётся пассивная телеметрия в продакшене и последовательное отсечение гипотез данными.</p><p>Счётчики на каждом слое находят виновника быстрее логов: разрыв между двумя соседними числами прямо называет слой, в котором теряются сообщения.</p><p>Вежливый тест, который шлёт запрос и ждёт ответа, скрывает целый класс ошибок пакетирования. Пачечный тест их обнажает.</p><p>Отсутствие ошибок не доказывает, что дефект исправлен. Доказательством служит положительный сигнал: сработавшее предупреждение о том, что опасные условия возникли, а сбоя при этом не случилось.</p><h2>Случай первый: запись, которой не могло не быть</h2><p>Управляющий слой Tailscale разбит на шарды, у каждого своя база SQLite, и обращается к ней ровно один процесс. Такой однописательный режим — именно то, для чего SQLite и предназначен, что делает дальнейшее особенно неприятным.</p><p>Резервное копирование снимало полную копию базы каждые несколько минут и складывало файл в объектное хранилище. Работало это без единого происшествия с начала 2023 года, пока конвейер, читавший резервные копии, не сообщил об ошибке. Проверка встроенной командой контроля целостности подтвердила худшее: база повреждена.</p><p>Первый случай сочли единичным. Базу починили, причину не нашли. Потом это повторилось. И ещё раз. Всего до устранения первопричины набралось <a href="https://tailscale.com/blog/sqlite-wal-reset-bug">19 отдельных инцидентов за полгода</a>, и каждый означал простой: процесс на шарде останавливался, пока базу чинили или восстанавливали. На ранних инцидентах простой превышал час, и всё это время у клиентов на шарде не работали консоль администратора и API.</p><h3>Почему он не поддавался обычным приёмам</h3><p>Дефект сопротивлялся всем стандартным подходам сразу:</p><ul><li>Не на что было списать: низкоуровневый код работы с базой никто не трогал годами, а внимательное чтение ничего не дало.</li><li>Не нашлось общих факторов. Повреждения не привязывались ни к конкретному шарду, ни к клиенту, ни к функции продукта, ни ко времени суток, ни к уровню нагрузки.</li><li>Он не воспроизводился синтетически. Надёжного триггера не было, поэтому оставалось только развернуть пассивную телеметрию в боевой среде и ждать следующего случая.</li></ul><p>Расписания у инцидентов тоже не было: они случались то через часы, то через недели. Между октябрём и декабрём наступила шестинедельная тишина, после которой повреждения вернулись.</p><p>Команда сделала два шага, которые и составляют суть этой истории. Купила контракт поддержки у разработчиков SQLite, получив прямой доступ к людям, написавшим саму базу. И методично составила список гипотез, отсекая их данными, а не рассуждениями. В списке были сломанные блокировки при закрытии файла, неверная работа с памятью, принадлежащей базе, и обращение из нескольких потоков при отключённой потокобезопасности. Каждый инцидент приносил данные, каждая гипотеза отпадала по очереди.</p><h3>Улика: транзакция, которой не стало</h3><p>Пока первопричину искали, платформу надо было держать живой. Команда автоматизировала жёсткую остановку при обнаружении повреждения, поставила монитор, непрерывно проверявший целостность резервных копий, и переписала инструкции по восстановлению. Время восстановления упало ниже часа.</p><p>А затем построила конвейер журналирования транзакций. Идея простая: писать каждый изменяющий базу запрос в отдельный журнал. Поскольку писатель один, а транзакции сериализуемы, история изменений линейна и детерминирована, и её можно проиграть поверх последней заведомо целой копии, обойдя повреждённые страницы. Приём годится там, где порядок фиксаций известен: при единственном писателе он получается сам собой. Наивный журнал запросов на многописательной базе этого не даёт, потому что конкурентные транзакции переплетаются и без явного порядка фиксаций проигрывание не восстановит то же состояние.</p><p>Конвейер сработал и выдал улику. В двух инцидентах журналы не проигрывались чисто: данные, записанные и зафиксированные одной транзакцией, оказывались необъяснимо невидимы для последующих. Запись исчезла бесследно и без единой ошибки.</p><p>Этого не может быть. В сериализуемой однописательной базе зафиксированная запись не может пропасть. Значит, виноват слой с достаточной конкурентностью, чтобы такое спрятать, а такой слой ровно один — контрольные точки.</p><h3>Шестнадцатилетняя гонка</h3><p>SQLite с журналом предзаписи работает с двумя файлами. База — это набор страниц; при изменении данных новые страницы пишутся не в основной файл, а сначала в журнал. Позже контрольная точка переносит их в базу. Обычно момент переноса SQLite выбирает сам, но Tailscale управляла контрольными точками вручную, чтобы снимать быстрые согласованные копии. Именно этот нестандартный, хотя и полностью документированный выбор и вывел их на дефект.</p><p>Метрики во время инцидентов показывали, что SQLite сообщает о переносе большего числа страниц, чем в журнале вообще было. Разработчики базы как раз готовили инструмент для этого слоя: обёртку над виртуальной файловой системой, которая пишет дополнительные трассировочные журналы. Обёртку развернули в продакшене, и ждать пришлось недолго.</p><p>Журналы показали редкую гонку данных (race condition) между контрольной точкой и пишущей транзакцией. Если запись происходит в определённый момент работы контрольной точки, та сбивается: считает часть страниц перенесёнными в основной файл, хотя перенос не состоялся. Данные теряются навсегда, а страницы, которые на них ссылаются, например индексные, записываются как ни в чём не бывало. Файл становится структурно повреждённым, что проверка целостности всё это время и фиксировала.</p><p>Дефекту дали имя по сбросу журнала предзаписи и оценили его возраст минимум в шестнадцать лет. Он прожил так долго именно из-за редкости, это классический heisenbug: чтобы поймать его в тестовой среде, разработчикам пришлось дописать код, вызывающий гонку намеренно.</p><h3>Ложная тревога, чуть не сорвавшая исправление</h3><p>Исправление вышло в версии 3.52.0, и Tailscale раскатывала его осторожно, начав с нескольких канареечных шардов. После общей раскатки монитор резервных копий немедленно покраснел, сообщив о повреждении в тринадцати базах.</p><p>Настоящего повреждения не было. В ту же версию попала оптимизация, слегка изменившая округление при переводе текста в число с плавающей точкой, а Tailscale хранила метки времени высокой точности текстом и превращала их в числа в вычисляемом столбце. Индекс по вычисляемому выражению перестал соответствовать новому результату вычисления, и проверка целостности честно назвала это повреждением. Канареечные шарды дефект пропустили просто потому, что на них не оказалось меток времени, попадающих под изменённое округление.</p><p>Разбирали это с трёх сторон сразу. Разработчики SQLite отозвали версию целиком и выпустили 3.51.3, содержавшую только исправление гонки. Tailscale перешла на хранение меток времени целыми секундами, поскольку перевод текста в целое число однозначен. А в 3.53.0 появилось автоматическое восстановление таких индексов, чтобы проблема не возникала впредь.</p><p><b>Главный урок этого эпизода:</b><br />Канареечная выкатка проверяет только те формы данных, которые в канарейке есть. Если на канареечных узлах нет тех же значений, что в проде, канарейка не подтверждает ничего. Это касается и обновлений самой базы, драйверов и инструментов миграции, а не только кода приложения.</p><h3>Как доказали, что дефект действительно исправлен</h3><p>Самая дисциплинированная часть расследования пришлась на финал. Отсутствие повреждений доказательством не считалось: команда уже пережила шесть недель обманчивой тишины. Поэтому драйвер базы пропатчили так, чтобы он выдавал предупреждение всякий раз, когда пишущая транзакция и сброс журнала пересекаются во времени.</p><p>Логика прямая: если предупреждение сработает, а база останется целой, значит, исправление сработало ровно там, где раньше был бы инцидент. Ждали два месяца. Предупреждение сработало, подтвердив, что условия для гонки в их среде действительно возникают. С того момента прошло ещё четыре месяца без единого происшествия с базами.</p><h2>Случай второй: три процента, терявшиеся только на чистой машине</h2><p>Второй сюжет проще по масштабу и полезнее в быту. Сервис представлял собой небольшой пересыльщик TCP: принять соединение, читать текстовые строки, передавать дальше. На тестовом стенде входило 97 004 строки, а выходило 94 183. Ни ошибок, ни исключений, просто пропавшие сообщения.</p><p>На ноутбуке автора всё воспроизводилось идеально: сто тысяч строк на входе, сто тысяч на выходе. Это расхождение и было первой уликой — тест проверял не то, что делает продакшен.</p><h3>Сменить машину раньше, чем код</h3><p>Первый час, по его собственному признанию, ушёл впустую: менялись и бинарник, и машина, и профиль нагрузки разом, а выводов это не давало. Дальше автор поменял ровно одну переменную: взял чистый сервер с тем же бинарником и тем же скриптом нагрузки. Потери появились снова, 97 128 строк из ста тысяч. Среда меняла вероятность проявления, но не сам факт дефекта, а чистая машина без истории и без накопленных настроек работает как микроскоп для ошибок синхронизации.</p><h3>Считать, а не логировать</h3><p>Дальше нужен был не ещё один прогон, а способ понять, на каком слое теряются сообщения. Логи рассказывают истории, счётчики складываются. Автор расставил счётчик на каждом слое: клиент считает отправленные строки, сервер считает разобранные переводы строки, сервер считает отправленные ответы, клиент считает полученные ответы. Один прогон, четыре числа, и разрыв между соседними прямо называет виновный слой.</p><p>Сервер разобрал всё до последней строки, а ответов отправил меньше, чем разобрал. Это отпечаток пальца конкретного дефекта, и дальше оставалось найти его в коде ответа.</p><h3>read() ничего не обещает про сообщения</h3><p>Виновником оказалась одна строка: сервер отправлял по одному ответу на каждое чтение, а не на каждую разобранную строку.</p><p>TCP — это поток байтов, а не очередь сообщений. Вызов чтения не имеет понятия о том, что такое одно сообщение в вашем протоколе. Ядро вправе слить десяток сообщений в один сегмент, и одно чтение заберёт все десять, а ответ уйдёт один.</p><p>Вежливый локальный тест отправлял сообщение, дожидался подтверждения и отправлял следующее. Одно сообщение на сегмент — дефект спал. Нагрузка на стенде шла пачками, тысячами сообщений в секунду, ядро их группировало, одно чтение проглатывало сотню строк.</p><p>Исправление переносит ответ внутрь цикла по строкам и накапливает остаток в буфере, чтобы пережить строку, разорванную между двумя чтениями. Это вторая половина того же семейства ошибок, и без неё починка неполная:</p><p><b>Вывод автора расследования:</b><br />Локальный тест это не нагрузочный тест, ноутбук это не сервер, а одно чтение из сокета это не одно сообщение.</p><h2>Третий сюжет: гонки, которые видит только поддержка</h2><p>Третий сюжет про биллинг кредитов на бессерверном Postgres, где транзакции по условиям задачи были недоступны. Автор наткнулся на четыре гонки, разберём две самые показательные. Все они, по его собственной формулировке, относятся к тому сорту дефектов, которые не показываются в тестах и показываются в почте поддержки.</p><h3>Классический двойной расход</h3><p>Наивная версия, которую пишут первой:</p><p>Два одновременных запроса читают баланс, равный пяти, оба проходят проверку, оба записывают четыре. Пользователь получил две операции по цене одной. Дефект существует ровно между чтением и записью, и последовательный тест в это окно не попадает никогда.</p><h3>Инвариант переезжает в условие запроса</h3><p>Общее решение — сделать проверку и запись одним оператором, перенеся условие корректности в WHERE:</p><p>Одиночный UPDATE в Postgres атомарен. Не хватило баланса — условие не совпало, вернулось ноль строк, и вы точно знаете, что списание не произошло. Транзакция для этого не нужна вовсе. Приём обобщается: перенесите инвариант в условие выборки, и запись просто не случится, когда инвариант нарушен.</p><h3>Вебхук, доставленный дважды</h3><p>Платёжные провайдеры повторяют доставку уведомлений при таймаутах, пятисотках и сетевых сбоях, а иногда дублируют событие и в штатном режиме. Если обработчик начисляет кредиты, доставка «хотя бы один раз» означает начисление хотя бы один раз.</p><p>Обычное решение с таблицей обработанных событий требует транзакции, а её нет: падение между двумя операторами либо начислит дважды при повторе, либо потеряет начисление совсем. Рабочий вариант в один оператор использует изменяющее данные обобщённое табличное выражение, где вставка в журнал операций работает воротами: не прошла вставка, значит, не выполнилось и обновление баланса.</p><p>Деталь, которую стоит забрать отдельно: уникальный индекс под эту схему должен быть частичным. Начисления от администратора приходят с произвольным идентификатором из скрипта, и глобальный уникальный индекс рисковал бы столкнуть их друг с другом или с идентификатором операции другого типа. Приветственные начисления идут вообще без идентификатора, и с ними коллизии не будет в любом случае: Postgres не считает два пустых значения равными. Ограничение индекса двумя типами операций от платёжного провайдера держит проверку уникальности ровно там, где она нужна.</p><h2>Что из этого складывается</h2><p>Первые два расследования дают общую методику поиска, и она изложена ниже. Третий случай стоит особняком: это не детектив, а набор приёмов, которые убирают целый класс гонок ещё на этапе проектирования, до того как искать станет нечего.</p><h2>Что забрать с собой</h2><p>Общего у трёх расследований больше, чем различий. Во всех трёх случаях проверка была написана в форме, которая не воспроизводит реальность: последовательный запрос вместо пачки, одиночный вызов вместо конкуренции, одна машина вместо двух. И во всех трёх дефект спокойно проходил через тесты, а в случае с SQLite прожил так шестнадцать лет.</p><p>Соседний сюжет про то, как тесты перестают отражать реальность, разбирали в материале о том, <a href="https://tproger.ru/articles/pochemu-statichnye-moki-ubivayut-testirovanie--i-chto-my-s-etim-sdel">почему статичные моки убивают тестирование</a>.</p><p>Полезнее всего здесь дешёвые привычки. Счётчик на границе каждого слоя ставится за час. Пачечный клиент пишется за вечер. Датчик, доказывающий исправление положительным сигналом, добавляется одной строкой в драйвер. Всё это стоит несопоставимо меньше, чем полгода расследования.</p><p>Три постмортема, на которых строится разбор: <a href="https://tailscale.com/blog/sqlite-wal-reset-bug">разбор Tailscale о поиске шестнадцатилетнего бага в SQLite</a>, <a href="https://dev.to/datacpp_3670/the-3-drop-that-only-showed-up-on-a-clean-server-a-debugging-retrospective-1g3c">ретроспектива потери трёх процентов сообщений</a> и <a href="https://dev.to/xiaojun_mao_c154743594bc9/credit-billing-without-transactions-4-race-conditions-i-hit-on-serverless-postgres-4730">четыре гонки в биллинге на бессерверном Postgres</a>.</p><p>Возьмите самый подозрительный сервис и запустите по нему пачечный тест вместо последовательного. Это самый дешёвый способ узнать, какой из ваших дефектов сейчас спит.</p>]]></content:encoded>
    </item>
    <item>
      <title>Как исправить hydration-ошибки RSC в Next.js: практический гид</title>
      <link>https://tproger.ru/articles/kak-ispravit-hydration-owibki-rsc-v-next-js-prakticheskij-gid</link>
      <comments>https://tproger.ru/articles/kak-ispravit-hydration-owibki-rsc-v-next-js-prakticheskij-gid?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Евгений Стребков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/kak-ispravit-hydration-owibki-rsc-v-next-js-prakticheskij-gid</guid>
      <description><![CDATA[<p>Разбираем, почему возникают hydration mismatches в React Server Components и Next.js App Router, и как находить, исправлять и предотвращать их в production.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/kak-ispravit-hydration-owibki-rsc-v-next-js-prakticheskij-gid">Как исправить hydration-ошибки RSC в Next.js: практический гид</a>»</p>]]></description>
      <category><![CDATA[JavaScript]]></category>
      <category><![CDATA[Веб-разработка]]></category>
      <category><![CDATA[Лучшая практика]]></category>
      <category><![CDATA[Производительность]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[TypeScript]]></category>
      <category><![CDATA[React]]></category>
      <category><![CDATA[Фронтенд]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 21 Jul 2026 11:37:03 GMT</pubDate>
      <content:encoded><![CDATA[<p>Hydration mismatch в Next.js легко поймать в next dev, но в production он превращается в минимизированный код ошибки React и ссылку на декодер. В статье разбираем, почему ошибки гидратации особенно болезненны в приложениях с React Server Components, какие причины встречаются чаще всего и какой рабочий процесс помогает находить и предотвращать такие баги.</p><p>Речь пойдёт не о теории reconcile-алгоритма, а о практике: что проверять первым делом, как изолировать проблему через Suspense, куда смотреть в production-логах и как писать тесты, которые ловят регрессии до попадания к пользователям.</p><h2>Что такое hydration mismatch</h2><p>Гидратация — это процесс, при котором React берёт серверный HTML и навешивает на него обработчики событий, после чего страница становится интерактивной. React ожидает, что дерево, которое он отрендерил на клиенте, точно совпадёт с тем, что пришло с сервера. Если строки, атрибуты или структура различаются, возникает hydration mismatch.</p><p>В development-режиме React покажет предупреждение, текст расхождения и стек компонента. В production всё сводится к коротким кодам вроде #418 или #425. Без телеметрии вы не узнаете, на каком маршруте, в каком компоненте и из-за каких данных произошёл сбой.</p><h2>Почему это больно именно в RSC</h2><p>В классическом SSR обычно один серверный рендер и один клиентский проход гидратации. App Router добавляет Server Components, Client Components, потоковую передачу, Suspense-границы, динамические данные маршрута и RSC payload, который едет рядом с HTML.</p><p>Когда несовпадение происходит вне Suspense-границы, React может отбросить весь серверный HTML и перерендерить дерево на клиенте. Приложение заплатило цену серверного рендера, а пользователь не получил ни производительности, ни преимуществ стриминга. Это не просто предупреждение в консоли, а реальная потеря производительности.</p><h2>Ключевые выводы</h2><ul><li>Hydration mismatch в production без телеметрии почти невозможно локализовать: нужна инструментация на клиенте.</li><li>Основные причины: browser-only API, дата/время/локаль, состояние авторизации, невалидный HTML, расширения браузера, CSS-in-JS.</li><li>Граница 'use client' — это не только маркер сборки, но и граница гидратации: серверный рендер должен быть детерминирован.</li><li>Suspense-границы помогают изолировать сбой и не давать ему сломать всё дерево.</li><li>Проверяйте hydration только на production-сборке: next dev ведёт себя иначе.</li><li>Добавьте Playwright-smoke-тесты на критичные маршруты, чтобы ловить регрессии в CI.</li></ul><h2>Самые частые причины</h2><p>Перед тем как копать RSC payload или сравнивать HTML, стоит проверить шесть типовых сценариев. Они покрывают подавляющее большинство production-инцидентов.</p><ul><li><b>Browser-only API во время рендера:</b> window, document, localStorage, navigator — сервер не знает об этих значениях.</li><li><b>Дата, время и локаль:</b> Date, Intl.DateTimeFormat, относительное время — сервер обычно в UTC, пользователь в своей зоне.</li><li><b>Состояние авторизации:</b> сервер рендерит выклогнутый UI, клиент сразу видит авторизованного пользователя.</li><li><b>Невалидный HTML:</b> браузер чинит DOM до гидратации, а React сравнивает с исходным деревом.</li><li><b>Расширения и middleware:</b> браузерные плагины и edge-переписывания меняют HTML.</li><li><b>CSS-in-JS и порядок классов:</b> styled-components и Emotion могут генерировать разные имена классов при стриминге.</li></ul><h3>Browser-only API и сторонние провайдеры</h3><p>Самая частая причина — не ваш собственный код, а сторонний провайдер, который читает localStorage, window или navigator при инициализации. Под это попадают аналитика, фичер-флаги, A/B-тесты, session replay и персонализация.</p><p>Проблемный вариант: провайдер читает localStorage прямо при рендере.</p><p>Исправление: серверные флаги передаются в Client Component, а локальные оверрайды применяются после гидратации.</p><p><b>Принцип:</b> серверный и первый клиентский рендер должны получить одинаковый результат. Браузерные оверрайды включаются в useEffect после монтирования.</p><h3>Дата, время и локаль</h3><p>Сервер часто работает в UTC, а пользователь — в своей зоне. Date.toLocaleString(), Intl.DateTimeFormat и функции вроде formatDistanceToNow() дают разные строки в зависимости от часового пояса и времени между рендером и гидратацией.</p><p>Проблемный вариант: относительное время считается на сервере.</p><p>Исправление: сервер отдаёт стабильную абсолютную дату, клиент заменяет её на относительную после монтирования.</p><p>suppressHydrationWarning здесь уместен, потому что расхождение ожидаемо, ограничено листовым элементом  и управляется явно. Но оборачивать им большой контейнер, чтобы скрыть неизвестную ошибку, — значит замазать баг, а не починить его.</p><h3>Состояние авторизации</h3><p>Типичный сценарий: сервер рендерит UI для неавторизованного пользователя, потому что маршрут статический или не читает куки, а клиент сразу видит залогиненного пользователя. При каждой загрузке страница перерендеривается.</p><p>Решение — читать куки на сервере через cookies() из next/headers.</p><p>С cookies() маршрут становится динамическим — это обычно правильный компромисс для UI, зависящего от авторизации. Начиная с Next.js 15, cookies() асинхронный и требует await. В Next.js 16 синхронный доступ к request-time API полностью уходит.</p><h3>Невалидный HTML</h3><p>Браузер молча чинит невалидную вёрстку. React же гидратирует не исходную строку, а DOM, который построил браузер. Классический пример —  внутри <p></p>: браузер закроет параграф до div, и React увидит другое дерево.</p><p>Браузер превратит это в примерно такую структуру:</p><p>Если HTML приходит из CMS или редактора, валидируйте и нормализуйте его на сервере. Для собственных компонентов следите за предупреждениями validateDOMNesting в DevTools.</p><h3>Расширения браузера и middleware</h3><p>Менеджеры паролей, переводчики, грамматические плагины и другие расширения могут вставлять или переупорядочивать узлы до гидратации. Edge middleware и CDN-трансформации тоже могут переписывать HTML в пути.</p><p>Если несовпадение затрагивает только &lt;html&gt; или &lt;body&gt;, сначала подозревайте расширения. React 19 стал терпимее к инъекциям в head/body, но на старых версиях такие ошибки особенно шумные.</p><p>suppressHydrationWarning на корневых элементах — документированный escape hatch, но он работает только на один уровень вглубь и не должен использоваться для сокрытия неизвестных расхождений в продуктовом UI.</p><h3>CSS-in-JS и порядок классов</h3><p>В проектах со styled-components или Emotion имена классов могут зависеть от порядка рендера. Стриминг и Suspense меняют этот порядок, поэтому нужен registry с useServerInsertedHTML.</p><h2>Production workflow для отладки</h2><p>Не начинайте с diff-а огромных HTML-документов. Работайте по порядку, сужая область поиска.</p><ol><li>Настройте клиентскую телеметрию: перехватывайте console.error и отправляйте hydration-ошибки на свой endpoint.</li><li>Воспроизводите баг на production-сборке: next build &amp;&amp; next start, а не next dev.</li><li>Используйте Suspense-границы, чтобы изолировать проблемный участок и понять, в каком поддереве ошибка.</li><li>Сравнивайте серверный HTML (curl) и клиентский DOM после гидратации.</li><li>Когда найдёте расходящийся элемент, проверьте: browser-only API, дата/время, авторизацию, HTML-вложенность, расширения, стили.</li></ol><h3>Инструментация: instrumentation-client.ts</h3><p>Файл instrumentation-client.ts в Next.js запускается после загрузки документа, но до гидратации React. Это удобная точка для лёгкой клиентской телеметрии.</p><p>Если используете LogRocket, Sentry или другой инструмент, прикрепите тот же payload к текущей сессии — тогда можно будет увидеть, как выглядела страница в момент сбоя.</p><h3>Изоляция через Suspense</h3><p>Suspense-границы не только показывают fallback при загрузке. Если hydration mismatch случается внутри границы, React может ограничить восстановление этим поддеревом, а не переключать весь root на клиентский рендер.</p><p>Оберните поочерёдно основные секции. Если страничная ошибка исчезает после оборачивания конкретной секции, баг почти наверняка внутри неё.</p><h3>Сравнение HTML и DOM</h3><p>Получите серверный HTML через curl с нужными куками:</p><p>В Chrome DevTools после загрузки страницы скопируйте живой DOM:</p><p>Сохраните результат в /tmp/client-render.html и сравните:</p><p>Этот метод хорошо ловит HTML-слой, но может пропустить расхождения на уровне reconciler-а и RSC payload. Если raw HTML совпадает, проверяйте Client Components и браузерное состояние.</p><h2>Профилактика</h2><p>Лучше не допускать ошибки, чем потом их чинить. Несколько практик, которые помогают держать серверный и клиентский рендер синхронизированными.</p><ol><li>Server Component должен быть детерминированным: одни и те же входные данные дают одни и те же выходные HTML и RSC payload.</li><li>Все browser-only API, куки, заголовки, локаль и время должны оставаться за границей 'use client' или читаться через request-time API на сервере.</li><li>Для клиентского UI сначала рендерите стабильный baseline, а улучшения добавляйте в useEffect после гидратации.</li><li>Валидируйте HTML из внешних источников до того, как React его увидит.</li><li>Тестируйте hydration на production-сборке в CI.</li></ol><h3>Пример: стабильный baseline + клиентское улучшение</h3><p>Скелетон — это стабильная базовая разметка. Карточки товаров появляются после монтирования. Сервер и первый клиентский рендер совпадают, а пользователь получает нужный контент чуть позже.</p><h3>Smoke-тесты в CI</h3><p>Ручное тестирование пропустит регрессии. Добавьте Playwright-тест на критичные маршруты.</p><p>Запускайте такой тест только против production-сборки, никогда против next dev. Сделайте его обязательной проверкой для маршрутов, где hydration failure критичен: продуктовые страницы, дашборды, чекаут, личный кабинет.</p><h2>FAQ</h2><h2>Выводы</h2><p>Hydration mismatch — не придирка React, а реальный баг производительности и корректности. Каждое несовпадение означает, что приложение могло отбросить серверный HTML, за который уже заплатило ресурсами.</p><p>В приложениях с React Server Components, где цель — меньше клиентского JavaScript и более ранний стриминг полезного UI, hydration failures тихо отменяют эти преимущества. Поэтому важно держать браузерную логику за границей 'use client', рендерить стабильные серверные baseline и проверять гидратацию в production-условиях до того, как ошибку найдут пользователи.</p><blockquote>Hydration errors should be fixed, not ignored — официальная позиция React.</blockquote><p><b>Источник:</b> <a href="https://blog.logrocket.com/how-fix-rsc-hydration-mismatches-next-js/" rel="noopener noreferrer">LogRocket Blog — How to fix RSC hydration mismatches in Next.js</a>.</p><p>Проверьте свои критичные маршруты на production-сборке, настройте телеметрию и не давайте hydration-ошибкам копиться в консоли.</p>]]></content:encoded>
    </item>
    <item>
      <title>Microsoft сломала localhost в Windows 11 — миллионы разработчиков не могут локально тестить проекты</title>
      <link>https://tproger.ru/news/microsoft-slomala-localhost-v-windows-11---milliony-razrabotchikov-ne-mogut-lokalno-testit-proekty</link>
      <comments>https://tproger.ru/news/microsoft-slomala-localhost-v-windows-11---milliony-razrabotchikov-ne-mogut-lokalno-testit-proekty?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Булат Яббаров]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/microsoft-slomala-localhost-v-windows-11---milliony-razrabotchikov-ne-mogut-lokalno-testit-proekty</guid>
      <description><![CDATA[<p>Обновление Windows 11 KB5066835 сломало localhost: HTTP.sys перестал работать, и миллионы разработчиков не могут тестировать проекты</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/microsoft-slomala-localhost-v-windows-11---milliony-razrabotchikov-ne-mogut-lokalno-testit-proekty">Microsoft сломала localhost в Windows 11 — миллионы разработчиков не могут локально тестить проекты</a>»</p>]]></description>
      <category><![CDATA[Stack Overflow]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[.NET]]></category>
      <category><![CDATA[Windows]]></category>
      <category><![CDATA[Microsoft]]></category>
      <category><![CDATA[Windows 10]]></category>
      <category><![CDATA[Asp.NET]]></category>
      <category><![CDATA[Баги и ошибки]]></category>
      <category><![CDATA[Сервер]]></category>
      <category><![CDATA[Windows 11]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 17 Oct 2025 10:31:02 GMT</pubDate>
      <content:encoded><![CDATA[<p>Не прошло и двух дней после официального завершения поддержки Windows 10, как пользователи <b>Windows 11</b> <a href="https://www.techpowerup.com/341976/microsoft-breaks-localhost-with-windows-11-october-update-users-forced-to-revert">столкнулись</a> с серьезной ошибкой.</p><p>Последнее октябрьское обновление системы — <b>KB5066835</b> — нарушило работу localhost, что фактически лишило разработчиков возможности тестировать веб-приложения локально.</p><p>Проблему активно обсуждают на <b>Microsoft Support Forums</b>, <b>Stack Overflow</b> и <b>Server Fault</b>: серверы перестали отвечать на запросы, отвалилась отладка в Visual Studio, а ASP.NET-приложения не компилируются.</p><p>По оценкам экспертов, сбой затронул <b>миллионы веб-разработчиков и инженеров</b>, использующих Windows 11 в качестве локальных серверов и рабочих станций.</p><h2>Что пошло не так</h2><p>Пакет <b>KB5066835</b> был задуман как <b>обновление безопасности</b>, улучшавшее сентябрьский релиз <b>KB5065789</b>, но именно он привел к поломке <b>HTTP.sys</b> — системного компонента ядра Windows, отвечающего за маршрутизацию локального HTTP-трафика.</p><p>После установки апдейта, <b>localhost перестал отвечать на запросы</b>, а соединения по HTTP/2 начали обрываться.</p><h2>Как временно исправить</h2><p>Microsoft пока официально не подтвердила проблему, но сообщество уже нашло обходное решение:</p><ol><li>Удалить октябрьское обновление <b>KB5066835</b>.</li><li>Если не помогло — удалить и предыдущее <b>KB5065789</b>.</li><li>После этого localhost начинает работать штатно. Однако это <b>временная мера</b> и пользователи рискуют остаться без последних исправлений безопасности.</li></ol><h2>Неудачи Microsoft продолжаются</h2><p>Это уже <b>второй крупный сбой за неделю</b>. В понедельник компания случайно «сломала» <b>Media Creation Tool</b> — утилиту для установки Windows — всего за день до окончания поддержки Windows 10.</p><p>А на прошлой неделе Microsoft окончательно обязала пользователей <b>входить в Windows 11 только через онлайн-аккаунт</b>, что вызвало волну критики.</p>]]></content:encoded>
    </item>
    <item>
      <title>WebAssembly выходит за пределы браузера: серверные и embedded-применения</title>
      <link>https://tproger.ru/articles/webassembly-vyhodit-za-predely-brauzera--servernye-i-embedded-primeneniya-257873</link>
      <comments>https://tproger.ru/articles/webassembly-vyhodit-za-predely-brauzera--servernye-i-embedded-primeneniya-257873?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Денис Кудерин]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/webassembly-vyhodit-za-predely-brauzera--servernye-i-embedded-primeneniya-257873</guid>
      <description><![CDATA[<p>Как WebAssembly используют в серверных и embedded-системах. Преимущества WASM: безопасность, переносимость и эффективность. Примеры внедрения от Fastly и других компаний. Перспективы технологии в 2025 году.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/webassembly-vyhodit-za-predely-brauzera--servernye-i-embedded-primeneniya-257873">WebAssembly выходит за пределы браузера: серверные и embedded-применения</a>»</p>]]></description>
      <category><![CDATA[Инструменты]]></category>
      <category><![CDATA[Компиляторы]]></category>
      <category><![CDATA[Безопасность]]></category>
      <category><![CDATA[Производительность]]></category>
      <category><![CDATA[Микросервисы]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[Браузеры]]></category>
      <category><![CDATA[WebAssembly]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 17 Sep 2025 12:00:03 GMT</pubDate>
      <content:encoded><![CDATA[<p>WebAssembly (WASM) — язык программирования низкого уровня для стековой виртуальной машины. Когда он только появился, его воспринимали  исключительно как технологию для ускорения веб-приложений. Сегодня WASM стремительно выходит за границы браузера, открывая новые возможности для серверных и встраиваемых систем. Кардинально меняется сам подход к созданию кроссплатформенных приложений.</p><h2>WebAssembly в браузере: как всё начиналось</h2><p>Прежде чем говорить о настоящем и будущем WebAssembly, вспомним, с чего он начинался. Технология создавалась исключительно для работы в браузере. WebAssembly использовался (и используется сейчас): для оптимизации производительности, миграции legacy-нативных приложений, запуска кода на языках, отличных от JavaScript.</p><p>Ярче всего успех этого подхода демонстрирует Figma — популярный редактор для дизайнеров интерфейсов. Для многих стало неожиданностью, что редактор Figma, будучи веб-приложением, написан на C++.</p><p><b>Александр Коротаев</b>, фронтенд-разработчик, автор ТГ канала «Трудно быть Коротаевым»:</p><blockquote>На заре появления WASM многие ошибочно считали его то ли машиной для ускорения JS, то ли нативным модулем, который имеет доступ к операционной системе. Буквально чудо-коробочка, в которую можно поместить весь код, и он станет быстрее в три раза. Но в реальности технология столь ограничена в применении, что она до сих пор остается нишевой, хотя и очень перспективной.</blockquote><p>До WebAssembly разработчики Figma использовали технологию asm.js — предшественника WASM. Специальный компилятор преобразовывал (транспилировал) код C++ в высокооптимизированный JavaScript, который браузерные движки могли выполнять с близкой к нативной производительностью. У этого подхода были недостатки: большой размер получаемого кода и затраты на его парсинг и компиляцию в браузере.</p><figure><img src="https://media.tproger.ru/user-uploads/113565/2025-09-12/ca50f24f-8007-4880-b346-6b7e63692456.png" alt="" /></figure><p>Переход на WebAssembly стал переломным моментом. Поскольку WASM — это бинарный машинно-ориентированный формат, он гораздо компактнее и требует меньше ресурсов для обработки браузером. В результате миграции с asm.js на WebAssembly, Figma получила трёхкратный прирост производительности.</p><p>Этот кейс наглядно показал, что WebAssembly — это не просто ещё одна веб-технология, а настоящий прорыв, который стирает границы между нативными и веб-приложениями. Успех Figma и подобных проектов заложил фундамент для следующего логического шага: если WebAssembly так эффективен в браузере, почему бы не запускать его где угодно?</p><h2>Почему WebAssembly выходит за пределы браузера</h2><p>WebAssembly изначально создавался как безопасная, эффективная и портируемая платформа для компиляции высокоуровневых языков. Ключевые преимущества этого инструмента — изоляция выполняемого кода, платформонезависимость и высокая производительность — оказались востребованы не только в вебе.</p><p>Серверные и встроенные системы долгое время страдали от проблем совместимости, безопасности и сложности распространения кода. Традиционные подходы к изоляции (например, контейнеризация) требуют значительных ресурсов и не всегда дают достаточный уровень безопасности. WebAssembly предлагает альтернативу: песочницу с минимальными накладными расходами и встроенными механизмами безопасности.</p><p>Главным катализатором этого процесса стал стандарт WASI (WebAssembly System Interface), разработанный при участии Mozilla, Fastly и других компаний. WASI предоставляет стандартизированный интерфейс, где WebAssembly-модули взаимодействуют с операционной системой и решают проблему переносимости между различными платформами.</p><p><b>Александр Коротаев</b>, фронтенд-разработчик, автор ТГ канала «Трудно быть Коротаевым»:</p><blockquote>Открытая «кроссплатформенная» обертка WASI — это довольно большой прорыв в разработке, так как в текущем состоянии все современные продукты, выпускающиеся для разных ОС с одной кодовой базой, имеют большие, подчас legacy модули совместимости, или же запускаются внутри особых песочниц, сильно увеличивающих размер бандла. Например, браузерный движок Electron или React Native.</blockquote><h2>Как WebAssembly работает вне браузера</h2><p>Вне браузера WebAssembly исполняется в специальных средах выполнения (runtimes), которые взаимодействуют с операционной системой через WASI. Известные примеры — <a href="https://wasmtime.dev/">Wasmtime</a> от Mozilla, <a href="https://github.com/bytecodealliance/lucet">Lucet</a> от Fastly и <a href="https://wasmer.io/">Wasmer</a>.</p><p>Эти среды выполняют роль «концептуальной операционной системы», предоставляют модулям WebAssembly стандартизированный доступ к системным ресурсам: файлам, сети, случайным числам и другим функциям.</p><figure><img src="https://media.tproger.ru/user-uploads/113565/2025-09-12/029b3ae4-a5db-416b-817f-b296969a3226.png" alt="" /></figure><p>WebAssembly принципиально отличается от традиционных подходов тем, что изолируется на уровне инструкций, а не процессов. Каждый модуль выполняется в собственной песочнице с чётко определенными границами доступа к ресурсам. Это значительно снижает риск компрометации системы даже в случае уязвимостей в самом коде.</p><h2>Безопасность как фундаментальное преимущество</h2><p>Безопасность WebAssembly основана на нескольких уровнях защиты. Модули выполняются в изолированной среде, отделённой от хост-системы с помощью техник изоляции отказов. Это означает, что приложения выполняются независимо и не могут покинуть песочницу без явного разрешения через API.</p><p>Система контролирует выполнение кода с помощью статической проверки типов — все функции нужно явно объявлять перед использованием. Даже косвенные вызовы проверяются на соответствие сигнатурам прямо во время работы программы. Такой подход блокирует распространённые атаки — переполнение буфера и внедрение вредоносного кода.</p><p>Память в WebAssembly изолирована — напрямую с ней работать нельзя. Когда система обращается к памяти, она проверяет границы доступа, а локальные переменные хранятся в защищённом стеке вызовов.</p><p>Важность такого подхода к безопасности сложно переоценить в свете общих трендов защиты данных. К 2025 году безопасность и конфиденциальность стали ключевыми приоритетами для индустрии. Это особенно актуально на фоне растущих рисков при работе с большими языковыми моделями (LLM), которые могут невольно запоминать и воспроизводить конфиденциальные данные из тренировочных наборов.</p><p>Если запускать изолированные модули WebAssembly на своей инфраструктуре вместо публичного облака, можно безопасно обрабатывать чувствительные данные без риска утечки.</p><p><b>Александр Коротаев</b>, Фронтенд-разработчик, автор ТГ канала «Трудно быть Коротаевым»:</p><blockquote>Здесь явно подчеркивается безопасность платформы из коробки, но не стоит забывать, что на разработчике все еще лежит ответственность за безопасность данных и пользователей. Режим «разрешить все» — стандарт для любого MVP, и без аудита перед релизом тут все еще не обойтись. Платформа лишь гарантирует, что память процесса будет защищена от несанкционированного доступа, что уже давно делается во всех популярных операционных системах. Чтобы выйти за пределы стека или прочитать чужую память, надо использовать очень старые компиляторы или сильно низкоуровневые средства разработки.</blockquote><h2>Серверные применения WebAssembly</h2><p>Серверный ландшафт традиционно строился на монолитных приложениях и виртуальных машинах, но сегодня индустрия движется к более легковесным и изолированным компонентам. WebAssembly предлагает компромисс между производительностью нативного кода и безопасностью интерпретируемых сред. Эта технология особенно востребована в сценариях, где критически важны быстрое масштабирование и минимальное время запуска.</p><h2>Микросервисы и бессерверные архитектуры</h2><p>WebAssembly идеально подходит для микросервисных архитектур благодаря легковесности и быстрому запуску. В отличие от традиционных контейнеров, WASM-модули не требуют отдельной ОС и запускаются за миллисекунды.</p><p>Кейс: компания Fastly использует WebAssembly для исполнения пользовательского кода на серверах. Их технический директор Тайлер МакМаллен <a href="https://habr.com/ru/articles/446764/">отмечает</a>: «Мы рассматриваем WebAssembly как платформу для быстрого и безопасного кода в облаке на границе сети».</p><figure><img src="https://media.tproger.ru/user-uploads/113565/2025-09-12/45f4a6a2-5b2f-440c-a634-a3b4a3f4accf.jpg" alt="" /></figure><h2>Безопасные расширения приложений</h2><p>Многие приложения позволяют пользователям запускать собственный код через плагины и расширения. Но это создаёт риски для безопасности. В WebAssembly пользовательский код выполняется с минимальными рисками.</p><p>Веб-сервер Angie <a href="https://angie.software/news/articles/wasm/">использует</a> WASM для безопасности пользовательских модулей. Это решает проблему совместимости, характерную для традиционных модулей, написанных на C.</p><p>Экономическая эффективность таких вариантов становится решающим фактором. По <a href="https://explodingtopics.com/blog/list-of-llms">данным на 2025 год</a>, глобальный рынок больших языковых моделей (LLM), чьи backend-системы часто используют микросервисные архитектуры, демонстрирует колоссальный рост. Прогнозируется, что к 2033 году он достигнет $140,8 млрд.</p><p>Для таких масштабов нужны технологии с качествами, которые как раз предоставляет WebAssembly: безопасность, переносимость и эффективное использование ресурсов. Почти все компании из списка Fortune 500 уже <a href="https://cybernews.com/security/ai-adoption-outpace-security-at-fortune500-firms/">используют</a> генеративный ИИ в своих бизнес-процессах, и для многих из них WebAssembly — ключевой инструмент для развёртывания и масштабирования этих рабочих нагрузок.</p><p><b>Александр Коротаев</b>, Фронтенд-разработчик, автор ТГ канала «Трудно быть Коротаевым»:</p><blockquote>Здесь все закономерно: бизнес всегда выбирал решения, где можно было написать код один раз и поставить его сразу на несколько платформ. Даже если сами решения  сырые и небезопасные, дешевле было увеличить поддержку пользователей и настроить аудит безопасности, чем реализовать фичу для каждой платформы отдельно. Так на рынок вышли Python, Node.js, React Native, стремительно обгоняя конкурентов за счет скорости разработки.</blockquote><p><br /></p><h2>WebAssembly в embedded-системах</h2><p>WebAssembly успешно работает на серверах, но главные изменения происходят во встроенных системах. В IoT всегда была проблема совместимости: разные процессоры, операционные системы и периферийные устройства.</p><p>Технология предлагает принципиально новый подход — единую бинарную форму, способную работать на любом микроконтроллере с минимальными адаптациями. Теперь разработчики могут не привязываться к конкретным платформам и сосредоточиться на бизнес-логике приложения.</p><h2>Удаленные интерфейсы и централизованный мониторинг</h2><p>Производители встраиваемых систем всё чаще нуждаются в удаленных интерфейсах и централизованном мониторинге. WebAssembly позволяет повторно использовать код, написанный для embedded-устройств, в веб-интерфейсах для удалённого управления.</p><p>Согласно <a href="https://www.qt.io/blog/does-webassembly-matter-for-embedded-systems-makers">исследованию</a> Qt Company, более 77% респондентов из промышленной автоматизации считают удалённое управление и централизованный мониторинг критически важными в ближайшие десять лет. WebAssembly предоставляет экономичный способ реализации таких решений.</p><p><b>Александр Коротаев</b>, Фронтенд-разработчик, автор ТГ канала «Трудно быть Коротаевым»:</p><blockquote>А это, пожалуй, самая продающая фича: обычно у компаний, которые выходят на рынок со своими железками, базами данных и прочими продуктами, все продажи буквально построены на том, что программисты у клиента знают, как это быстро встроить. Так, бизнес готов платить деньги. Обычно у них есть проблемы с API для разных языков программирования, ОС и девайсов: либо хорошо все в JS, а в мобилках не заводится, либо наоборот. А то и вообще: стоит забросить поддержку платформы хоть на полгода, сразу всёперестает работать. Потому поставлять модуль для WASI должно быть дёшево, при этом  потенциально можно закрыть даже платформы будущего. Это инновация сродни изобретению стандарта USB.</blockquote><p><br /></p><h2>Прототипирование и сотрудничество</h2><p>WebAssembly упрощает процесс прототипирования и обратной связи для embedded-устройств. Разработчики могут скомпилировать приложение, разместить его на веб-сервере и предоставить доступ всем заинтересованным сторонам. При этом не нужно распространять устройства или проходить сложные процессы публикации.</p><p>Компания Qt использует этот подход в Qt Design Viewer, позволяя разработчикам делиться интерактивными дизайнами, созданными в Qt Design Studio, с коллегами по всему миру.</p><h2>Примеры внедрения: история ByteFog</h2><p>Компания Inetra из Новосибирска <a href="https://habr.com/ru/companies/jugru/articles/441140/">разработала</a> технологию peer-to-peer для доставки видео ByteFog. Система работает на множестве платформ: Windows, Linux, Android, iOS, Web и Tizen.</p><figure><img src="https://media.tproger.ru/user-uploads/113565/2025-09-12/2ec3300a-dcc3-41aa-acf5-7e51b78f9131.webp" alt="" /></figure><p>Изначально веб-версия использовала Netscape Plugin API, но когда основные браузеры прекратили поддержку этой технологии в 2015 году, компания осталась без веб-версии на два года. Поэтому в 2017 году они обратились к WebAssembly.</p><p>Используя компилятор Emscripten, разработчики перенесли существующее C++-приложение в браузер. Главной сложностью было разграничить транспортный слой и бизнес-логику через интерфейсы. Основной канал доставки видео заменили на AJAX, а P2P-слой — на WebRTC.</p><p>Результат компиляции — двоичный.wasm-файл и «клеевой код» на JavaScript, взаимодействующий с браузерными API. Это позволило запускать сложную P2P-систему Peers.TV напрямую в браузере без плагинов.</p><figure><img src="https://media.tproger.ru/user-uploads/113565/2025-09-12/6f383fd2-9857-497f-848a-d296791fb36e.png" alt="" /></figure><h2>Fastly Terrarium: экспериментальная платформа для WebAssembly-приложений</h2><p>В 2021 году инженеры Fastly <a href="https://www.fastly.com/blog/terrarium-reframes-compiler-sandbox-relationship">выпустили</a> Terrarium — экспериментальную платформу для запуска WebAssembly-модулей на периферийных устройствах (edge devices), над которой работали несколько лет. Сейчас проект всё ещё в демо-версии.</p><p>Terrarium  показывает, как можно запускать пользовательский код в изолированных средах с минимальной задержкой. Платформа использует рантайм Lucet, разработанный инженерами Fastly, и поддерживает компиляцию из Rust, C++ и AssemblyScript.</p><p>Ключевая особенность подхода — стандарт WASI для системных вызовов, что помогаетпереносить модули между разными средами. Это особенно важно для edge-вычислений, где код должен работать на разнородном оборудовании.</p><p>По данным тестирования, время запуска модулей составляет около 50 микросекунд, а потребление памяти измеряется килобайтами на инстанс. Такие показатели достигаются за счёт изоляции на уровне инструкций, а не процессов.</p><p>Хотя Terrarium не стал коммерческим продуктом, его наработки повлияли на другие решения Fastly. Компания <a href="https://www.fastly.com/blog/how-fastly-and-developer-community-invest-in-webassembly-ecosystem">развивает</a> направление WebAssembly-вычислений далее — экосистема постоянно обновляется.</p><h2>Технические вызовы и ограничения</h2><p>Несмотря на впечатляющие возможности WebAssembly за пределами браузера, технология сталкивается с объективными сложностями в реальных проектах. Разработчикам приходится решать две задачи одновременно: изолировать код для безопасности и при этом давать доступ к системе. Важно также сохранить кроссплатформенность, но не терять в производительности на конкретных устройствах.</p><p>Эти компромиссы особенно заметны в embedded-среде, где каждое решение напрямую влияет на энергопотребление, стоимость и надежность системы.</p><p><b>Александр Коротаев</b>, Фронтенд-разработчик, автор ТГ канала «Трудно быть Коротаевым»:</p><blockquote>А здесь кроется главное: почему такое решение не было написано ранее? Дело в том, что оно явно затратное по ресурсам, если сравнивать ту же логику, написанную на низком уровне. Сейчас любые устройства стали мощнее, чем ранее, и теперь разница уже не так заметна. Поэтому WASI может широко распространяться, без типичных минусов высокоуровневых абстракций: потребления памяти и энергии сильно выше чем у конкурентов.</blockquote><p><br /></p><h2>Доступ к аппаратным ресурсам</h2><p>WebAssembly ограничивает прямой доступ к аппаратуре во встроенных системах — это плата за безопасность. Это усложняет работу embedded-разработчикам.</p><p>Сообщество WebAssembly уже решает проблемы. Стандарт WASI продолжает развиваться, и в будущем появятся более гибкие способы работы с оборудованием.</p><h2>Размер файлов и производительность</h2><p>WebAssembly-модули могут иметь значительный размер, особенно при включении стандартных библиотек. В случае ByteFog размер бандла достигал 100 МБ, что создавало проблемы для инструментов сборки и загрузки в браузере.</p><p>Чтобы уменьшить размер, нужно тщательно удалять неиспользуемый код и подбирать настройки компиляции. Кроме того, передача данных между хост-системой и WebAssembly-модулем обходится дорого.</p><p><b>Александр Коротаев</b>, Фронтенд-разработчик, автор ТГ канала «Трудно быть Коротаевым»:</p><blockquote>Тут имеется ввиду краеугольная проблема WASM модулей — ввод и вывод. Дело в том, что он довольно низкоуровневый, и если в случае с микроконтроллерами они буквально будут говорить на «одном языке» с железом, то более высокоуровневые системы, передающие данные в том же JSON, столкнутся с довольно затратным процессом сериализации данных. Чтение строки с английскими буквами это одно, а текст на разных языках — это уже задачка со звездочкой. Так что в случае LLM надо будет серьезно работать надо протоколом обмена данными.</blockquote><h2>Инструменты и экосистема</h2><p>Экосистема WebAssembly вне браузера всё ещё развивается. Поддержка различных языков программирования неравномерна: лучше всего дела обстоят у C/C++ и Rust, с интерпретируемыми языками всё сложнее.</p><p>Отладка WebAssembly-модулей ограничена в сравнении с традиционными средствами. Разработчикам часто приходится использовать косвенные методы и работать с преобразованным кодом. Это особенно важно в контексте другой быстрорастущей тенденции — переносить выполнение ИИ-моделей с серверов на сами устройства пользователей (edge computing).</p><p>Например, современные компактные LLM, такие как Phi-4-mini-flash, демонстрируют впечатляющую производительность на мобильных чипах ARM, обрабатывая запросы за 90–100 мс прямо на устройстве без облака. Для подобных сценариев WebAssembly с его переносимостью и низким потреблением ресурсов выглядит идеальной средой, если сможет предложить более прямой и эффективный доступ к специфическим возможностям железа.</p><h2>Будущее WebAssembly вне браузера</h2><p>Перспективы WebAssembly вне браузера выглядит многообещающим. Стандарт WASI совершенствуется,  поддерживая новые системные интерфейсы и возможности. Разработчики получают всё более мощные инструменты для создания и отладки WASM-модулей.</p><p>В embedded-сфере WebAssembly может стать стандартом для безопасного выполнения кода на различных устройствах IoT (интернета вещей). Его способность работать на ресурсо-ограниченных устройствах при изоляции делает инструмент привлекательной альтернативой традиционным подходам.</p><p>Майлз Боринс, технический директор руководящего комитета Node.js, <a href="https://habr.com/ru/articles/446764/">видит</a> потенциал WebAssembly в решении одной из наибольших проблем фреймворка: «Это способ достичь скорости, близкой к нативной, и повторно использовать код, написанный на других языках (C и C++), сохранять портативность и безопасность».</p><p><b>Александр Коротаев</b>, Фронтенд-разработчик, автор ТГ канала «Трудно быть Коротаевым»:</p><blockquote>Как я понял, под фундаментальными проблемами имеется в виду ограничение на кол-во операций с потоками и файлами в текущий версиях Node.js, что не дает серверам на «ноде» тягаться с Nginx на равных.</blockquote><p><br /></p><h2>Итоги</h2><p>WebAssembly превращается из узкоспециализированной веб-технологии в универсальную платформу для выполнения кода. Безопасность, переносимость и производительность WebAssembly делают его эффективным решением для серверных и встраиваемых систем.</p><p>У WebAssembly всё ещё есть проблемы с доступом к аппаратным ресурсам и большим размерам модулей. Однако инструменты и стандарты активно развиваются — скорее всего, эти ограничения постепенно устранят.</p><p>Для разработчиков WebAssembly открывает новые возможности повторного использования кода и создания безопасных, переносимых приложений. Для индустрии в целом — это шаг к более безопасным и эффективным моделям распределения и выполнения кода.</p><p>Как <a href="https://habr.com/ru/articles/446764/">отмечает</a> Шон Уайт, директор Mozilla по R&amp;D: «WebAssembly уже меняет способы доставки людям новых видов привлекательного контента. С WASI преимущества WebAssembly получат больше пользователей и больше устройств в разных местах».</p><p>WebAssembly больше не ограничивается браузером — он становится универсальной платформой для среды, где код должен выполняться безопасно и эффективно везде: от облачных серверов до крошечных устройств интернета вещей.</p>]]></content:encoded>
    </item>
    <item>
      <title>Код из 2000-х вернулся в Linux благодаря ИИ. Старый ftape-драйвер снова работает на ядре версии 6.8</title>
      <link>https://tproger.ru/news/kod-iz-2000-h-vernulsya-v-linux-blagodarya-ii--staryj-ftape-drajver-snova-rabotaet-na-yadre-versii-6-8</link>
      <comments>https://tproger.ru/news/kod-iz-2000-h-vernulsya-v-linux-blagodarya-ii--staryj-ftape-drajver-snova-rabotaet-na-yadre-versii-6-8?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Булат Яббаров]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/kod-iz-2000-h-vernulsya-v-linux-blagodarya-ii--staryj-ftape-drajver-snova-rabotaet-na-yadre-versii-6-8</guid>
      <description><![CDATA[<p>Старый ftape-драйвер для QIC-лент, удалённый из Linux в 2006 году, ожил в ядре 6.8: разработчик с помощью Claude Code адаптировал код под современные API</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/kod-iz-2000-h-vernulsya-v-linux-blagodarya-ii--staryj-ftape-drajver-snova-rabotaet-na-yadre-versii-6-8">Код из 2000-х вернулся в Linux благодаря ИИ. Старый ftape-драйвер снова работает на ядре версии 6.8</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Ретро]]></category>
      <category><![CDATA[Linux]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[Работа]]></category>
      <category><![CDATA[Разработка]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Mon, 08 Sep 2025 13:18:58 GMT</pubDate>
      <content:encoded><![CDATA[<p><b>В Linux 6.8 снова заработал драйвер ftape, который не обновлялся с начала 2000-х</b>. Он обеспечивал поддержку ленточных накопителей формата QIC, которые подключались к обычному флоппи-контроллеру.</p><p>Код считался устаревшим, его удалили из ядра в версии 2.6.20 (в 2006 году), а теперь <b>воскресили с помощью ИИ-помощника</b>.</p><p>За проект <a href="https://dmitrybrant.com/2025/09/07/using-claude-code-to-modernize-a-25-year-old-kernel-driver">взялся</a> разработчик из Wikimedia — <i>Дмитрий Брант</i>, который сначала не рассчитывал на быстрый успех. Но благодаря <i>Claude Code</i> (ИИ-помощник от Anthropic), старый код удалось привести в рабочее состояние <b>всего за два вечера</b>.</p><h2>Что за драйвер и зачем он нужен?</h2><p>ftape — это драйвер для лент, использующих QIC-картриджи. Такие накопители были популярны в 1990-х для резервного копирования, особенно в малом бизнесе и домашних системах.</p><p>В отличие от дорогих SCSI-устройств, QIC-ленты подключались прямо к <b>контроллеру флоппи-дисков</b> (или через LPT-порт) — и в этом была вся магия. Драйвер буквально «обманывал» флоппи-контроллер, заставляя его работать с лентами.</p><p>ftape умел снимать <b>полные дампы картриджей в raw-режиме</b>, которые потом можно было расшифровать. Это важно для тех, кто хочет <b>восстановить архивы со старых лент</b>, даже если файловая система повреждена.</p><h2>Как ИИ помог воскресить драйвер</h2><p>Работа велась в три этапа:</p><ol><li><b>Миграция под новое ядро.</b> Claude Code получил старый код, совместимый только с ядром 2.4, и на основе подсказок заменил устаревшие вызовы ядра на актуальные API, устранил ошибки компиляции, адаптировал структуры данных.</li><li><b>Преобразование в модуль.</b> Драйвер был встроенным, а теперь работает как загружаемый модуль (.ko), что делает его удобнее и безопаснее.</li><li><b>Отладка на современных системах.</b> Разработчик подавал ИИ ассистенту dmesg-логи и сравнивал с поведением старого драйвера. После нескольких итераций и ручных правок модуль заработал — <b>ленты определяются, данные считываются</b>.</li></ol><blockquote>На проект, который казался адом из макросов и документации, ушло всего пару вечеров и три запроса.</blockquote><h2>Почему это важно</h2><ul><li>Проект демонстрирует <b>практическую пользу ИИ в разработке системного ПО</b>, особенно при адаптации заброшенных проектов.</li><li>Драйвер позволяет работать со <b>старыми ленточными архивами</b> без необходимости содержать старые дистрибутивы или «заводить» музейную технику.</li><li>Разработка открывает путь к <b>восстановлению данных с дефектных носителей</b>: сейчас планируют добавить утилиты для низкоуровневого анализа и восстановления по raw-дампам.</li></ul><h2>Но не все заслуга ИИ</h2><p>Дмитрий подчеркивает: <b>без понимания архитектуры ядра и Си-языка ничего бы не вышло</b>. ИИ — всего лишь инструмент, который можно направить, если знаешь, куда двигаться.</p><blockquote>Он как подчиненный инженер: все сделает, хочет угодить, но требует четкой постановки задачи. Ошибается, признает ошибки, но ответственность все равно на человеке.</blockquote><h2>Где это можно использовать</h2><ul><li>В <b>архивных лабораториях</b> — для восстановления старых данных.</li><li>В проектах по <b>реставрации ретро-компьютеров</b>.</li><li>Для системных экспериментов и исследований истории хранения информации.</li></ul><p>Модуль работает на <b>Ubuntu 24.04</b> и других дистрибутивах с ядром 6.8+, но требует <b>контроллер флоппи-дисков</b> на материнской плате.</p>]]></content:encoded>
    </item>
    <item>
      <title>Релиз Go 1.25: умный GOMAXPROCS для контейнеров, ускоренный на 40% GC и «черный ящик» для отладки</title>
      <link>https://tproger.ru/news/reliz-go-1-25--umnyj-gomaxprocs-dlya-kontejnerov--uskorennyj-na-40--gc-i--chernyj-yashhik--dlya-otladki</link>
      <comments>https://tproger.ru/news/reliz-go-1-25--umnyj-gomaxprocs-dlya-kontejnerov--uskorennyj-na-40--gc-i--chernyj-yashhik--dlya-otladki?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Булат Яббаров]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/reliz-go-1-25--umnyj-gomaxprocs-dlya-kontejnerov--uskorennyj-na-40--gc-i--chernyj-yashhik--dlya-otladki</guid>
      <description><![CDATA[<p>Go 1.25 получил container-aware GOMAXPROCS, GC быстрее на 40%, «черный ящик» Flight Recorder и новые инструменты для отладки и тестирования</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/reliz-go-1-25--umnyj-gomaxprocs-dlya-kontejnerov--uskorennyj-na-40--gc-i--chernyj-yashhik--dlya-otladki">Релиз Go 1.25: умный GOMAXPROCS для контейнеров, ускоренный на 40% GC и «черный ящик» для отладки</a>»</p>]]></description>
      <category><![CDATA[Linux]]></category>
      <category><![CDATA[Инструменты]]></category>
      <category><![CDATA[JSON]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[Windows]]></category>
      <category><![CDATA[Golang]]></category>
      <category><![CDATA[macOS]]></category>
      <category><![CDATA[ARM]]></category>
      <category><![CDATA[Kubernetes]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 13 Aug 2025 07:52:43 GMT</pubDate>
      <content:encoded><![CDATA[<p>Состоялся <a href="https://go.dev/doc/go1.25">релиз</a> Go 1.25. Разработчики заметно улучшили рантайм и инструменты, при этом не изменяя сам язык.</p><p>Одно из главных новшеств — <b>container-aware GOMAXPROCS</b>: теперь по умолчанию значение GOMAXPROCS учитывает лимиты CPU в cgroup.</p><p>На Linux это позволит процессам внутри контейнеров (например, в Kubernetes) автоматически адаптировать использование процессорных ресурсов к выделенной квоте.</p><p>Параметр обновляется динамически, если лимиты меняются, и может быть отключен через переменные окружения.</p><h2>Новый сборщик мусора — до 40% быстрее</h2><p>В экспериментальном режиме появился <b>garbage collector нового поколения</b> с улучшенной локальностью и масштабируемостью.</p><p>Он особенно эффективен в приложениях с большим количеством мелких объектов, снижая накладные расходы на GC на 10–40%. Включается через GOEXPERIMENT=greenteagc.</p><h2>Trace Flight Recorder: отладка по горячим следам</h2><p>Введен <b>runtime/trace.FlightRecorder</b> — «черный ящик» для приложений на Go.</p><p>Он постоянно пишет трейс в кольцевой буфер, позволяя при наступлении события выгрузить последние секунды исполнения в файл.</p><p>Нововведение значительно упрощает отладку редких и трудно воспроизводимых багов.</p><h2>Другие изменения в рантайме и инструментах</h2><ul><li>Исправлена ошибка компилятора с отложенной проверкой nil, из-за которой некорректный код мог выполняться без паники.</li><li>Добавлена поддержка DWARF5 — меньше отладочной информации и быстрее линковка.</li><li>Улучшено выделение памяти для слайсов — быстрее в ряде сценариев.</li><li>В Linux теперь можно видеть имена анонимных VMA ([anon: Go: heap]) в отладочных инструментах ядра.</li><li>Новый пакет testing/synctest для тестирования конкурентного кода с виртуальным временем.</li><li>Экспериментальный пакет encoding/json/v2 с ускоренным парсингом и расширенной конфигурацией маршалера.</li><li>Новый метод WaitGroup.Go для удобного запуска горутин с учетом синхронизации.</li></ul><h2>Платформенные изменения</h2><p>Go 1.25 требует macOS 12 и выше. 32-битная Windows/ARM-платформа будет удалена в следующем релизе.</p><p>На RISC-V появился режим сборки плагинов и поддержка профиля RVA23U64.</p>]]></content:encoded>
    </item>
    <item>
      <title>Карьера через пет-проект: как выбрать идею и довести до результата</title>
      <link>https://tproger.ru/articles/karera-cherez-pet-proekt--kak-vybrat-ideyu-i-dovesti-do-rezultata</link>
      <comments>https://tproger.ru/articles/karera-cherez-pet-proekt--kak-vybrat-ideyu-i-dovesti-do-rezultata?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Владислав Устинов]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/karera-cherez-pet-proekt--kak-vybrat-ideyu-i-dovesti-do-rezultata</guid>
      <description><![CDATA[<p>Разбираемся, как создать пет-проект и не выгореть: идея, MVP, обратная связь и упаковка.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/karera-cherez-pet-proekt--kak-vybrat-ideyu-i-dovesti-do-rezultata">Карьера через пет-проект: как выбрать идею и довести до результата</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Git]]></category>
      <category><![CDATA[Опрос]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[Google]]></category>
      <category><![CDATA[Работа]]></category>
      <category><![CDATA[GitHub]]></category>
      <category><![CDATA[Боты]]></category>
      <category><![CDATA[Навыки]]></category>
      <category><![CDATA[HR]]></category>
      <category><![CDATA[Telegram]]></category>
      <category><![CDATA[React]]></category>
      <category><![CDATA[Финтех]]></category>
      <category><![CDATA[Фронтенд]]></category>
      <category><![CDATA[Английский]]></category>
      <category><![CDATA[Бэкенд]]></category>
      <category><![CDATA[YouTube]]></category>
      <category><![CDATA[Приложение]]></category>
      <category><![CDATA[Дизайн]]></category>
      <category><![CDATA[Vue]]></category>
      <category><![CDATA[Пет-проект]]></category>
      <category><![CDATA[Notion]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 29 Jul 2025 10:00:03 GMT</pubDate>
      <content:encoded><![CDATA[<h2>Как найти идею для пет-проекта</h2><p>Новички, когда сталкиваются с пет-проектами, бросаются в две крайности. Создают очередной To-Do list, который ничем не выделяется, либо пытаются сделать что-то слишком сложное, например, убийцу Notion, и забрасывают работу на полпути. Так как же выбрать идею, которую получится довести до конца?</p><h3>Ключевые нюансы при выборе идеи пет-проекта</h3><p>Сначала надо подумать, какая у вас или вашего окружения есть проблема, которую вы могли бы решить своим проектом? Учите английский и любите сериалы? Так почему бы не сделать телеграм-бота, который будет присылать отрывки с определённой лексикой? Считаете своё резюме и портфолио слишком скучными? Можно оформить их в виде современного лендинга, правда придётся прикрутить интересные фичи, иначе это не пет-проект. Например, если вы фронтенд-разработчик, то можно сделать необычную анимацию, добавить несколько цветовых тем, демонстрацию проектов прямо на странице, интерактивную карту навыков и опыта.</p><p>Ваш «питомец» должен решать какую-то проблему и выделяться фишкой, иначе он никого не впечатлит.</p><blockquote>Впечатляют проекты, которые выглядят как реальные продукты. Например, когда кандидат делает пет-проект под конкретную потребность: финтех-дашборд, Telegram-бот или полноценное веб-приложение, которым уже пользуются или которое может быть полезно.</blockquote><blockquote>Как-то я пришёл на хакатон — занимался рекомендательными системами. Тогда был пик популярности Word2Vec — это модель, которая переводит слова в векторы и позволяет находить между ними смысловую близость. Я посмотрел на статистику и увидел: на одном из сайтов 25% запросов не давали результатов. Тут возникла идея, как это улучшить.<br /><br />Решил собрать демку и сделал прототип: например, на запрос «кресло из крокодиловой кожи» модель показывала зелёные кожаные кресла. Не крокодиловые, но всё равно релевантные запросу.<br /><br />За неделю допилил прототип до презентабельного состояния, показал коллегам и руководителю. Они дали «зелёный свет», через 2 месяца была первая MVP, которую уже начали продавать существующим клиентам. Ещё через месяц — первый клиент, интеграция, запуск.<br /><br />Спустя ~5 лет количество клиентов уже измерялось сотнями :)</blockquote><p><b>Подумайте, какие навыки хотите показать</b></p><p>Если делаете проект для портфолио, то можно выбрать несколько вакансий, на которые вы претендуете. Какие там требования к стеку, какие нужны навыки?</p><p>Например, если хотите работать фронтенд-разработчиком в онлайн-школе, то почему бы не сделать простое образовательное приложение на React и заточить его под себя? Смотрите, кого ищет рынок, и подстраивайтесь под его запросы.</p><p><b>Не затягивайте со сроками</b></p><p>Если рекрутер увидит, что вы полгода делали дизайн кнопки для сайта, то, скорее всего, подумает, что не умеете планировать работу и доводить проекты до конца.</p><p>Выбирайте несложный и интересный проект, который вы не затяните и который будет вам по силам.</p><blockquote>Основная ошибка — это незаконченные, «сырые» решения. HR смотрят на проекты, в том числе, как на способность завершать начатое. Если в портфолио много таких работ, это наводит на мысли, что разработчик быстро теряет интерес, плохо планирует время или бросает задачи при первых трудностях.</blockquote><p><b>Не используйте учебные работы, либо используйте их правильно</b></p><p>Многие онлайн-школы обещают готовое портфолио по окончании обучения, но оно обычно состоит из учебных проектов. В целом, это неплохо, но есть пара нюансов:</p><ol><li>У вас и ваших одногруппников эти работы одинаковые. Представьте лицо HR, когда он увидит несколько похожих проектов в разных резюме.</li><li>Учебные проекты не совсем ваши, ведь вы повторяли код и основные конструкции за преподавателями. Работодателю важно, как вы пишете сами, а не копируете.</li></ol><p>Следует разделять учебные проекты и пет-проекты. В первом случае вы осваиваете новые навыки и технологии, во втором стараетесь их показать. Выбрасывать работы с учёбы тоже не нужно, просто надо подумать, как их можно улучшить, какую фишку добавить, как переработать, чтобы отличиться от десятка таких же работ. Как пример, можно изменить фронтенд, добавить новую логику в бэкенд, разработать уникальную фичу.</p><h2>Всё равно не могу ничего придумать, что делать?</h2><p>Если самостоятельно не получается что-то придумать, то можно спросить у ИИ.</p><p>ChatGPT и другие языковые модели отлично умеют генерировать идеи на заданную тему. Часто в ответах появляются нестандартные, свежие задачи, которые вам бы и не пришли в голову. Даже если сгенерированные проекты кажутся банальными — всегда можно докрутить, добавить свою логику или фишку. Но используйте ИИ как вдохновителя, не просите его написать код проекта за вас — это будет заметно и станет не преимуществом, а «красным флагом».</p><p>Пример промпта для идеи пет-проекта:</p><p><b>Возьмите задачу с фриланса</b></p><p>Зайдите на любую фриланс-биржу и полистайте разделы с небольшими заказами. Часто там попадаются простые, но жизненные — например, сделать мини-сервис для бронирования столиков или инструмент для учёта личных трат. Никто не обязывает брать заказ — достаточно посмотреть, что нужно заказчикам, и сделать что-то подобное для портфолио.</p><p><b>Спросите друзей или аудиторию в соцсетях</b></p><p>Иногда самая классная идея приходит от окружения. Просто расскажите друзьям, что хотите сделать проект, и спросите, с какими неудобствами в жизни, работе или учёбе они сталкиваются. Кто-то устал вручную напоминать детям делать домашку — тут можно создать бота. Кто-то жалуется на путаницу в личных финансах — почему бы не собрать на эту тему простое приложение? Иногда полезные задачи всплывают и в тематических чатах или сообществах.</p><blockquote>У меня был разработчик, уставший от хаоса в списках фильмов, которые он хочет посмотреть. Сделал пет-проект — личный медиапланировщик с нейтральным UI. Проект не стал стартапом, но в портфолио смотрелся отлично. Если сложно — можно взять существующую идею и улучшить. Например, сделать привычный To do-лист с уклоном в UX, нейросети или интеграции. Главное — показать свою силу, а не сделать ещё один клон.</blockquote><h2>Как довести пет-проект до конца и не забросить его</h2><p>Вы выбрали идею для проекта, прикинули стек, сроки, пошли писать код и… забросили. Часто бывает, что вначале полны энтузиазма, а под конец либо ничего не получается, либо появляются мысли, что проект — пустая трата времени. Чтобы такого не было, лучше соблюдать следующие правила:</p><p><b>Чтобы сделать пет-проект, не делайте его.</b> По крайней мере, сразу. Мотивация — вещь непредсказуемая: сегодня идея кажется классной, а завтра — сущей ерундой. Не спешите сразу бросаться на проект, лучше дайте идее «настояться» неделю или две. Если прошло прилично времени, а руки всё ещё чешутся, то это хороший знак — за проект можно браться.</p><p><b>Определите для себя MVP</b> — минимальный рабочий продукт, который точно сможете довести до релиза. Всё, что не критично для запуска, сразу откладывайте, иначе перфекционизм и погоня за новыми фичами утащат вас на дно.</p><p>Например, если вы хотите сделать кроссплатформенный видеоплеер для изучения языков, то можно откинуть идею со встроенным ИИ, голосовым ассистентом и автоматической генерацией субтитров. Конечно, это всё здорово, но затягивает процесс. Простого перевода субтитров и автоматического создания карточек на первом этапе будет уже достаточно.</p><p><b>Разбейте проект на задачи и подзадачи.</b> Например, дизайн плеера, его вкладок, основная логика, подключение API, отладка.</p><p>Не забывайте отмечать выполненные задачи, когда мотивация вас покинет, у вас перед глазами будет уже какой-то прогресс, из-за которого жалко бросать работу на полпути.</p><p><b>Определитесь со сроками.</b> Пусть они будут примерными — главное, чтобы был ориентир. Например, дать себе месяц на MVP, неделю на запуск базовой версии, пару дней на исправление багов. Без сроков любая задача может растянуться, а когда есть конечная точка, появляется стимул не бросать начатое.</p><blockquote>Один из основных критериев — полезность продукта. Нет смысла изобретать велосипед. То, что вы создаёте, должно быть либо лучшего того, что уже есть, либо вообще уникальным. И тут не важно, в какой сфере вы решите это всё произвести, главное, чтобы было чёткое понимание, зачем это делается и какой будет итог. Проще говоря, без плана не нужно начинать, иначе велик риск всё забросить. Большая часть тех, кто начал и не закончил, как раз не прорабатывали свои идеи.</blockquote><p><b>Используйте знакомый стек.</b> Если этот проект нужен для портфолио, то лучше выбрать стек, в котором вы уже уверенно работаете. Иначе утонете в новом, не доведёте до конца, либо получите в итоге что-то непрезентабельное.</p><p>Конечно, это правило не абсолютное, использовать новые для вас технологии можно, просто это надо делать дозировано.</p><p>Если очень грубо, то ориентир выглядит так: 80% кода — это знакомый нам стек, 20% — место для экспериментов и обучения. Такой подход позволяет прокачать новые навыки и довести проект до финала без выгорания.</p><p><b>Занимайтесь регулярно по чуть-чуть.</b> Берегите себя, отдыхайте, не надо сидеть по 5 часов в день над проектом, если за него не платят. Вначале можно выезжать на мотивации, но со временем это приведёт к выгоранию.</p><p>Лучше постараться выработать привычку и заниматься петом, например, каждый день по 30 минут. Не можете соблюдать эту привычку по каким-то причинам? Не проблема, вместо 30 минут найдите 5. Да, за это время вы ничего не успеете, но сохраните «регулярность» —  на следующий день будет проще.</p><p><b>Делитесь результатами.</b> Не держите всё в столе, делитесь ходом работы и результатом. Покажите ваш MVP друзьям, обсудите его на форуме, заведите репозиторий на GitHub. Без обратной связи можно легко что-то упустить.</p><p>Аналогично с трудностями. Если сталкиваетесь с багами или просто чего-то не понимаете, то спрашивайте. В том же телеграм есть тематические чаты по пет-проектам, где можно запросить обратную связь.</p><p>А вот ещё несколько советов от Анастасии Егоровой — фронтенд-разработчика, автора  программы курса SkillBox по Vue 3 и ведущей ютуб-канала <a href="https://www.youtube.com/@CosyFrontendNastia">CosyFrontend</a>.</p><blockquote>Проблема пет-проектов в том, что их редко доводят до конца. Нет дедлайнов, нет ответственности перед руководством и коллегами, нет мотивации в виде будущей оплаты. Особенно сложно становится, когда пет-проект тянется уже не первую неделю, а первоначальная архитектура оказывается совсем неподходящей для дальнейшей разработки, что нередко бывает, когда мы пробуем новые технологии.<br /><br />У некоторых разработчиков количество таких заброшенных и недоделанных проектов — десятки штук. Что можно придумать для того, чтобы большинство ваших домашних проектов доводились бы до конца?<br /><br />1. Фиксировать прогресс, например, на доске Trello, чтобы самому видеть продвижение по проекту. Не забывать коммитить в гит. Некоторым разработчикам помогает отписываться о состоянии проекта в личный блог.<br /><br />2. Избегать перфекционизма — сначала сделать рабочую версию, а потом постепенно ее улучшать.<br /><br />3. Возвращаться без чувства вины — забросить проект может любой разработчик, у каждого из нас бывают авралы на работе, активности в жизни, выгорания, моменты прокрастинации.<br /><br />P.S. Когда мы обсуждали тему пет-проектов и их забрасывания в одном из айтишных чатов, один из разработчиков отметил: «А никак не нужно доводить их до конца — пет-проекты для того и существуют, чтобы попробовать на них новую идею и забросить». Так что такое мнение тоже есть, но справедливо ли оно для вас — решайте сами 😀</blockquote><h2>Как оформить пет-проект</h2><p>Для работодателя важен не столько масштаб проекта, сколько подход к работе, качество кода и умение доводить дело до конца, поэтому проект должен выглядеть презентабельно.</p><p><b>Поработайте над UI/UX.</b> Приятный и удобный интерфейс — ваш первый плюс в глазах работодателя. Потратьте время на то, чтобы кнопки, цвета и структура приложения были понятны с первого взгляда.</p><p>Чтобы убедиться, что пользователям удобно использовать сервис — запросите обратную связь у знакомых, коллег и родственников. Учтите их замечания.</p><p><b>Упакуйте проект в GitHub.</b> Если у вас пустой репозиторий, который называется my project, то проект никто не оценит. У HR большой поток откликов, иногда они принимают решение за пару секунд, поэтому очень важно, чтобы по вашему репозиторию как можно быстрее можно было понять, что вы сделали, как это работает и какие технологии вы использовали.</p><p>Сделайте подробное описание readme —  в паре абзацев расскажите, что это за проект, для кого, какие проблемы решает. Добавьте описание стека архитектуры. Чем подробнее, тем лучше.</p><p>Добавьте скриншоты, гифки, видео работы сервиса. А ещё лучше его демоверсию.</p><p>Постарайтесь проработать структуру проекта, чтобы она была логичной. В нём не должно быть дублей и мусора. Если кто-то впервые откроет ваш репозиторий, ему должно быть понятно, что это за проект.</p><p>То же самое с историей коммитов. Сделайте её читаемой с внятными комментариями, чтобы рекрутер видел не только ваш проект, но и процесс создания.</p><p>Опишите результаты  по конкретным метрикам, если, конечно, это возможно. Опубликовали приложение в Google play и получили хорошее удержание пользователей? Расскажите об этом. Вашу фичу оценили в социальных сетях? Поделитесь приятным фидбеком. Метрик нет, делали проект только под себя? Расскажите, как он помог вам решить проблему.</p><blockquote>Лучше всего оформить проект на GitHub с описанием задач, технологий и особенностей реализации. Выделяются разработчики, которые показывают, что не просто пишут код, но и обосновывают решение и объясняют, как всё устроено.<br /><br />Желательно, чтобы код был чистым, с продуманной архитектурой и, по возможности, прошёл ревью опытных коллег. Будет плюсом, если в проекте видно, что разработчик следит за качеством: пишет документацию и покрывает код тестами.</blockquote><p><b>Распишите проект как кейс.</b> Подготовьте шпаргалку. Это мини-история, где вы рассказываете о проекте. Какая проблема побудила вас его сделать, какие возникли трудности на этапе разработки, как их решали, какой получили результат. У вас получится подробное описание пути разработки от идеи до финала.</p><p>Это можно расписать в виде заметки, сделать пост в социальных сетях, опубликовать статью. Вы получите подробную шпаргалку, которую можно использовать для презентации проекта в портфолио или на собеседованиях.</p><p>Главное, не делайте проект ради проекта, старайтесь принести какую-то пользу и здраво оценивайте свои возможности.</p>]]></content:encoded>
    </item>
    <item>
      <title>Как эффективно дебажить баги</title>
      <link>https://tproger.ru/articles/kak-effektivno-debazhit-bagi</link>
      <comments>https://tproger.ru/articles/kak-effektivno-debazhit-bagi?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Baskon]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/kak-effektivno-debazhit-bagi</guid>
      <description><![CDATA[<p>В статье разбираем баг-трекеры, отладчики, логгеры, авто-тесты, профилировщики и статический анализ. Учимся быстро находить и устранять баги.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/kak-effektivno-debazhit-bagi">Как эффективно дебажить баги</a>»</p>]]></description>
      <category><![CDATA[Тестирование]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[Баги и ошибки]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Sun, 27 Jul 2025 12:00:03 GMT</pubDate>
      <content:encoded><![CDATA[<p>В 1947 году инженеры, работавшие с компьютером Mark II в Гарварде, сделали знаменитую запись в журнале: «First actual case of bug being found» («Первый реальный случай обнаружения жучка»). Причиной сбоя оказалась моль, застрявшая между контактами реле. Хотя сама фраза прижилась, концепция «жучков» (bugs) как причин неисправностей в машинах гораздо старше: ещё в 1878 году Томас Эдисон<a href="https://www.techinsider.ru/popmem/756223-kogda-byl-obnaruzhen-pervyy-v-mire-kompyuternyy-bag/"> жаловался</a> на них в своих телеграфных аппаратах.</p><p>Сегодня под «багами» понимают уже не насекомых, а любые ошибки в работе систем. Этот термин прочно вошёл в обиход, давно выйдя за пределы IT.</p><p>Ошибки в программах неизбежны, но ключ к качественной разработке — умение быстро их находить и исправлять. <a href="https://queue.acm.org/detail.cfm?id=3068754#:~:text=Software%20developers%20spend%2035,embrace%20debugging%20as%20an%20exercise">Исследования показывают</a>, что разработчики тратят 35–50% рабочего времени на тестирование и отладку, а эти этапы поглощают 50–75% бюджета проекта.</p><p>В этой статье мы разберем современные инструменты и подходы к поиску и устранению багов.</p><h2>1. Трекеры багов</h2><p>История инструментов для отслеживания ошибок уходит корнями в прошлое. Ещё в 1970-х разработчики Bugtraq в AT&amp;T Bell Labs использовали физические баг-тикеты, прикрепляя их к пробковым доскам. Знаковый скачок произошёл в 1998 году, когда Mozilla открыла доступ к первому веб-трекеру — Bugzilla. Дальнейшая эволюция привела к появлению Jira от Atlassian в 2002 году и прототипа Sentry на GitHub в 2008-м.</p><h3>Зачем нужен баг-трекер ?</h3><p>Исправление ошибки начинается с её фиксации. На небольшом проекте с одним разработчиком запомнить пару багов возможно. Но по мере роста числа дефектов ручное отслеживание становится неэффективным. Баг-трекер — это специализированная система, где для каждой ошибки создаётся запись (тикет, задача). В тикете должны быть ответы на самые важные вопросы:</p><ul><li>Что пошло не так?</li><li>Что должно было происходить?</li><li>Как вызвать ошибку?</li><li>Какой контекст у ошибки ?</li></ul><p>Баг-трекеров существует великое множество, ведь по сути это автоматизированные цифровые записные книжки. Баги можно отслеживать с помощью Jira, Redmine, Битрикса, Yandex Tracker, GitHub Issues, Sentry, BugHerd и др.</p><p>Баг-трекеры выбираются исходя из потребностей команды. В больших компаниях популярны решения внутри их корпоративного трекера; часто в open-source проектах баг-трекером для комьюнити выступает GitHub Issues, а в небольших командах таковым выступает закреп в чатах TG-группы.</p><p>Без баг-трекера сложно держать всё под контролем. Даже в маленькой команде со временем начинают теряться детали и приоритеты. Трекеры дают структуру, прозрачность и позволяют планомерно исправлять ошибки.</p><h2>2. Отладчики</h2><p>Отладчики (дебаггеры) — это специализированные программы, позволяющие исследовать и контролировать выполнение другой программы (целевой) с целью поиска и исправления ошибок. Их основной функционал — исполнить программу построчно с фиксацией состояния памяти после каждого шага.</p><p>Отладчики с графическим интерфейсом по умолчанию встроены во все популярные IDE. Там можно напрямую в коде поставить точку остановки, удобно смотреть значения переменных и стек вызовов. Хоть и когда-то роль отладчиков выполнялась с помощью ручки, тетрадки и собственной памяти.</p><p>Основная задача отладчика — это предоставить информацию о ходе выполнения программы.</p><h3>Как эффективно использовать ?</h3><h4>Сформулируйте гипотезу и не одну</h4><p>Подумайте, какую информацию вам нужно получить, предположите, с какой строчки ход исполнения идёт неверно.</p><h4>Расставьте точки останова для проверки гипотезы</h4><p>Поставьте точки останова непосредственно перед строчками с ошибкой, чтобы пропускать участки с кодом, в котором вы уверены, и который оттестирован.</p><h4>Идите по шагам и следите за переменными с неправильными значениями</h4><p>Используйте бинарный поиск для локализации ошибки: сначала поставьте точку останова в середине подозрительного участка, проверьте состояние данных. Если ошибка «левее» — переместите точку в середину левой половины, иначе — в правую. Повторяйте до победного.</p><h4>Меняйте значения переменных по ходу выполнения</h4><p>Во время паузы в отладчике (на точке останова/шаге) вы можете изменить значение любой переменной вручную → продолжить выполнение → мгновенно увидеть последствия без перезапуска программы. Это нужно, чтобы проверить гипотезу о том, как исправить найденный баг или найти краевые случаи.</p><p>Отладчик показывает, что происходит в программе «внутри», но польза от него только тогда, когда у тебя есть тактика поиска.</p><h2>3. Профилировщики</h2><p>Смысл профилировщиков в том, чтобы измерять производительность программы (время выполнения функций, использование памяти, CPU, дисковых операций, сети) для выявления узких мест и оптимизации. Основной смысл профилировщиков — поиск багов, связанных с производительностью.</p><h3>Как эффективно использовать ?</h3><h4>Определите метрики и точки измерения</h4><p>Подумайте и поймите, какой именно показатель у вас проблемный (тестировать загрузку CPU, искать утечку памяти, следить за нагрузкой на процессор) и какие процессы вам нужно контролировать.</p><h4>Воссоздайте проблемную ситуацию</h4><p>Загрузите своё ПО массивом данных, имитирующим по объёму целевой. Убедитесь, что профилированная нагрузка репрезентативна.</p><h4>Оцените вызываемую нагрузку</h4><p>Не пытайтесь оптимизировать всё сразу. Начните с 1–2 самых проблемных функций или процессов, дающих наибольший выигрыш. Используйте принцип Парето, т.е. сначала займитесь проблемами, у которых соотношение улучшение производительности/время на починку самое лучшее.</p><h4>Изучите алгоритмы и структуры данных</h4><p>Чтобы уметь исправлять боттлнекс, надо знать, как эффективно работать с данными, какие алгоритмы существуют и в каких ситуациях применимы. Даже небольшая база знаний в этой области значительно ускорит вам профилирование программ.</p><p>Профилировщик — инструмент, помогающий экономить ресурсы компьютера. С ним понятно, где есть проблемы и наибольшее тормоза, и можно не тратить время на оптимизацию того, что и так работает быстро или ни на что не влияет.</p><h2>4. Логгеры</h2><p>Логгеры — инструменты для записи информации (логов) о ходе выполнения программы в файлы или консоль. Их основная задача — предоставить детальную историю работы программы после её выполнения или в реальном времени. Это критично для мониторинга, аудита, анализа ошибок (особенно тех, что сложно воспроизвести в отладчике) и понимания поведения системы в различных условиях. Логи помогут сформулировать сценарии возникновения ошибки для её воспроизведения.</p><p>Как правило, это первый инструмент поиска ошибок у всех разработчиков, который они реализуют через функции типа print().</p><h3>Как эффективно использовать ?</h3><h4>Структурируйте логирование</h4><p>Распределите логи по типам. Например, вы можете отслеживать действия пользователей или фиксировать выполнение ключевых функций. Пишите логи разных типов в разные файлы и директории — вам потом будет проще в них копаться.</p><h4>Выстройте иерархию логирования</h4><p>Стандартная такая: DEBUG, INFO, WARN, ERROR, FATAL.</p><p>Иерархия нужна, чтобы быстрее понимать, когда всё идёт в бездну, и быстрее реагировать. Неочевидно, но также это нужно вам, чтобы расставить приоритеты событий, происходящих в ПО.</p><h4>Добавляйте в логи контекст</h4><p>Фиксируйте время, пользователей, состояние ПО и любую другую информацию, потому что иначе логи перестанут быть полезными и читаемыми. Ваша задача — вложить максимально полезной информации, чтобы можно было чётко восстановить последовательность событий.</p><h4>Думайте о производительности</h4><p>Помните предыдущий пункт, но не переборщите: логи не должны забивать вам всю систему. Если вы будете фиксировать выполнение каждой строчки и дату/время — перезагрузите всю систему, и ваше ПО просто перестанет работать. Помните: вывод в консоль или файл — это дорогая операция.</p><h4>Пользуйтесь ИИ</h4><p>Все современные популярные модели достаточно умны, чтобы проанализировать код и добавить в него логи. Главное — заранее объяснить ей стратегию логирования. Воспользуйтесь для этого Cursor, WindSurf, Codex и иными ИИ-ориентированными IDE, чтобы они знали контекст.</p><p>Хорошие логи способы заменить все прочие инструменты поиска багов, но также способны и засыпать читающего тонной ненужных данных, а заодно и растратить ресурсы компьютера.</p><h2>5. Авто-тесты</h2><p>Авто-тесты (автоматизированные тесты) — это программный код, написанный для проверки корректности работы другого кода (продукта) без ручного вмешательства. Их основная задача — быстро, надёжно и повторяемо верифицировать функциональность, предотвращать регрессии (появление старых ошибок при внесении изменений) и документировать ожидаемое поведение системы.</p><p>Даже если вы не тестировщик — пишите автотесты. Вы значительно сократите себе часы жизни на ручной проверке результатов. Чем больше проект, тем важнее писать автотесты, чтобы избежать фразы: «А раньше работало?».</p><p>Регрессионные авто-тесты помогают найти баги при их появлении, убить жучка в зародыше, чтобы это насекомое не въелось в ваш код и не отложило там яйца, плодя проблемы каскадом.</p><h3>Какие бывают тесты ?</h3><p>Небольшое введение в классификацию тестов, чтобы лучше понимать, что именно можно тестировать и что проверять.</p><h4>Модульные тесты (Unit Tests)</h4><p>Проверяют отдельные мельчайшие части кода (функции, методы, классы) в изоляции от зависимостей (которые заменяются заглушками). Нужны, чтобы проверить корректность логики отдельного компонента. Быстрые, дешёвые, дают мгновенную обратную связь.</p><h3>Интеграционные тесты (Integration Tests)</h3><p>Проверяют взаимодействие нескольких модулей, компонентов или систем (например, проверить доступность API или успешное чтение/запись в БД). Нужны, чтобы убедиться, правильно ли соединённые части работают вместе, а также выявить проблемы взаимодействия.</p><h4>Сквозные тесты (End-to-End / E2E Tests):</h4><p>Тестируют всю систему целиком с точки зрения пользователя, имитируя его действия в реальной среде (браузер, мобильное приложение). Воспроизводят сценарии использования, например, покупку товара или загрузку Excel-файла из БД. Нужны, чтобы проверить работоспособность всей системы. Могут быть очень затратны.</p><h3>Как эффективно использовать ?</h3><h4>Пишите тесты по принципам FIRST</h4><ul><li><b>Fast</b> – тесты должны быть быстрые, иначе замедлят разработку.</li><li><b>Independent </b>– тесты должны быть изолированы друг о друга, чтобы не падать, как домино.</li><li><b>Repeatable</b> – воспроизводимые, при одинаковых вводных давать одинаковый результат.</li><li><b>Self-Validating</b> – результат строго бинарный: успех/не успех.</li><li><b>Timely</b> – тест нужно писать заранее, чтобы сэкономить себе часы жизни в будущем, а не писать их после того, как тысячу раз рукам сам проверял, что всё ок.</li></ul><h4>Следуйте Пирамиде тестирования</h4><p>Тесты должны выполняться в порядке от простых и быстрых к наиболее сложным и долгим, так, чтобы 90% ошибок попадали в первые и быстрые тесты, экономя вам время в ожидании окончания тестирования.</p><h4>Следите за покрытием тестов</h4><p>Отслеживайте, насколько ваш код покрыт тестами — так, чтобы минимальным количеством тестов покрыть максимальное количество кода.</p><h4>Настройте CI/CD сами или попросите вашего DevOps</h4><p>Интегрируйте запуск тестов в процесс сборки (CI/CD-пайплайн). Тесты должны запускаться автоматически при каждом коммите и пулл-реквесте. Это же всё-таки АВТО тесты.</p><p>Даже если вы не тестировщик, то неработающие функции  исправлять придётся вам же.</p><h2>6. Статический анализ кода</h2><p>Статический анализ кода — это процесс автоматической проверки исходного кода без его выполнения. Инструменты статического анализа (линтеры, SAST — Static Application Security Testing) сканируют код, ищут потенциальные ошибки, уязвимости безопасности, нарушения стиля кодирования, сложные для понимания конструкции.</p><p>По умолчанию есть во всех популярных IDE.</p><h3>Как эффективно использовать ?</h3><h4>Изучите их</h4><p>Изучите, какие анализаторы кода бывают, зачем они нужны и как работают. После чего принимайте решение: нужны ли они вам в проекте или будут только замедлять процесс CI/CD.</p><p>Если вы новичок, то можете узнать для себя много нового — например, самые банальные ошибки вроде SQL-инъекций.</p><h4>Настройте их</h4><p>После того как разобрались в том, как они работают и зачем нужны, настройте инструменты статического анализа под ваши задачи. Тот же линтер без единых настроек форматирования для всех будет просто вреден для проекта.</p><h4>Запускайте их как авто-тесты</h4><p>Статическая проверка кода — это тоже набор тестов, только написанный не вами и тестирующий не то, как ваш код работает, а то, как он написан.</p><p>Статические анализаторы кода — специфичные инструменты отлова ошибок. В большинстве своём хитрый баг они не найдут, но надо понимать, что на данный момент лучший статический анализатор кода — это мозг разработчика.</p><h2>Итог</h2><p>Баги — неизбежные спутники разработки, но их цена растет как снежный ком с каждым этапом жизненного цикла ПО.</p><p>Эффективная отладка — это не искусство, а системный подход, опирающийся на правильные инструменты и методики. Используйте описанные выше инструменты и подходы, чтобы отлавливать баги, но главное, не оставляйте их на потом, тогда <a href="https://www.youtube.com/watch?v=mS9LCR5P5wI">ваш Гомер из будущего</a> скажет спасибо.</p>]]></content:encoded>
    </item>
    <item>
      <title>Вышел Python 3.14 RC1: релиз-кандидат с ускоренным интерпретатором. Финальный релиз — в октябре</title>
      <link>https://tproger.ru/news/--vywel-python-3-14-rc1--reliz-kandidat-s-uskorennym-interpretatorom--finalnyj-reliz---v-oktyabre</link>
      <comments>https://tproger.ru/news/--vywel-python-3-14-rc1--reliz-kandidat-s-uskorennym-interpretatorom--finalnyj-reliz---v-oktyabre?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Булат Яббаров]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/--vywel-python-3-14-rc1--reliz-kandidat-s-uskorennym-interpretatorom--finalnyj-reliz---v-oktyabre</guid>
      <description><![CDATA[<p>Вышел Python 3.14 RC1 с JIT-компилятором и free-threaded режимом — релиз уже доступен, финальная версия выйдет в октябре</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/--vywel-python-3-14-rc1--reliz-kandidat-s-uskorennym-interpretatorom--finalnyj-reliz---v-oktyabre">Вышел Python 3.14 RC1: релиз-кандидат с ускоренным интерпретатором. Финальный релиз — в октябре</a>»</p>]]></description>
      <category><![CDATA[Оптимизация]]></category>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[JSON]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[Windows]]></category>
      <category><![CDATA[Microsoft]]></category>
      <category><![CDATA[macOS]]></category>
      <category><![CDATA[Разработка]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 23 Jul 2025 07:32:03 GMT</pubDate>
      <content:encoded><![CDATA[<p>Команда Python <a href="https://pythoninsider.blogspot.com/2025/07/python-314-release-candidate-1-is-go.html">объявила</a> о выходе первой версии релиз-кандидата Python 3.14.</p><p>Это финальная стадия перед полноценным релизом, который запланирован на <b>7 октября 2025 года</b>. Версия 3.14.0rc1 уже <a href="https://www.python.org/downloads/release/python-3140rc1/">доступна</a> для загрузки на официальном сайте Python.</p><h2>Что важно знать</h2><p>Python 3.14 RC1 — это максимально приближенная к финалу сборка. Отныне в код ядра будут вноситься <b>только багфиксы</b>, прошедшие ревью. Следующий и последний релиз-кандидат — <b>3.14.0rc2</b> — выйдет 26 августа.</p><p>Важно: с этого момента <b>не будет изменений ABI</b>, а бинарные сборки, созданные под RC1, будут совместимы с финальной версией 3.14.</p><p>Разработчиков библиотек призывают начать адаптацию своих пакетов под 3.14 и публиковать .whl-сборки на PyPI.</p><h2>Главное в Python 3.14</h2><p>Список нововведений в 3.14 впечатляет — это не просто минорный апдейт. Вот ключевые фичи:</p><h2>Улучшения производительности и инфраструктуры</h2><ul><li><b>Экспериментальный JIT-компилятор</b> включён в официальные сборки для macOS и Windows.</li><li><b>Новый тип интерпретатора</b>, обеспечивающий ускорение кода (для некоторых компиляторов).</li><li><b>PEP 779: Free-threaded Python</b> — полная поддержка свободных потоков.</li><li><b>Улучшенные сообщения об ошибках</b>.</li><li><b>Оптимизация</b> генерации UUID v3–v5 (ускорение до 40%).</li></ul><h2>Новые языковые возможности и модули</h2><ul><li><b>PEP 750:</b> шаблонные строки t"..." — аналог f-строк, но для кастомной обработки.</li><li><b>PEP 649:</b> отложенное вычисление аннотаций типов.</li><li><b>PEP 765:</b> теперь return, break, continue нельзя использовать так, чтобы они покидали finally.</li><li><b>PEP 734:</b> изоляция интерпретаторов в stdlib.</li><li><b>Новый модуль</b> compression.zstd для поддержки алгоритма Zstandard.</li><li><b>Цветной вывод</b> в CLI-инструментах (unittest, argparse, json, calendar).</li><li><b>Обновление</b> uuid, pdb, поддержка подключения к удалённым процессам.</li></ul><h2>Разработка и отладка</h2><ul><li><b>PEP 768:</b> интерфейс внешней отладки без накладных расходов.</li><li><b>Новый CLI</b> для анализа запущенных Python-процессов.</li><li><b>HMAC теперь реализован внутри Python</b> с формально верифицированной библиотекой HACL*.</li></ul><h2>Что убрали или изменили</h2><ul><li>Подписи PGP для артефактов релиза больше не предоставляются. Вместо них — поддержка <b>Sigstore</b>.</li><li>Установщик для Windows заменяется новым <b>Python Install Manager</b> (доступен в Microsoft Store).</li></ul><p>Внимание: несмотря на стабильность RC1, использовать его в продакшене пока не рекомендуется. Но для тестов и подготовки библиотек — самое время.</p>]]></content:encoded>
    </item>
    <item>
      <title>Что еще есть в терминале Linux: 7 команд, которые экономят кучу времени</title>
      <link>https://tproger.ru/articles/chto-eshhe-est-v-terminale-linux--7-komand--kotorye-ekonomyat-kuchu-vremeni</link>
      <comments>https://tproger.ru/articles/chto-eshhe-est-v-terminale-linux--7-komand--kotorye-ekonomyat-kuchu-vremeni?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Вадим Егорцев]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/chto-eshhe-est-v-terminale-linux--7-komand--kotorye-ekonomyat-kuchu-vremeni</guid>
      <description><![CDATA[<p>Семь советов для ускорения работы в терминале Linux. Как быстро обработать файлы, отладить Bash-скрипт и редактировать длинные пути в Линукс.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/chto-eshhe-est-v-terminale-linux--7-komand--kotorye-ekonomyat-kuchu-vremeni">Что еще есть в терминале Linux: 7 команд, которые экономят кучу времени</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Linux]]></category>
      <category><![CDATA[Оптимизация]]></category>
      <category><![CDATA[JSON]]></category>
      <category><![CDATA[MySQL]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[Регулярные выражения]]></category>
      <category><![CDATA[Google]]></category>
      <category><![CDATA[SQL]]></category>
      <category><![CDATA[Работа]]></category>
      <category><![CDATA[Tor]]></category>
      <category><![CDATA[Боты]]></category>
      <category><![CDATA[Docker]]></category>
      <category><![CDATA[QA]]></category>
      <category><![CDATA[1C]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 22 Jul 2025 14:00:03 GMT</pubDate>
      <content:encoded><![CDATA[<p><b>Сколько статей про «полезные команды Linux» вы уже прочитали?</b> Алиасы, history, базовые горячие клавиши — факты для джунов, которые опытным админам уже снятся. Если свободно пользуетесь grep и awk, создаете циклы, применяете регулярные выражения — эта статья для вас.</p><p>Рассказываем про 7 команд, влияющие на скорость работы в терминале. Вы узнаете:</p><ul><li>про встроенные bash-операции, которые заменяют пайплайны,</li><li>про способы работы с файловыми дескрипторами,</li><li>про wildcards, которые избавляют от сложных конструкций с find.</li></ul><p>Каждая команда в подборке решает конкретную проблему:</p><ul><li>массовая обработка файлов,</li><li>отладка скриптов,</li><li>работа с длинными путями.</li></ul><h2>1. Bash variable expansions</h2><figure><img src="https://media.tproger.ru/user-uploads/105601/2025-07-10/b5f2b475-b18e-49cb-a00c-9197ab87b9f4.jpg" alt="" /></figure><p>Вместо <i>basename</i>, <i>cut </i>для простых операций со строками можно использовать встроенные возможности Bash:</p><p><b>%</b> режет справа до первого совпадения, <b>%%</b> — до последнего. Символ <b>#</b> работает слева направо.</p><p>В реальной работе это помогает при массовой обработке файлов. Например, есть 1000 логов, и нужно каждый переименовать.</p><p>Если использовать <i>basename</i>, запустится 1000 отдельных процессов. <b>Variable expansions</b> работают без <i>fork/exec</i>, без задержек на создание процессов.</p><p>Bash variable expansions используют в циклах с файлами и при работе с массивами. Когда скрипт обрабатывает сотни файлов, разница в скорости становится заметной. Еще и код выглядит чище.</p><h2>2. Here-string (&lt;&lt;&lt;)</h2><figure><img src="https://media.tproger.ru/user-uploads/105601/2025-07-10/ef72e05d-6f80-49aa-842b-32c209d8b724.jpg" alt="" /></figure><p>Here-string упрощает передачу строковых данных в команды без создания временных файлов или использования echo с пайпом.</p><p>Реальная экономия времени проявляется при отладке и модификации скриптов. Например, когда SQL-запрос или конфигурация зашиты в <i>here-документ</i>. С <b>here-string </b>данные собраны в одном месте, легко редактируются и переиспользуются.</p><p>Работает не только с базами данных. Отправка в API, конфигурирование сетевых устройств через expect, передача команд в Docker — через &lt;&lt;&lt; код будет понятнее, а сопровождение проще.</p><h2>3. /proc/$$/fd</h2><figure><img src="https://media.tproger.ru/user-uploads/105601/2025-07-10/f314de69-9459-4ecb-ab62-2c7b5c7b54f3.jpg" alt="" /></figure><p>Каждый процесс имеет стандартные дескрипторы <b>0</b> (stdin), <b>1</b> (stdout), <b>2</b> (stderr), которые представлены как символические ссылки. Директория <b>/proc/$$/fd </b>предоставляет доступ к файловым дескрипторам текущего процесса:</p><p>Переменная <b>$$</b> содержит PID текущего процесса, поэтому /proc/$$/fd ведет к дескрипторам именно вашего шелла.</p><p>Практическое применение — отладка перенаправлений и работа с дескрипторами в сложных скриптах:</p><h2>4. Wildcards с диапазонами</h2><figure><img src="https://media.tproger.ru/user-uploads/105601/2025-07-10/08dbc2a0-5e2e-49a3-9486-a042a0480369.jpg" alt="" /></figure><p>Про <b>*</b> и <b>?</b> говорят чаще, чем про диапазоны в квадратных скобках. Такие маски используют реже, а зря — они решают массу задач по отбору файлов.</p><p>Wildcards автоматически раскрываются шеллом в список подходящих файлов — это их основная функция. Кавычки нужны только когда передаете символы [, ] как литеральные:</p><p>Экономия времени заметна при работе с логами, бэкапами и в скриптах автоматизации. Например, для архивации файлов с определенными номерами, очистки временных файлов с нужными паттернами.</p><h2>5. sudo !!</h2><figure><img src="https://media.tproger.ru/user-uploads/105601/2025-07-10/9434c945-925f-40b3-9062-994fce2091c6.jpg" alt="" /></figure><p>Набрали длинную команду, нажали Enter, получили «<b>Permission denied</b>». Рука на рефлексе тянется к стрелке вверх и Home, чтобы добавить sudo в начало.</p><p>Вот способ в разы быстрее:</p><p>Двойное восклицание <b>!!</b> — это ссылка на предыдущую команду целиком. Bash подставит всю строку со всеми аргументами и ключами. Кажется мелочью, но для админа, который 10 раз в день забывает sudo, это серьезная оптимизация.</p><p>Двойное восклицание универсально и работает не только с sudo:</p><ul><li><b>time !!</b> для замера времени выполнения,</li><li><b>nohup !! &amp;</b> для запуска в фоне,</li><li><b>strace !!</b> для отладки.</li></ul><p>Если между командой и sudo !! выполнялись другие команды, восклицание сработает для последней из них. Для поиска конкретной команды в истории используйте <b>!строка</b>.</p><h2>6. ^старое^новое</h2><figure><img src="https://media.tproger.ru/user-uploads/105601/2025-07-10/1888b625-8ae5-4d0e-a73d-25260ff7d893.jpg" alt="" /></figure><p>Основной способ исправления опечатки — стрелка вверх, поиск ошибки, исправление. Смотрите, как можно сделать это побыстрее:</p><p>Символ <b>^</b> ищет первое вхождение слова и заменяет его. Работает с последней командой.</p><p>Заменяется только первое вхождение. Если ошибочное слово встречается несколько раз, способ не сработает. В таких случаях придется использовать классическое редактирование или <i>history expansion</i>.</p><h2>7. Alt+.</h2><figure><img src="https://media.tproger.ru/user-uploads/105601/2025-07-10/4d1c03bb-66b2-4cb0-8c3e-ce80c3406ec5.jpg" alt="" /></figure><p>Создали файл с длинным именем — теперь его нужно отредактировать, переместить, изменить права. Каждый раз перепечатывать путь утомительно и чревато ошибками.</p><p>Комбинация <b>Alt+.</b> (Alt + точка) вставляет последний аргумент предыдущей команды в текущую позицию курсора. Повторное нажатие перебирает аргументы из более ранних команд.</p><p>Экономия времени проявляется при работе с файлами и директориями. Например: распаковали архив, теперь нужно зайти в созданную папку, затем посмотреть содержимое, потом изменить права. Вместо того, чтобы 3 раза печатать один путь, можно 3 раза нажать Alt+.</p><p>Еще этой комбинацией вставляются:</p><ul><li>имена пользователей,</li><li>IP-адреса,</li><li>названия сервисов,</li><li>параметры конфигурации.</li></ul><p>Alt + точка работает в большинстве шеллов. Привыкнув к ней, начинаешь использовать на автомате.</p><h2>Что запомнить</h2><ul><li><b>${filename%.*} </b>и встроенные операции со строками работают быстрее внешних утилит. % режет справа, # — слева. Полезно при работе с циклами для массовой обработки файлов.</li><li><b>&lt;&lt;&lt;</b> — here-string удобен для передачи коротких строковых данных в команды. С многострочными данными лучше использовать here-document или переменные.</li><li><b>/proc/$$/fd</b> — доступ к файловым дескрипторам текущего процесса. Ускоряет отладку перенаправлений и работу с дескрипторами.</li><li><b>file[1-5] и [^b]* </b>— диапазоны в wildcards для точного отбора файлов. Кавычки нужны только для передачи литеральных символов.</li><li><b>sudo !!</b> — повторяет последнюю команду с sudo. Также работает с time !!, nohup !! &amp;. Если между нужной командой и !! выполнялись другие операции, используйте !строка для поиска конкретной команды в истории.</li><li><b>^старое^новое</b> — заменяет первое вхождение в предыдущей команде. Работает только с последней командой и заменяет первое совпадение.</li><li><b>Alt+. </b>— вставляет последний аргумент предыдущей команды. Повторное нажатие перебирает аргументы из истории команд. Экономит время при работе с длинными путями.</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>10 библиотек Python, которые меняют карьеру</title>
      <link>https://tproger.ru/articles/10-bibliotek-python--kotorye-menyayut-kareru</link>
      <comments>https://tproger.ru/articles/10-bibliotek-python--kotorye-menyayut-kareru?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Татьяна Жукова]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/10-bibliotek-python--kotorye-menyayut-kareru</guid>
      <description><![CDATA[<p>10 библиотек Python, которые помогут прокачаться в аналитике, ML и разработке. Как они работают и почему меняют карьеру.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/10-bibliotek-python--kotorye-menyayut-kareru">10 библиотек Python, которые меняют карьеру</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Тестирование]]></category>
      <category><![CDATA[Парсинг]]></category>
      <category><![CDATA[Инструменты]]></category>
      <category><![CDATA[Производительность]]></category>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[JSON]]></category>
      <category><![CDATA[MySQL]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[Нейронные сети]]></category>
      <category><![CDATA[Искусственный интеллект]]></category>
      <category><![CDATA[SQL]]></category>
      <category><![CDATA[DevOps]]></category>
      <category><![CDATA[Работа]]></category>
      <category><![CDATA[Базы данных]]></category>
      <category><![CDATA[Навыки]]></category>
      <category><![CDATA[Django]]></category>
      <category><![CDATA[Сервисы]]></category>
      <category><![CDATA[Jupyter Notebook]]></category>
      <category><![CDATA[Визуализация]]></category>
      <category><![CDATA[Образование]]></category>
      <category><![CDATA[OpenAI]]></category>
      <category><![CDATA[Анализ данных]]></category>
      <category><![CDATA[Бэкенд]]></category>
      <category><![CDATA[Аналитика]]></category>
      <category><![CDATA[Библиотеки]]></category>
      <category><![CDATA[аналитик]]></category>
      <category><![CDATA[PostgreSQL]]></category>
      <category><![CDATA[Бизнес]]></category>
      <category><![CDATA[Разработка]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 17 Jul 2025 14:00:03 GMT</pubDate>
      <content:encoded><![CDATA[<p>У Python тысячи библиотек, но лишь немногие действительно меняют карьеру. Они помогают не просто решать задачи, а ускорять проекты, прокачивать навыки и выходить на следующий уровень в аналитике, машинном обучении и разработке. В этом материале мы собрали 10 библиотек, которые помогут зарабатывать на Python и развивать навыки.</p><h2>1. Pandas</h2><p>Pandas — библиотека для работы с данными в Python, позволяющая легко загружать, анализировать, очищать и преобразовывать числовую информацию в удобной табличной форме. По сути, это Excel, который смог, и позволяет делать всё автоматизировано и на порядки быстрее.</p><p>Библиотека строится вокруг двух ключевых структур: <b>Series</b> (одномерный массив с индексами); <b>DataFrame </b>(таблица с индексами и колонками).</p><h3>Какие задачи решает библиотека</h3><p>Pandas полезна для следующих задач:</p><ul><li>Сам анализ данных: можно быстро фильтровать, группировать, агрегировать и строить сводные таблицы.</li><li>Очистка данных: удаляем пустые строки, заменяем значения, приводим типы.</li><li>Загрузка данных из CSV, Excel, SQL.</li><li>Визуальная разведка данных (EDA) перед построением моделей.</li><li>Подготовка данных для ML и отчётов.</li><li>Автоматизация отчётов и ETL-пайплайнов.</li></ul><p>Благодаря Pandas аналитик превращается в инженера данных, а ML-специалист может сосредоточиться на моделях, а не на ручной подготовке датасетов.</p><h3>Как пользоваться</h3><p>Ниже разберём простейший кейс: нужно загрузить данные о зарплатах разработчиков из CSV, посчитать среднюю зарплату по языкам программирования и отобрать топ-5.</p><h3>Почему это меняет карьеру</h3><p>Работа с Pandas становится границей между знанием Python и умением решать задачи бизнеса. Для <b>джуна </b>это шанс сразу показать практическую пользу: выгрузки, отчёты и базовый анализ можно делать в десятки раз быстрее и аккуратнее, чем вручную в эксельке.</p><p>Для <b>аналитика</b> Pandas превращается в главный рабочий инструмент, позволяя не просто проверять гипотезы и делать сводные таблицы, а строить полноценные отчётные пайплайны, автоматизировать рутинные выгрузки и концентрироваться на сути данных, а не на правках ручками.</p><p>Для <b>ML-инженера</b> владеть Pandas — значит уметь готовить датасеты качественно; быстро очищать и приводить данные к нужному виду, что напрямую влияет на результат моделей. Без этого работа над проектами машинного обучения часто превращается в бесконечную возню с данными.</p><p>Наконец, даже для <b>разработчиков</b> Pandas может стать неожиданным бустом в карьере. Например, когда нужно автоматизировать отчёты для бизнеса или быстро анализировать логи и данные из БД без поднятия дашбордов — Pandas даёт гибкость и скорость, которые редко даёт что-то ещё в экосистеме Python.</p><h2>2. Django</h2><p>Django — фреймворк для веб-разработки на Python, который позволяет быстро создавать надежные и масштабируемые веб-приложения. Он следует принципам DRY (Don’t Repeat Yourself — не повторяй себя), предоставляя разработчику ORM, роутинг, систему авторизации, админку, работу с формами, шаблонами и инструментами безопасности из коробки.</p><p>Django подходит как стартапам, которым нужно быстро выйти на рынок, так и крупным проектам с миллионами пользователей. Это не просто библиотека, а полноценный каркас для построения и сопровождения веб-сервисов.</p><h3>Какие задачи решает библиотека</h3><p>Каркас, действительно, каркасный. Задачи следующие:</p><ul><li>Создание веб-приложений и API любой сложности.</li><li>Быстрая разработка MVP, прототипов и коммерческих проектов.</li><li>Упрощение работы с базами данных через ORM, без написания сырого SQL.</li><li>Построение административных панелей для управления данными без ручной разработки.</li><li>Гибкая маршрутизация и работа с формами, валидацией и шаблонами.</li><li>Реализация аутентификации, авторизации и защиты приложений.</li></ul><p>Django позволяет сосредоточиться на бизнес-логике и продукте, не тратить недели на настройку инфраструктуры.</p><h3>Как пользоваться</h3><p>Устанавливаем:</p><p>Создаем проект и приложение:</p><p>Пример модели:</p><p>Миграция базы данных:</p><p>Создание админки:</p><p>После этого можно запустить сервер:</p><p>И перейти по адресу http://127.0.0.1:8000/admin для управления записями через готовую админ-панель.</p><h2>3. PyTorch</h2><p>PyTorch — мощная библиотека Python. Она позволяет строить и обучать нейронные сети, проводить вычисления с автоматическим дифференцированием и работать с GPU для ускорения самих вычислений.</p><p>Главное отличие PyTorch от других ML-фреймворков — динамическая вычислительная графика (define-by-run): модель строится и изменяется во время выполнения кода, что даёт гибкость при создании и отладке сложных моделей.</p><p>Сегодня PyTorch используется в продакшен системах, научных исследованиях, компьютерном зрении, NLP и генеративных моделях, занимая ведущее место в индустрии.</p><h3>Какие задачи решает библиотека</h3><p>В функционал PyTorch входят:</p><ul><li>Построение нейронных сетей любой сложности (CNN, RNN, трансформеры);</li><li>Обучение и тестирование моделей на CPU и GPU;</li><li>Реализация кастомных слоёв и loss-функций;</li><li>Разработка и деплой ML/AI моделей в продакшен;</li><li>Быстрая итерация гипотез с удобной отладкой.</li></ul><p>С PyTorch можно начать с простых нейронных сетей, а затем перейти к реализации современных архитектур.</p><h3>Как пользоваться</h3><p>Установим PyTorch (на CPU, для GPU потребуется версия с CUDA):</p><p>Рассмотрим кейс обучения простой нейронной сети для классификации рукописных цифр MNIST.</p><p>После обучения можно использовать torch.save() для сохранения модели и torch.load() для загрузки в продакшн.</p><h3>Почему это меняет карьеру</h3><p>PyTorch — билет в мир современной разработки AI и машинного обучения. Владение инструментом даёт <b>разработчику</b> возможность уверенно войти в области, которые продолжают оставаться топовыми на рынке: искусственный интеллект, компьютерное зрение, NLP, генерация изображений и видео и т.д.</p><p>Для <b>начинающего ML/AI-специалиста </b>PyTorch помогает лучше понять, как устроены нейронные сети, и под капотом увидеть, как происходят вычисления. Это ускоряет рост навыков и делает разработчика востребованным в исследованиях и R&amp;D-проектах.</p><p>Для <b>дата-сайентистов</b> PyTorch позволяет превратить исследовательские ноутбуки в готовые к деплою модели, благодаря PyTorch Lightning, TorchScript и ONNX.</p><p>Для<b> разработчиков, которые хотят выйти на рынок AI</b>, PyTorch — это мастхев: проекты в стартапах и крупных компаниях всё чаще строятся вокруг него. Умение писать кастомные loss-функции, проектировать сложные пайплайны обучения, настраивать обучение на кластерах и GPU — компетенции, которые существенно бустят зарплату.</p><p>PyTorch в целом помогает расширять портфолио: с ним можно создавать генеративные модели, строить LLM, участвовать в соревнованиях и работать с самыми современными подходами в машинном обучении.</p><h2>4. Polars</h2><p>Polars — современная библиотека для обработки данных в Python, созданная как альтернатива Pandas. Она использует колоночную архитектуру и многопоточность, что позволяет работать с большими объёмами данных значительно быстрее и с меньшим потреблением памяти.</p><p>Polars вдохновлена Pandas, но её API оптимизировано для производительности и удобства, а также даёт разработчику возможность писать цепочки ленивых вычислений, которые оптимизируются перед выполнением. Это делает её отличным инструментом для аналитиков, дата-инженеров и дата-сайентистов, которым нужно обрабатывать данные быстро.</p><h3>Какие задачи решает библиотека</h3><p>Polars явно есть, чем гордиться:</p><ul><li>Загрузка, очистка и преобразование больших датасетов;</li><li>Анализ данных с использованием цепочек преобразований;</li><li>Быстрая агрегация и группировка данных;</li><li>Ленивые вычисления: построение пайплайнов преобразования данных, которые выполняются только при вызове collect().</li><li>Обработка данных, которые не помещаются в память, за счёт эффективности и колоночной архитектуры.</li></ul><p>Если Pandas начинает притормаживаться на данных в несколько гигабайт, Polars обычно продолжает работать быстро, позволяя без боли обрабатывать большие CSV.</p><h3>Как пользоваться</h3><p>Установка:</p><p>Давайте загрузим данные и проведем базовые трансформации:</p><p>А вот и пример ленивых вычислений:</p><p>В чем особенность:</p><ul><li>pl.read_csv загружает данные сразу.</li><li>pl.scan_csv создаёт план вычислений для последующей оптимизации.</li><li>Используются выражения (pl.col, .with_columns, .agg), которые композируются без создания промежуточных копий, это ускоряет процесс.</li></ul><h3>Почему это меняет карьеру</h3><p>Polars меняет карьеру, потому что даёт преимущество в скорости и эффективности при работе с данными. Там, где Pandas уже не справляется, полярный медведь приходит на помощь.</p><p>Для <b>дата-инженеров</b> Polars полезен при построении ETL и пайплайнов обработки данных, где важна скорость и предсказуемое потребление ресурсов. Его можно использовать в продакшен-скриптах, для подготовки данных к ML и для автоматизации отчётности.</p><p>Для <b>дата-сайентистов </b>Polars даёт возможность анализировать больше данных за меньшее время, быстро итерировать гипотезы и ускорять исследования. Его API достаточно близок к Pandas, поэтому переход не требует месяцев переучивания.</p><p>Освоение Polars показывает работодателям, что ты не просто знаешь стандартные инструменты, но умеешь выбирать оптимальные решения для реальных задач, повышая эффективность работы команды. В эпоху роста данных это критично для любого Python-разработчика, работающего с аналитикой и машинным обучением.</p><h2>5. FastAPI</h2><p>FastAPI — современный фреймворк для создания API на Python, заточенный под скорость, асинхронность и валидацию данных из коробки. Он построен на Starlette и Pydantic, автоматически создаёт OpenAPI-документацию, поддерживает асинхронное программирование и позволяет писать производительные REST и WebSocket API с минимальным количеством кода.</p><p>Вместо долгой настройки, как у Flask или Django, в FastAPI многое готово изначально: удобная работа с запросами и ответами, декларативная валидация, документация Swagger, асинхронность и высокая производительность без лишних усилий.</p><h3>Какие задачи решает</h3><p>Задач, действительно, много:</p><ul><li>Быстрая разработка REST API для мобильных и веб-приложений;</li><li>Создание бэкенда для ML/DS моделей (деплой моделей в виде API);</li><li>Построение микросервисов с хорошей производительностью;</li><li>Реализация websocket-серверов и асинхронных API;</li><li>Подготовка внутренних инструментов или бэкендов для MVP.</li></ul><p>FastAPI помогает быстро запускать API и уверенно масштабировать его в полевых условиях. Это один из немногих фреймворков Python, который по скорости работы сопоставим с Node.js и Go.</p><h3>Как пользоваться</h3><p>Во-первых, нужно установить FastAPI и Uvicorn (используем ASGI-сервер для запуска):</p><p>Простейший API-пример с эндпоинтом GET /:</p><p>Запускаем сам сервер:</p><p>После запуска API будет доступен по адресу http://127.0.0.1:8000/. Автоматически доступна интерактивная документация Swagger по адресу http://127.0.0.1:8000/docs.</p><p>FastAPI поддерживает валидацию параметров запроса, тел запросов и путей прямо через типы Python. Например, простой эндпоинт с параметром:</p><p>При вызове http://127.0.0.1:8000/items/10?q=test FastAPI автоматически проверит, что item_id — это число, и распарсит q как строку.</p><h3>Почему это меняет карьеру</h3><p>FastAPI — билет в мир бэкенда, где скорость и чистота кода имеют довольно высокое значение. Для <b>Python-разработчика </b>это возможность быстро освоить создание API и микросервисов, не увязнув в громоздкой настройке, как в Django, и при этом получить систему, готовую к продакшену.</p><p>Для <b>ML-специалиста</b> FastAPI становится инструментом для деплоя моделей: можно обернуть пайплайн предсказаний в API, подключить авторизацию или логирование и получить работающий сервис за считанные дни.</p><p>Вообще умение быстро поднимать и поддерживать API — навык, который ценят в бигтехе и стартапах. На разработчиков, которые владеют FastAPI, часто равняются: они умеют превращать идеи бизнеса в работающие сервисы за минимальное время.</p><h2>6. Typer</h2><p>Typer — современная библиотека для создания CLI-приложений на Python с минимальным количеством кода и автоматической генерацией документации. Автор библиотеки — Себастьян Рамирес, создатель FastAPI.</p><p>Главная особенность Typer — использование type hints для автоматического парсинга аргументов командной строки. Вы получаете удобную и читаемую CLI с поддержкой автодополнения и цветного вывода за считанные минуты.</p><h3>Какие задачи решает библиотека</h3><p>Список задач такой:</p><ul><li>Создание CLI-утилит любого уровня сложности.</li><li>Быстрое прототипирование и упаковка Python-скриптов в удобные инструменты для продакшена.</li><li>Генерация подробной справки (--help) и автодополнения команд.</li><li>Облегченная поддержка и масштабирование CLI за счёт структуры и читаемого кода.</li><li>Организация CLI с подкомандами, вложенными аргументами и обработкой ошибок.</li></ul><p>Typer использует аннотацию типов и минимум шаблонного кода.</p><h3>Как пользоваться</h3><p>Установка:</p><p>Пример минимальной CLI:</p><p>Теперь можно запустить из консоли:</p><p>Результат будет такой: Привет, Алиса! Тебе 25 лет.</p><h3>Почему это меняет карьеру</h3><p>Typer меняет карьеру тем, что открывает путь к созданию удобных CLI-инструментов, которые автоматизируют рутину и повышают продуктивность.</p><p>С Typer можно быстро превращать свои Python-скрипты в надежные утилиты, которыми удобно пользоваться и другим разработчикам, и сотрудникам из других отделов. CLI-приложения часто становятся клеем инфраструктуры: они позволяют автоматизировать деплой, миграции БД, сбор данных, интеграцию с внешними API и локальную разработку.</p><p>Если вы <b>Data Scientist или ML-инженер</b>, Typer позволяет оборачивать пайплайны в CLI, которые легко запускать из Jenkins, Airflow или вручную. Если вы <b>DevOps или Backend-инженер</b>, можете создавать CLI для работы с инфраструктурой и сервисами без сложных зависимостей.</p><p>Кроме того, работа с Typer улучшает навык структурирования кода, понимание CLI, использования type hints и разработки инструментов, которые делают работу проще для других. А это, очевидно, ценится в любой команде и повышает востребованность специалиста.</p><h2>7. Rich</h2><p>Rich — библиотека Python для красивого форматирования и интерактивного отображения информации в терминале. С её помощью можно выводить цветные таблицы, маркдаун, прогресс-бары, подсвеченный синтаксис кода, деревья каталогов и логирование в понятной и привлекательной форме.</p><p>Rich создана для того, чтобы «оживить» консоль Python, сделать логи удобными для восприятия, а CLI-инструменты — профессионально выглядящими без лишних усилий. Это библиотека, которая улучшает и UX, и DX.</p><h3>Какие задачи решает</h3><p>Про красоту не забываем! Задачи следующие:</p><ul><li>Цветное и структурированное логирование, понятное при чтении логов в реальном времени.</li><li>Отображение прогресс-баров для долгих операций.</li><li>Вывод таблиц, деревьев каталогов, JSON прямо в терминале.</li><li>Подсветка синтаксиса кода для CLI-инструментов.</li><li>Создание CLI-интерфейсов, которые выглядят профессионально и современно.</li><li>Улучшение читаемости при отладке скриптов.</li></ul><p>С помощью Rich можно быстро сделать понятными даже сложные данные при отладке или демонстрации.</p><h3>Как пользоваться</h3><p>Установка Rich:</p><p>Для примера выведем таблицу с подсветкой в консоли:</p><p>В результате в терминале получится цветная таблица, которая выглядит понятно и презентабельно.</p><h3>Почему это меняет карьеру</h3><p>Rich — это библиотека, которая помогает быстро повысить качество любого CLI-инструмента или дев-опыт в команде. <b>Разработчик</b>, который использует Rich, делает свои инструменты удобными не только для себя, но и для коллег: логирование становится понятным, а отладка скриптов — наглядной.</p><p>Во многих стартапах и продвинутых командах важна скорость обратной связи при тестировании пайплайнов и автоматизаций, и Rich помогает выводить ключевую информацию максимально читаемо.</p><p>Кроме того, Rich позволяет быстро создавать CLI-интерфейсы, которые выглядят как продакшен-продукты, даже если это внутренние инструменты. Руководство будет радоваться и думать о вас как о крутом разрабе.</p><p>Для <b>дата-инженеров и разработчиков DevOps</b> Rich полезна при создании админ-утилит и при мониторинге пайплайнов, для <b>Python-разработчиков</b> — при создании библиотек и фреймворков с CLI.</p><h2>8. LangChain</h2><p>LangChain — фреймворк для создания приложений на базе LLM, например, GPT, Claude, Mistral, Gemini. Он позволяет строить цепочки обработки запросов, интегрировать LLM с данными и инструментами, добавлять память и управление состояниями, а также связывать работу модели с внешними API и базами знаний.</p><p>LangChain предоставляет удобный слой абстракции над вызовами LLM и ускоряет разработку чат-ботов, RAG-приложений, агентов с инструментами, систем анализа документов и других AI-сервисов.</p><h3>Какие задачи решает</h3><p>Список внушительный:</p><ul><li>Интеграция LLM в Python-приложения без необходимости писать тот самый клеевой код вручную.</li><li>Построение цепочек с последовательной обработкой сообщений, включая преобразования и вызовы внешних функций.</li><li>Добавление памяти в чат-боты для сохранения истории общения и контекста.</li><li>Использование агентов для динамического вызова инструментов (веб-поиск, базы данных, API).</li><li>Создание RAG-систем с интеграцией LLM и векторных БД.</li><li>Быстрая сборка прототипов LLM-приложений, которые можно развернуть в продакшен.</li></ul><h3>Как пользоваться</h3><p>Установка:</p><p>Создадим простую цепочку с чатом GPT:</p><p>Благодаря единым абстракциям, можно гибко комбинировать цепочки, память и вызов внешних инструментов, не усложняя код.</p><h3>Почему это меняет карьеру</h3><p>LangChain меняет карьеру, потому что открывает новый пласт Python-разработки в AI и LLM-инженерии, быстро превращая пользователя GPT в создателя полноценных AI-приложений. Вместо того чтобы писать хаотичный клеевой код, вы начинаете системно проектировать цепочки запросов, учитесь строить продуманные промпты и объединять их с инструментами, памятью и внешними API.</p><p>Работа с LangChain погружает в практическую LLM-инженерию: вы начинаете создавать RAG-приложения, которые умеют искать и анализировать данные перед генерацией ответа и строить агентов. Это востребовано в продуктах, где нужно подключать ИИ к базам знаний, автоматизировать задачи и разрабатывать интерактивные системы, которые реально используют модели в продакшене.</p><p>LangChain позволяет быстро собирать и запускать MVP AI-продуктов, что дает конкурентное преимущество при создании стартапов или внутренних сервисов. А ещё учит мыслить структурами и проектировать масштабируемую архитектуру LLM-приложений и видеть, как генеративный ИИ можно превратить в рабочий инструмент.</p><h2>9. SQLAlchemy</h2><p>SQLAlchemy — это мощная ORM и toolkit для работы с базами данных в Python, позволяющая писать SQL-запросы декларативно, создавать модели таблиц и управлять транзакциями в Python-коде без ручного написания SQL.</p><p>Библиотека даёт разработчику два уровня контроля:</p><ul><li>Core: низкоуровневая работа с SQL выражениями и соединениями;</li><li>ORM: высокоуровневая декларативная работа с моделями, классами и связями между таблицами.</li></ul><p>SQLAlchemy поддерживает PostgreSQL, MySQL, SQLite, Oracle и другие СУБД, давая единую абстракцию, без привязки к конкретному движку.</p><h3>Какие задачи решает</h3><p>Пул задач следующий:</p><ul><li>Описание таблиц в виде Python-классов и управление ими через сессии;</li><li>Создание, чтение, обновление и удаление данных;</li><li>Миграция SQL на декларативный стиль без потери гибкости;</li><li>Полный контроль над транзакциями и выполнением запросов;</li><li>Работа с асинхронными приложениями при создании FastAPI/Django-приложений;</li><li>Экранирование параметров, которое снижает вероятность SQL-инъекций и ошибок.</li></ul><h3>Как пользоваться</h3><p>Создадим минимальный пример для SQLite с таблицей пользователей:</p><p>Этот код создаёт базу example.db, таблицу users, добавляет туда одного пользователя и выводит всех пользователей в базе. При необходимости можно использовать SQLAlchemy Core для написания гибких запросов вручную, если нужно работать ближе к SQL.</p><h3>Почему это меняет карьеру</h3><p>SQLAlchemy меняет карьеру <b>Python-разработчика</b> тем, что даёт понимание системной работы с данными, архитектуры приложений и взаимодействия с реальными базами данных. Вы учитесь строить продуманные бэкенды, которые работают с транзакциями, миграциями, связями между таблицами и сложными выборками.</p><p>Знание SQLAlchemy открывает дорогу в мир API, микросервисов и продуктов, где требуется качественное управление данными и гибкая логика работы с БД. Работа с SQL теперь совсем не страшная.</p><h2>10. Seaborn</h2><p>Seaborn — библиотека для визуализации данных на Python, построенная поверх Matplotlib и упрощающая создание информативных и стильных графиков с минимальным количеством кода.</p><p>Она автоматически заботится о красивых стилях, цветах, разметке графиков, легендах и позволяет легко строить распределения, линейные графики, тепловые карты и другие визуализации.</p><p>Библиотека тесно интегрируется с Pandas DataFrame, позволяя использовать колонки данных напрямую для построения графиков, что делает её идеальной для EDA (разведочного анализа данных) и подготовки визуализаций для отчётов и презентаций.</p><h2>Какие задачи решает</h2><p>Визуализация безумно важна, особенно в контексте дата-аналитики. Seaborn отвечает за:</p><ul><li>Быстрое построение информативных графиков для анализа данных и поиска инсайтов;</li><li>Автоматическую обработку ошибок отображения и масштабирования, что экономит время;</li><li>Поддержку сложных визуализаций по типу ящиков с усами или тепловых карт без десятков строк кода;</li><li>Стилизацию графиков без ручных настроек Matplotlib;</li><li>Возможность добавлять статистические элементы (линию регрессии, KDE, распределение);</li><li>Интеграцию с Jupyter Notebook для интерактивного анализа данных.</li></ul><h3>Как пользоваться</h3><p>Допустим, у нас есть датасет с данными о чаевых:</p><p>В три строки мы получаем чистый и читаемый ящик с усами, показывающий, как счет за ужин распределяется по дням недели.</p><p>Для построения более сложных графиков можно использовать диаграмму рассеяния:</p><p>Тут мы добавляем цветовую кодировку по полу, чтобы увидеть зависимости между переменными.</p><h3>Почему это меняет карьеру</h3><p>Seaborn меняет карьеру, потому что даёт навык визуального анализа данных, что критично в современной аналитике и дата-инженерии. Умение быстро строить графики и видеть аномалии, распределения и взаимосвязи между переменными превращает работу с данными из слепого копания в числах в структурный анализ.</p><p>Использование Seaborn в Python-стеке помогает выделиться среди разработчиков, которые ограничиваются Pandas и текстовыми логами, ведь визуализация часто позволяет быстрее заметить закономерности и убедить команду или заказчика в правильности гипотезы.</p><p>Seaborn также учит пониманию данных через визуальные паттерны, что улучшает навыки построения моделей машинного обучения (так понятнее, какие признаки важны), и помогает создавать наглядные отчёты для продуктовых решений, где результат анализа нужно доносить до людей не из айти-индустрии.</p><p><i>А какими библиотеками пользуетесь вы? Делитесь в комментариях!</i></p>]]></content:encoded>
    </item>
    <item>
      <title>5 инструментов, которые используют айтишные команды</title>
      <link>https://tproger.ru/articles/5-instrumentov--kotorye-ispolzuyut-ajtiwnye-komandy</link>
      <comments>https://tproger.ru/articles/5-instrumentov--kotorye-ispolzuyut-ajtiwnye-komandy?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Анна Ельцова]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/5-instrumentov--kotorye-ispolzuyut-ajtiwnye-komandy</guid>
      <description><![CDATA[<p>Показываем, какими инструментами пользуются внутри айтишных команд и какие можно использовать для себя здесь и сейчас или внедрить в свою команду.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/5-instrumentov--kotorye-ispolzuyut-ajtiwnye-komandy">5 инструментов, которые используют айтишные команды</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[C++]]></category>
      <category><![CDATA[Инструменты]]></category>
      <category><![CDATA[Git]]></category>
      <category><![CDATA[Статистика]]></category>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[Микросервисы]]></category>
      <category><![CDATA[Ruby]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[IDE]]></category>
      <category><![CDATA[SQL]]></category>
      <category><![CDATA[Windows]]></category>
      <category><![CDATA[DevOps]]></category>
      <category><![CDATA[Ruby on Rails]]></category>
      <category><![CDATA[GitHub]]></category>
      <category><![CDATA[TypeScript]]></category>
      <category><![CDATA[Сервисы]]></category>
      <category><![CDATA[React]]></category>
      <category><![CDATA[Docker]]></category>
      <category><![CDATA[Adobe]]></category>
      <category><![CDATA[Redis]]></category>
      <category><![CDATA[Маркетинг]]></category>
      <category><![CDATA[QA]]></category>
      <category><![CDATA[Аналитика]]></category>
      <category><![CDATA[Приложение]]></category>
      <category><![CDATA[Kubernetes]]></category>
      <category><![CDATA[PostgreSQL]]></category>
      <category><![CDATA[Grafana]]></category>
      <category><![CDATA[Бизнес]]></category>
      <category><![CDATA[CI/CD]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 26 Jun 2025 14:00:03 GMT</pubDate>
      <content:encoded><![CDATA[<p>В статье собрали 5 решений — от трекеров задач и онлайн-досок до комплексных платформ для управления проектами. Инструменты помогут закрывать горящие дедлайны, ускорять разработку и четко распределять задачи — все то, что используют в больших командах. Рассказываем, что делать с этими фичами и как их использовать.</p><h2>1. МояДоска</h2><p><a href="https://moyadoska.com/">«МояДоска»</a> — это российский SaaS-сервис для совместной работы и визуализации идей. У онлайн-доски бесконечный размер: это значит, что вы можете размещать сколько угодно элементов и никогда не упретесь в границу. Так, команды, преподаватели и креативные специалисты могут проводить брейнштормы, планирования, презентации и обучение в одном пространстве.</p><figure><img src="https://media.tproger.ru/user-uploads/101078/2025-06-26/4fe2215f-6b29-4d0c-a490-281b2d045ddc.jpeg" alt="" /></figure><h3>Что под капотом</h3><p>Фронт написан на React + PixiJS, а бэк — Node.js + PostgreSQL. Это обеспечивает быстрый и понятный интерфейс и стабильную работу даже при большом объёме объектов на доске. Команда выпускает обновления несколько раз в месяц, а о новинках можно узнать в <a href="https://t.me/moyadoska">Telegram-канале</a> сервиса. Например, в недавнем апдейте появилась возможность превратить фрейм в таблицу или тетрадь за пару кликов, а еще задать нужное число столбцов, колонок, толщину границ и цвет.</p><figure><img src="https://media.tproger.ru/user-uploads/101078/2025-06-26/0f1a8489-ffe3-4003-8ecc-09d25bbba3b3.png" alt="" /></figure><p><b>Из главных функций:</b></p><ul><li>Понятный интерфейс</li><li>Совместная работа в реальном времени</li><li>Привычные инструменты: фигуры, стрелки, стикеры, текст, загрузка файлов, маркер, карандаш</li><li>Обрезка фото прямо на доске, воспроизведение аудио, поддержка PDF</li><li>Гибкое управление доступом</li><li>Возможность повторного использования шаблонов</li><li>Поддержка фреймов и создание логичных пространств для разных задач</li></ul><figure><img src="https://media.tproger.ru/user-uploads/101078/2025-06-26/21a6ecbd-a6b5-40c9-ae19-71a85b919c46.png" alt="" /></figure><h3>Переезд на сервис</h3><p>«МояДоска» интегрируется в процессы на разных этапах, упрощая жизнь команде. Например, сама команда сервиса перешла с Miro на свою доску для стратегического планирования. С помощью стикеров и стрелок они построили дерево решений, чтобы лучше расставить приоритеты. А одно маркетинговое агентство перевело все документы и сессии планирования на доску, отказавшись от Google Docs и таблиц. Это ускорило принятие решений: сотрудники работали с данными в одном формате, точно собрались в одном кабинете перед маркерной доской.</p><h2>2. METEOR</h2><p><a href="https://u-meteor.ru">METEOR</a> — инструмент управления проектами. Это трекер задач с дашбордами, досками канбан, диаграммами Ганта и API, который работает в виде веб-приложения как в облаке, так и на своих серверах. Продукт создавался как универсальный центр управления задачами: он объединяет в себе все — от разработки и тестирования до маркетинга и поддержки. Сейчас его используют более 250 команд и свыше 2000 пользователей ежедневно.</p><h3>Что под капотом</h3><p>В основе — стек Ruby on Rails, React и TypeScript, PostgreSQL и Redis, плюс современная инфраструктура на Docker и Kubernetes.</p><p>Система разбита на микросервисы — за фоновую обработку, нотификации и работу с файлами отвечает отдельный функционал. Авторизация построена через OAuth 2.0 (Google, Yandex), а для аналитики используется Posthog и ELK-стек. Мониторинг реализован на Prometheus + Grafana. Обновления выходят каждую неделю, а обратная связь приходит разработчикам METEOR через Telegram-бот.</p><p><b>Вот главные функции:</b></p><ul><li>Гибкие доски задач (Kanban, Scrum) — 6 видов.</li><li>Списки задач с группировками и иерархией.</li><li>Автоматические отчеты (ежедневные/еженедельные сводки).</li><li>Умные напоминания (Telegram-бот, email).</li><li>Глубокая аналитика (время выполнения задач, загрузка команды).</li><li>Потоковая автоматизация процессов</li></ul><figure><img src="https://media.tproger.ru/user-uploads/101078/2025-06-26/60e0eb0a-c1b1-473b-b343-1c4fb1b3fbd6.png" alt="" /><figcaption>Упрощенная схема сущностей системы</figcaption></figure><p>METEOR — мощный инструмент для автоматизации процессов, с триггерами, серверными функциями и ИИ-аналитикой. Он позволяет гибко настраивать сложные операции.</p><p>Все данные анализируются, и внутри самого сервиса можно понять, как работает команда: кто загружен, сколько времени уходит на задачи, где стопперы в процессе.</p><p>Разработчики используют METEOR для линковки задач с pull-requests и контроля бэклога. Менеджеры получают отчеты автоматически и не тратят часы, чтобы собрать всю информацию вручную. QA ведут тест-кейсы и баги в удобных досках, а DevOps отслеживают инциденты и шаги деплоя. Даже HR подключаются — через систему проходят кандидаты и стажеры.</p><h3>Переезд на сервис</h3><p>После внедрения METEOR команды замечают, что продуктивность их работы сильно повышается:</p><ul><li>скорость выполнения задач увеличивается в среднем на 25% — благодаря автоматическим напоминаниям и чётким процессам;</li><li>количество потерянных задач снижается на 70% — исчезают хаотичные чаты и забытые письма;</li><li>на составление отчетов и сбор метрик уходит не 5 часов, а всего 30 минут в неделю;</li><li>а экономия времени — около 75 часов в месяц на команду из 10 человек.</li></ul><figure><img src="https://media.tproger.ru/user-uploads/101078/2025-06-26/f3f086f0-5846-4a35-adba-dc4fbe17f1c0.png" alt="" /><figcaption>Карточка задачи</figcaption></figure><p>METEOR не просто помогает контролировать задачи — он становится частью операционного «ядра» команды, избавляя от хаоса, ускоряя работу и делая все немного спокойнее.</p><h2>3. Gitlife</h2><p><a href="https://gitlife.ru">GitLife</a> — это универсальная платформа для хостинга репозиториев и построения полного DevOps-процесса внутри компании. Разработана с прицелом на закрытые контуры, импортозамещение и гибкость — подходит как для современных Git-проектов, так и для инфраструктур, где все еще используется SVN.</p><p>Помимо самого Gitlife, разработчики делают Gitlife AI, в котором есть доступ к топовым ИИ-моделям и инструментам, чтобы разрабатывать ИИ-решения.</p><h3>Что под капотом</h3><p>Внутри Gitlife собраны модули для:</p><ul><li>Кода — репозитории, ветвление.</li><li>Задач — бэклоги, спринты, дашборды.</li><li>Документации — совместное редактирование документов, управление правами.</li><li>Аналитики — карты потока ценности, качество кода, метрики по инженерам.</li><li>Пайплайны — модуль «Конвейер» управляет сборками и CI/CD.</li></ul><p>Gitlife используется ИТ-отделами и R&amp;D-подразделениями в компаниях с высокими требованиями к информационной безопасности. Подходит как для небольших команд, так и для распределённых корпораций с десятками проектов.</p><p>Что решает:</p><ul><li>Безопасный и полностью локальный хостинг исходного кода (Git + SVN)</li><li>Управление задачами и CI/CD в одном месте</li><li>Централизованный доступ, права, аудиты и история изменений</li><li>Полная поддержка DevOps-процессов на российском ПО</li><li>Альтернатива GitHub, GitLab и Bitbucket в условиях ограниченного доступа и санкционных рисков</li></ul><figure><img src="https://media.tproger.ru/user-uploads/101078/2025-06-26/bb3f815f-ce07-4c9d-9243-7ace4b14d5ba.png" alt="" /><figcaption>Создание пайплайна</figcaption></figure><h3>Переезд на сервис</h3><p>Инструмент подходит практически всем командам — от инди-разработчиков до крупных проектов с множеством ролей. Например, гейм-девелопер может разрабатывать персональный проект и хранить код бесплатно, стартап — разрабатывать MVP, а крупный бизнес — управлять большими командами и проектами максимально безопасно.</p><h2>4. Cerebro</h2><p><a href="https://cerebrohq.com/ru/">Cerebro</a> — профессиональная система для совместной работы и управления проектами. Она помогает ставить задачи, планировать этапы, следить за выполнением, обмениваться файлами и комментировать их прямо в системе. Особенно полезна для команд, которые делают VFX, 3D, анимацию или дизайн — но при этом легко адаптируется и под другие команды.</p><p>Платформа охватывает полный цикл — от первых идей и планирования до комментирования финальных шотов (отдельных сцен или кадров в видео/анимации) и соблюдения дедлайнов. Такой подход помогает команде ускорить работу на 20%, сократить время на правки и держать весь процесс под контролем — от начала до сдачи проекта.</p><p>Cerebro подходит для команд от 1 до 1000+ человек с задачами на проекте от 1 до 10000+. Сервис работает с 2009 года, сейчас им пользуются более 400 команд в России и СНГ.</p><h3>Что под капотом</h3><p>Cerebro поддерживает десктоп (Windows, Mac и Linux), веб-версию и мобильное приложение, локальное, облачное и гибридное развертывание. Инструмент построен на клиент-серверной архитектуре — она гибкая, поэтому можно настраивать конфиги исходя из потребностей бизнеса.</p><p>Из технологий:</p><ul><li><b>Backend:</b> C, C++, Python, SQL</li><li><b>Frontend:</b> JS, TypeScript, ReactJS, Qt, PyQt</li><li><b>Мобильные клиенты:</b> React Native</li><li><b>БД: </b>PostgreSQL с проприетарными расширениями + SQLite</li><li><b>Файловое хранилище:</b> Cargador</li><li><b>Плагины: </b>Tentaculo (встраивается в производственные программы)</li></ul><figure><img src="https://media.tproger.ru/user-uploads/101078/2025-06-26/d51c709f-2b9c-4e0b-95c0-2b78d61f5c1e.png" alt="" /></figure><p>Cerebro покрывает весь пайплайн — от идеи до финала. Вот основные возможности сервиса:</p><ul><li>Множественные уровни вложенности задач — подходит для сложных иерархий продакшена</li><li>Планирование с помощью диаграммы Ганта и специального инструмента «План»</li><li>Канбан-доска для визуального контроля задач</li><li>Инструмент «Моё пространство» — для персонализированной фильтрации и отбора задач</li><li>Уровни доступа и ролевое управление</li><li>Расширенная статистика по проектам, командам, сотрудникам</li><li>Совместная работа над большими файлами (видео, изображения, 3D) — Mirada позволяет комментировать, делать подрисовки, оставлять голосовые заметки</li><li>Интеграция с пакетами Adobe, Autodesk и мессенджерами, возможность встраивать в любые пайплайны</li><li>Удобное подключение фрилансеров</li></ul><figure><img src="https://media.tproger.ru/user-uploads/101078/2025-06-26/5411ad9d-a74b-46ed-9774-61d60ff69885.png" alt="" /><figcaption>Навигатор и форум</figcaption></figure><h3>Переезд на сервис</h3><p>Обычно внедрение начинается еще на этапе препродакшена — во время разработки концепции и четкого плана действий. Затем система сопровождает проект на всех стадиях, вплоть до постпродакшена (финального тестирования и релиза), где она закрывает 80-100% задач. Cerebro позволяет собирать всё в одном месте: задачи, правки, сроки, бюджеты, загрузку сотрудников и статус проекта в целом.</p><p>После переезда снимается много рутинных задач: больше не нужно вручную назначать исполнителей, комментировать медиаконтент, передавать файлы между программами и так далее. В среднем проекты выполняются на 20% быстрее, без потери качества. В больших студиях объем выпускаемых шотов может вырасти до 20+ тысяч — это уже работает у других клиентов, среди которых СберМаркетинг, Sinners, Black Point и другие. Cerebro также помогает переехать с других такс-трекеров и систем для управления проектами.</p><h2>5. Replit Teams</h2><p><a href="https://replit.com/teams">Replit Teams</a> — это платформа для совместной разработки в реальном времени. По сути, это интегрированная IDE + git-репозиторий + система управления задачами — и все доступно через браузер. Подходит как для командной работы в стартапах, так и для образовательных проектов, хакатонов и небольших продуктовых команд.</p><p>А главная фишка — встроенный ИИ, к которому можно обращаться прямо во время написания кода. Инструмент разработан с акцентом на простоту входа, командную работу и быстрое прототипирование. Поддерживает более 50 языков программирования и позволяет запускать полноценные веб-приложения в облаке.</p><figure><img src="https://media.tproger.ru/user-uploads/101078/2025-06-26/70b00e25-9ec7-4858-911c-b2d7a181104e.png" alt="" /></figure><h3>Что под капотом</h3><p>Внутри Replit Teams есть интерфейсы для:</p><ul><li>Кода — редактор с автокомплитом, подсветкой синтаксиса, терминалом и интеграцией с Git.</li><li>Задач — встроенный таск-менеджер с распределением задач по участникам.</li><li>Общения — встроенные комментарии в коде, возможность ревью и обсуждений.</li><li>CI/DevOps — запуск и отладка приложений без настройки окружения.</li><li>Доступа — гибкие роли, приглашения по ссылке, настройки приватности.</li></ul><h3>Переезд на сервис</h3><p>Replit Teams позволяет моментально начать работу: не нужно ставить зависимости, конфигурировать CI или закупать сервера. Подходит как для быстрой прокачки навыков, так и для реальных командных проектов в продакшене.</p><p>Сейчас инструмент активно используют в стартапах — для быстрого MVP, парного программирования, хакатонов и удаленных командах — как замена локальным IDE и конфигурациям.</p><p>Рассказывайте в комментариях, какими сервисами пользуетесь вы.</p>]]></content:encoded>
    </item>
    <item>
      <title>Как TanStack Query ускоряет работу с API и сокращает код</title>
      <link>https://tproger.ru/articles/kak-tanstack-query-uskoryaet-rabotu-s-api-i-sokrashhaet-kod</link>
      <comments>https://tproger.ru/articles/kak-tanstack-query-uskoryaet-rabotu-s-api-i-sokrashhaet-kod?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Дмитрий Скляр]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/kak-tanstack-query-uskoryaet-rabotu-s-api-i-sokrashhaet-kod</guid>
      <description><![CDATA[<p>Использование TanStack Query дает разработчикам возможность упростить работу с API, сократить дублирование кода и ускорить разработку. Рассказываем о проблемах, связанных с использованием API, и соответствующих решениях для повышения эффективности разработки.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/kak-tanstack-query-uskoryaet-rabotu-s-api-i-sokrashhaet-kod">Как TanStack Query ускоряет работу с API и сокращает код</a>»</p>]]></description>
      <category><![CDATA[Интернет]]></category>
      <category><![CDATA[API]]></category>
      <category><![CDATA[JavaScript]]></category>
      <category><![CDATA[Парсинг]]></category>
      <category><![CDATA[Инструменты]]></category>
      <category><![CDATA[JSON]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[GitHub]]></category>
      <category><![CDATA[TypeScript]]></category>
      <category><![CDATA[React]]></category>
      <category><![CDATA[Redux]]></category>
      <category><![CDATA[Xen]]></category>
      <category><![CDATA[Фронтенд]]></category>
      <category><![CDATA[Бэкенд]]></category>
      <category><![CDATA[Сервер]]></category>
      <category><![CDATA[Бизнес]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 28 May 2025 14:00:04 GMT</pubDate>
      <content:encoded><![CDATA[<p><i>Представьте: вы — фронтенд-разработчик, и постоянно сталкиваетесь с рядом проблем. Еще один endpoint, еще один запрос, еще десяток строк почти идентичного кода. Вручную прописываете типы, парсите ответы, обрабатываете ошибки, обновляете кэш… А через неделю бэкенд-команда меняет API — и все, что вы строили, рассыпается как карточный домик.</i></p><p><i>Так случалось, пока не появились инструменты вроде <a href="https://tanstack.com/query/latest">TanStack Query</a> и не родились «обертки», которые уменьшают объемы рутины. Как перестать тонуть в запросах на разработку API и начать дышать свободно, рассказывает Дмитрий Скляр, старший разработчик компании Axenix. </i></p><h2>API: нервная система цифрового мира</h2><p>В современном ИТ-ландшафте API давно перестал быть просто техническим термином. Теперь он — один из столпов, на котором держится цифровая цивилизация.</p><p>Философия современной разработки давно сместилась от принципа «сделай все сам» к парадигме «собери из лучших компонентов». API стал языком, на котором взаимодействуют цифровые сервисы. Он превратил ИТ-ландшафты и интернет из собрания разрозненных приложений и сайтов в единую живую экосистему, где каждый элемент может взаимодействовать с другим.</p><p>Когда разработчик использует API картографического сервиса, ему не нужно разбираться в геоданных или алгоритмах прокладки маршрутов — он просто отправляет запрос и получает готовое решение. Это похоже на то, как мы пользуемся электричеством: не нужно понимать, как работает электростанция, чтобы включить свет в комнате.</p><p>Но настоящую революцию API совершил в бизнесе, создав целые экосистемы цифровых услуг. Такие компании, как Stripe, Twilio или Plaid построили свои империи именно на API, предоставляя другим разработчикам готовые «кирпичики» для создания финансовых, коммуникационных или аналитических сервисов.</p><p>Внутри крупных компаний API выступают в роли «дипломатов» между микросервисами и ИТ-системами, позволяя разным командам работать независимо, но при этом сохранять общую согласованность. Когда маркетинговая система запрашивает данные о продажах, а сервис логистики получает информацию о новых заказах — все это происходит через четко определенные API-контракты, которые делают сложные системы управляемыми и гибкими.</p><h2>Боль, которую никто не замечает</h2><p>Но не все так просто и далеко не так радужно.</p><p>Да, формально API — это универсальный мост, например, между фронтендом и бэкендом. На практике же он часто напоминает шаткую подвесную конструкцию: данные приходят в разном формате, документация устаревает еще до релиза, а поля user_name и username существуют одновременно просто потому, что «исторически сложилось».</p><p>Типичный сценарий: вы пишете код для запроса списка товаров, все типизируя и описывая модели — 50 строк. Добавляете фильтрацию — еще 30 строк. А через месяц бэкенд меняет структуру ответа, забывает предупредить — и вы тратите день на поиск багов в трех разных местах.  И самое обидное: 80% этого кода — копипаст. Проверка ошибок, трансформация данных, инвалидация кэша — все одно и то же, но плодится как вирусы.</p><p>Сюда можно добавить также сложность поддержки — API меняется, код устаревает.</p><p>Другой момент: код для каждого API-метода имеет схожую структуру. Повторяются основные шаблоны, а различия лишь в типах данных и отдельных деталях. Чем больше API-методов, тем сложнее отслеживать изменения в коде и поддерживать его в актуальном состоянии.</p><p>В итоге — дублирование кода, которое усложняет приложение, снижает его читаемость и замедляет разработку новых функций. Документация? Либо устарела, либо ее вообще не писали.</p><h2>Спасение — в системе</h2><p>Однажды наши разработчики устали писать однотипные хуки, чинить сломанные запросы и объяснять новичкам, что где находится, почему именно так это работает и почему нельзя просто взять и использовать что-то другое. Устали писать однотипный код для каждого запроса, захотели минимизировать ошибки и ускорить разработку, а также сделать работу с API более структурированной и понятной. Также у команд назрела потребность в скорейшем включении в проект новых разработчиков. Для всех этих задач подходит одно решение: унифицированный подход к API, который также наводит порядок в данных и отчетах, упрощая аналитику и логику приложения.</p><p>Тогда и родилась идея фабрики API — слоя абстракции, который скрывает рутину. Для этого мы привлекли возможности <a href="https://tanstack.com/query/latest">TanStack Query</a>, семейство библиотек для управления состоянием данных (data fetching) в клиентских приложениях. Помимо <a href="https://tanstack.com/query/latest">TanStack Query (ранее React Query)</a>, к этому классу инструментов также относятся: RTK Query (из Redux Toolkit), Apollo Client (для GraphQL) и SWR.</p><p>Их общая философия: «делать рутину невидимой для разработчика». Рассмотрим Конкретные проблемы и их решения.</p><h3>Однотипные хуки для каждого запроса</h3><p>В большинстве проектов без дополнительной абстракции каждый хук под API-запрос пишется вручную. Меняется только URL и параметры, а структура остаётся одинаковой: queryKey, queryFn, опции запроса. Это быстро приводит к копипасту, дублированию логики и усложнению поддержки.</p><p>Например, для каждого ресурса вроде пользователей, продуктов, заказов и т.д. приходится повторять одну и ту же конструкцию. Если нужно изменить поведение запроса (например, добавить retry или staleTime), правки необходимо делать в десятках мест.</p><p><b>Решение: Универсальная обёртка над хуками TanStack Query</b></p><p>Создание единой функции-генератора для хуков позволяет избавиться от повторяющегося кода. Она принимает ключ, функцию запроса и опциональные параметры — и возвращает сразу «пачку» готовых хуков.</p><p>Такой подход:</p><ul><li>снижает количество шаблонного кода;</li><li>упрощает масштабирование;</li><li>централизует поведение всех запросов;</li><li>позволяет быстро адаптироваться к изменениям (например, добавить логирование, типизацию, трансформации и т.п.).</li></ul><h3>Хрупкость при изменении API</h3><p>В типичном приложении без централизованной трансформации мы напрямую используем ответ от бэкенда. Любое изменение формата требует правок в типах, в местах использования данных, и часто приводит к багам.</p><p><b>Решение: Централизованная трансформация данных +</b> <a href="https://github.com/typestack/class-transformer">class-transformer</a>.</p><p>С помощью <a href="https://github.com/typestack/class-transformer">class-transformer</a> можно объявить классы сущностей и задать правила преобразования один раз.</p><p>Плюсы:</p><ul><li>Все данные автоматически приходят в нужном виде;</li><li>Компоненты работают с гарантированно типизированными данными;</li><li>Один источник правды: при изменении API – правим только Entity-класс;</li><li>Удобно масштабируется, особенно если API большое и сложное.</li></ul><h3>«Мусор» в данных и отчётах</h3><p><b>Решение: Валидация данных при трансформации (например, через class-validator); автоматическая синхронизация кеша (актуальные данные во всём приложении).</b></p><p>Почему это лучше ручного подхода? Смотрите: строк кода на 1 endpoint при ручном управлении <b>потребуется 30+</b>, а <b>с фабрикой —  5-10</b>. Времени для добавления нового поля —  1<b> час вручную, с фабрикой —  5 минут</b>. Количество мест для правки при изменении API —  вручную их много, с фабрикой — лишь одно.</p><p>Реальный кейс: в проекте с 50+ endpoint’ами переход на фабрику <b>сократил код на 70%</b>. Разработчики перестают быть «переводчиками» между API и интерфейсами сервисов и приложений, а сосредотачиваются на бизнес-логике. Как сказал один тимлид: <i>«Теперь мы не фиксим баги данных, а делаем фичи, которые нравятся пользователям»</i>.</p><p>Еще пример: вместо пяти отдельных хуков для CRUD-операций фабрика дает одну функцию createApi(). Вместо ручного парсинга — автоматическую трансформацию данных через <a href="https://github.com/typestack/class-transformer">class-transformer</a>. А главное — единые правила игры для всего проекта.</p><p>Как это работает? Представьте, что вы говорите системе: «Вот endpoint для товаров, вот их модель данных, вот правила валидации» —  а все остальное она делает за вас. Хотите получить товар по ID? Пишете useGetByIDQuery. Нужно обновить? —   useUpdatetMutation. И никакого шаманства с ручным описанием каждого хука.</p><p>Но главное — когда бэкенд меняет API, правки нужны только в одном месте. А новые разработчики перестают спрашивать: <i>«Почему у нас три разных способа загрузить список пользователей?»</i>.</p><h2>Как договориться и не сойти с ума</h2><p>Проблема в том, что без четкого контракта, набора правил и подходов фронтенд- и бэкенд-разработчики живут в параллельных реальностях. Один думает, что данные придут в camelCase, другой шлет их в snake_case. Один ожидает массив, другой неожиданно подсовывает null. Итог —  бесконечные баги, исправления «на живую» и испорченные нервы.</p><p>Решение? Четкий контракт. Простой, прозрачный, однозначный. В нем должны быть:</p><ol><li>Единые правила именования — если бэкенд отдает snake_case, фронтенд не должен гадать, будут ли остальные поля в camelCase, или, например, если в одной модели данных full_name , в другой не будет fullname и так далее.</li><li>Единый формат запросов и ответов.</li><li>Договоренности о структуре URL, формате данных и кодах ошибок.</li><li>Строгая типизация — TypeScript-интерфейсы, которые знают, какие поля обязательны, а какие могут отсутствовать.</li><li>Документация, которая не врет — если Swagger говорит, что поле email есть, оно должно быть. Всегда.</li></ol><p>И самое главное — этот контракт должен соблюдаться. Если бэкендеры меняют API, они обязаны предупредить. Иначе фронтенд превращается в сапера, который каждое утро разминирует прод.</p><p>Но, как правило, контракт сделать тяжело.  Каждый видит REST по-своему: разные URL, форматы данных, обработка ошибок. Модели данных непоследовательны — поля то есть, то их нет, вложенность меняется. Документации либо нет, либо она устарела, так что API изучаем методом проб и ошибок. От такого надо отказываться сразу и стараться договорится на берегу.</p><p>Для унификации и строгого соответствия данных мы используем <a href="https://github.com/typestack/class-transformer">class-transformer</a>: автоматически приводим данные к нужным форматам, вместо работы с сырыми JSON-объектами. Так получаются экземпляры классов с методами и свойствами. Далее убираем ручную обработку и проверки данных, преобразовываем вложенные структуры и применяем кастомные трансформации.</p><h4>Что получаем в итоге?</h4><p>Когда контракт есть, а обертка API готова, магия начинает работать:</p><ul><li><b>Простота использования</b>: вместо десятков хуков — единая фабрика createApi(). Меньше boilerplate-кода.</li><li><b>Мощные возможности</b>: данные приходят уже в нужном формате без ручных проверок. Кэш, инвалидация и оптимизации —  <a href="https://tanstack.com/query/latest">TanStack Query</a> делает за вас всю грязную работу.</li><li><b>Новички влетают в проект: </b>больше не нужно объяснять, почему useGetEntity в одном компоненте работает не так, как в другом.</li><li><b>Активное сообщество: </b><a href="https://tanstack.com/query/latest">TanStack Query</a> —  тысячи разработчиков, готовых ответить на вопросы. Здесь можно найти примеры для любых кейсов: от интеграции с <a href="https://nextjs.org/">Next.js</a> до кастомного кеширования.</li><li><b>Нет ограничений по использованию: </b><a href="https://tanstack.com/query/latest">TanStack Query</a> —  не только для React, есть версии для <a href="https://tanstack.com/query/latest/docs/framework/vue">Vue</a>, <a href="https://tanstack.com/query/latest/docs/framework/svelte">Svelte</a> и даже <a href="https://tanstack.com/query/latest/docs/framework/solid">Solid.js</a>. Также работает с любым API — REST, GraphQL, WebSockets.</li><li><b>Работа с SSR без боли: </b>готовая интеграция с <a href="https://nextjs.org/">Next.js</a>, <a href="https://remix.run/">Remix</a> и другими фреймворками. При этом данные, полученные на сервере, автоматически передаются на клиент. <a href="https://tanstack.com/query/latest">TanStack Query</a> синхронизирует серверный и клиентский рендеринг.</li></ul><p>Но есть и ложка дегтя. Отладка усложняется, если что-то сломается внутри обертки — придётся копать глубже. Возникает зависимость от библиотек: <a href="https://github.com/typestack/class-transformer">class-transformer</a>, axios и сам <a href="https://tanstack.com/query/latest">TanStack Query</a> становятся обязательными.</p><p>Однако игра стоит свеч. Потому что время, сэкономленное на рутине, можно потратить на то, что действительно важно —  фичи, которые понравятся пользователям, а не бесконечные правки API-вызовов.</p><h4>Сравнительные примеры</h4><p>GET /products — Список продуктов</p><p>GET /products/:id — Один продукт по id</p><p>POST /products — Создание продукта</p><p>PUT /products/:id — Обновление продукта по id</p><p>DELETE /products/:id — Удаление продукта по id</p><h4>Как это выглядит в обертке</h4><h4>Все свойства и возвращаемые хуки и конфиги из фабрики:</h4><h4>Пример использования в компонентах:</h4><h4>Использование конфигов:</h4><h4>Для сравнения с классическим решением:</h4><figure><img src="https://media.tproger.ru/user-uploads/115291/2025-05-22/efa40892-0692-4a19-9796-8f993267a22d.png" alt="Сравнение обычного использования и фабрики" /><figcaption>Сравнение обычного использования и фабрики</figcaption></figure><h2>Когда стоит переходить на обертку?</h2><p>Не каждый проект нуждается в таком подходе к API. Если у вас два-три endpoint’а и они никогда не меняются — возможно, обертка будет избыточной. Но представьте стартап, где каждый месяц добавляются новые сущности: сначала товары, потом отзывы, потом промокоды, рекомендации, аналитика.</p><p>Вот где система раскрывается на полную! Новая сущность? Пять минут на добавление — и готовы все CRUD-операции. Изменился бэкенд? Правим в одном месте — и все работает.  Пришел новый разработчик? Он не тратит неделю на изучение особенностей API.</p><p>Правда, если бэкенд живет в мире хаотичных endpoint’ов (например, GET /fetch_items, но DELETE /removeProduct), обертка не спасет.</p><h4>Но как навести порядок?</h4><p>Главный секрет — общаться. Не ждать, пока API сломается, а сразу договориться:</p><ul><li>Какие будут названия полей (created_at vs createdAt);</li><li>Как структурированы ошибки;</li><li>Когда и как можно менять контракт.</li></ul><p>Как сказал один разработчик: «фронтенд и бэкенд — как соседи по коммуналке. Можно ругаться из-за бардака на кухне, но лучше сесть и написать правила совместного проживания».</p><p>А напоследок —  график, для закрепления разницы между работой с оберткой и без нее.</p><figure><img src="https://media.tproger.ru/user-uploads/115291/2025-05-22/5f23aca4-8353-4ff4-8923-f24685395bb2.png" alt="График сравнительного примера" /><figcaption>График сравнительного примера</figcaption></figure>]]></content:encoded>
    </item>
    <item>
      <title>Почему микросервисы не нужны: антихайповый разбор</title>
      <link>https://tproger.ru/articles/pochemu-mikroservisy-ne-nuzhny--antihajpovyj-razbor</link>
      <comments>https://tproger.ru/articles/pochemu-mikroservisy-ne-nuzhny--antihajpovyj-razbor?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Денис Кудерин]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/pochemu-mikroservisy-ne-nuzhny--antihajpovyj-razbor</guid>
      <description><![CDATA[<p>Почему микросервисная архитектура нужна не во всех случаях. Причины популярности микросервисов — маркетинг, хайп и законы рынка. </p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/pochemu-mikroservisy-ne-nuzhny--antihajpovyj-razbor">Почему микросервисы не нужны: антихайповый разбор</a>»</p>]]></description>
      <category><![CDATA[Инструменты]]></category>
      <category><![CDATA[Микросервисы]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[Google]]></category>
      <category><![CDATA[Боты]]></category>
      <category><![CDATA[Сервисы]]></category>
      <category><![CDATA[Яндекс]]></category>
      <category><![CDATA[Маркетинг]]></category>
      <category><![CDATA[Бэкенд]]></category>
      <category><![CDATA[Приложение]]></category>
      <category><![CDATA[Spotify]]></category>
      <category><![CDATA[Сервер]]></category>
      <category><![CDATA[Kubernetes]]></category>
      <category><![CDATA[микро]]></category>
      <category><![CDATA[Бизнес]]></category>
      <category><![CDATA[CI/CD]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Sat, 19 Apr 2025 09:00:03 GMT</pubDate>
      <content:encoded><![CDATA[<p>Микросервисы действительно ускоряют разработку и обладают массой других достоинств. Netflix и Amazon построили на них свои гигантские системы — это на самом деле гибко, современно и обеспечивает проекту масштабирование.</p><p>Но правда в том, что это решение подходит далеко не всем компаниям. В 90% ситуаций микросервисная архитектура (она же MSA) — избыточность, а не необходимость. Это не просто сложно, а очень сложно. Микросервисы требуют мощной инфраструктуры, глубоких знаний DevOps, тонкой настройки мониторинга и отказоустойчивости. И самое главное — они редко нужны на старте проекта.</p><p>Если ваш сервис пока обслуживает десятки и сотни, а не миллионы пользователей, если у вас маленькая команда и ограниченный бюджет, если вы просто хотите сделать   работающий продукт, забудьте про микросервисы — они вам не нужны. И мы подробно расскажем, почему. Статья основана на опыте сотен разработчиков, которые в свое время наступали на одни и те же грабли. Материал поможет избежать их ошибок и убережет от лишних трат.</p><h2>Почему все говорят про микросервисы</h2><p>Архитектура микросервисов — прогрессивная модель для создания ПО, при которой приложение состоит из автономных, почти не связанных друг с другом модулей. Это упрощает разработку проектов и управление ими, поэтому подход применяют известные крупные бренды типа PayPal и Netflix.</p><p>Если вы погружены в ИТ-тематику, интересуетесь вакансиями для специалистов, читаете каналы и блоги программистов, у вас может сложиться впечатление, что микросервисы — волшебная кнопка для разработчиков, без которой не обойтись. Но это не так: популярность этой темы — результат нескольких причин. О них — ниже.</p><h3>Маркетинг на волне хайпа</h3><p>Разработчики инструментов в этой сфере хорошо зарабатывают на своих продуктах.</p><p>Микросервисы — не просто архитектура, это целая индустрия. Компании вроде Google и AWS активно продвигают Kubernetes, Istio и прочие сложные инструменты. Им это выгодно: чем больше людей верят, что без этого стека нельзя, тем больше подписок, лицензий и консультаций продаются.</p><p>Реальность более прозаична. Вам говорят, что «Kubernetes нужен всем», но для стартапа из трех-пяти человек это слишком дорогое удовольствие. Половина постов и кейсов про «успешный переход на микросервисы» спонсирована компаниями, которые продают инструменты для этого перехода.</p><h2>Ориентированность на резюме</h2><p>Многие разработчики (особенно начинающие) учат микросервисы не потому, что столкнулись с их необходимостью, а потому, что это круто звучит. В итоге в вакансиях пишут «знание Docker/K8s — огромный плюс», а на собеседованиях спрашивают про «опыт работы с распределенными системами», даже если у компании всего лишь сайт-визитка.</p><p>Это создает порочный круг:</p><ul><li>новички учат Kubernetes, потому что это востребовано;</li><li>компании требуют Kubernetes, потому что так делают конкуренты;</li><li>в итоге люди тратят месяцы на сложные технологии, которые никогда не применят.</li></ul><p>Факт. Несмотря на универсальность микросервисов, далеко не все гиганты перешли на такой формат работы. Например, GitLab и Spotify до сих пор работают на монолитах.</p><h3>Завышенные ожидания по проекту</h3><p>Создатели стандартного проекта искренне считают, что он слишком сложен для монолита. Начинающие разработчики часто переоценивают масштаб своих задач. Они внимательно читают доклады Netflix про архитектуру и решают, что их pet-проект тоже нуждается в распределенной системе.</p><p>Что происходит на практике:</p><ul><li>Вместо одного приложения — 10 сервисов, которые падают вразнобой.</li><li>Вместо локальной отладки — часы борьба с сетью и синхронизацией данных.</li><li>Вместо «гибкости» — множество лишних элементов.</li></ul><p>В итоге пока вы разбираетесь с Istio и мониторингом, ваш конкурент уже запустит тот же функционал на монолите и получит первых клиентов.</p><h2>Нужны ли вашему проекту микросервисы</h2><p>Прежде чем принимать решение о переходе на микросервисную архитектуру, необходимо трезво оценить текущие и прогнозируемые потребности вашего проекта. Микросервисы — это не универсальное решение, а архитектурный подход со строго определенной областью применения. Его внедрение должно быть обосновано конкретными техническими и бизнес-требованиями, а не модными тенденциями в разработке.</p><p>Чтобы понять, стоит ли внедрять в ваш проект микросервисы, ответьте на три важных вопроса.</p><h3>Действительно ли ваш проект настолько масштабен?</h3><p>Микросервисы — это не разделение кода на части, это создание независимых продуктовых единиц, каждая из которых могла бы работать как отдельное приложение.</p><p>Сразу проверьте себя:</p><ul><li>Если ваш сервис — это один API, который обслуживает 5 конечных адресов, микросервисы вам не нужны.</li><li>Если вы не можете четко объяснить, какие части системы могут жить автономно (например, платежи без каталога товаров), значит, у вас монолит. И это нормально.</li></ul><p>Монолит — низкие начальные затраты, но с ростом кода поддержка становится дороже. Микросервисы — огромные стартовые вложения (DevOps, оркестрация, мониторинг), зато потом система масштабируется с меньшими расходами. Второй вариант выгоднее лишь в том случае, если у вас миллионы пользователей и десятки команд. До этой точки монолит — более целесообразное решение.</p><p>Далеко не все приложения достаточно масштабны, чтобы разбить их на более мелкие составные части. Но даже в случае, если на начальной стадии запуска сложно оценить потенциал продукта, лучше начать с монолита. А грамотный код всегда можно перевести на микросервисы, когда это понадобится.</p><h3>Действительно ли вам необходимо масштабировать части приложения автономно?</h3><p>Типичный аргумент за микросервисы: «У нас нагрузка только на платежи, а не на каталог — выгодно масштабировать их по отдельности». На самом деле 99% стартапов никогда не сталкиваются с такой нагрузкой, где это критично. Кроме того, современные облака (AWS, GCP) умеют масштабировать отдельные модули монолита.</p><p>Пример. Команда разбила HR-систему на 10 микросервисов. В итоге форма подачи заявок зависела от сервиса сотрудников, который в свою очередь зависел от сервиса отделов. При пиковой нагрузке (раз в месяц) все равно масштабировали все сервисы сразу.</p><p>Если вы не Amazon — вам, скорее всего, хватит вертикального масштабирования (+1 сервер) или модульного монолита.</p><h3>Есть ли у вас услуги, связанные с транзакциями?</h3><p>В монолите транзакция — это пара строк кода. В микросервисах — сложный квест.</p><p>Вот как это выглядит:</p><ol><li>Платежный сервис списал деньги.</li><li>Инвентарный сервис не ответил (упал или залагал).</li><li>Теперь у пользователя списаны деньги, но заказ не создан.</li></ol><p>Микросервисы создают проблемы согласованности. В монолите вы обновляете данные одной транзакцией, в MSA это стоит в 10 раз дороже.</p><h2>7 причин не лезть в микросервисы</h2><p>Значительная часть начинающих прогеров по умолчанию считает, что микросервисы — это прогрессивно и круто. Но они просто не видят подводных камней. На самом деле MSA — это компромисс со сложностью, деньгами и нервами. И не нужно считать, что монолит — это отсталая технология. Решения, касающиеся архитектуры продукта, нужно принимать, основываясь на объективных данных, а не хайпе.</p><p>Рассмотрим главные причины, по которым вам не стоит связываться с микросервисами.</p><h3>Сложность съедает пользу</h3><p>Итак, ваша небольшая команда из 5-10 человек решила перейти на микросервисы с расчетом на гибкость, масштабируемость и прочие фишки новой архитектуры.</p><p>На практике получается следующее:</p><ul><li>Kubernetes (или иной подобный инструмент) становится источником проблем. Вместо написания кода вы теперь разбираетесь, почему поды (базовые строительные блоки) не стартуют, настраиваете контроллеры, обновляете Helm-чарты. Это занимает 30-50% рабочего времени.</li></ul><ul><li>Раньше логи были в одном файле, теперь размазаны по 15 сервисам, хранятся в разных форматах, требуют сложной агрегации. Чтобы найти одну ошибку, приходится тратить кучу времени.</li><li>Проблемы с сетевым взаимодействием. Каждый вызов между сервисами — это таймауты, повторные запросы, непонятные ошибки.</li></ul><p>Команда тратит полгода на переход. Но сервис получает те же 100 запросов в секунду. Только теперь он становится медленнее, сложнее в поддержке, дороже в эксплуатации.</p><p>Сложность ради сложности — это точно не про эффективность. Прежде чем переходить на микросервисы, подумайте — готовы ли вы тратить половину времени не на продукт, а на борьбу с инфраструктурой?</p><h3>Микросервисы не лечат плохой код</h3><p>У вас есть монолит — большой, тяжелый, с запутанными зависимостями. И вот вы решаете: «Давайте разобьем это на микросервисы!» В теории звучит отлично: каждый сервис — маленький, независимый, аккуратный.</p><p>Но на практике оказывается, что вы просто взяли ваш запутанный код и разделили его на несколько сервисов, не устранив существующие зависимости. Они не исчезают, а лишь меняют форму: вместо вызовов методов внутри одного приложения появляются HTTP-запросы между сервисами. Это не решение проблемы неорганизованного кода, вы создаете новую зависимость — сетевые взаимодействия.</p><p>Микросервисы не улучшают плохой код, они лишь усложняют его структуру. Если архитектура изначально плохо организована, сначала необходимо устранить хаос, и только затем рассматривать вопросы масштабирования. Для этого требуется квалифицированная команда специалистов</p><h3>Нужна подготовленная команда</h3><p>Микросервисами нужно умело управлять. В теории все выглядит красиво — независимые сервисы, гибкое масштабирование, быстрые обновления. Но на практике оказывается, что для такой архитектуры нужны особые люди и процессы, которых у большинства команд просто нет:</p><ul><li>Без полноценного DevOps или SRE-инженера вы быстро утонете в бесконечной настройке и мониторинге. Это не та работа, которую можно взвалить на бэкендера — она требует специфических знаний и постоянного внимания.</li><li>Когда сервисов становится много, появляется новая головная боль — согласование контрактов между командами. Кто за что отвечает? Как тестировать изменения? Что делать, если один сервис ломает другой? Без четких договоренностей и CI/CD-культуры это превращается в хаос.</li><li>В большинстве стартапов два бэкендера, один стажер и горящие сроки. Они едва успевают пилить фичи, не то что разбираться с продвинутыми практиками DevOps.</li></ul><p>В таких условиях попытка внедрить микросервисы чаще всего заканчивается тем, что команда тратит 80% времени на поддержку инфраструктуры вместо разработки продукта.</p><h3>Деньги тратятся быстрее</h3><p>Когда речь заходит о микросервисах, многие почему-то забывают простую истину — за все надо платить:</p><ul><li>Без профессионального DevOps-инженера (а хорошие специалисты стоят дорого) ваш «распределенный рай» быстро превратится в ад. Кто будет настраивать Kubernetes, разбираться с падающими подами и оркестрировать логи?</li><li>Базовый мониторинг вроде Prometheus + Grafana — это только начало. Когда сервисов станет много, вам понадобятся системы трассировки и еще десяток инструментов, каждый из которых требует времени и денег.</li><li>Главная скрытая цена микросервисов — время инженеров. В монолите проверка занимает минуты. В мире микросервисов вам сначала придётся поднять пол-инфраструктуры, чтобы просто удостовериться, что код вообще работает.</li></ul><p>Для проектов с нагрузкой меньше 100k пользователей микросервисы обходятся в 2-3 раза дороже монолита. И это без учета скрытых затрат — нервов, задержек и упущенных возможностей.</p><h3>Отладка микросервисов — это головная боль</h3><p>Отладка в микросервисной архитектуре требует серьезных затрат времени и финансов. В монолите все просто — есть трассировка стеков (список вызовов), есть логи, и обычно проблема лежит где-то между ними.</p><p>Но в мире микросервисов ошибка может прятаться где угодно: в сервисе А, который не так ответил сервису Б, который передал кривые данные сервису В, а тот и вовсе решил ничего не отвечать. И все это с таймаутами, повторными запросами и загадочными HTTP-статусами.</p><p>Можно потратить целый день, чтобы понять, почему падает система. В итоге окажется, что проблема была в том, что два сервиса по-разному интерпретируют дату. В монолите такая ошибка обнаружилась бы за 5 минут. В микросервисах — это полноценное расследование с изучением логов каждого участника цепочки.</p><p>Если вы не готовы к тому, что поиск каждой ошибки будет напоминать путешествие с непредсказуемым пунктом назначения, возможно, микросервисы — не ваш выбор. Ведь время, потраченное на отладку — это время, которого не хватило на создание новых возможностей для вашего продукта.</p><h3>Легкого масштабирования не будет</h3><p>Многие думают, что стоит только разбить приложение на микросервисы, и масштабирование станет решением всех проблем. В реальности все не так просто. Микросервисы — это не автоматическое масштабирование по щелчку пальцев, а сложный механизм, который требует тщательной настройки.</p><p>Для эффективного масштабирования вам понадобятся четкие границы и детально продуманные контракты между сервисами, иначе вы получите клубок зависимостей.</p><p>Без этого масштабирование не сработает. Вместо того чтобы увеличивать только перегруженный сервис, вам придется масштабировать весь кластер целиком. Так что прежде чем разбивать систему, подумайте: действительно ли ваша нагрузка требует таких сложных решений?</p><h2>Когда микросервисы все же нужны</h2><p>Иногда микросервисная архитектура действительно необходима. Но точно не тогда, когда об этом кричат маркетологи или модные блогеры.</p><p>Вот три реальных ситуации, когда MSA имеет смысл.</p><h3>Независимые продукты под одной крышей</h3><p>Типичный пример — Яндекс. Это не просто такси, но и доставка еды, и грузоперевозки. Абсолютно разные бизнес-процессы, которые разрабатываются отдельными командами, используют разные технологии, масштабируются независимо.</p><p>Здесь микросервисы — не прихоть, а необходимость.</p><h3>Огромные масштабы</h3><p>Если у вас одновременно работают 100+ разработчиков, миллионы запросов в секунду, десятки дата-центров по всему миру, монолит просто не выдержит такой нагрузки. Но обратите внимание — мы говорим про реальных гигантов уровня Amazon.</p><h3>Технический стек из разных компонентов</h3><p>Иногда часть системы логичнее писать на Go (где важна скорость), часть на Python (для ML), а часть оставить на JVM (для legacy).</p><p>Микросервисы позволяют:</p><ul><li>использовать оптимальный язык для каждой задачи;</li><li>обновлять компоненты независимо;</li><li>не тащить в проект лишние зависимости</li></ul><p>Все эти случаи объединяет одно: микросервисы решают конкретные проблемы, а не внедряются «на всякий случай». Если ваш проект не подпадает под эти критерии — возможно, стоит еще раз подумать. Использовать микросервисы без необходимости — это неоправданная роскошь.</p><h2>Итоги</h2><p>Микросервисы обрели свой культовый статус вполне заслуженно — в свое время они решили множество проблем, которые ранее считались в индустрии почти неразрешимыми. Истории Uber, SoundCloud и других гигантов индустрии стали для нового поколения программистов источниками вдохновения.</p><p>Однако сегодня ясно, что безосновательное внедрение этой архитектуры ведет к непредсказуемым затратам и последствиям. Стоит учесть все факторы — от  масштаба проекта до его бюджета — прежде чем считать микросервисы самым эффективным решением по умолчанию.</p><p>А если хочешь писать код, который не стыдно показывать, собрали всё для фронтендеров и бэкендеров в <a href="https://t.me/+c6lPaQBXLvE4YmMy">одном месте</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>Энтузиаст рассказал, как запустил Go на PlayStation 2 — через TinyGo, ps2dev и боль</title>
      <link>https://tproger.ru/news/entuziast-rasskazal--kak-zapustil-go-na-playstation-2---cherez-tinygo--ps2dev-i-bol</link>
      <comments>https://tproger.ru/news/entuziast-rasskazal--kak-zapustil-go-na-playstation-2---cherez-tinygo--ps2dev-i-bol?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Булат Яббаров]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/entuziast-rasskazal--kak-zapustil-go-na-playstation-2---cherez-tinygo--ps2dev-i-bol</guid>
      <description><![CDATA[<p>Go запустили на PlayStation 2: энтузиаст адаптировал TinyGo и ps2dev для MIPS-процессора консоли и обошёл ограничения LLVMa</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/entuziast-rasskazal--kak-zapustil-go-na-playstation-2---cherez-tinygo--ps2dev-i-bol">Энтузиаст рассказал, как запустил Go на PlayStation 2 — через TinyGo, ps2dev и боль</a>»</p>]]></description>
      <category><![CDATA[JSON]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[Работа]]></category>
      <category><![CDATA[Golang]]></category>
      <category><![CDATA[PlayStation]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 28 Mar 2025 08:22:54 GMT</pubDate>
      <content:encoded><![CDATA[<p>Разработчик под псевдонимом Ricardo <a href="https://rgsilva.com/blog/ps2-go-part-1/">опубликовал</a> подробный отчёт о том, как ему удалось запустить Go-программу на PlayStation 2 — консоли 2000 года.</p><p>Он использовал компилятор TinyGo, SDK ps2dev и собственные костыли, чтобы адаптировать современный язык программирования под устаревшую архитектуру.</p><h2>TinyGo, MIPS и странности платформы</h2><p>PS2 построена на процессоре MIPS R5900 (архитектура MIPS-III с расширениями), который не поддерживается стандартной сборкой Go. Проблему частично решает TinyGo, который компилирует Go-код в LLVM IR.</p><p>Но даже с ним возникли сложности: ни LLVM, ни сам TinyGo не умеют работать с особенностями PS2 «из коробки». Пришлось вручную описывать платформу через ps2.json, определять baremetal-окружение, runtime и заглушки под прерывания.</p><h2>Первые успехи: «Hello from Go»</h2><p>Чтобы код TinyGo можно было линковать с библиотеками из ps2dev (а они скомпилированы под ABI N32), автору пришлось добиваться совместимости: целиться в MIPS-III, использовать hard-float, отключать abicalls и собирать IR с последующей ручной сборкой объектника через Clang с нужными флагами.</p><p>После успешного линка и запуска в эмуляторе PCSX2 программа вывела строку и число на отладочный экран PS2.</p><h2>Собственный main() и отладка</h2><p>Дальше автор отказался от загрузчика на C и написал полноценный main() на Go, вручную выделяя память под кучу и завершая программу через exit() из ps2dev. Он добавил простую обёртку над scr_printf() — теперь можно печатать текст прямо из Go.</p><h2>DDIVU и проклятие деления</h2><p>Серьёзным багом стал сбой fmt.Sprintf: PS2 не поддерживает инструкцию DDIVU, которую LLVM генерирует при делении uint64.</p><p>Автор обошёл это, подключив функции __udivdi3, __divdi3 и прочие, а затем пропатчил компилятор TinyGo, чтобы он использовал их при делении int64 и uint64.</p><h2>Что дальше</h2><p>Демо работает. Go-код запускается напрямую, выводит текст и корректно делит числа.</p><p>Впереди — системные вызовы, inline-ассемблер, поддержка прерываний и, возможно, новая цель в LLVM для процессора r5900.</p>]]></content:encoded>
    </item>
    <item>
      <title>Context Collapse: как микросервисы могут сойти с ума</title>
      <link>https://tproger.ru/articles/context-collapse--kak-mikroservisy-mogut-sojti-s-uma</link>
      <comments>https://tproger.ru/articles/context-collapse--kak-mikroservisy-mogut-sojti-s-uma?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Анна Ельцова]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/context-collapse--kak-mikroservisy-mogut-sojti-s-uma</guid>
      <description><![CDATA[<p>Даже самая идеальная микросервисная архитектура может упасть. В статье обсудим зарубежный материал, где автор рассказывает о проблеме Context Collapse.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/context-collapse--kak-mikroservisy-mogut-sojti-s-uma">Context Collapse: как микросервисы могут сойти с ума</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[JavaScript]]></category>
      <category><![CDATA[Java]]></category>
      <category><![CDATA[Тестирование]]></category>
      <category><![CDATA[Git]]></category>
      <category><![CDATA[Производительность]]></category>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[JSON]]></category>
      <category><![CDATA[Микросервисы]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[Работа]]></category>
      <category><![CDATA[Node.js]]></category>
      <category><![CDATA[Сервисы]]></category>
      <category><![CDATA[Docker]]></category>
      <category><![CDATA[Redis]]></category>
      <category><![CDATA[OpenTelemetry]]></category>
      <category><![CDATA[Grafana]]></category>
      <category><![CDATA[CI/CD]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 25 Mar 2025 12:40:02 GMT</pubDate>
      <content:encoded><![CDATA[<p>В феврале на Medium вышла статья <a href="https://levelup.gitconnected.com/context-collapse-the-silent-microservices-killer-76a60058561e">Context Collapse: The Silent Microservices Killer</a>. Перевели ее для вас, так как тема довольно редкая и интересная. Ниже предлагаем обсудить проблему контекста и как он может упасть.</p><h2>Что вообще такое context collapse</h2><p>Есть вероятность, что вы слышите этот термин в первый раз. Немного лирики: в мире микросервисов есть два понятия: технический контекст и доменный контекст (Bounded Context).</p><h2>Технический контекст</h2><p>Технический контекст — это информация, которая передается между микросервисами для выполнения запросов или операций. В нем лежит большое количество данных: идентификаторы запросов (например, TraceID в трассировке), пользовательские сессии, метаданные или параметры аутентификации.</p><p>Без технического контекста микросервисы не могут:</p><ul><li>отслеживать, откуда пришел запрос и куда он направляется,</li><li>сохранять согласованность данных между сервисами,</li><li>выявлять сбои (например, через логи или трассировку).</li></ul><h2>Доменный контекст (Bounded Context)</h2><p>Доменный контекст происходит из методологии Domain-Driven Design (DDD) — это про четкое разделение бизнес-логики между микросервисами. У каждого сервиса должна быть своя «ограниченная область» (Bounded Context), где термины, данные и правила имеют уникальное значение.</p><p>Например, в интернет-магазине слово «заказ» может означать разные вещи для сервиса оплаты (финансовая транзакция) и сервиса доставки (отправка покупателю). Если границы контекста не определены четко, возникает путаница: сервисы начинают дублировать логику или интерпретировать данные по-разному.</p><p>Без доменного контекста:</p><ul><li>код будет дублироваться и появится избыточность,</li><li>усложнится взаимодействие между сервисами,</li><li>систему будет сложнее поддерживать.</li></ul><h2>Вернемся к коллапсу контекста</h2><p>Автор статьи просит нас представить следующую картину: вы сделали новую архитектуру, она масштабируется, разделяется, деплои проходят гладко, CI/CD пайплайны цветут и пахнут — другими словами, не архитектура, а мечта. Все работает как часы, поэтому вы сидите, попивая кофе и раскладывая пасьянс.</p><p>Вдруг приходит пользователь и сообщает, что платеж был проведен дважды. На панели мониторинга появляются задержки, и логи здесь вообще бесполезны. Вы начинаете разбираться и спустя несколько часов споров с терминалом, находите причину: один из сервисов забыл, кто вообще такой этот пользователь, прямо во время проведения транзакции.</p><p>Тра-та-та, это и есть контекстный коллапс. Как называет его автор — тихий убийца микросервисов в 2025 году. Поймать этот баг с помощью breakpoints нельзя, при этом он будет уничтожать вашу производительность и код в целом.</p><h2>Что на самом деле происходит</h2><p>Представьте, что микросервисы — это эстафетный забег: каждый сервис передает «эстафетную палочку» — идентификаторы пользователей, сессионные данные, намерения — следующему участнику. Контекстный коллапс случается, когда эта палочка выпадает на бегу.</p><p>Сервис теряет важное состояние, например:</p><ul><li>«Это корзина Пети»</li><li>"Этот платеж уже прошел"</li></ul><p>И начинается хаос: дублирующиеся API-запросы, потерянные транзакции или, что еще хуже, повреждение данных.</p><p>В 2025 году появляется все больше слишком фрагментированных архитектур и гипермасштабируемых систем. Ваши запросы могут проходить через 10, 20 и даже 30 сервисов, но если на каком-то этапе отвалился контекст, то это конец.</p><p>В статье автор не делает акцента на том, какой именно это контекст — технический или доменный. На самом деле может произойти все что угодно: это может быть как потеря технического контекста, так и нарушение доменных границ (когда сервисы лезут не в свое дело). Оба случая приводят к хаосу: данные становятся несогласованными, ошибки множатся, а разработчики теряют контроль над системой.</p><h2>Как понять, что контекст вот-вот может «коллапснуться»</h2><p>Вы наверняка были в такой ситуации: вы на 100% уверены, что система должна работать, но она не работает, хотя ошибок в коде никаких, казалось бы, нет. Вот основные признаки коллапса, с которыми вы можете столкнуться:</p><ul><li>Всплеск пинга: сервисы запрашивают данные, которые должны бы уже знать, создавая огромное количество лишних вызовов и перегружая API.</li><li>Дублирующиеся действия: повторные списания, задвоенные отправки писем, неожиданные повторные заказы. Пользователи возмущены, рейтинг падает.</li><li>Мистические баги: логи говорят «всё в порядке», но результат явно неверный. Код не видит проблему, а отладка превращается в кошмар.</li></ul><p>Давайте рассмотрим на примере. Клиент решает перевести деньги с одного счёта на другой. Сервис транзакций отправляет запрос в модуль проверки лимитов, затем передаёт его в систему обработки платежей. Но из-за потери контекста на одном из этапов модуль проверки лимитов теряет информацию о сессии клиента и воспринимает его как нового пользователя. В результате:</p><ul><li>Лимиты не распознаются, и транзакция блокируется, даже если у пользователя достаточно денег.</li><li>Либо, наоборот, проверка пропускается, и клиенту позволяют перевести больше лимита.</li><li>Сервис обработки платежей не получает подтверждение проверки и отправляет повторный запрос, а это может привести к двойному списанию средств.</li></ul><p>Клиент идет громить службу поддержки, она — разработчиков, а они размахивают руками, потому что в логах все отлично.</p><p>Опрос CNCF за 2024 год показал, что 68% команд, которые используют микросервисы, сталкиваются с необъяснимыми проблемами производительности. И всему виной в том числе контекстный коллапс.</p><h2>5 решений, как бороться с контекстным коллапсом</h2><p>Да, контекстный коллапс — крайне неприятный баг. Главное — чтобы все сервисы работали слаженно и «знали» друг друга.</p><h3>1. Правильно передавайте контекст</h3><p>Вам нужно передавать критические важные данные — идентификаторы пользователей, состояние транзакций, метаданные запроса — в каждом шаге цепочки. Стоит использовать OpenTelemetry, чтобы распространять контекст по сервисам.</p><p>Вот пример реализации middleware автором на Go:</p><h3>2. Кэшируйте с умом</h3><p>Нет смысла заставлять сервисы угадывать, если они просто могут запомнить. Быстрый кэш, например, с Redis, может хранить временный контекст — например, токены сеанса или состояния запросов, — поэтому сервисы не будут постоянно спрашивать «кто это?» Вот фрагмент кода на Питоне, где используется Redis для хранения и извлечения контекста:</p><p>Это позволяет поддерживать контекст во всех вызовах, не перегружая вашу базу данных. А еще TTL (time-to-live) Redis сам за собой убирает — устаревшие данные не скрываются.</p><h3>3. Используйте Event-Driven Architecture</h3><p>Микросервисы без сохранения состояния выглядят отлично, пока не контекст не коллапснется. Событийная архитектура идет от обратного: вместо того чтобы надеяться, что службы все запомнят, регистрируйте каждый шаг как событие. Если служба все-таки забудет, воспроизведите поток. Вот пример на Node.js с Kafka:</p><p>Здесь также можно использовать RabbitMQ. В общем, больше никаких отговорок со стороны сервиса из разряда «я забыл».</p><h3>4. Проверяйте логи</h3><p>Когда контекст теряется, логи — ваше место преступления. Настройте Grafana Loki или Datadog для поиска «потерянных контекстов». Вот пример с Grafana:</p><p>Тэгните логи с помощью request_id или user_id, а затем вызовите Loki:</p><h3>5. Тестируйте на коллапсы</h3><p>Профилактика лучше, чем лечение. Добавьте хаос-тестирование с помощью, например, Chaos Mesh, чтобы моделировать потери контекста.</p><p>Хаос-тестирование — это метод преднамеренного введения сбоев в систему, чтобы проверить, насколько она устойчива и надежна. Обычное тестирование и мониторинг могут выявить проблемы, но хаос-тестирование (Chaos Engineering) помогает увидеть, как система поведет себя в случае неожиданных отказов.</p><p>Прервите mid-requests к сервисам — сможет ли система восстановится в таком случае? Если нет, значит, ваша передача контекста недостаточно надежна.</p><p>Эти решения не универсальны. Начните с правильного распространения контекста для быстрых улучшений, затем добавьте кэширование или событийную архитектуру для масштабируемости и постоянно аудируйте систему.</p>]]></content:encoded>
    </item>
    <item>
      <title>Что такое AJAX и как он работает</title>
      <link>https://tproger.ru/articles/chto-takoe-ajax-i-kak-on-rabotaet</link>
      <comments>https://tproger.ru/articles/chto-takoe-ajax-i-kak-on-rabotaet?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Денис Кудерин]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/chto-takoe-ajax-i-kak-on-rabotaet</guid>
      <description><![CDATA[<p>Что такое AJAX. Показываем, в каких случаях нужен AJAX и как правильно с ним работать. Рассматриваем пошаговую инструкцию и основные нюансы ✔ Tproger</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/chto-takoe-ajax-i-kak-on-rabotaet">Что такое AJAX и как он работает</a>»</p>]]></description>
      <category><![CDATA[Интернет]]></category>
      <category><![CDATA[API]]></category>
      <category><![CDATA[JavaScript]]></category>
      <category><![CDATA[Инструменты]]></category>
      <category><![CDATA[Производительность]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[Браузеры]]></category>
      <category><![CDATA[HTML]]></category>
      <category><![CDATA[HR]]></category>
      <category><![CDATA[XML]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 06 Mar 2025 10:00:04 GMT</pubDate>
      <content:encoded><![CDATA[<p>Технология AJAX (Asynchronous JavaScript and XML) — мощный инструмент разработки динамичных и производительных интерактивных веб-приложений. AJAX меняет подход к обновлению содержимого страниц и позволяет загружать данные в асинхронном режиме без перезагрузки. Благодаря этой технологии сохраняется высокая скорость загрузки, юзерам удобнее пользоваться сайтами.</p><p>Узнаем, что собой представляет технология, как формируются AJAX запросы, как работает инструмент, каковы его преимущества, недостатки и ограничения.</p><h2>Основные компоненты AJAX</h2><p>Термин AJAX используется в программировании с 2005 года, хотя подобные способы обмена данными применялись и ранее. Это универсальное решение для веб-приложений, которое объединяет несколько компонентов. Именно благодаря AJAX реализованы такие проекты, как современные соцсети, Google Maps, Gmail, Google Docs и многие другие.</p><p>Основная задача  AJAX — запросы к серверу в обход перезагрузки страницы. Это уменьшает время отклика и позволяет веб-приложению работать в интерактивном режиме. Несмотря на присутствие в названии отсылки к XML, использовать этот язык разметки не обязательно.</p><p>Технология реализуется через JavaScript — происходит заданный скриптом асинхронный обмен данными между сервером и браузером. Именно на JS создаются запросы для коммуникации с сервером и динамического изменения страницы.</p><p>Асинхронность — ключевое условие запросов AJAX. Они выполняются в фоновом режиме, пока пользователь продолжает работу с сайтом. Загрузка и обработка данных выполняются параллельно.</p><p>Код на JavaScript — не единственный компонент AJAX. В него также входят форматы хранения данных XML или JSON. При этом JSON для отправки запросов AJAX используется чаще, поскольку код у этого формата короче, что существенно упрощает передачу данных.</p><p>Важнейший компонент технологии — объект <b>XMLHttpRequest,</b> который отвечает за все запросы AJAX. Этот API предоставляет клиенту полноценный функционал для взаимного обмена данными с сервером. Раньше XHR поддерживали не все браузеры — разработчикам приходилось дополнительно подключать библиотеку jQuery с встроенным объектом. Сейчас большинство популярных браузеров, включая Chrome и Firefox, работают с XMLHttpRequest напрямую.</p><p>Примечание. В современных программных веб-продуктах вместо XHR нередко используют Fetch AP, но говорить о массовом тренде преждевременно.</p><p>Передача данных выполняется через стандартный протокол взаимодействия клиента и сервера HTTP. Браузер инициирует запрос, получает в ответ HTML-страницу, либо сообщение об ошибке (если в запросе есть неточности). Используются стандартные методы получения данных — GET и POST. Первый (GET) применяется при получении данных от сервера, второй (POST) используется для отправки данных на сервер в теле HTTP-запроса.</p><p>Благодаря способности AJAX работать с разными форматами, типами данных и серверными API, эта методика универсальна. Асинхронный обмен позволяет веб-приложениям быстро загружаться, плавно работать и не перезагружаться после каждого запроса пользователя к серверу. Это особенно актуально для приложений, требующих постоянного взаимодействия с сетевым устройством — социальных сетей, онлайн-магазинов, браузерных версий мессенджеров.</p><h2>Как работает AJAX</h2><p>Магия асинхронных запросов AJAX базируется на взаимодействии с DOM-объектами браузерной страницы. Процесс выглядит следующим образом:</p><ol><li>С помощью JavaScript браузер отправляет HTTP-запрос на сервер, где происходит обработка данных и отправка ответа. Чтобы отправить запрос, потребуется создать объект XMLHttpRequest — без него отправлять запросы и получать ответы без перезагрузки не получится.</li><li>При этом запрос необходимо настроить — указать метод GET/POST, URL и перейти на асинхронный режим работы.</li><li>Сервер возвращает данные, с которыми начинает работать JavaScript. Когда браузер принимает исходный код страницы, он выстраивает множество виртуальных элементов на базе этого кода — сюда входят заголовки, изображения, текст, ссылки и прочее.</li><li>При этом к каждому компоненту виртуальной модели можно обращаться отдельно с целью изменить его свойства или содержание. JavaScript позволяет поменять фон страницы, изменить заголовок и внести другие изменения, не перегружая страницу.</li></ol><p>Простой пример запроса AJAX выглядит следующим образом (используется метод получения данных GET):</p><p>В этом примере мы создаем объект XMLHttpRequest, настраиваем запрос, обрабатываем ответ и данные, отправляем запрос на сервер. Данные выводятся в консоль без перезагрузки страницы — обновляется только нужный элемент интерфейса.</p><p>В следующем примере показан код для отправки формы с использованием запроса AJAX:</p><p>С помощью этого кода пользователь отправляет данные формы на сервер и получает ответ без перезагрузки страницы. В браузере запускается скрипт, привязанный к кнопке «Отправить». Все процессы происходят внутри скрипта — новая информация встроена в уже открытую страницу.</p><h3>Отладка AJAX-запросов</h3><p>Для эффективной разработки и поддержки приложений программистам важно научиться отлаживать и тестировать запросы AJAX. Для этого необходимы встроенные инструменты браузеров Chrome, Firefox, Edge и других.</p><p>Эти инструменты позволяют:</p><ul><li>просматривать отправленные на сервер запросы во вкладке Network;</li><li>проверять атрибуты запросов/ответов и их содержимое;</li><li>следить за временем выполнения отправленных запросов, выявлять узкие места и оптимизировать процессы.</li></ul><p>Для тестирования запросов полезно создавать фейковые API или проверять работу реальных интерфейсов вне контакта браузера с помощью библиотек MSW или Postman.</p><p>Прогерам будут полезны ценные советы по оптимизации процессов при работе с запросами:</p><ul><li>Используйте кэширование, чтобы уменьшить количество запросов. Это снижает нагрузку на сервер и повышает производительность.</li><li>Применяете сжатие данных для снижения объема отправляемой информации. Это ускоряет процесс передачи и обработки данных.</li><li>Всегда обрабатывайте ошибки для улучшения пользовательского опыта. Лучше заранее предусмотреть все варианты, чтобы снизить риск возможных проблем при использовании приложения.</li></ul><h2>Преимущества AJAX</h2><p>Перечислим основные плюсы технологии:</p><ul><li><b>Обновление данных без необходимости перезагружать страницу. </b>Это улучшает опыт пользователей и делает взаимодействие с приложением более плавным и быстрым. Юзерам гораздо удобнее видеть обновление на той же странице, чем загружать новую.</li><li><b>Уменьшение трафика. </b>Поскольку браузер получает от сервера не всю страницу полностью, а только ограниченную запросом информацию, тратится меньше ресурсов на передачу данных.</li><li><b>Снижение нагрузки на сервер</b>. Если приложение открывает страницы «на лету», достаточно один раз прогрузить стандартные элементы (шапку, меню, подвал), а остальные части загружать по необходимости.</li><li><b>Быстрота и отзывчивость приложений.</b> Чем меньше данных в запросе AJAX, тем быстрее придет ответ от сервера. В современных продуктах скорость и удобство — ключевые конкурентные преимущества.</li><li><b>Экономия ресурсов. </b>Безлимитный интернет есть не у всех и не везде, а запросы AJAX используют ресурсы в минимальном режиме.</li></ul><p>Необходимо также понимать, что технология не универсальна и подходит не для всех ситуаций и приложений.</p><h2>Недостатки AJAX</h2><p>В числе основных минусов AJAX:</p><ul><li><b>Потенциальные проблемы с SEO-контентом. </b>Содержание страниц, которое подгружается с помощью AJAX, часто недоступно для поисковиков, что негативно сказывается на индексации. Поисковые системы видят исходный ход, но не данные с серверов. Это может быть проблемой для сайтов, которые нуждаются в привлечении пользователей. Для сеошников работа с сайтами на AJAX — головная боль.</li><li><b>Кэширование.</b> Динамическое содержание может создать сложности с кэшированием, что приводит к загрузке неактуальных данных.</li><li><b>Зависимость от JavaScript. </b>Пользователь может отключить JavaScript, что ограничит функциональность сайта. Данные не смогут прийти с сервера, интерактивного обновления не получится.</li><li><b>Усложнение проекта.</b> Работа с запросами AJAX требует от разработчиков определенной квалификации. Они должны предвидеть различные внештатные ситуации, связанные с асинхронными запросами, и заранее прописать скрипты на такие случаи. Потребуется также продумать бэкенд — ответы сервера на различные запросы.</li></ul><p>При нестабильной связи AJAX может не получить ответа от сервера либо не отправить запрос. Такая ситуация нарушает логику загрузки страницы — ее придется все-таки перезагружать и начинать все с нуля.</p><h2>Где используется AJAX</h2><p>Технологию используют для улучшения пользовательского опыта при работе с сайтами и веб-приложениями. AJAX-запросы решают множество подзадач:</p><ul><li><b>Динамическое обновление.</b> С помощью AJAX обновляются отдельные элементы страниц — таблицы, списки, графики. Это особенно удобно на сайтах, где применяются фильтры — например, на страницах онлайн-магазинов.</li><li><b>Автозаполнение и поиск.</b> AJAX используется для мгновенной выдачи результатов поиска. Юзер только начинает вводить текст в поисковую строку и уже видит релевантные варианты. Это удобно для формирования точных и подробных поисковых запросов.</li><li><b>Отправка формы. </b>Чтобы отправить данные заполненных форм, пользователю не нужно ждать обновления, что делает работу более плавной. Например, можно залогиниться после просмотра сайта, оставшись на той же странице.</li><li><b>Загрузка данных для конкретного пользователя.</b> В соцсетях или на сайтах с интерактивными опциями новые сообщения, уведомления и комментарии подгружаются без обновления страницы.</li><li><b>Динамические интерфейсы.</b> Этот процесс вы можете наглядно наблюдать на Гугл-картах и в подобных приложениях — по мере прокрутки подгружаются новые части территории. Аналогичная опция реализована на сайтах с интерактивными прогулками по гостиницам, музеям и другим локациям.</li></ul><p>Иными словами, AJAX-запросы используются везде, где требуются обновления содержания без перезагрузки: чтобы получить список новых сообщений в чате или в общей ленте; подгрузить позиции на витрине товаров; увидеть рекламные баннеры и т.д.. В Ютубе на этой технологии основано сворачивание видео в компактный плеер в углу.</p><p>AJAX — незаменимый инструмент для разработки динамических интерфейсов и улучшения пользовательского опыта. Механизм основан на асинхронности работы браузера и сервера. При нормальной скорости интернета данные передаются мгновенно, так что пользователям даже не приходится ждать. При этом AJAX универсален и может работать с разными форматами данных и серверными API.</p>]]></content:encoded>
    </item>
    <item>
      <title>Как читать чужой код и понимать его: гайд, как не разбить экран компьютера</title>
      <link>https://tproger.ru/articles/kak-chitat-chuzhoj-kod-i-ponimat-ego--gajd--kak-ne-razbit-ekran-kompyutera</link>
      <comments>https://tproger.ru/articles/kak-chitat-chuzhoj-kod-i-ponimat-ego--gajd--kak-ne-razbit-ekran-kompyutera?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Анна Ельцова]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/kak-chitat-chuzhoj-kod-i-ponimat-ego--gajd--kak-ne-razbit-ekran-kompyutera</guid>
      <description><![CDATA[<p>Как читать не свой код. Показываем, как правильно понимать и разбираться в чужом коде. Рассматриваем пошаговую инструкцию и основные нюансы ✔ Tproger</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/kak-chitat-chuzhoj-kod-i-ponimat-ego--gajd--kak-ne-razbit-ekran-kompyutera">Как читать чужой код и понимать его: гайд, как не разбить экран компьютера</a>»</p>]]></description>
      <category><![CDATA[Инструменты]]></category>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[IDE]]></category>
      <category><![CDATA[Кодстайл]]></category>
      <category><![CDATA[Приложение]]></category>
      <category><![CDATA[Библиотеки]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 31 Jan 2025 10:00:03 GMT</pubDate>
      <content:encoded><![CDATA[<p>Представьте себе ситуацию: вы пришли в новую компанию, и вам сказали переписать чужой код. Ну, по крайней мере, сделать так, чтобы он работал. И вот вы сидите, ухватившись руками за голову, и пытаетесь понять, что делает эта функция и зачем нужна эта кнопка. Еще хуже — если нет документации. Рано или поздно с этим сталкиваются почти все прогеры, но без паники: прочесть, а, главное, понять чужой код — задача сложная, но выполнимая.</p><p>Разбираться в чужом коде — очень крутой навык, поскольку в нем вы можете найти новые приемы и подходы, посмотреть на логику решения конкретной задачи (можете сравнивать со своей), плюс быстрее адаптироваться к процессам в компании.</p><p>В статье расскажем, как читать чужой код без стресса, а еще рассмотрим типичные ошибки и посоветуем крутые лайфхаки.</p><h2>Разбираемся на практике</h2><p>Поскольку автор этой статьи — филолог по образованию и айтишник в душе, мы не придумали ничего лучше, чем создать код для библиотечной системы. Проект довольно сложный, поскольку в нем много файлов. В общем, давайте копаться.</p><h4>Структура проекта:</h4><p>Library_project/</p><p>├── Library/</p><p>│   ├── models/</p><p>│   │   ├── book.py</p><p>│   │   └── catalog.py</p><p>│   ├── utils/</p><p>│   │   ├── search.py</p><p>│   │   └── reports.py</p><p>│   └── tests/</p><p>│       └── test_catalog.py</p><p>└── main.py</p><h4>Код проекта:</h4><p>Представление о проекте есть, а теперь давайте по шагам читать чужой код.</p><h2>Шаг 1: Поймите, что в принципе делает код</h2><p>Первое, что нужно сделать при анализе чужого кода — понять его цель. Вместо того, чтобы сразу погружаться в реализацию, начните с конца: что делает программа и какую проблему она решает?</p><p>Давайте посмотрим на файл main.py:</p><p>Из него понимаем, что:</p><ol><li>Проект связан с библиотекой (судя по названию модуля);</li><li>Есть тестовый сценарий, в котором видно основную функциональность;</li><li>Код организован в пакеты и модули.</li></ol><p>Если запустим тесты, увидим следующее:</p><p>Теперь мы знаем, что система как минимум умеет:</p><ul><li>Выдавать книги;</li><li>Искать книги по названию;</li><li>Показывать статус.</li></ul><h2>Шаг 2: Изучите общую структуру кода</h2><p>Когда вы поняли, что делает программа, нужно разобраться в ее архитектуре, и здесь важно задавать правильные вопросы:</p><p>Вопрос 1: Как организованы данные?</p><p>Помним, что у проекта есть четкая структура:</p><p>Library_project/</p><p>├── Library/</p><p>│   ├── models/</p><p>│   │   ├── book.py         # Данные о книгах</p><p>│   │   └── catalog.py      # Управление каталогом</p><p>│   ├── utils/</p><p>│   │   ├── search.py       # Поиск</p><p>│   │   └── reports.py      # Генерация отчетов</p><p>│   └── tests/</p><p>│       └── test_catalog.py # Тесты</p><p>└── main.py                 # Точка входа в приложение</p><p>Она говорит нам о том, что:</p><ul><li>Данные о книгах и каталоге разделены;</li><li>Дополнительные функции лежат в отдельном модуле;</li><li>Есть модуль для тестов;</li><li>Система в целом следует принципам модульности.</li></ul><p>Вопрос 2: Как взаимодействуют компоненты?</p><p>Посмотрим на импорты в catalog.py:</p><p>Это показывает, что:</p><ul><li>Каталог зависит от класса Book;</li><li>Приложение подтягивает даты (чтобы проверять сроки).</li></ul><p>Вопрос 3: Какие главные операции выполняются в системе?</p><p>В классе LibraryCatalog видим:</p><p>Отсюда понятно, что система может:</p><ul><li>Выдавать книги на конкретный срок;</li><li>Возвращать книги;</li><li>Делать поиск по каталогу.</li></ul><h2>Шаг 3: Изучите документацию и комментарии</h2><p>При чтении чужого кода документация и комментарии — ваши лучшие друзья. Например:</p><p>Здесь мы видим docstring, который кратко описывает назначение класса. Более наглядный пример — метод borrow_book из файла /models/catalog.py:</p><h2>Шаг 4: Проанализируйте главную точку входа в программу</h2><p>Точка входа — место, с которого начинается выполнение программы. В нашем случае это main.py, но давайте посмотрим внимательнее, на что он ссылается:</p><p>Из этого кода видно, что первым делом импортируются классы: LibraryCatalog из файла /models/catalog.py, BookSearch из файла /utils/search.py и класс ReportGenerator из файла /utils/reports.py.</p><p>Далее — функция run_basic_tests, в которой создается экземляр класса LibraryCatalog. В переменную status записывается значение вызова метода borrow_book, который возвращает статус выдачи книги.</p><p>Затем выводится информация о тесте выдачи книги. По аналогии, в переменные search_results, return_status, overdue_report записываются значения вызова методов search_by_title, return_book и generate_overdue_report соответственно.</p><h2>Шаг 5: Определите ключевые функции и классы</h2><p>В любом проекте есть основные компоненты, вокруг которых строится вся логика. В нашем случае это:</p><p>LibraryCatalog — центральный класс. В нем реализованы основные методы управления  библиотекой, такие как: добавление новой книги (add_book), выдача книги читателю (borrow_book), возврат книги в библиотеку (return_book), получение списка всех выданных книг (get_borrowed_books) и поиск книги (find_book).</p><p>BookSearch — утилитный класс. В нем реализованы методы поиска книги по автору и по названию.</p><h2>Шаг 6: Используйте инструменты IDE для навигации и анализа</h2><p>В современных IDE есть мощные инструменты для анализа кода. Рассмотрим несколько основных на примере нашего «чужого» кода.</p><ul><li><b>Find Usages:</b></li></ul><figure><img src="https://media.tproger.ru/user-uploads/101078/2025-01-29/2d0a67e6-f386-402d-9e21-abada847e66a.png" alt="" /></figure><figure><img src="https://media.tproger.ru/user-uploads/101078/2025-01-29/aaa474da-8e16-4dc9-abd2-318cf3e454be.png" alt="" /></figure><p>Здесь мы ищем метод borrow.book и видим, как он используется в тестах и других частях кода.</p><ul><li><b>Go to Definition</b> — видим, как создается объект:</li></ul><figure><img src="https://media.tproger.ru/user-uploads/101078/2025-01-29/df361ff8-07cf-43d7-8dd7-ffb2a04ccf90.png" alt="«Как читать чужой код»" /></figure><figure><img src="https://media.tproger.ru/user-uploads/101078/2025-01-29/bd209a94-69ee-42bb-ba26-27adfc4c20d2.png" alt="" /></figure><ul><li><b>Structure View</b> — позволяет увидеть все методы и свойства классов в одном месте:</li></ul><figure><img src="https://media.tproger.ru/user-uploads/101078/2025-01-29/15efccac-3f80-402a-bfc5-be06d3ca692d.png" alt="«Как понимать не свой код»" /></figure><figure><img src="https://media.tproger.ru/user-uploads/101078/2025-01-29/8370982b-aa2d-4f03-adc0-9c586c44e740.png" alt="" /></figure><h2>Шаг 7: Отладка и запуск — пошаговое выполнение кода</h2><p>Один из лучших способов понять, как работает чужой код — пройтись по нему в отладчике.</p><p>С помощью отладчика можно видеть значения всех переменных на момент исполнения, проверять различные условия в реальном времени, а также понимать последовательность выполнения кода.</p><p><b>1. Установим breakpoint в методе borrow_book:</b></p><p>2. <b>Запустим тест и пошагово посмотрим:</b></p><figure><img src="https://media.tproger.ru/user-uploads/101078/2025-01-29/69bfc18f-76ab-411b-b8ed-36e886cf954e.png" alt="" /></figure><p>Этот скриншот показывает значения переменных:</p><p><b>3. Затем можно посмотреть пошаговое выполнение кода с помощью функций Step Over, Step Into, Step Out:</b></p><figure><img src="https://media.tproger.ru/user-uploads/101078/2025-01-29/eee25a30-e18b-492e-838b-d6a70f9cbf74.png" alt="" /></figure><p><b>4. Теперь можно попробовать выдать 2 раза одну книгу разным людям и запустить отладку:</b></p><figure><img src="https://media.tproger.ru/user-uploads/101078/2025-01-29/91018ceb-fcfc-4d2a-a4ed-305a9a650ffe.png" alt="" /></figure><p>На этом скриншоте мы видим, что книга с этим id доступна для выдачи. Продолжим выполнять код, нажимаем на кнопку Resume Program:</p><figure><img src="https://media.tproger.ru/user-uploads/101078/2025-01-29/ae92ab74-1d2b-402a-bb2a-c578bd7e8f35.png" alt="" /></figure><p>Теперь мы можем увидеть, что книга уже была выдана. То же самое появляется и в выводе при завершении программы. Так мы пошагово отслеживаем проверку выдачи книги и изменение статуса ее доступности. В общем, полезная штука, если в коде сложная логика, плюс можно найти потенциальные проблемы.</p><h2>Несколько советов, чтобы не сойти с ума, читая чужой код</h2><h4>Рисуйте диаграммы</h4><p>Будущая версия вас обязательно скажет спасибо за то, что этот хаос переменных и циклов вы оформили в виде понятной схемы — что, зачем и куда ведет; а еще оставляли комментарии типа «Вот это не трогай, оно тебя сожрет». На самом деле, визуально представлять чужой код — огромный плюс, особенно если вам потом придется работать над ним вместе с коллегами.</p><h4>Создайте мини-документацию для себя</h4><p>Представьте, что ведете личный дневник по горячим следам. Если в коде вы наткнулись на нечто неочевидное, сделайте краткую запись: что это за модуль, зачем он тут, и как он связан с другими частями. Через неделю, когда вы снова откроете проект, сами себе скажете: «Ого, какой я молодец, всё прописал!».</p><h4>Не пытайтесь понять весь код целиком</h4><p>Если вы считаете, что сядете и поймете весь код за один присест — пересчитайте. Это наш код с библиотекой не такой мудреный, а бывают и проекты, где десятки файлов, подключение API и сотни циклов. Даже опытные разработчики начинают с малого: выбирают один модуль, функцию или файл, и разбираются в них, а уже потом переходят к остальному.</p><h4>Оставайтесь в контексте</h4><p>Если вы изучаете код без понимания, где и как он применяется, это всё равно что настраивать выключенный монитор. Понять контекст можно через вопросы, например: «Что за проект? Какая целевая аудитория? Какие задачи решает этот код?». Например, вы понимаете, что этот модуль связан с оплатами, значит, нужно разобраться, как работает система транзакций.</p><h4>Не забывайте про библиотеки</h4><p>Если в чужом коде много сторонних библиотек и фреймворков, о которых вы могли даже не слышать, обязательно их изучите — именно здесь появляется много багов. И в целом, узнавать новые инструменты — полезно и весело, поскольку они могут выполнять за вас большую часть работы.</p><p>Поздравляем, вы прошли игру. Читать чужой код — практически искусство. Самое важное помнить, что миллионы разработчиков по всему миру с вами в одной лодке. Рассказывайте в комментах, какие проблемы возникали у вас при чтении чужого кода.</p><p>Кстати! Хочешь разбираться в коде быстрее и эффективнее? Собрали для тебя полезные советы <a href="https://t.me/+ySi8k_7h_rxkNzY6">тут</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>Чек-лист по Node.js для новичков: обработка ошибок</title>
      <link>https://tproger.ru/articles/chek-list-dlya-node-js-novichkov--obrabotka-owibok-254149</link>
      <comments>https://tproger.ru/articles/chek-list-dlya-node-js-novichkov--obrabotka-owibok-254149?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Татьяна Жукова]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/chek-list-dlya-node-js-novichkov--obrabotka-owibok-254149</guid>
      <description><![CDATA[<p>Чек-лист для Node.js новичков. Показываем основные подходы к обработке ошибок. Рассматриваем пошаговую инструкцию и практические примеры ✔ Tproger</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/chek-list-dlya-node-js-novichkov--obrabotka-owibok-254149">Чек-лист по Node.js для новичков: обработка ошибок</a>»</p>]]></description>
      <category><![CDATA[JavaScript]]></category>
      <category><![CDATA[Java]]></category>
      <category><![CDATA[Тестирование]]></category>
      <category><![CDATA[Парсинг]]></category>
      <category><![CDATA[JSON]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[Node.js]]></category>
      <category><![CDATA[Приложение]]></category>
      <category><![CDATA[Сервер]]></category>
      <category><![CDATA[Библиотеки]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Mon, 27 Jan 2025 10:04:22 GMT</pubDate>
      <content:encoded><![CDATA[<p>Ошибки — неизбежная часть разработки, но в Node.js они могут не просто сломать приложение, а привести к утечкам данных, бесконечным зависаниям или даже сбоям всего сервера. Поэтому обработка потенциальных ошибок — не опциональный шаг, а ключевой элемент надежного кода. Сегодня разберем, какие бывают ошибки в Node, как правильно с ними работать и что иногда упускают новички.</p><h2>Типы ошибок в Node.js и основные подходы к их обработке</h2><h3>Синхронные ошибки</h3><p>В экосистеме Node синхронные ошибки представляют собой исключения, которые возникают в процессе выполнения кода и приводят к немедленному завершению программы, если их не обработать. Встречаются в тех случаях, когда код выполняется последовательно, без использования асинхронных операций. Разработчик, взаимодействующий с Node с нуля, должен понимать природу таких ошибок и уметь эффективно организовывать их обработку.</p><p>Если такая ошибка не перехвачена, она приведёт к аварийному завершению процесса. Какие есть примеры?</p><h4>Ошибки типа (TypeError, ReferenceError)</h4><p>Они возникают, когда код обращается к переменной, которая не определена, или передаёт в функцию аргумент неподходящего типа.</p><h4>Ошибки парсинга JSON</h4><p>Если переданный JSON-строковый объект невалиден, JSON.parse() выбросит исключение.</p><h4>Деление на ноль или некорректные математические операции</h4><p>JavaScript допускает деление на ноль, но оно может приводить к логическим ошибкам.</p><p>Но как правильно обрабатывать синхронные ошибки?</p><h4>Используем try...catch</h4><p>Классический способ перехвата ошибок в синхронном коде — использование конструкции try...catch.</p><h4>Генерируем пользовательские ошибки</h4><p>Можно явно выбрасывать ошибки с пояснением:</p><h4>Используем process.on('uncaughtException', callback)</h4><p>Node позволяет перехватывать необработанные ошибки глобально:</p><p>Синхронные ошибки в Node могут возникать по разным причинам: неверный тип данных, ошибки в логике или работе с JSON и т.д.. При работе важно помнить, что их можно перехватывать try...catch, выбрасывать вручную с пояснениями и даже обрабатывать глобально с помощью process.on(). Это снижает вероятность неожиданного завершения работы сервера и повышает надежность приложений.</p><h3>Асинхронные ошибки</h3><p>В отличие от синхронных, асинхронные ошибки в Node не прерывают выполнение кода немедленно, а возникают в процессе работы асинхронных операций. Это делает их обработку более сложной, поскольку ошибки могут всплывать после завершения основной логики программы.</p><p>Асинхронные ошибки в Node могут проявляться в трёх основных сценариях:</p><ol><li>Ошибки в коллбэках;</li><li>Ошибки в промисах;</li><li>Ошибки в async/await.</li></ol><p>Разработчик должен уметь обрабатывать потенциальные ошибки во всех этих случаях, чтобы избежать непредсказуемого поведения приложения.</p><h4>Ошибки в коллбэках</h4><p>Коллбэк-функции — один из старейших способов работы с асинхронностью в Node. Однако при их использовании легко столкнуться с ошибками, если не следить за правильной передачей аргументов и выполнением условий.</p><p>Пример: ошибка внутри коллбэка</p><p>Здесь, если файл nonexistent.txt отсутствует, в err передается ошибка, и программа не падает, а просто выводит сообщение. Однако, если бы в коде не было проверки if (err), приложение завершилось бы при попытке обработать data.</p><p>Как правильно обрабатывать ошибки в коллбэках?</p><ol><li>Всегда проверять аргумент err;</li><li>Передавать ошибки дальше, если не знаем, как с ними работать.</li></ol><p>Пример обработки ошибки и её проброса:</p><h4>Ошибки в промисах</h4><p>Промисы — более современный способ работы с асинхронностью в Node. Они позволяют избежать глубокой вложенности (callback hell) и обеспечивают удобный механизм обработки ошибок.</p><p>Пример: промис с ошибкой</p><p>Здесь, если в fetchData произойдёт ошибка (reject вызывается с new Error()), она будет перехвачена в .catch().</p><p>Как правильно обрабатывать ошибки в промисах?</p><ol><li>Использовать .catch() для перехвата ошибок;</li><li>Использовать .finally(), если нужно выполнить код в любом случае;</li><li>Не забывать возвращать промисы из функций.</li></ol><p>Пример корректной обработки:</p><h4>Ошибки в async/await</h4><p>async/await — современный способ работы с асинхронным кодом, который позволяет писать его в стиле синхронного. Однако ошибки в таком коде не всегда очевидны, особенно если промисы не обернуты в try...catch.</p><p>Пример ошибки в async/await:</p><p>Если getUser() выбросит ошибку, программа аварийно завершится. Чтобы избежать этого, нужно использовать try...catch.</p><p>Как правильно обрабатывать ошибки в async/await?</p><ol><li>Оборачивать вызовы await в try...catch;</li><li>Использовать catch() для перехвата на уровне вызова.</li></ol><p>Пример правильной обработки:</p><p>Или можно обработать ошибку прямо в .catch():</p><p>Асинхронные ошибки в Node могут проявляться в коллбэках, промисах и async/await. Каждый из этих подходов требует своей стратегии обработки ошибок:</p><ul><li>В коллбэках всегда проверяйте err;</li><li>В промисах используйте .catch() и .finally();</li><li>В async/await оборачивайте код в try...catch.</li></ul><p>Грамотная обработка ошибок в асинхронном коде — залог стабильности и предсказуемости работы Node-приложения.</p><h2>Чек-лист для новичков: как правильно обрабатывать ошибки в Node.js</h2><p>Ошибки в коде неизбежны, но грамотная обработка позволяет минимизировать их влияние на работу приложения. Даже если вероятность проблемы кажется низкой, её игнорирование может привести к неожиданным сбоям, утечке данных и того хуже. Рассмотрим, какие шаги должен предпринять новичок, чтобы сделать своё приложение в Node.js устойчивым к ошибкам.</p><h3>Всегда обрабатывайте ошибки, даже если они маловероятны</h3><p>Игнорирование ошибок может привести к фатальным последствиям: например, неожиданное исключение может привести к падению всего сервера. Поэтому всегда старайтесь обрабатывать даже маловероятные ошибки.</p><p>Пример ошибки без обработки:</p><p>Этот код вызовет исключение SyntaxError и остановит выполнение программы.</p><p>Правильный вариант с обработкой:</p><p>Даже если кажется, что JSON всегда будет корректным, лучше обработать его парсинг в try...catch, чтобы избежать сбоев.</p><h3>Используйте централизованный обработчик ошибок (middleware в Express)</h3><p>Если в вашем приложении на Express.js ошибки обрабатываются в каждом обработчике маршрута отдельно, это приведёт к дублированию кода. Вместо этого используйте централизованный middleware.</p><p>Что делать с централизованным обработчиком ошибок в Express?</p><ol><li>Определите middleware для обработки ошибок;</li><li>Все ошибки передавайте через next(error);</li><li>Express автоматически передаст ошибку в обработчик.</li></ol><p>Пример:</p><p>Теперь любая ошибка, возникшая в обработчиках маршрутов, будет передаваться в этот middleware, логироваться и возвращать корректный ответ клиенту.</p><h3>Логируйте ошибки (например, с помощью Winston или Pino)</h3><p>Логирование ошибок помогает отслеживать сбои и анализировать их причины. В продакшен-приложениях нельзя ограничиваться console.log() — лучше использовать специализированные библиотеки.</p><p><b>Как работает Winston?</b></p><p>Winston — это гибкий логгер для Node.js, поддерживающий сохранение логов в файлы, базу данных и удалённые сервисы.</p><p>Установка:</p><p>Настройка логгера:</p><p>Использование в коде:</p><p>Теперь ошибки будут логироваться как в консоли, так и в файле errors.log.</p><h3>Генерируйте пользовательские ошибки через Error (или свои классы ошибок)</h3><p>Вместо простых строковых сообщений об ошибках используйте объекты Error или создавайте собственные классы ошибок для лучшей структуризации.</p><p>Простой пример с Error:</p><p>Создание собственного класса ошибок:</p><p>Использование классов ошибок делает код более читаемым и удобным для отладки.</p><h3>Не забывайте про process.on('unhandledRejection') и process.on('uncaughtException')</h3><p>В приложениях на Node.js есть два типа необработанных ошибок, которые могут привести к завершению процесса:</p><ul><li>unhandledRejection — когда промис отклонён (Promise.reject()), но у него нет обработчика .catch();</li><li>uncaughtException — когда код выбрасывает исключение, но оно не обрабатывается try...catch.</li></ul><p>Чтобы защититься, добавьте обработчики для глобальных ошибок:</p><p>Эти обработчики помогут отлавливать неожиданные ошибки и предотвращать аварийное завершение программы.</p><h3>Добавьте тесты для проверки поведения вашего кода при ошибках</h3><p>Тестирование обработки ошибок помогает убедиться, что приложение корректно реагирует на сбои. Поэтому используйте Jest для тестирования.</p><p>Пример теста на обработку ошибок с Jest:</p><p>Регулярные тесты помогут выявлять проблемы до развертывания в продакшен.</p><p>Резюмируем:</p><ul><li>Обрабатывайте ошибки, даже если они маловероятны — лучше перестраховаться, чем допустить неожиданный сбой.</li><li>Используйте централизованный обработчик ошибок (middleware) в Express — это упростит код и улучшит поддержку.</li><li>Логируйте ошибки (Winston, Pino) — так вы сможете отслеживать и анализировать сбои.</li><li>Создавайте собственные классы ошибок — это сделает код чище и понятнее.</li><li>Обрабатывайте глобальные ошибки (unhandledRejection, uncaughtException) — чтобы сервер не падал неожиданно.</li><li>Пишите тесты на обработку ошибок — так ваш код будет надёжнее.</li></ul><h2>Практические примеры: обработка ошибок в Node.js</h2><p>Ошибки — неотъемлемая часть разработки, и их грамотная обработка играет ключевую роль в создании надёжных приложений. Рассмотрим практические примеры реализации обработки ошибок в API на Express, создания пользовательских классов ошибок и настройки глобального обработчика.</p><h3>Обработка ошибок в API с использованием Express</h3><p>Для примера создадим маршрут, который вызовет ошибку, и настроим обработчик:</p><p>Что здесь важно?</p><ul><li>Передача ошибок через next(error) — это стандартный способ уведомить Express о том, что произошла ошибка;</li><li>Централизованный обработчик (middleware) позволяет управлять ошибками в одном месте.</li></ul><h3>Пример пользовательского класса ошибок</h3><p>Иногда стандартного объекта Error недостаточно для описания специфики ошибки. В таких случаях можно создать собственный класс:</p><p>Что здесь важно?</p><ul><li>Так можно чётко разделять типы ошибок;</li><li>Так можно упростить добавление новой логики обработки для каждого типа ошибок.</li></ul><h3>Как настроить глобальный обработчик ошибок</h3><p>Некоторые ошибки не обрабатываются в отдельных блоках try...catch или маршрутах. Для таких ситуаций нужны глобальные обработчики ошибок.</p><h4>Глобальная обработка unhandledRejection и uncaughtException</h4><p>Глобальные обработчики защищают приложение от аварийных завершений:</p><p>Что здесь важно?</p><ul><li>unhandledRejection — позволяет обрабатывать промисы без catch;</li><li>uncaughtException — защищает приложение от ошибок, не пойманных в try...catch.</li></ul><p>Пример с промисом:</p><p>Обработка ошибок — обязательная часть разработки в Node.js, особенно для приложений в продакшене. Рассмотренные примеры помогут программисту:</p><ul><li>Правильно организовать обработку ошибок в API;</li><li>Создавать пользовательские классы ошибок для улучшения читаемости и поддержки кода;</li><li>Настраивать глобальные обработчики, чтобы защитить приложение от необработанных ошибок.</li></ul><h2>Частые ошибки при обработке ошибок в Node.js</h2><p>Даже опытные разработчики иногда совершают ошибки при обработке. Недочёты могут привести к неожиданным сбоям, утечкам данных или усложнению отладки. Рассмотрим наиболее распространённые ошибки, которые допускают программисты, и разберём, как их избежать.</p><h3>Пропуск ошибок в асинхронных функциях</h3><p>Асинхронный код в Node.js требует особого внимания, поскольку ошибки в промисах и async/await могут не перехватываться автоматически.</p><h4>Ошибка: нет обработки ошибок в промисах</h4><p>Если файл не существует, программа завершится с ошибкой UnhandledPromiseRejectionWarning.</p><h4>Правильный вариант: обработка через try...catch</h4><p>Теперь даже если файл отсутствует, приложение не вылетит, а отобразит сообщение об ошибке.</p><p>Запоминаем:</p><ul><li>Всегда используйте try...catch внутри async-функций;</li><li>При использовании промисов добавляйте .catch(), чтобы предотвратить unhandledRejection;</li><li>Используйте глобальный обработчик process.on("unhandledRejection"), если работаете с большим количеством промисов.</li></ul><h3>Логирование конфиденциальных данных</h3><p>Логирование — полезная практика, но если неосторожно записывать ошибки в логи, можно случайно сохранить конфиденциальные данные — пароли, токены или платежные данные.</p><h4>Ошибка: логирование чувствительных данных</h4><p>Ошибка здесь в том, что в логи попадает пароль пользователя.</p><h4>Правильный вариант: фильтрация логов</h4><p>Запоминаем:</p><ul><li>Не логируйте req.body, req.headers, req.query без фильтрации;</li><li>Используйте безопасные библиотеки для логирования, например, winston или pino, с возможностью маскировки данных;</li><li>Избегайте передачи ошибок клиенту без обработки — error.message может содержать внутренние данные системы.</li></ul><h3>Попытка поглощать ошибки вместо их корректной обработки</h3><p>Некоторые разработчики, чтобы избежать сбоев, просто подавляют ошибки, не анализируя их причины. Это приводит к тому, что ошибки замалчиваются, а баги остаются незамеченными.</p><h4>Ошибка: пустой catch-блок</h4><p>Здесь ошибка просто пропадает — приложение продолжает работать, но данные не загружаются, и отладка становится сложнее.</p><h4>Правильный вариант: логирование и повторная обработка</h4><p>Запоминаем:</p><ul><li>Не подавляйте ошибки, если они могут повлиять на логику приложения;</li><li>Логируйте ошибки и передавайте их на следующий уровень обработки, если они критичны;</li><li>Используйте автоматический перезапрос при сбоях, если это возможно (например, с помощью retry-механизмов).</li></ul><p>Обработка ошибок в Node.js — не просто техническая деталь, а критически важная часть разработки. Проблемы могут возникнуть в любом месте кода: от синхронных операций до асинхронных вызовов, API-запросов и работы с базами данных. Следование простым правилам поможет разработчику (будь то джун или сеньор) писать более устойчивый код, избегать критичных багов и создавать по-настоящему надёжные приложения в Node.js.</p>]]></content:encoded>
    </item>
    <item>
      <title>Как отладить код: советы для начинающих</title>
      <link>https://tproger.ru/articles/kak-otladit-kod--sovety-dlya-nachinayushhih</link>
      <comments>https://tproger.ru/articles/kak-otladit-kod--sovety-dlya-nachinayushhih?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Елизавета Малышева]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/kak-otladit-kod--sovety-dlya-nachinayushhih</guid>
      <description><![CDATA[<p>Как отладить код. Показываем основные варианты отладки кода для начинающих. Рассматриваем пошаговую инструкцию ✔ Tproger</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/kak-otladit-kod--sovety-dlya-nachinayushhih">Как отладить код: советы для начинающих</a>»</p>]]></description>
      <category><![CDATA[Тестирование]]></category>
      <category><![CDATA[Для начинающих]]></category>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[IDE]]></category>
      <category><![CDATA[Рефакторинг]]></category>
      <category><![CDATA[Советы]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 15 Jan 2025 10:00:02 GMT</pubDate>
      <content:encoded><![CDATA[<p>В 2017 году Amazon потерял сотни миллионов долларов из-за одной опечатки.</p><p>Сбой длился 4 часа и привёл к сбою в работе Netflix, Airbnb и даже Комиссии по ценным бумагам и биржам США. А виной всему человеческий фактор: сотрудник занимался рутинной отладкой системы, ошибся в команде и отключил сервера, которые отключать было нельзя.</p><p>Да, относиться к отладке кода нужно не менее внимательно, чем к его написанию. Поэтому сегодня мы покажем, как отладить сложный код просто и без паники. Поговорим о ключевых инструментах и дадим советы, которые помогут даже начинающим разработчикам быстро найти проблему.</p><h2>Так отлаживать или дебажить?</h2><p>Дебажить –– англицизм, который значит то же самое. Используйте тот термин, который вам нравится. А мы будем их чередовать.</p><p>Итак, <b>отладка </b>— процесс выявления и исправления ошибок в программном коде.</p><p>Ошибки бывают разные:</p><h3>Синтаксические</h3><p>Синтаксическая ошибка –– это, например, забытая закрывающаяся скобка или пропущенный отступ.</p><p>Здесь синтаксическая ошибка в том, что мы забыли двоеточие в первой строке:</p><p>В Python обязательно нужно ставить двоеточие после объявления функции. Без этого язык не поймет, что за двоеточием следует тело функции. Поэтому программа выполнена не будет.</p><p>Как правильно:</p><h3>Логические</h3><p>Логические ошибки –– неправильная логика программы. Код может выполняться без проблем в синтаксисе и не выбрасывать исключения, но при этом не давать ожидаемого результата. Такие ошибки трудно отследить, потому что Python не сообщает о них явно.</p><p>Допустим, мы пишем программу для проверки чётности:</p><p>Вместо проверки number % 2 == 0 проверяется number % 2 == 1. Это логическая ошибка.</p><h3>Исключения</h3><p>Исключения — ошибки, которые возникают во время выполнения программы. Например, деление на ноль или попытка получить элемент списка по индексу, которого нет.</p><p>Разберём деление на ноль. Это действие вызовет исключение ZeroDivisionError:</p><p>Такие исключения можно обрабатывать, чтобы программа не упала. Используем try-except:</p><p>Итак, каждая ошибка требует своего подхода. Но если знать, как правильно дебажить, вы сможете значительно ускорить процесс и сделать свой код качественным, понятным и надёжным.</p><p>Перейдём к инструкции по отладке.</p><h2>Шаг 1: Анализируем ошибки и логи</h2><p>Перед тем, как отлаживать код, важно понять: что именно пошло не так? Поэтому первый шаг –– анализ.</p><p>Типы ошибок мы уже разобрали, поэтому будет полегче. Иногда их не получается увидеть сразу в коде –– если бы всё было так просто! Тогда на помощь приходят логи, которые предоставляет программа или ваша IDE.</p><h3>Что с ними делать:</h3><ol><li><b>Изучите сообщение об ошибке</b>. Важно понять, где и почему произошёл сбой. Обычно сообщение указывает тип ошибки и место, где она возникла. Мы уже видели такое поведение в предыдущем разделе, когда забыли поставить двоеточие;</li><li><b>Проверьте логи</b>. В логах будут важные данные об ошибке. Обратите внимание на ключевые слова: Error или Exception;</li><li><b>Воспроизведите ошибку</b>. Попробуйте выполнить код несколько раз. Возможно, это был случайный баг, который больше не повторится.</li></ol><figure><img src="https://media.tproger.ru/user-uploads/105990/2025-01-09/3a5b921c-e8b2-44e4-95ed-f08fa42c3352.png" alt="" /></figure><h2>Шаг 2: Разделяем задачу на более мелкие части</h2><p>Сломанный код лучше разбить на более мелкие и понятные части. Это поможет вам найти ошибку быстрее, так как вы точно определите, где её точно нет.</p><h3>Как это работает:</h3><p>Если ошибка возникает в сложном фрагменте, то лучше разделить его на более мелкие шаги.</p><p>Пример: Если программа загружает файл, обрабатывает данные и записывает результат, проверьте отдельно каждую функцию:</p><ul><li>Загружается ли файл?</li><li>Обработались ли данные?</li><li>Успешно ли записывается результат?</li></ul><p>Также можно сузить область поиска ошибки. Если задача большая, начните с проверки небольших фрагментов кода, чтобы изолировать проблемный участок. Загоните ошибку в угол.</p><p>Это лучше, чем хаотично бросаться то в одну, то в другую часть кода и искать иголку в стоге сена.</p><h2>Шаг 3: Воссоздаём проблему</h2><p>Репродукция ошибки — самая важная задача. Чтобы понять, как исправить ошибку, вам нужно её увидеть и поймать. Иногда она проявляется только при определенных условиях, а при каких –– неясно.</p><h3>Тут стоит схитрить:</h3><ul><li>Попробуйте воспроизвести ошибку при разных входных данных. Может быть, строка не ломает программу, а число –– да;</li><li>Пользуйтесь инструментами отладки и отслеживайте каждый шаг программы.</li></ul><p>И тут мы подобрались к самому интересному. Пока что мы говорили о том, как решать проблему. Но не упомянули, с помощью чего. Исправляемся.</p><h3>Отладчики и логирование</h3><p>Отладчики встроены в большинство IDE. Например, в PyCharm или Visual Studio есть встроенные отладчики, с помощью которых можно поставить точки останова.</p><p><b>Точка останова (breakpoint)</b> — инструмент, с помощью которого вы можете остановить программу на определенном этапе и изучить её состояние. Например, проверить, какие значения принимают переменные или что именно происходит перед вызовом ошибки.</p><h3>Как это работает:</h3><ol><li>Установите точку останова в нужной строке;</li><li>Запустите программу в режиме отладки;</li><li>Выполнение остановится на этой строке: изучите текущие данные.</li></ol><h3>Разберём на примере Visual Studio:</h3><p>Напишем небольшую функцию, в которой рассчитывается площадь прямоугольника:</p><p>Поставим точки останова на переменных width, height и result:</p><figure><img src="https://media.tproger.ru/user-uploads/105990/2025-01-09/5a407a82-deb0-414e-bfe1-d8769478f691.png" alt="" /></figure><p>Перейдём вот в эту панельку:</p><figure><img src="https://media.tproger.ru/user-uploads/105990/2025-01-09/334bf52a-3bb1-4e47-b811-5e171235987a.png" alt="" /></figure><p>И запустим дебаггинг:</p><figure><img src="https://media.tproger.ru/user-uploads/105990/2025-01-09/1ccba761-1868-409c-809f-e7236ebae904.png" alt="" /></figure><p>После запуска в редакторе появится новая панелька –– для управления отладкой:</p><figure><img src="https://media.tproger.ru/user-uploads/105990/2025-01-09/6ebecc8b-39e8-4810-b0c8-17f4ba15d78f.png" alt="" /></figure><p>С помощью неё можно остановить или перезапустить отладку, перейти к следующей точке останова и так далее.</p><p>В панели слева появятся значения, за которыми мы следим:</p><figure><img src="https://media.tproger.ru/user-uploads/105990/2025-01-09/dd57b9aa-07ee-4ed5-81f4-b16fdd0a5325.png" alt="" /></figure><p>Здесь вы можете увидеть, чему равна каждая переменная.</p><p>Напишем функцию с ошибкой, которую уже разбирали:</p><p>Мы пытаемся получить элемент, индекс которого не существует. Красная плашка предупреждает, что возникло исключение:</p><figure><img src="https://media.tproger.ru/user-uploads/105990/2025-01-09/83ad8cc2-3a9a-4ff4-9b77-893fc85e255d.png" alt="" /></figure><p>List index out of range –– такого индекса в списке нет. Вроде всё понятно, но можно разобраться.</p><p>Сбоку мы видим список colors, его элементы и длину len(). В Python, как и во многих других языках, отсчёт начинается с 0. Если в списке 3 элемента, то индекс последнего –– 2. Поэтому мы и получаем ошибку.</p><p>Помимо точек останова можно следить за стеком вызовов.</p><p><b>Стек вызовов </b>— цепочка вызванных функций. Она показывает, что происходит на каждом шаге программы.</p><p>Это особенно важно при сложных ошибках, скрытых глубоко в коде. Перепишем немного и сделаем несколько программ:</p><p>Ошибка всё ещё на месте, но теперь её появление происходит не сразу в функции main, а глубже.</p><p>И стек вызовов нам показывает, что сначала выполняется main, затем display_favorite_color и уже потом get_favorite_color, где и живёт ошибка:</p><figure><img src="https://media.tproger.ru/user-uploads/105990/2025-01-09/5226b4c3-9504-47a5-a679-ebebf8ad5bc9.png" alt="" /></figure><p>Эту проблему можно решить с помощью  try-except. Советуем попробовать самостоятельно🙂.</p><p>И последний способ отладки, который разберём –– <b>логирование</b>. Можно использовать print() или модуль, который уже заботливо написали за нас. Результат одинаковый — вывод нужных данных в определённое время. Так мы поймём, что лежит в переменной и почему программа ломается.</p><p>Примеры с print мы уже разбирали в предыдущих шагах. Метод простой и лёгкий –– то, что нужно для новичков.</p><p>Разберём вариант посложнее с модулем logging. Его нужно импортировать и настроить:</p><p>Теперь подробнее про конфигурацию. В logging есть несколько типов сообщений:</p><ul><li>Отладочные –– DEBUG. Они показывают подробности о значениях переменных или работе отдельных функций;</li><li>Информационные –– INFO. В них можно прописывать статусы выполнения программы;</li><li>Предупреждения –– WARNING. Сообщения с потенциальными проблемами;</li><li>Ошибки –– ERROR и CRITICAL.</li></ul><p>Мы указали, что хотим видеть все сообщения с помощью строки 3. Теперь в консоли будет отображаться все, что нужно: предупреждения, ошибки и обычные сообщения отладки.</p><p>А на следующей строке указываем, в каком формате хотим видеть сообщение. В итоге получаем точное время, тип сообщения и само сообщение:</p><figure><img src="https://media.tproger.ru/user-uploads/105990/2025-01-09/578e4185-621c-4213-90a7-8586c7d0d923.png" alt="" /></figure><p>Это намного удобнее, чем прописывать все данные в print вручную.</p><p>Если нам нужны только ворнинги, то меняем конфигурацию:</p><h2>Шаг 4: Тестируем — юнит-тесты и их роль</h2><p>Когда речь идёт об отладке кода, нельзя забывать о тестах. Потому что они помогают выявить ошибки и опасные места на моменте разработки, когда их ещё легко заметить и поправить.</p><p>Юнит-тесты — отличный способ проверять, что каждый блок вашего кода работает как положено.</p><p>Они особенно полезны в отладке сложных программ и приложений, где ошибки могут проявляться только после нескольких шагов или при конкретных входных значениях. Например, при списках.</p><p>Для этого можно использовать pytest или unittest.</p><p>Давайте поработаем с pytest. Напишем в файле main.py очень простую функцию:</p><p>Функция принимает число и возвращает квадрат числа.</p><p>Напишем тест. Для этого нужно установить pytest в свою IDE и создать файлик. Например, test.py:</p><p>Наша гипотеза: 2 в квадрате равно 4. Для того, чтобы её проверить, используем assert.</p><p>Если в терминале запустить команду pytest test.py, то увидим, что всё прошло успешно:</p><figure><img src="https://media.tproger.ru/user-uploads/105990/2025-01-09/ea665183-bc93-4960-a0f0-7120409b02b7.png" alt="" /></figure><p>Если же заменить 4 на 5, то тест упадёт. Так как 2 в квадрате –– не 5:</p><figure><img src="https://media.tproger.ru/user-uploads/105990/2025-01-09/73a7653b-74a0-4fe1-9c1d-335290b99332.png" alt="" /></figure><h2>Советы по улучшению процесса отладки</h2><p>Мы разобрались, как дебажить и тестировать код. Напоследок дадим три базовых совета, которые актуальны не только для Python, но и для любого языка программирования.</p><h3>Делите код на небольшие модули</h3><p>Разбивайте программу на маленькие независимые части. Так их легче тестировать и искать ошибки. Например, вместо одной огромной функции лучше написать несколько компактных. Каждая из них будет отвечать за конкретную задачу. Рефакторинг поможет упростить логику и предотвратить дублирование кода.</p><h3>Пишите автоматические тесты</h3><p>Автоматическое тестирование позволяет ловить ошибки на ранних этапах. Вы можете и не увидеть их сразу. Зато они вас видят.</p><p>Поэтому после написания каждой новой функции добавляйте тесты. Это избавит от сюрпризов в будущем, когда изменение одной программы неожиданно ломает другую.</p><h3>Комментируйте код</h3><p>Не забывайте комментировать код. Объяснять, зачем и как работает каждая функция. Комментарии помогут и вам, и вашей команде быстрее разобраться в коде, особенно спустя несколько месяцев.</p><p>Ну и конечно, называйте функции и переменные понятно. Не усложняйте жизнь себе и коллегам. То, что изначально сделано качественно и с умом, с меньшей вероятностью придётся дебажить.</p><p>Но если всё-таки пришлось, следуйте нашей инструкции, и всё обязательно получится.</p>]]></content:encoded>
    </item>
    <item>
      <title>Python 3.12, 3.13 и 3.14: обновляться или нет?</title>
      <link>https://tproger.ru/articles/python-3-12--3-13-i-3-14--obnovlyatsya-ili-net-</link>
      <comments>https://tproger.ru/articles/python-3-12--3-13-i-3-14--obnovlyatsya-ili-net-?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Александр Киселев]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/python-3-12--3-13-i-3-14--obnovlyatsya-ili-net-</guid>
      <description><![CDATA[<p>Эта статья поможет вам быстро разобраться, что нового появилось в версиях 3.12, 3.13 и 3.14 и решить для себя, пришло ли время обновляться. Основной упор сделан на ключевые нововведения, чтобы составить общую картину и понять куда развивается язык.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/python-3-12--3-13-i-3-14--obnovlyatsya-ili-net-">Python 3.12, 3.13 и 3.14: обновляться или нет?</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Оптимизация]]></category>
      <category><![CDATA[Производительность]]></category>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 09 Jan 2025 14:00:03 GMT</pubDate>
      <content:encoded><![CDATA[<p>Сегодня разберемся, что нового появилось в версиях 3.12, 3.13, 3.14, и решить, пришло ли время обновить проект.  Основной упор сделан на ключевые нововведения, чтобы составить общую картину и понять, куда развивается язык.</p><p>По итогам 2023 года JetBrains публиковали <a href="https://www.jetbrains.com/lp/devecosystem-2023/python/">статистику</a>, в которой основная версия Python 3.11 во многих компаниях всё еще использовалась с долей 27%. На втором месте Python 3.10 с долей 26%. Свежих данных по итогу 2024 года еще нет, но по моим скромным  опросам 3.11 всё еще лидирует во многих компаниях. Обновляться на 3.12 и 3.13 никто не спешит. Почему?</p><p>Для начала давайте разберем все изменения, которые накопились за два года.</p><h2>Python 3.12 — ключевые изменения</h2><h3>Улучшенные f-строки</h3><p>Теперь внутри выражений f-строк можно использовать практически любые валидные конструкции Python:</p><ul><li>Многострочные выражения;</li><li>Те же кавычки, что и у f-строки;</li><li>Бэкслэши и юникод-escape-последовательности;</li><li>Комментарии внутри выражений.</li></ul><p>Это снимает многие ограничения, упрощает написание f-строк и улучшает читаемость кода.</p><p>Изменения описаны в <a href="https://peps.python.org/pep-0701/">PEP-701</a></p><h3>«Персональный» GIL для каждого сабинтерпретатора</h3><p>Добавлена (на уровне C-API) возможность создавать субинтерпретаторы, у каждого из которых свой собственный GIL. Это прокладывает путь к полноценному параллелизму в Python за счёт использования Sub-Interpreters API (в будущем ожидается удобный Python-интерфейс).</p><p>Изменения описаны в <a href="https://peps.python.org/pep-0684/">PEP-684</a></p><h3>Новая система мониторинга исполнения</h3><p>Позволяет профилировщикам, отладчикам и другим инструментам «подписываться» на события в интерпретаторе (вызовы функций, переходы по строкам кода, исключения и т. п.) с минимальными накладными расходами. Теперь можно гибко настраивать, какие события отслеживать, а какие – нет.</p><p>Изменения описаны в <a href="https://peps.python.org/pep-0669/">PEP-669</a></p><h3>Оптимизации comprehension</h3><p>Списковые, словарные и множественные (set) генераторы теперь «инлайнены» (ранее генерировалась скрытая функция). Это позволяет ускорить comprehension почти в 2 раза.</p><p>Изменения описаны в <a href="https://peps.python.org/pep-0709/">PEP-709</a></p><h3>Удаление distutils</h3><p>Модуль distutils, долгое время используемый для управления сборкой и дистрибуцией Python-проектов, наконец-то полностью удалён из стандартной библиотеки в Python 3.12. Это решение было запланировано заранее и сопровождалось подробным руководством по миграции.</p><h3>Другие важные моменты</h3><ul><li>typing: появились новые возможности (<a href="https://peps.python.org/pep-0692/">PEP-692</a> и <a href="https://peps.python.org/pep-0698/">PEP-698</a>) — более гибкая аннотация **kwargs через TypedDict, а также декоратор @override;</li><li>Внутри asyncio улучшена производительность (например, отправка данных через сокеты без лишнего копирования и др.);</li><li>В sqlite3 добавлен CLI-режим, теперь можно запускать python -m sqlite3;</li><li>Улучшены ошибки типа NameError: «Did you forget to import ‘sys’?» и т. д.</li></ul><p><b>Итого:</b> 3.12 сфокусирован на удобстве (f-строки), оптимизации (comprehension, asyncio) и на дальнейшей подготовке к «многопоточному» Python за счёт независимых GIL.<br />Подробнее:  <a href="https://docs.python.org/3/whatsnew/3.12.html">What’s New In Python 3.12</a></p><h2>Python 3.13 — ключевые изменения</h2><h3>Новый интерактивный интерпретатор</h3><p>По умолчанию запускается «улучшенная» REPL (наработки из PyPy):</p><ul><li>Многострочное редактирование;</li><li>История (F2) с пропуском вывода и префиксов &gt;&gt;&gt;/...;</li><li>«Paste mode» (F3);</li><li>Цветные трейсы (traceback) и подсветка ошибок.</li></ul><h3>Экспериментальное отключение GIL</h3><p>Добавлена опция сборки CPython без GIL. Пока что это экспериментальная опция падения производительности в однопоточном режиме и несовместимость с большинством пакетов, которые еще не адаптированы для работы без GIL.</p><p>Изменения описаны в <a href="https://peps.python.org/pep-0703/">PEP-703</a></p><h3>JIT-компилятор</h3><p>Экспериментальный JIT в CPython (доп. опция сборки) пока отключён по умолчанию и даёт лишь небольшой прирост производительности, но ожидаются улучшения в будущих версиях.</p><p>JIT-компилятор (Just-In-Time) в Python ускоряет выполнение кода, превращая часто исполняемые части в машинный код прямо во время работы программы. Это даёт прирост производительности, особенно в интенсивных вычислениях, без необходимости переписывать код. В отличие от стандартной интерпретации, JIT оптимизирует «горячие» участки, сохраняя совместимость с Python, но пока остаётся экспериментальной функцией.</p><p>Изменения описаны в <a href="https://peps.python.org/pep-0744/">PEP-744</a></p><h3>Улучшения в стандартной библиотеке</h3><p>Что произошло:</p><ul><li>Новые модули и функции: dbm.sqlite3, base64.z85encode()/z85decode();</li><li>copy.replace() для быстрого создания «копий с изменениями» (аналог dataclasses.replace(), но для большинства встроенных типов);</li><li>random теперь имеет CLI: python -m random;</li><li>Массовое удаление старых (deprecate) модулей (PEP 594) — убраны cgi, telnetlib, imp, aifc, audioop и др.</li></ul><h3>Изменения в typing</h3><ul><li>TypeVar, ParamSpec и TypeVarTuple теперь могут иметь значения по умолчанию (PEP 696);</li><li>warnings.deprecated() (PEP 702) для единого способа помечать устаревшие функции и классы (как на уровне типов, так и в рантайме);</li><li>ReadOnly для TypedDict;</li><li>Прочие полезные мелочи.</li></ul><h3>Продление срока поддержки</h3><p><a href="https://peps.python.org/pep-0602/">PEP-602</a> теперь даёт новым релизам (начиная с 3.13) 2 года фича-апдейтов и 3 года security-апдейтов.</p><p><b>Итого: </b>3.13 продолжает курс на эксперименты с полной «многопоточностью» (free-threading CPython), вводит JIT, улучшает REPL и продолжает чистить стандартную библиотеку от «мертвых» модулей.</p><p>Подробнее:  <a href="https://docs.python.org/3/whatsnew/3.13.html">What’s New In Python 3.13</a></p><h2>Python 3.14 — ключевые изменения</h2><p>Полноценный выпуск 3.14 запланирован на октябрь 2025 года, но уже сейчас мы имеем представление о том, что войдет в эту версию.</p><h3>Отложенная оценка аннотаций</h3><p>Аннотации теперь не вычисляются сразу, а откладываются до тех пор, пока они не понадобятся. Это снижает накладные расходы при определении функций и классов, устраняя необходимость писать аннотации в кавычках для «forward references».</p><p>Изменения описаны в <a href="https://peps.python.org/pep-0649/">PEP-649</a></p><h3>Новая Python Configuration С-API</h3><p>Расширяет функциональность PEP 587, упрощает и унифицирует процесс конфигурирования Python и его встроенного использования. <br />Проще — лучше, но для обычных разработчиков на Django/FastAPI это пройдет максимально незаметно.</p><p>Изменения описаны в <a href="https://peps.python.org/pep-0741/">PEP-741</a></p><h3>Новые возможности языка</h3><ul><li>map() теперь имеет флаг strict=True по аналогии с zip(strict=True) — проверяет, что все итерации одной длины;</li><li>Добавлены методы float.from_number() и complex.from_number() для конверсии чисел (но не строк!);</li><li>Возможность установить уровень detail для dis (например, --show-positions, --specialized) и т. д;</li><li>Поддержка UUID v8 (uuid.uuid8()) и SHA-256 digest auth в urllib.request.</li></ul><h3>Улучшение ошибок</h3><ul><li>При неправильном распаковочном присваивании теперь показывается фактическое число элементов «got X»;</li><li>Расширены диагностические сообщения в разных участках (например, в ImportError);</li></ul><ul><li>Убран ряд deprecated методов и функционала в модулях ast, asyncio, itertools, pkgutil и т. д.</li></ul><h3>Оптимизация</h3><ul><li>Точки останова и отладка (breakpoint) переиспользуют один экземпляр Pdb;</li><li>Улучшен механизм auto-слежения за процессом (profiling, trace). Меньше накладных расходов при профилировании;</li><li>Множество мелких доработок в модулях и стандартных функциях (например, io, random, multiprocessing).</li></ul><p><b>Итого:</b> 3.14 продолжает курс на улучшение аннотаций (включая отложенную их оценку), вносит мелкие синтаксические удобства, серьёзно расширяет и оптимизирует стандартную библиотеку, удаляет много устаревшего кода.</p><p>Подробнее: <a href="https://docs.python.org/3.14/whatsnew/changelog.html">Python 3.14 Changelog</a></p><h3>Кратко о том, что изменилось:</h3><ul><li>3.12 — крупные шаги в сторону удобства (f-strings, классные улучшения asyncio), чистка старья (distutils) и подготовка к независимым GIL;</li><li>3.13 — экспериментальный free-threading (полное отключение GIL), базовый JIT, улучшенный REPL, удаление целого набора древних модулей, новые возможности в typing;</li><li>3.14 — отложенная оценка аннотаций, дальнейшие улучшения C API, новые фичи в базовых функциях (map(strict=…), и т. д.), подчистка долгих депрекейтов.</li></ul><p>Можно сделать только один вывод. Если вы сейчас работаете на версии 3.11, то особого смысла обновляться всё еще нет. Большая часть нововведений лишь готовит почву для более серьезных изменений. Для внедрения NoGIL как полноценного инструмента может понадобиться больше 5 лет.</p><p>Внятных бенчмарков, которые показывают прирост производительности «в бою» для популярных фреймворков не существует, так что здесь сложно сделать какие-то обоснованные выводы.</p><p>С точки зрения безопасности — для 3.11 патчи будут выходить до октября 2026 года, так что имеет смысл периодически «накатывать» новые минорные версии, чтобы закрыть известные уязвимости. До появления проблем с версиями пакетов, которые будут сбрасывать поддержку 3.11, ждать еще как минимум пару лет.</p><p>Итого, самым разумным решением будет дождаться релиза 3.14 в октябре. К тому времени подтянется и поддержка этой версии у большинства популярных пакетов, а еще станет понятней судьба всех «экспериментальных» нововведений. Больше про разработку рассказываю в своем <a href="https://t.me/kisel_it">Telegram</a>-канале.</p>]]></content:encoded>
    </item>
    <item>
      <title>10 пакетов Python, которые улучшат вашу кодовую базу</title>
      <link>https://tproger.ru/translations/10-paketov-python--kotorye-uluchwat-vawu-kodovuyu-bazu</link>
      <comments>https://tproger.ru/translations/10-paketov-python--kotorye-uluchwat-vawu-kodovuyu-bazu?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Анна Ельцова]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/translations/10-paketov-python--kotorye-uluchwat-vawu-kodovuyu-bazu</guid>
      <description><![CDATA[<p>Black, MyPy, Pydantic, Hypothesis и другие пакеты Python для чистого кода: форматирование, статический анализ, тестирование. Прокачайте свои проекты!</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/translations/10-paketov-python--kotorye-uluchwat-vawu-kodovuyu-bazu">10 пакетов Python, которые улучшат вашу кодовую базу</a>»</p>]]></description>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[Фреймворки и библиотеки]]></category>
      <category><![CDATA[Переводы]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Mon, 19 Aug 2024 10:00:03 GMT</pubDate>
      <content:encoded><![CDATA[<p>Data Scientist'ы и разработчики тратят немало времени на отладку кода, чтобы сделать его более эффективным и простым в дальнейшем использовании. Пользователь Medium <a href="https://medium.com/pythoneers/10-python-packages-i-use-to-elevate-my-codebase-standards-df9a19d9e766">нашел</a> 10 пакетов Python, которые повысили его продуктивность в работе. Рассказываем, как они помогают автоматизировать форматирование кода и тестировать его на выявление ошибок на первых этапах.</p><h2>Black</h2><p>Это <a href="https://github.com/psf/black">инструмент</a>, который одновременно выявляет ошибки и форматирует код на Python. В сообществе питонистов уже давно есть PEP8, оформляющий код в едином стиле, и пойти против него — практически преступление. Black менее красивый, но при этом более консистентный, плюс его нельзя конфигурировать. Об этом даже написано в readme.md пакета:</p><blockquote>By using it, you agree to cede control over minutiae of hand-formatting. In return, Black gives you speed, determinism, and freedom from <b>pycodestyle</b> nagging about formatting. You will save time and mental energy for more important matters.<br /><br />Используя его, вы соглашаетесь больше не контролировать форматирование вручную. Взамен Black «обещает» скорость, определенность и свободу от придирчивого отношения к стилю <b>pycodestyle</b>. Тем самым вы экономите свое время и силы для более важных дел.<br /></blockquote><p>Форматирование кода крайне важно при работе над крупными проектами и в больших командах — код будет в разы проще читать, равно как и выявлять ошибки.</p><p>Для установки вводим в командную строку:</p><p>А чтобы сразу приступить к работе с дефолтными настройками, прописываем:</p><figure><img src="https://media.tproger.ru/user-uploads/101078/2024-08-15/90af5382-2b3c-45fb-ab74-ba121e7d9184.png" alt="" /><figcaption>Неотформатированный и отформатированный с помощью Black код</figcaption></figure><h2>MyPy</h2><p>MyPy — <a href="https://github.com/python/mypy">инструмент</a> статической проверки типов, который поддерживает и динамическую типизацию (duck typing). Он помогает выявлять ошибки несоответствия типов в коде до его выполнения, повышает надежность программы, а еще — поддерживает другие библиотеки и разные режимы проверки типов.</p><p>Для установки вводим:</p><p>Пример кода с ошибками, который проверяет работу MyPy:</p><p>Вывод будет такой:</p><figure><img src="https://media.tproger.ru/user-uploads/101078/2024-08-15/a51709a1-cd7a-4ba8-be14-41c5d8c1d2fa.png" alt="" /></figure><h2>Pydantic</h2><p>Популярная <a href="https://docs.pydantic.dev/latest/">библиотека</a> для проверки данных и управления настройками. Внутри — интуитивно понятный синтаксис и user-friendly инструменты, которые проверяют данные на достоверность и соответствие заданным типам и ограничениям.</p><p>Pydantic определяет структуру данных декларативным способом с помощью аннотаций типов Python, а также использует схему JSON для интеграции инструментов и проверяет стандартные типы библиотек с помощью TydepDicts.</p><p>Вот простой пример, как работает Pydantic:</p><figure><img src="https://media.tproger.ru/user-uploads/101078/2024-08-15/87c606c1-9a36-47be-a5fd-e1bbd4cc60aa.png" alt="" /><figcaption>Код без использования Pydantic и с ним</figcaption></figure><p>Здесь можно увидеть, как использование библиотеки Pedantic уменьшило размер кода и сделало его более понятным за счет того, что в нежелательном кастомном методе validate() особо нет необходимости.</p><h2>Hypothesis</h2><p>Это мощная <a href="https://hypothesis.readthedocs.io/en/latest/">библиотека</a> Python для property-based тестирования, которая генерирует тестовые данные в соответствии с определенными правилами (strategies). Основная идея заключается в том, чтобы задать общие свойства программы, а Hypothesis автоматически сгенерирует множество входных данных для проверки этих свойств.</p><p>Библиотека интегрируется со многими популярными утилитами для тестирования, например, с pytest и unittest.</p><p>Установка:</p><p>Вот пример простого кода с ошибкой деления на 0, которую проверяет «Гипотеза»:</p><p>Тест выдаст следующее:</p><h2>Pre-commit</h2><p>Классный <a href="https://pre-commit.com/">фреймворк</a> Python для управления многоязычными прекоммитами и их поддержки. Он определяет набор проверок и преобразований, которые выполняются в вашем коде автоматически перед каждым коммитом.</p><p>Для установки:</p><p>Вот как это работает:</p><ul><li>Создаем файл .pre-commit-config.yaml в корневой структуре проекта:</li></ul><ul><li>Устанавливаем скрипты Git-хуков:</li></ul><ul><li>Сам коммит-код:</li></ul><p>Pre-commit автоматически проверит код на ошибки и исправит их.</p><h2>Vulture</h2><p><a href="https://pypi.org/project/vulture/">Пакет</a> Python, который выявляет мертвый код в ваших проектах и выдает подробный отчет.</p><p>Мертвый код — код, который никогда не использовался и не выполнялся, он может накапливаться с течением времени, но при этом не несет никакой пользы.</p><p>Устанавливаем:</p><p>Работает это так:</p><h2>Isort</h2><p>Утилита командной строки и одновременно <a href="https://pycqa.github.io/isort/">библиотека</a>, которая упрощает жизнь разработчикам. Она сортирует import Python — упорядочивает и делает его более читабельными, группируя по типу (стандартная библиотека, сторонние и локальные) и выстраивая в алфавитном порядке внутри каждой группы.</p><p>Для установки:</p><p>Пример до и после использования Isort:</p><figure><img src="https://media.tproger.ru/user-uploads/101078/2024-08-15/eb5815aa-bb68-4dba-b11a-46ebc4a6d455.png" alt="" /><figcaption><br /></figcaption></figure><h2>PyDocstyle</h2><p><a href="http://www.pydocstyle.org/en/stable/">Утилита</a> проверяет, соответствует ли ваши docstrings стандарту PEP 257. Это стиль, который упорядочивает высокоуровневую структуру таких строк — что они должны содержать и как их писать (при этом он не затрагивает синтаксис в самих строках).</p><p>Для установки:</p><p>Затем пишем это и проверяем свой код:</p><figure><img src="https://media.tproger.ru/user-uploads/101078/2024-08-15/7250cb05-d4f3-4c46-8a03-ac9e7da0ed7f.png" alt="" /><figcaption>Пример кода автора</figcaption></figure><p>Вывод будет следующий:</p><figure><img src="https://media.tproger.ru/user-uploads/101078/2024-08-15/1f8c1f3d-8d23-4008-8e63-b8933c6625d6.png" alt="" /></figure><h2>Bandit</h2><p><a href="https://bandit.readthedocs.io/en/latest/">Программа</a> проверяет безопасность кода. Она ищет наиболее частые проблемы в приложениях на Python.mlt, анализирует AST (абстрактное синтаксическое дерево) и запускает набор плагинов для выявления ошибок.</p><p>Код, который проверял автор статьи на ошибки безопасности:</p><p>Вот какой результат выдал «Бандит»:</p><figure><img src="https://media.tproger.ru/user-uploads/101078/2024-08-15/68f2fd3f-ffe9-4dbf-82f4-97ae9dacad02.png" alt="" /></figure><h2>Radon</h2><p><a href="https://radon.readthedocs.io/en/latest/">Пакет</a> Python, который анализирует исходный код и вычисляет различные метрики, включая Cyclomatic Complexity (CC), Maintainability Index (MI), Raw metrics (SLOC, комментарии, пустые строки), и Halstead metrics. Radon помогает найти слишком сложные части кода, которые можно упростить, а также выдает отчеты для документирования и проверки кода. Пакет особенно полезен в больших проектах, когда код должен быть качественным, отлаженным и системным.</p><p>Устанавливаем:</p><p>Код, который автор статьи тестировал на сложность:</p><p>Для теста: random cc code.py</p><p>Чтобы эффективнее использовать Radon, можно создать файл конфигурации random.cfg — так будет проще управлять действиями пакета:</p><p>Эта конфигурация исключает определенные каталоги и устанавливает минимальные пороговые значения для Cyclomatic Complexity and Maintainability Index.</p><p><i>Конечно, это далеко не все фичи, которые будут действительно полезны питонистам. Если у вас есть другие крутые решения — приносите в комментарии. </i></p>]]></content:encoded>
    </item>
    <item>
      <title>Продвинутый дебаг в Xcode: средства отладки, про которые часто забывают</title>
      <link>https://tproger.ru/articles/advanced-debuggin-in-xcode</link>
      <comments>https://tproger.ru/articles/advanced-debuggin-in-xcode?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Типичный программист]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/advanced-debuggin-in-xcode</guid>
      <description><![CDATA[<p>Senior iOS-разработчик Noveo напоминает о доступных из коробки техниках: продвинутые брейкпоинты, влияние на состояние приложения, правка UI.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/advanced-debuggin-in-xcode">Продвинутый дебаг в Xcode: средства отладки, про которые часто забывают</a>»</p>]]></description>
      <category><![CDATA[Лучшая практика]]></category>
      <category><![CDATA[Мобильная разработка]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[iOS]]></category>
      <category><![CDATA[Советы]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Mon, 13 Apr 2020 13:09:06 GMT</pubDate>
      <content:encoded><![CDATA[<p>Senior iOS-разработчик Noveo напоминает о доступных из коробки, но часто игнорируемых разработчиками средствах отладки кода в среде Xcode: продвинутое использование брейкпоинтов, влияние на состояние приложения, редактирование UI без перезагрузки и другие техники, которые помогут ускорить отладку приложения или поиск багов.</p><h2>Intro</h2><p>Каждый разработчик, независимо от квалификации и типа текущей задачи, постоянно находится в знакомом всем цикле: мы пишем код, запускаем и исправляем. Количество итераций у каждого разное, но делаем мы это ежедневно множество раз.</p><p>По данным некоторых исследований, мы в среднем тратим до 60% времени на отладку — и это именно усредненное значение, для кого-то, особенно для начинающих разработчиков, оно может быть ещё больше. Пост призван уменьшить это время и сделать процесс отладки эффективнее и приятнее.</p><figure><img src="https://media.tproger.ru/uploads/2020/04/Kod-iznachalnyj-kod_2x.png" alt="" /></figure><p>Давайте посмотрим на процесс изнутри. Я привёл немного странный пример, но он достаточно связан с ежедневной рутиной и отлично опишет большинство кейсов. Этот код вычисляет высоту ячейки таблицы. Высота зависит от некоторых констант и параметров. Допустим, в некоторых случаях высота рассчитывается неверно. Наша задача — изучить эту функцию, например узнать значение флага showTitle в момент вычисления. Что первым приходит на ум? Правильно, поместить print() для отладки.</p><p>Запускаем проект — он у нас большой, да и Xcode неидеальный. Чаще всего происходит всем знакомая ситуация: добавили одну строчку и ждём минуту, пока соберётся. А ведь кроме сборки и запуска нужно ещё и восстановить условия, добраться до нужного экрана, воспроизвести проблему и только после этого посмотреть вывод свежедобавленного print‘a.</p><p>Как это обычно бывает, с первого раза расставить print‘ы в полезных местах довольно трудно. Так произошло и в этот раз. Само по себе знание о состояниии флага нам почти ни о чём не говорит, поэтому было решено добавить ещё один print с информацией об элементе, для которого производится расчёт. Затем мы пожелали переопределить некоторые значения констант и сделать исключение для одного элемента.</p><figure><img src="https://media.tproger.ru/uploads/2020/04/Kod-posle-jeksprerimentov_2x.png" alt="" /></figure><p>И снова нас ждёт сборка, воспроизведение условий и анализ. Мне кажется, все через это проходили и, надеюсь, это — притянутая за уши история, существующая лишь как вводная для этой статьи. Справедливости ради замечу, что отладка через print’ы сама по себе не является чем-то плохим. Порой это единственный способ отладить что-то в сложных ситуациях, например когда ошибки происходят в оптимизированном компилятором коде. Но сегодня разговор пойдёт о простых сценариях, которые чаще всего происходят во время разработки.</p><h2>Breakpoints</h2><p>Мы уже выяснили, что отладка через добавление вывода в консоль не совсем эффективна и нам нужен какой-то инструмент, который облегчит нам жизнь. Таким инструментом являются брейкпоинты. Все мы любим этот механизм, который представлен практически в любой среде разработки на любых платформах и языках, и пользуемся им. Где-то он реализован лучше, где-то хуже, но в целом Apple предоставила нам мощный и гибкий механизм точек останова. Однако, работая с разными людьми, я заметил, что пользуются ими в большинстве случаев исключительно для остановки программы — просто чтобы убедиться, что её выполнение пошло по запланированному сценарию. Иногда люди пользуются консолью отладки и командой po, но лишь в тех случаях, когда нужно разок выяснить состояние переменной. Я предлагаю рассмотреть дополнительные возможности отладчика, встроенного в нашу IDE, и привести примеры ситуаций, в которых они могут пригодиться.</p><h3>Conditional breakpoints</h3><figure><img src="https://media.tproger.ru/uploads/2020/04/Okno-redaktirovanija-brejkpointa.png" alt="" /></figure><p>Начнём с очевидного: conditional breakpoints. Как ни странно, строка, позволяющая указать условия срабатывания брейкпоинта, всегда у нас перед глазами, но почему-то люди удивляются такой возможности. Для удивлённых самим наличием такого диалога — его можно увидеть, если дважды нажать на сам брейкпоинт. В эту строку можно записать любое выражение, которое может вернуть булево значение, будь то сравнение переменной из текущей области видимости или вовсе значение какого-то синглтона. Но будьте внимательны — медленно вычисляемое выражение способно существенно снизить производительность вашей программы.</p><h3>Skipping</h3><p>Следующей возможностью, которая тоже обделена вниманием разработчиков, является игнорирование N-го количества срабатываний. Эта возможность может пригодиться, например, в рекурсивных функциях, чтобы посмотреть, что происходит на N-ой глубине, или же посмотреть результат функции для N-го элемента массива. В примере с массивом этот способ будет предпочтительнее установки условия, т.к. не требует вычисления выражения.</p><h3>Actions</h3><figure><img src="https://media.tproger.ru/uploads/2020/04/GIF-nazhatija-na-Add-Action.png" alt="" /></figure><p>Но самое интересное дня нас кроется за кнопкой Add Action. Эта кнопка позволяет добавить дополнительное действие, которое будет вызвано в момент срабатывания брейкпоинта. Как вы видите, есть 6 типов действий, которыми можно дополнить брейкпоинт:</p><ol><li>Apple script. Позволяет запустить скрипт на одноименном языке.</li><li>Capture GPU Frame. Для отладки приложений, использующих движок Metal, может потребоваться эта опция.</li><li>Debugger command. Позволяет выполнить команду отладчика. О ней мы поговорим позже.</li><li>Log-message. Позволяет вывести текстовое сообщение в лог.</li><li>Shell command. Позволяет выполнить произвольную команду в среде, дефолтной для системы командной оболочки, sh/bash/zsh.</li><li>Sound. Позволяет проиграть звук из динамиков компьютера, на котором запущен Xcode.</li></ol><p>Я не буду рассказывать о первых двух типах — они слишком специфичны и вряд ли вам пригодятся. А ещё пропущу последний пункт, так как особо рассказывать там нечего. Но помнить о нём стоит — он может вам пригодиться, например, когда нужно быстро совершить некое действие в приложении вслед за триггером, которым и может являтся звук от брейкпоинта, поставленного в нужное место.</p><h3>Log message</h3><figure><img src="https://media.tproger.ru/uploads/2020/04/Redaktirovanie-brejkpointa-s-jekshenom-Log-Message.png" alt="" /></figure><p>Рассмотрим чуть более подробно тип дополнительного действия «Log message».</p><p>Если мы его выберем, к нашим услугам окажется строка ввода формата сообщения. Обратите внимание, что в строке можно указывать полезные плейсхолдеры, два из которых позволяют подставить информацию о брейкпоинте и одно, самое полезное, позволяет подставить результат вычисления произвольного выражения. Таким выражением может быть переменная или любая другая конструкция используемого вами языка программирования. Но это не имеет никакого смысла, если не поставить галочку «Automatically continue after evaluating actions». Именно она в паре с любым из действий позволит нам экономить время на дебаге. Больше не нужно писать print(), пересобирать проект и ждать вечность. В любой момент времени, без перезапуска проекта вам доступен вывод в консоль отладки любой информации о ходе выполнения программы. А для знающих толк в извращениях дебаге Apple предусмотрела возможность воспроизвести выражения, используя встроенный синтезатор речи.</p><h3>Shell command</h3><figure><img src="https://media.tproger.ru/uploads/2020/04/Redaktirovanie-brejkpointa-s-jekshenom-shell-command..png" alt="" /></figure><p>Нетрудно догадаться, что этот экшен позволяет запустить произвольную команду в стандартной оболочке терминала ОС. Как и «Log message», она позволяет вычислить результат выражения в текущем контексте и дополнить им аргументы вызова команды. Для чего это может быть полезно? Примеров использования можно придумать массу. Из реальной жизни: запуск троттлинга через Charles. Необходимо было замедлять запросы из определённой точки, при этом в остальное время соединение должно было быть полноценным. Я не успевал включать-выключать троттлинг вручную и ещё совершать действия в симуляторе. Такой трюк с брейкпоинтом и «Shell command» отлично меня выручил. В другой раз мне понадобилось изменять информацию на сервере прямо параллельно с запросом, чтобы отловить довольно странный баг. Тут тоже был кстати этот вид брейкпоинта. Особые извращенцы могут собрать конструкцию на Arduino с электрошокером и бить себя током при каждом срабатывании нежелательного кода. Шучу. Не пытайтесь это воспроизвести в реальной жизни.</p><h3>Debugger command</h3><figure><img src="https://media.tproger.ru/uploads/2020/04/Redaktirovanie-brejkpointa-s-jekshenom-Debugger-command.png" alt="" /></figure><p>Одним из самых интересных видов экшенов я считаю «Debugger command». Этот экшен позволяет действительно безгранично влиять на отлаживаемую программу. Debugger command — это команды отладчика LLDB, а LLDB — это отладчик для проекта LLVM, который сейчас используется Apple и Xcode для сборки программ. Отладчик LLDB позволяет подключаться к процессу, прерывать выполнение программы и воздействовать на её память. Для этого отладчик имеет множество команд, некоторые из которых станут героями сегодняшнего повествования. Именно благодаря отладчику LLDB у нас в принципе есть такая замечательная возможность отлаживать программу, в частности устанавливать брейкпоинты. Начнём мы с самой известной команды — po. Наверняка многие из вас уже не раз использовали эту команду при отладке, но для меня в своё время это стало открытием, хотя я уже имел некоторый опыт в разработке под iOS на тот момент. Po — это сокращение от print object. Команда позволяет вычислить выражение из правой части от команды и распечатать в консоли результат выполнения. При этом у объекта запросится его debugDescription, если он определён, или просто description, если нет. У po существует команда-прародитель — print, или p, которая точно так же вычислит выражение и распечатает результат, но только в этом случае вам будет доступна сырая информация об объекте или скалярном типе. Обе эти команды будут компилировать введенное выражение в текущем контексте, что неминуемо замедлит выполнение кода при срабатывании брейкпоинта. К счастью, в Xcode 10.2 Apple добавили ещё одну команду отладчика — v, которая работает значительно быстрее. Она позволяет вывести в консоль значение переменной из текущей области видимости, но, в отличии от p и po, без компиляции выражения. Естественное ограничение, накладываемое этой особенностью, — вывод в консоль возможен только для хранимых свойств.</p><figure><img src="https://media.tproger.ru/uploads/2020/04/exampleimg.png" alt="" /></figure><h3>Affecting execution flow</h3><p>Такая комбинация (брейкпоинт + debugger command po + автоматическое продолжение) заменит нам описанную ранее Log message. Что же ещё мы можем сделать с помощью такой комбинации? Например, с помощью дебаггера мы можем пропустить выполнение нескольких строчек кода, будто они закомментированы. При этом вам не нужно пересобирать программу и заново воспроизводить условия. Для этого достаточно ввести thread jump --by 1 для скачка вперёд на одну строчку или же thread jump --line 44 для перехода, как вы уже могли догадаться, к 44 строчке. Но будьте осторожны — вы не можете на 100% безопасно перепрыгивать по строчкам. Дело в том, что вы можете перепрыгнуть через инициализацию некоторой переменной, и это вызовет краш. Дело осложняется тем, что Swift «ленив» по своей природе, и инициализация может происходить не там, где вам кажется. Плюс компилятор при сборке вашей программы вставляет дополнительные инструкции, например для управления памятью, пропуская которые вы рискуете получить в лучшем случае утечку, в худшем — краш.</p><h3>Affecting debugger</h3><figure><img src="https://media.tproger.ru/uploads/2020/04/Redaktirovanie-brejkpointa-s-vvedennoj-komandoj-i-Leo-DiKaprio-iz-mema-We-Need-Go-Deeper-.png" alt="" /></figure><p>Кроме влияния на вашу программу, с помощью отладчика вы можете влиять на сам отладчик. Например, мы можем поставить брейкпоинт из брейкпоинта. Вы спросите, зачем это нужно? Бывают методы общего назначения, которые срабатывают по ряду триггеров. Например функция по отправке сообщения в аналитику может вызываться сотню раз в секунду, а нам нужно отловить именно ту отправку, которую породит нажатие на кнопку. В этом случае мы можем поставить брейкпоинт на метод нажатия кнопки и добавить команду установки брейкпоинта на произвольной строке программы в произвольном файле. Команда bp s -o -f Calc.swift -l 44 расшифровывается как breakpoint set one-shot на файл Calc.swift на строку 44. Модификатор -o или --one-shot создаст специальный тип брейкпоинта, который «живёт» ровно до момента своего срабатывания, а после исчезает. Таким нехитрым способом мы можем создавать интересные алгоритмы установки брейкпоинтов для отладки нетривиальных багов.</p><h3>Other breakpoints types</h3><figure><img src="https://media.tproger.ru/uploads/2020/04/Panel-perekljuchenija-vidov-levoj-funkcionalnoj-kolonki-XCode-c-otkrytym-Breakpoint-Navigator-i-neskolkimi-brejkopintami.png" alt="" /></figure><p>А есть ли ещё виды брейкпоинтов, о которых мы можем не знать? Конечно, есть. Xcode позволяет добавить некоторые виды брейкпоинтов, которые не относятся к какому-то конкретному файлу и строке. В Xcode есть вкладка Breakpoint Navigator, которая позволяет управлять уже созданными брейкпоинтами сквозь все файлы проекта, а также создавать новые. Внизу окна нашего IDE есть кнопка со значком плюса.</p><figure><img src="https://media.tproger.ru/uploads/2020/04/Nizhnjaja-funkcionalnaja-panel-leovoj-koloki-XCode-pri-otkrytom-Breakpont-Navigator.png" alt="" /></figure><p>Это позволяет использовать 6 дополнительных типов брейкпоинтов:</p><ol><li>Swift Exception брейкпоинт — брейкпоинт, останавливающий программу при срабатывании не перехваченного throw для Swift кода.</li><li>Exception брейкпоинт — то же самое, но для мира ObjC. Может показаться, что это не актуальный в современном мире брейкпоинт, но это не так. Стоит помнить, что нам пока всё ещё нужен UIKit, написанный на ObjC, ошибки которого мы можем отловить с помощью такого вот брейкпоинта.</li><li>Symbolic breakpoint — позволяет останавливать процесс выполнения программы при выполнении кода, ассоциированного с некоторым идентификатором, который Apple называет символом. О символах я расскажу чуть позже.</li><li>OpenGL ES Error брейкпоинт — брейкпоинт, останавливающий программу при возникновении ошибки OpenGL при разработке соответствующих приложений.</li><li>Constraint Error breakpoint — очевидно, остановит вашу программу при возникновении ошибки автолейаута.</li><li>Test Failure breakpoint может вам помочь при отладке тестов.</li></ol><p>Так как уместить в этой сессии обзор всех типов точек останова не представляется возможным, я остановлюсь только на самых часто используемых. По своему опыту — я всегда использую Exception breakpoint. Довольно часто при разработке программ я сталкиваюсь с перехваченными системными исключениями, отладить которые порой проблематично из-за крайне неинформативного call stack’а. Думаю, вы сталкивались хоть раз с такой или подобной ошибкой:</p><figure><img src="https://media.tproger.ru/uploads/2020/04/Soobshhenie-v-Debugger-Console-pri-padenii-prilozhenija-iz-za-ne-perehvachennogo-iskljuchenija-ObjectiveC.png" alt="" /></figure><h3>Exception breakpoint</h3><p>Для того, чтобы сделать стек вызова более информативным, мы можем добавить Exception breakpoint. Он позволит остановить программу прямо на моменте выброса исключения и отследить цепочку событий, которые привели к такому результату. По умолчанию неперехваченное исключение вызовет аварийную остановку приложения, и в стеке вызова мы ничего полезного не увидим, т.к. исключение будет пробрасываться вверх по стеку вызова и вся информация о месте выброса будет утеряна. Exception breakpoint позволяет остановить программу в момент выброса исключения и уже привычными нами методами получить гораздо больше информации о проблеме, пройдясь по стеку вызова и просмотрев значения переменных, если это необходимо. Я считаю этот тип брейкпоинта очень полезным и использую его на всех проектах по умолчанию. Для этого в Xcode есть удобный механизм, который позволяет указать брейкпоинту уровень и хранить его на трёх уровнях:</p><ol><li>Проект.</li><li>Воркспейс.</li><li>Пользователь.</li></ol><p>Просто нажмите на брейкпоинт правой кнопкой мыши и выберите Move breakpoint. Перенесённый на уровень пользователя, брейкпоинт будет доступен на всех проектах, какой бы вы ни открыли в вашем Xcode.</p><h3>Symbolic Breakpoint</h3><figure><img src="https://media.tproger.ru/uploads/2020/04/Okno-dobavlenija-Symbolic-Breakpoint.png" alt="" /></figure><p>Вторым часто используемым типом брейкпоинтов является Symbolic Breakpoint. Ранее я уже писал, что этот брейкпоинт позволяет останавливать программу при выполнении кода, ассоциированного с каким-то символом, и обещал рассказать подробнее про символы. Так вот, символы — это человекопонятные идентификаторы, которые ассоциируются с тем или иным адресом в памяти. LLDB умеет маппить известные ей символы в адреса функций и наоборот. При каждой сборке проекта система создаёт особый бандл из специальных файлов в формате dSYM, которые расшифровываются как Debug Symbols. Эти файлы хранят что-то вроде таблицы, содержащей в себе некоторые адреса методов и некоторые идентификаторы, среди которых сигнатуры методов, имена файлов, смещения и номера строк. Именно благодаря этим файлам мы можем поставить брейкпоинт на строку файла, получить читаемый стек вызова или расшифровать crashlog приложения из AppStore.</p><p>Благодаря этому механизму мы можем поставить брейкпоинт на любом методе класса, зная только его название. При этом нам не нужно достоверно знать, где этот метод объявлен и доступны ли вообще нам исходные файлы. Давайте рассмотрим реальный пример. Вас перевели на новый проект, и первая задача — исправить непонятное поведение на форме ввода данных кредитной карты, когда посреди набора фокус вдруг перепрыгивал на поле ввода имени. Сходу ничего не понятно, кода много, но симптомы ясны. Для расследования необходимо понять, кто и почему инициирует смену фокуса. Можно долго читать код, искать логику в неочевидных расширениях классов, а как надоест — сделать наследника UITextField, переопределив там метод becomeFirstResponder(), поменять реализации и уже там поставить брейкпоинт. А можно за 10 секунд создать символьный брейкпоинт -[UITextField becomeFirstResponder], и программа остановится в момент смены фокуса. По цепочке бэктрейса мы сможем легко восстановить последовательность событий, которые приводят к нежелательным результатам.</p><p>У тех, кто пользуется таким видом брейкпоинта в первый раз, наверняка возник вопрос: а что это за символ -[UITextField becomeFirstResponder]? Это ObjectiveC-сигнатура метода установки текста для лейбла. Использование ObjectiveC обусловлено тем, что UIKit написан именно на этом языке. Пара слов для тех, кто имел мало опыта с ObjectiveC. Знак минуса обозначает, что нас интересует инстанс-метод, а не метод класса, далее в квадратных скобках записывается название класса и через пробел метод, двоеточие указывает на то, что этот метод принимает параметр. Тут можно возразить, что пример притянут за уши. Я согласен — в хорошем коде не будет десятка мест с установкой текста лейбла, но моя цель — показать, как это может работать. Давайте рассмотрим более реальный пример. Допустим, для целей отладки нам может понадобиться распечатать последовательность показа вью контроллеров. Добавляем брейкпоинт с символом -[UIViewController viewDidAppear:], указываем дополнительное действие po NSStringFromClass([instance class]) и, конечно же, не забываем поставить галочку «Automatically continue after evaluating actions».</p><p>Мы снова вынуждены использовать ObjC, даже в дополнительной команде, так как находимся в его контексте. Что касается Swift, то символы записываются как название ClassName.methodName(param:). Прописывать параметры не обязательно, LLDB попытается разрешить неоднозначность, если есть методы с одинаковым названием, но разными параметрами.</p><p>Рассказывая о символьных брейкпоинтах, я не могу не рассказать о возможности искать символы. Остановив программу любым способом, с помощью брейкпоинта или же просто нажав на пиктограмму паузы, мы можем воспользоваться командой image lookup -r -n и найти интересующие вас символы в вашей программе и во всех загруженных библиотеках. Это действительно делает вас чуть ли не богом дебага, потому как вы властны искать символы везде, скажем в UIKit’e, искать приватные методы, останавливать и изучать внутреннее устройство системных библиотек. Надеюсь, я убедил в вас в силе этого метода и он не раз поможет вам сэкономить время.</p><figure><img src="https://media.tproger.ru/uploads/2020/04/Poisk-privatnogo-metoda-v-UIKite-c-pomoshhju-image-lookup.png" alt="" /></figure><h3>Watchpoints</h3><p>Вотчпоинты позволяют останавливать программу, когда изменяется значение переменной. Корректнее будет сказать, что этот механизм позволяет следить за изменениями памяти по заданному адресу с заданным размером, но благодаря LLDB и Xcode разработчику достаточно сделать несколько кликов. Использование вотчпоинтов будет удобным, когда за изменением переменной не следует никакого сайд-эффекта прямо после изменения, но её состояние важно для отложенных вычислений. В ряде случаев может быть непонятно, что инициирует это изменение, и вотчпоинты позволят быстро узнать это. Достаточно приостановить выполнение программы в контексте нужного класса и воспользоваться окном Variables View. Тут будут перечислены переменные в текущем фрейме, доступные к отлаживанию. В крупных проектах вычисление доступных переменных и их типов может занимать некоторое время, поэтому иногда нужно подождать несколько (десятков?) секунд перед тем, как переменные будут доступны к манипуляциям над ними. Приятным бонусом является возможность «заглянуть» внутрь объектов Objective-C: функциональность Variables View позволяет увидеть приватные переменные этих объектов. По клику правой кнопки мыши по переменной нам доступно не так много опций — мы можем изменять значение переменных скалярных типов и, собственно, добавлять вотчпоинты.</p><figure><img src="https://media.tproger.ru/uploads/2020/04/Levaja-kolonka-DebuggerView-s-kontekstnym-menju-po-odnoj-iz-peremennyh..png" alt="" /></figure><p>Конечно же, вотчпоинт можно установить и командой LLDB: watchpoint set variable &lt;variable_name&gt;, или, пользуясь функцией сокращения команд LLDB, просто: w s v &lt;variable_name&gt;, но помните, что переменная должна быть видна отладчику, то есть находиться в текущем фрейме. Помимо установки брейкпоинта на изменение переменной, нам доступна установка вотчпоинта на область памяти: watchpoint set expression -- 0x0d78ab5ea8. В обоих случаях при изменении содержимого памяти по отслеживаемому адресу произойдет прерывание программы. Установленные точки останова можно посмотреть командой watchpoint list или в Debugger navigator. Так как любые вотчпоинты в итоге следят за адресом памяти, они становятся неактуальны после перезапуска и не сохраняются между перезапусками приложения. Даже если вы установили брейкпоинт на изменение переменной, под капотом механизм lldb вычислил её адрес и поставил вотчпоинт по этому адресу.</p><h3>Affecting state</h3><p>Будем закругляться. Последнее, о чем я хотел поведать в рамках этой статьи, — влияние на состояние приложения из LLDB. До этого я говорил только об изменении состояния какого-либо объекта системы при остановке по брейкпоинту. Но что, если нам требуется приостановить программу в произвольный момент времени? Нажатие на значок паузы приводит к приостановке программы, но вот вместо привычного нам кода мы увидим код ассемблера. Так как же добраться до произвольного объекта и выполнить с ним хитрые манипуляции?</p><h3>Memory graph</h3><figure><img src="https://media.tproger.ru/uploads/2020/04/Panel-instrumentov-otladchika-Xcode-s-podsvechennoj-knopkoj-Memory-Graph.png" alt="" /></figure><p>Большинство iOS-разработчиков уже с первых месяцев своей работы используют этот инструмент. Для тех, кто ни разу им не пользовался, поясню. Memory graph позволяет сделать дамп памяти программы и отобразить в виде списка и графа все экземпляры объектов, которые сейчас находятся в памяти. Зачастую этот инструмент используется для выявления утечек объектов и анализа связей, которые привели к такому результату. Но сегодня от этого инструмента нам нужна только возможность остановить программу в произвольное время, найти нужный объект и узнать его адрес. Но что мы можем сделать с этой, казалось бы, бесполезной информацией?</p><p>На самом деле — всё, что угодно. Тут нам на помощь приходит мощь ObjC. Мы можем написать [0x7fafffa54a5 setValue:[UIColor redColor] forKey:@"switchedOffColor"] — и мы уже поменяли значение цвета выключенной лампы на красный, используя стандартные методы NSObject, доступные нам из коробки. Но что, если нам недостаточно этих методов, а нужно «дёрнуть» за свои рычаги? Всё просто — мы можем использовать кастинг: [(MyLamp *)0x7fafffa54a5 powerOff]. Используя подобные техники можно воздействовать на любые сервисы, менеджеры и вью модели вашего приложения в любой момент времени. Мы можем сохранить значение этого адреса в переменную для удобства: (MyLamp *)$lamp = 0x7fafffa54a5. Важно, что название переменной должно начинаться со знака доллара. Это переменная будет жить до полной остановки программы, то есть ей можно пользоваться не только в текущем сеансе отладки, но и при следующем прерывании программы в рамках одного запуска. ObjectiveС предоставляет поистине широкие возможности для того, чтобы похакать текущее состояние и обойти многие ограничения, но что делать с классами, доступными только в Swift? Конечно же, при попытке кастинга Swift-класса в ObjC-контексте ничего не произойдёт. К счастью, в Swift есть подобный механизм. Точнее, функция, имя которой — unsafeBitCast. Мы вправе использовать его с адресом: unsafeBitCast(0x7fafffa54a5, to: MySwiftLamp.self) и получить экземпляр класса MySwiftLamp по адресу. Помните, её использование небезопасно, о чём нам намекает её имя, и её крайне осторожно нужно применять в коде приложения. Хотя, когда вам осознанно нужно будет использовать эту функцию, вы будете достаточно опытны для таких предупреждений.</p><h3>View Hierarchy</h3><figure><img src="https://media.tproger.ru/uploads/2020/04/Panel-instrumentov-otladchika-Xcode-s-podsvechennoj-knopkoj-View-Hiererchy.png" alt="" /></figure><p>Рядом со инструментом Debug Memory Graph соседствует другой, не менее полезный инструмент, — View Hierarchy. Он позволяет быстро найти нужную View, посмотреть её параметры и лейаут, посмотреть активные и неактивные констрейнты. С iOS 11 этот инструмент ещё научился отображать ViewController’ы в иерархии, таким образом находить нужную View стало легче. Неочевидным тут является возможность фильтрации по имени и возможность отключить/включить отображение View, скрытых за экраном. Также я обратил внимание, что редко кто пользуется панелью управления внизу окна визуального отображения View.</p><figure><img src="https://media.tproger.ru/uploads/2020/04/Panel-instrumentov-otladchika-View-Hierarchy.png" alt="" /></figure><p>Кроме того, что она может регулировать глубину просмотра иерархии, она позволяет указать «включить отображение обрезанного контента» и «включать отображение констрейнтов». Обязательно поиграйтесь со всеми инструментами, я уверен — вы найдете полезное для себя применение для некоторых из них. Но в рамках этого рассказа нам нужна только возможность найти нужную View и узнать её адрес. Далее действуем по накатанной: po unsafeBitCast(0x7fafffa54a5, to: UIView.self), но в таком случае мы получим ошибку. Мы сейчас находимся в контексте ObjectiveC и не можем использовать po со Swift-кодом. Мы вынуждены использовать команду expession, или просто e с указанием языка: e -l Swift -- unsafeBitCast(0x7fafffa54a5, to: UIView.self), но и тут наши попытки не увенчаются успехом, мы получим ошибку error: &lt;EXPR&gt;:3:35: error: use of unresolved identifier 'UIView'. Это произойдет из-за модульной природы Swift’а. Для успешного выполнения операции нам потребуется сделать импорт модуля UiKit: e -l Swift -- import UIKit, и после этого мы наконец добьёмся результата: e -l Swift -- unsafeBitCast(0x7fafffa54a5, to: UIView.self).</p><p>Ура! Мы получили описание в консоли. Теперь давайте попробуем поменять, скажем, цвет её бэкграунда. Для начала сохраним View в переменную, чтобы облегчить процесс доступа к ней. Как и в случае с ObjectiveC, при создании переменной в LLDB контексте её название должно начинаться со знака доллара: e -l Swift -- let $view = unsafeBitCast(0x7fafffa54a5, to: UIView.self), далее мы можем применить необходимые изменения: e -l Swift -- $view.backgroundColor = .red. Чтобы увидеть изменения, необходимо продолжить выполнение программы. Но есть способ увидеть изменения и без этого, находясь в режиме «паузы». Дело в том, что мы не видим изменения не потому, что приложение приостановлено, а потому, что все изменения UIView копятся в транзакцию CALayer и применяются только в конце «вращения» текущего RunLoop’а с помощью вызова CATrasaction.flush(). Когда приложение приостановлено для отладки, операционная система всё ещё живёт своей жизнью, вы можете свернуть это приложение и открыть другое. Операционная система всё ещё опрашивает состояние UI вашего приложения и отрисовывает ваше приложение несколько десятков раз в секунду, только RunLoop приостановлен, CATrasaction.flush не вызывается, изменения не применяются. Да, достаточно сделать вызов e -l Swift -- CATrasaction.flush(), и мы увидим изменения.</p><p>На этом пора завязывать. Надеюсь, приведённые примеры кому-то облегчат жизнь, сохранят время и нервы. Добавьте в закладки, и в следующий раз, когда на поиск и отладку очередного бага у вас будет уходить более 15 минут, загляните в эту статью — возможно, какой-нибудь приём вам пригодится.</p>]]></content:encoded>
    </item>
    <item>
      <title>Отладка и устранение распространённых ошибок в JavaScript</title>
      <link>https://tproger.ru/translations/javascript-common-errors-debugging</link>
      <comments>https://tproger.ru/translations/javascript-common-errors-debugging?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Сергей Штукатуров]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/translations/javascript-common-errors-debugging</guid>
      <description><![CDATA[<p>Типичные ошибки JavaScript разобраны на примерах: у объекта girl нет свойства named, поэтому обращение к girl.named.lucky вызывает TypeError.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/translations/javascript-common-errors-debugging">Отладка и устранение распространённых ошибок в JavaScript</a>»</p>]]></description>
      <category><![CDATA[JavaScript]]></category>
      <category><![CDATA[Для начинающих]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[Переводы]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Mon, 29 Apr 2019 09:47:50 GMT</pubDate>
      <content:encoded><![CDATA[<p>Временами работа над кодом JavaScript заставляет чувствовать себя выдохшимся и измождённым, поэтому некоторые подсказки по отладке никогда не будут лишними. На примерах из песен мы постараемся разобрать типичные ошибки в коде на JS и способы, которыми их можно найти и устранить.</p><h2>Свойство не определено</h2><p>Этот код выдаёт ошибку «Uncaught TypeError: Cannot read property ‘lucky’ of undefined». Дело в том, что объект girl не имеет свойства named, хотя у него есть свойство name. Поскольку свойство girl.named не определено, мы не можем получить к нему доступ, то есть оно просто не существует. Если мы заменим girl.named.lucky на girl.name, то код вернёт нам «Lucky».</p><p>Свойство — некоторое значение, привязанное к объекту JavaScript. Почитать больше об объектах можно <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects">здесь</a> (статья на английском языке).</p><h3>Отладка ошибок TypeError</h3><p>Ошибки типа TypeError появляются, когда вы пытаетесь выполнить действия с данными, которые не соответствуют нужному типу, например применяете .bold() к числу, запрашиваете свойство undefined или пытаетесь вызвать как функцию что-то, не являющееся функцией. Например, вы увидите такую ошибку, если вызовете girl(), поскольку это объект, а не функция. В последнем случае вы получите «Uncaught TypeError: yourVariable.bold is not a function» и «girl is not a function».</p><p>Для отладки этих ошибок надо разобраться с переменными. Что такое girl? И что такое girl.named? Вы можете понять это изучая код, выводя переменные с помощью console.log, используя команду debugger или просто напечатав имя переменной в консоли. Удостоверьтесь, что вы можете манипулировать содержащимся в переменной типом данных. Если тип данных не подходит, модифицируйте его нужным образом, добавьте условие или блок try..catch, чтобы контролировать выполнение операции, или используйте эту операцию на другом объекте.</p><h2>Переполнение стека</h2><p>Если верить авторам песни «Baby One More Time», слово «hit» в строчке «Hit me baby, one more time» означает «позвони», то есть Бритни хочет, чтобы её бывший позвонил ей ещё раз. Это, возможно, приведёт к ещё большему количеству звонков в будущем. По сути это рекурсия, которая может вызвать ошибку в случае переполнения стека вызовов.</p><p>Конкретные сообщения об ошибке зависят от браузера, но выглядят они примерно так:</p><p>Переполнение стека может произойти, если в рекурсии не предусмотрен базовый случай или если код никогда не обращается к этому случаю.</p><p>В показанной выше функции stillBelieve никогда не примет значение false, и поэтому мы раз за разом будем вызывать oneMoreTime, увеличивая одиночество, и никогда не завершим выполнение функции.</p><p>Если же Бритни решит положиться на своих друзей, это уменьшит её одиночество, она перестанет верить, что можно вернуть отношения, и не будет больше ждать звонка от бывшего партнёра.</p><p>Есть похожие случаи с бесконечными циклами, когда система не выдаёт сообщение об ошибке, но вместо этого страница, на которой исполняется код, зависает. Это происходит в случае цикла while без условия завершения.</p><p>Исправить это можно примерно так же, как и предыдущий пример.</p><h3>Отладка бесконечных циклов и рекурсий</h3><p>Для начала, если возникла проблема с бесконечным циклом, закройте вкладку, если вы пользуетесь Chrome или Edge, или окно браузера, если у вас Firefox. Затем просмотрите код: есть ли там что-то, что создаёт бесконечный цикл или рекурсию. Если ничего не обнаружили — добавьте в цикл или функцию команду debugger и проверьте значение переменных на нескольких начальных итерациях. Если они не соответствуют ожидаемым, вы это обнаружите.</p><p>В приведённом выше примере стоило бы добавить debugger самой первой строкой функции или цикла. Затем нужно открыть отладочную вкладку в Chrome и изучить переменные в Scope. С помощью кнопки «next» можно проследить, как они меняются с каждой итерацией. Обычно это помогает найти решение проблемы.</p><p><a href="https://developers.google.com/web/tools/chrome-devtools/javascript/">Здесь</a> можно найти руководство на английском языке по отладке с помощью Chrome’s DevTools, а <a href="https://developer.mozilla.org/en-US/docs/Tools/Debugger">здесь</a> — для Firefox.</p><h2>Ошибка синтаксиса</h2><p>SyntaxError — вероятно самая распространённая разновидность ошибок в JavaScript. Эти ошибки возникают, если вы не соблюдаете правила синтаксиса языка. Копируя посыл песни Бритни «Everytime», JavaScript говорит отсутствующим скобкам и кавычкам: «Вы нужны мне, крошки».</p><p>Соответствующие расширения текстового редактора помогут избежать ошибок. Bracket Pair Colorizer размечает скобки в коде разными цветами, а Prettier или другой инструмент статического анализа кода поможет быстро найти ошибки. Постарайтесь придерживаться правильной разметки и делайте блоки кода как можно короче и с минимальной вложенностью. Такой подход сильно облегчает отладку.</p><p>Теперь, вооружившись новыми навыками отладки, вы станете немного сильнее в JavaScript, чем были вчера.</p>]]></content:encoded>
    </item>
    <item>
      <title>10 консольных команд для упрощения отладки JavaScript-кода</title>
      <link>https://tproger.ru/translations/javascript-debug-tricks</link>
      <comments>https://tproger.ru/translations/javascript-debug-tricks?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Corewood]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/translations/javascript-debug-tricks</guid>
      <description><![CDATA[<p>Подборка из десяти функций консоли JavaScript: группировка логов во вложенные деревья, трассировка стека и другие приёмы, облегчающие отладку.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/translations/javascript-debug-tricks">10 консольных команд для упрощения отладки JavaScript-кода</a>»</p>]]></description>
      <category><![CDATA[JavaScript]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[Переводы]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 23 Nov 2018 13:23:05 GMT</pubDate>
      <content:encoded><![CDATA[<p>Мало кто из программистов любит процесс отладки, так что дабы максимально его упростить, обратим внимание на десять консольных функций, которые призваны помочь в этом неблагодарном деле.</p><h3>Группировка логов</h3><p>Как понятно из имени метода, он позволит сгруппировать несколько логов в одно раскрывающееся дерево. Можно даже организовывать вложенные деревья для последующей группировки.</p><p>У этого приёма есть три метода: console.group('name') отмечает начало группировки, console.groupEnd('name') отмечает окончание, а console.groupCollapsed() создаёт группу в виде скрытого дерева.</p><figure><img src="https://media.tproger.ru/uploads/2018/11/1__fsPZTznKQEFvrYI3tyswA1.png" alt="" /></figure><h3>Трассировка стека</h3><p>В случае, если необходимо найти полный стек вызова функции, очень полезной будет функция console.trace(). Например, так можно отследить, откуда пришёл коллбек:</p><figure><img src="https://media.tproger.ru/uploads/2018/11/1_WpqaYPHjMvmDR8R7JPpfAA1.png" alt="" /></figure><h3>Счётчик вызовов</h3><p>Функция console.count() возвращает количество раз, когда её вызывали. Учтите, что если вы измените строку лога, отдаваемую функции, счётчик обнулится и начнёт отсчёт для новой строки. Также есть функция сброса счётчика console.countReset().</p><figure><img src="https://media.tproger.ru/uploads/2018/11/1_zarUNcE_U2MZt76JxuSDiw1.png" alt="" /></figure><h3>Таймер в консоли</h3><p>Команды console.time() и console.timeEnd() позволяют соответственно начать и остановить отсчёт времени. В основном это нужно для проверки производительности. Также можно передать функциям строку для создания специфического таймера.</p><figure><img src="https://media.tproger.ru/uploads/2018/11/1_fnuFkWChcKnqQv18CCtfRA1.png" alt="" /></figure><h3>Работа с логическими выражениями</h3><p>Допустим, вам нужно проверить, приняло ли какое-то выражение значение false и записать это в лог. В обычной ситуации можно использовать условный оператор if, но в нашем случае куда лучше подойдёт функция console.assert(). Функция принимает в качестве аргумента выражение, а также сообщение либо объект.</p><figure><img src="https://media.tproger.ru/uploads/2018/11/1_88PjXjyukZpDTHkW2CEsXg1.jpg" alt="" /></figure><h3>Профилирование</h3><p>Как часто вам приходило в голову, что стоило приступить к профилированию сразу, вместо оттягивания до последнего и ручного поиска той функции, с которой и стоило начать? console.profile() призвана помочь с этим. После завершения профилирования просто вызовите эту функцию.</p><h3>Метка времени</h3><p>Функция console.timeStamp() добавляет событие в таймлайн во время записи. Можно использовать, например, по окончании процесса обработки данных или для того, чтобы поймать момент возвращения вызова API. В качестве аргумента функция принимает название какого-либо события.</p><h3>Очистка консоли</h3><p>Простейшая функция console.clear() очищает консоль.</p><h3>Чтение размера буфера</h3><p>Свойство console.memory позволяет отображать размер буфера. Полезно, когда статистика производительности не совсем прозрачна и нет времени рассматривать графики.</p><figure><img src="https://media.tproger.ru/uploads/2018/11/1_-9StbJKYXCOELKhzOJMhgw1.jpg" alt="" /></figure><h3>Пользовательская таблица</h3><p>Функция console.table(), принимающая в качестве аргумента массив, выводит небольшую удобную таблицу, с которой можно взаимодействовать. Для вызова нужно передать ей массив объектов.</p><figure><img src="https://media.tproger.ru/uploads/2018/11/1_ZYb_JxgD-kKJ7mda8p3Zow1-1.png" alt="" /></figure><h3>Заключение</h3><p>Вряд ли процесс отладки когда-либо станет вашим любимым занятием, но с помощью этих приёмов жизнь может стать чуточку проще.</p>]]></content:encoded>
    </item>
    <item>
      <title>Facebook разработала SapFix, инструмент для генерирования и внедрения патчей</title>
      <link>https://tproger.ru/news/facebook-sapfix-ai-tool</link>
      <comments>https://tproger.ru/news/facebook-sapfix-ai-tool?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Екатерина Никитина]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/facebook-sapfix-ai-tool</guid>
      <description><![CDATA[<p>Инструмент на основе искусственного интеллекта сам находит баги, откатывает проблемный код и подбирает шаблон патча; работает в связке с Sapienz.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/facebook-sapfix-ai-tool">Facebook разработала SapFix, инструмент для генерирования и внедрения патчей</a>»</p>]]></description>
      <category><![CDATA[Тестирование]]></category>
      <category><![CDATA[Инструменты]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[Искусственный интеллект]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 14 Sep 2018 12:48:20 GMT</pubDate>
      <content:encoded><![CDATA[<p>На конференции @Scale 2018 Facebook представила свою новую разработку — инструмент на основе искусственного интеллекта, который самостоятельно находит в проекте баги и предлагает готовые патчи. SapFix может работать сам по себе либо в сочетании с Sapienz — это «умное» тестировочное ПО от Facebook для поиска ошибок в коде.</p><h3>Порядок работы SapFix</h3><p>Чтобы исправить баг, система частично или полностью «откатывает» ту часть кода, которая ее вызывает. Для решения наиболее сложных проблем SapFix обращается к базе готовых шаблонов, созданных людьми, и подбирает нужное из них. Если шаблон не подходит, система модифицирует его до тех пор, пока код не заработает.</p><figure><img src="https://media.tproger.ru/uploads/2018/09/2018-09-14.-sapfix_1.gif" alt="" /></figure><p>Определившись с конкретным патчем, SapFix генерирует несколько потенциальных решений для каждого бага и оценивает их качество по трем параметрам:</p><ul><li>вызывает ли оно ошибки компиляции;</li><li>продолжаются ли сбои;</li><li>вызывает ли решение новые сбои.</li></ul><p>Чтобы определить последние два параметра, система прогоняет модифицированные сборки по существующим тестам, а также по тем, что созданы Sapienz. Это процесс автоматический, но протекает изолированно от остального кода. SapFix не запустит код в продакшн, пока его не проверят разработчики-люди.</p><p>По словам создателей системы, это очень похоже на существующий процесс отладки. Однако SapFix может автоматически реагировать на обратную связь, внедрять одобренные патчи и удалять остальные. В некоторых случаях система даже предложит лучшие из имеющихся вариантов и предоставит разработчикам рекомендации.</p><figure><img src="https://media.tproger.ru/uploads/2018/09/2018-09-14.-sapfix_2.jpg" alt="" /></figure><h3>Развитие инструмента</h3><p>Facebook пока еще дорабатывает эту технологию, поэтому не рекомендует ее применять в тех же масштабах, что и Sapienz. Однако команда разработчиков доложила, что в процессе тестирования инструмента, с августа 2018 года, система SapFix уже успешно создала и внедрила несколько патчей.</p><p>Компания заявила, что намерена в будущем, когда разработка завершится, открыть код обоих инструментов.</p><p>Технологию Sapienz Facebook <a href="https://tproger.ru/news/facebook-introduced-sapienz/">представила</a> в мае 2018 года на конференции F8, но для тестирования Android-клиента Facebook ее применяли с осени 2017 года. По словам разработчиков, система уменьшает время на исправление ошибок до нескольких часов и даже минут.</p>]]></content:encoded>
    </item>
    <item>
      <title>Пишем низкоуровневый отладчик под Linux на Python</title>
      <link>https://tproger.ru/translations/making-a-low-level-linux-debugger</link>
      <comments>https://tproger.ru/translations/making-a-low-level-linux-debugger?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Никита Прияцелюк]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/translations/making-a-low-level-linux-debugger</guid>
      <description><![CDATA[<p>Серия статей о создании отладчика на библиотеках python-ptrace, pyelftools и distorm3, когда возможностей GDB и LLDB по контролю не хватает.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/translations/making-a-low-level-linux-debugger">Пишем низкоуровневый отладчик под Linux на Python</a>»</p>]]></description>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[Переводы]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Sun, 02 Sep 2018 17:03:01 GMT</pubDate>
      <content:encoded><![CDATA[<p>Существуют отличные отладчики вроде <a href="https://www.gnu.org/software/gdb/">GDB</a> и <a href="https://lldb.llvm.org">LLDB</a>. И хотя их можно настраивать с помощью скриптов, порой хочется иметь больше контроля над работой отладчика. В этой серии статей мы попробуем создать свой отладчик с помощью библиотек <a href="https://python-ptrace.readthedocs.io/en/latest/gdb.html">python-ptrace</a>, <a href="https://github.com/eliben/pyelftools">pyelftools</a> и <a href="https://pypi.org/project/distorm3/">distorm3</a>.</p><p>Исходники доступны на <a href="https://github.com/asrp/ptracedbg">GitHub</a>. Всё написано и скомпилировано на Linux x86_64.</p><p>Прим.перев. В этой статье используется устаревшая версия Python 2.</p><h2>Подготовка</h2><p>Чтобы избежать проблем с правами доступа, мы будем запускать отлаживаемый процесс как дочерний:</p><p>Здесь используется системный вызов ptrace для присоединения к дочернему процессу и его остановки. Теперь process содержит много удобных методов. Идея была заимствована из <a href="https://python-ptrace.readthedocs.io/en/latest/usage.html">примера</a> в документации python-ptrace.</p><h2>Считываем значения</h2><p>Начнём с простого. Получаем регистры:</p><p>Считываем байты из памяти:</p><h2>Ассемблерный REPL</h2><p>Теперь нам нужно научиться запускать ассемблерные инструкции по одной за раз. Давайте соберём нужные составляющие.</p><p>Одиночный шаг:</p><p>rip — это указатель на инструкцию. Префикс r обозначает длину в 64 бита. Как видите, он действительно смещается вперёд, когда мы делаем шаг.</p><p>Продолжаем до тех пор, пока дочерний процесс не получит сигнал (в нашем случае SIGTRAP). Это может привести к ошибке, если процесс завершится или будет получен другой сигнал:</p><p>process.singleStep() неблокирующий, поэтому для удобства мы добавим блокирующую версию:</p><p>Так делать не стоит, но пусть process пока побудет глобальной переменной.</p><p>Пишем в память. В ассемблере выполнение ассемблерной инструкции int3 приводит к тому, что процессу отправляется сигнал SIGTRAP. Её можно записать в виде одного байта 0xCC:</p><p>Также мы можем сравнить регистр rip до и после, чтобы проверить, что значение увеличилось ровно на 1.</p><p>Устанавливаем регистр:</p><p>Теперь у нас есть всё, что нужно, для запуска одной инструкции, переданной в виде байтов:</p><p>Здесь мы перезаписываем байты перед указателем на инструкцию с помощью instr, делаем шаг и возвращаем перезаписанные байты и позицию указателя инструкции. Последнюю часть делаем, только если указатель на инструкцию не изменялся (как в случае с jump или call).</p><p>При помощи таблицы преобразования ассемблерных инструкций в байты мы можем поместить это в цикл и сделать REPL.</p><h2>Вызов функции, первая попытка</h2><p>Что делать, если мы хотим вызвать ассемблерную функцию и приостановить выполнение после возвращения из неё?</p><p>Напишем для этого func_call(func_addr) (запустите её пошагово, чтобы посмотреть на промежуточные состояния). Сначала сохраним часть текущего состояния:</p><p>Мы могли бы просто использовать run_asm с инструкцией call. Это байт 0xE8, за которым следуют 5 байт little endian, описывающих разницу между текущим и целевым значениями rip.</p><p>Чтобы приостановить дочерний процесс после вызова, мы можем записать int3 (байт 0xCC) после инструкций вызова:</p><p>Мы можем перепроверить, что вызов был совершён:</p><p>Теперь пусть процесс работает, пока не будет получен сигнал SIGTRAP (желательно тот, что мы установили):</p><p>А теперь восстановим перезаписанные байты и значения регистра. В некоторых ситуациях они нам могут пригодиться:</p><h2>Получаем адрес функции</h2><p>Давайте попробуем вызвать скомпилированные Си-функции, но пока без аргументов и возвращаемого значения. Для этого нам всего лишь нужно найти адрес функции. Мы можем его получить из заголовка с помощью pyelftools:</p><p>А теперь сам вызов:</p><p>Вообще, этот метод получает не только функции, но и, наверное, все статические переменные.  Для библиотек общего пользования мы можем вызвать variables с полным путём к .so-файлу соответствующей библиотеки.</p><p>Тем не менее всегда это работать не будет, поскольку фактический регион используемой памяти не всегда начинается с 0 и нам нужно добавлять начало этого региона в качестве смещения.</p><p>Пока что мы можем это сделать следующим образом. С регионами памяти и /proc/pid/maps разберёмся чуть позже:</p><h2>Ставим точки останова</h2><p>Теперь у нас есть адреса функций и мы можем поставить точку останова, просто написав int3 (байт 0xCC) в начале функции:</p><p>И восстановить перезаписанное значение после прохождения точки останова:</p><p>Эти функции можно использовать следующим образом:</p><h2>Вызов функции, вторая попытка</h2><p>В общем и целом первый подход работает на удивление хорошо, хотя есть некоторые проблемы.</p><p>Слишком большое расстояние вызова. call (0xE8) принимает в качестве аргумента только 5 байт, однако для описания адреса (diff) может потребоваться 8 байт. Мы можем либо подождать, пока не окажемся в пределах функции, которую хотим вызвать (это работает только в том случае, если нам не нужно вызывать функцию сразу же), либо поместить целевой адрес в регистр, например, rax, и воспользоваться инструкцией call rax (байты FF D0).</p><p>Перезаписанные байты. Так как мы перезаписываем 7 байт (6 для call, один для int) и восстанавливаем их только после возвращения из функции, то в случае попытки их чтения из другого места можно получить неожиданные значения. Например, если мы совершили вызов внутри тела функции и выполнение программы снова доходит до old_rip.</p><p>В теории мы могли бы восстановить 6 из 7 байт после одного шага, оставив только 0xCC. Однако это не решает проблему, а только уменьшает её размер.</p><p>Ещё мы могли бы вручную создать стековый кадр.</p><p>Вместо этого мы зарезервируем новый участок памяти и запишем наши инструкции туда.</p><h2>Выделяем память</h2><p>Мы можем использовать системный вызов mmap() (номер вызова 9) для резервирования памяти. Ему требуются некоторые магические константы, часть которых можно найти в ptrace.syscall:</p><p>С помощью следующей функции мы можем вызвать mmap. Здесь syscall представлен байтами 0F 05:</p><p>Данная стратегия была позаимствована из <a href="https://github.com/eklitzke/ptrace-call-userspace">этого</a> примера. Для справки, вот константы:</p><p>Адрес зарезервированной памяти находится в rax после вызова, поэтому мы его извлекаем и возвращаем.</p><p>Это позволяет нам изменить вызов функции, сделав его немного безопаснее:</p><p>Тем не менее, в этой функции по-прежнему могут возникать ошибки сегментации.</p><h2>Получаем следующие инструкции</h2><p>Добавим в наш отладчик функцию, которая говорит нам, какие следующие инструкции. Для этого нам понадобится дизассемблер <a href="https://pypi.org/project/distorm3/">distorm3</a>, который можно установить с помощью pip.</p><p>Воспользуемся методом PtraceProcess.disassemble для получения итератора по следующим десяти инструкциям:</p><p>Запуск этой функции даст примерно следующий результат:</p><p>Метод PtraceProcess.dumpCode работает похожим образом, но с другим форматированием.</p><h2>Итог</h2><p>На этом пока всё. В следующей статье мы разберёмся с чтением/записью Си-переменных, запуском одиночных Си-команд, библиотеками общего пользования, динамической загрузкой и картами памяти (/proc/pid/maps).</p>]]></content:encoded>
    </item>
    <item>
      <title>Как использовать отладчик pdb для Python приложений</title>
      <link>https://tproger.ru/translations/debugging-python-with-pdb</link>
      <comments>https://tproger.ru/translations/debugging-python-with-pdb?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Кирилл Поздеев]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/translations/debugging-python-with-pdb</guid>
      <description><![CDATA[<p>Встроенный отладчик pdb позволяет искать ошибки в Python-коде прямо во время работы программы, без правок с print() и перезапуска приложения.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/translations/debugging-python-with-pdb">Как использовать отладчик pdb для Python приложений</a>»</p>]]></description>
      <category><![CDATA[Инструменты]]></category>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[Django]]></category>
      <category><![CDATA[Переводы]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Sun, 05 Aug 2018 10:38:33 GMT</pubDate>
      <content:encoded><![CDATA[<p>pdb — это встроенный отладчик для Python, который, в отличие от print(), позволяет отлаживать программу в процессе её работы.</p><h2>Отладка Python-кода с помощью print</h2><p>Как уже говорилось ранее, кто-то используют print() для отображения информации, которая помогает понять, что происходит в коде. Кто-то использует логи для тех же целей, но давайте не путать использование логов на продакшене и случаи, когда их используют во время поиска багов в коде и после удаляют.</p><p>Но самая большая проблема в использовании print() – это необходимость вносить изменения в код и перезапускать приложение, чтобы увидеть изменения. Давайте разберёмся, почему отладчики эффективнее.</p><h2>Команды Python-отладчика</h2><p>Главная задача отладчика – предоставить возможность заглянуть в процесс выполнения кода. Так, например, можно просмотреть стек вызовов, узнать значения переменных, установить брейкпоинты или запустить выполнение кода построчно. Можно провести аналогию с тем, как автомеханик заглядывает под капот автомобиля и начинает перебирать деталь за деталью, пока не найдет причину поломки.</p><p>Если вы работаете с Python, то можете не только просматривать код во время отладки, но даже запускать код из командной строки или изменять значения переменных на лету.</p><p>Python есть встроенный отладчик под названием pdb. Это простая консольная утилита, которая обладает основной функциональностью для отладки кода. Но если вы ищете что-то более продвинутое, то стоит обратить внимание на ipdb – отладчик с функциональностью из IPython.</p><p>Проще всего вызвать отладчик pdb из кода, где вы работаете:</p><p>Как только интерпретатор доберётся до этой строчки, запустится отладчик и в консоли будут доступны новые команды.</p><h3>list()</h3><p>Эта команда покажет часть кода, на выполнении которой сейчас находится интерпретатор. Можно передать два аргумента first и last для просмотра определённого участка кода. Если указать только first, то будет выведен код вокруг искомой строки.</p><h3>up(p) и down(d)</h3><p>Эти команды используются для передвижения по стеку вызовов. С их помощью можно отследить, откуда была вызвана текущая функция.</p><h3>step() и next()</h3><p>Другая пара не менее важных команд. С их помощью можно выполнять код построчно. Единственное различие между ними в том, что next() перейдёт к следующей строке вне зависимости от вызываемых функций, а step() перейдёт в вызванную функцию, если это возможно.</p><h3>break()</h3><p>Эта команда позволяет создавать брейкпоинты без внесений изменений в код. Ниже разберём этот этап более детально.</p><p>Краткий список команд отладчика pdb:</p><ul><li>args() — выводит аргументы функции;</li><li>continue() или (cont) — продолжит выполнение до первого брейкпоинта или до завершения программы;</li><li>help() — выводит список доступных команд или подсказки по определённой команде;</li><li>jump() — перепрыгивает к выполнению указанной строчки кода;</li><li>list() — выводит исходный код программы вокруг выбранной строки;</li><li>expression() — выводит значение выражения;</li><li>pp — выводит значение в «красивом» виде;</li><li>quit или exit() — отменяет выполнение программы;</li><li>return() — завершает выполнение текущей функции.</li></ul><h2>Продолжаем изучать Python-отладчик</h2><p>Рассмотренный ранее способ работы с отладчиком требовал внесения изменения в код для вывода чего-нибудь или установки брейкпоинта. Но часто при работе с внешними библиотеками появляется необходимость в их отладке. Конечно, можно открыть исходный код библиотеки и вызвать pdb.</p><p>Но теперь есть возможность запускать приложение напрямую из отладчика без внесения изменения в код. Для этого воспользуемся следующей командой:</p><p>Давайте разберём на примере. Есть простое приложение, которое отслеживает рабочее время. Для её работы используется библиотека requests, отвечающая за выполнение HTTP-запросов. Попробуем прервать выполнение во время запроса. Как это сделать? Запустим приложение через отладчик и установим брейкпоинт внутри библиотеки requests.</p><p>Как можно заметить, не нужно указывать полный путь до библиотеки. Можно указать относительную ссылку от sys.path. Таким же образом можно отлаживать и ваше приложение.</p><p>Теперь куда проще отлаживать код. Не надо вносить изменения в приложение или во внешние библиотеки.</p><p>Но что делать, если в приложении происходит много вызовов, а вам надо обработать только какой-то определённый? Можно точно указать условие, при выполнении которого отладчик будет прерывать выполнение приложения.</p><p>В данном примере прерывание произойдёт только в случае, если json будет иметь в себе ключ time_entry.</p><h2>Отладка кода Django</h2><p>Если вы используете Django, то скорее всего знаете, что, если в настройках значение параметра DEBUG установлено как True, то для каждого исключения будет выводиться отдельная страница с указанием типа исключения, стек вызовов, локальные переменные и т.д.</p><p>Если вы хотите прокачать отладчик, то установите<a href="https://django-extensions.readthedocs.io/en/latest/"> django-extensions</a> и используйте команду runserver_plus для запуска сервера. Также можно указать пароль для доступа к отладке следующей командой:</p><p>Прим. перев.  В Werkzeug, начиная с версии 0.11, появилась возможность доступа по паролю к отладчику. Это сделано для повышения безопасности при попытках несанкционированного доступа.</p><p>Если вы используете django-extensions, то получите страницу со всеми вызовами, кодом и окном отладчика.</p><p>Процесс отладки осуществляется с помощью WSGI библиотеки<a href="http://werkzeug.pocoo.org/"> Werkzeug</a>.</p><p>Существует множество способов отладки приложений, но специализированные инструменты могут дать вам огромное преимущество по сравнению с другими разработчиками и помогут сэкономить время и силы при поиске багов. Cреды разработки предлагают широкий выбор средств отладки, подробнее о них в нашей <a href="https://tproger.ru/translations/python-ide/">подборке лучших IDE и редакторов кода для Python</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>Facebook открыла исходный код инструмента отладки Sonar</title>
      <link>https://tproger.ru/news/facebook-sonar-open-source</link>
      <comments>https://tproger.ru/news/facebook-sonar-open-source?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Рамис Ганиев]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/facebook-sonar-open-source</guid>
      <description><![CDATA[<p>Facebook открыла код отладчика Sonar для Android и iOS. Инструмент объединяет знания о структуре приложений и поддерживает плагины.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/facebook-sonar-open-source">Facebook открыла исходный код инструмента отладки Sonar</a>»</p>]]></description>
      <category><![CDATA[Мобильная разработка]]></category>
      <category><![CDATA[Инструменты]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 13 Jun 2018 15:07:23 GMT</pubDate>
      <content:encoded><![CDATA[<p>Команда Facebook <a href="https://code.facebook.com/posts/1461914677288302/open-sourcing-sonar-a-new-extensible-debugging-tool/">объявила</a> об открытии исходного кода отладчика <a href="https://fbsonar.com/">Sonar</a> для Android и iOS приложений. Возможности кроссплатформенного инструмента расширяются при помощи дополнений и позволяют разработчикам обмениваться информацией о каждом модуле проекта.</p><h3>Зачем нужен Sonar?</h3><p>Facebook объяснила, что при разработке сложного приложения ни один сотрудник не знает, как работает каждый модуль. Разбросанность информации мешает команде добавлять новые функции, исследовать ошибки и оптимизировать работу для повышения производительности.</p><p>Новый отладчик позиционируется как средство объединения знаний о структуре приложений. На его создание команду Facebook вдохновил <a href="https://facebook.github.io/stetho/">Stetho</a>, входящий в состав средств разработки Chrome. Создатели Sonar снабдили новый продукт более понятным интерфейсом, поддержкой плагинов и платформ Android и iOS.</p><figure><img src="https://media.tproger.ru/uploads/2018/06/sonar_1.png" alt="" /></figure><p>Facebook выделила три полезные возможности Sonar:</p><ul><li>наглядное отображение компонентов Litho и ComponentKit для более четкого понимания иерархии проекта;</li><li>наложение потока запросов GraphQ против необработанных сетевых событий;</li><li>анализ производительности в реальном времени для быстрого устранения проблем.</li></ul><h3>Как устроен отладчик?</h3><p>Sonar состоит из двух частей: настольного клиента и мобильного SDK. Первый основан на open source проектах React.js, Flow, Metro, RSocket и Yarn, второй — на Folly и RSocket. Пользователи взаимодействуют с настольным клиентом, а SDK внедряется в разрабатываемое приложение и передает данные для отладки.</p><p>Набор плагинов позволяет проверять компоновку приложений, сетевой трафик и системные журналы. Составные инструменты Sonar фактически являются плагинами, а ядро отладчика служит связующим звеном.</p><figure><img src="https://media.tproger.ru/uploads/2018/06/sonar_2.jpg" alt="" /></figure><p>Для расширения возможностей Sonar необходимо написать плагин для обеих частей. Клиентская часть требует только компонент React для связи с SDK. Мобильный плагин для iOS разрабатывается на языке Swift или Objective-C, а для Android — на Java или Kotlin. Он выполняет роль серверного приложения для обработки клиентских запросов: регистрирует набор обработчиков и определяет ответы для них.</p><p>Более подробную инструкцию по использованию Sonar можно найти <a href="https://fbsonar.com/docs/understand.html">в документации</a>.</p><p>Facebook часто открывает для разработчиков новые инструменты. В марте 2018 года она <a href="https://tproger.ru/news/facebook-games-sdk/">представила</a> программный интерфейс Games SDK для создания игр с поддержкой С++ и Unity.</p>]]></content:encoded>
    </item>
    <item>
      <title>Тестирование и отладка Node-приложений в Docker-контейнерах</title>
      <link>https://tproger.ru/translations/testing-and-debugging-a-containerized-node-application</link>
      <comments>https://tproger.ru/translations/testing-and-debugging-a-containerized-node-application?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Георгий Лукьянов]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/translations/testing-and-debugging-a-containerized-node-application</guid>
      <description><![CDATA[<p>Запуск приложения в контейнере, а не прямо на вашем компьютере или сервере, имеет много преимуществ. Но сможем ли мы так же отлаживать приложение в контейнере, как если бы оно было установлено на машине? В этой статье рассказывается, как настроить приложение и среду для тестирования Node-контейнеров.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/translations/testing-and-debugging-a-containerized-node-application">Тестирование и отладка Node-приложений в Docker-контейнерах</a>»</p>]]></description>
      <category><![CDATA[Тестирование]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[Node.js]]></category>
      <category><![CDATA[Docker]]></category>
      <category><![CDATA[Переводы]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Sat, 02 Sep 2017 16:24:02 GMT</pubDate>
      <content:encoded><![CDATA[<p>Контейнеры в целом и Docker-контейнеры в частности немного изменили наше представление о развертывании и распространении программного обеспечения. Запуск приложения в контейнере, а не прямо на вашем компьютере или сервере, имеет много преимуществ. Но что насчет тестирования и отладки? Сможем ли мы также отлаживать приложение в контейнере, как если бы оно было установлено на машине? В этой статье рассказывается, как настроить приложение и среду для тестирования Node-контейнеров. Исходный код предложенного проекта можно найти <a href="https://github.com/gnschenker/debug-node/">GitHub</a>.</p><h2>Создание простого приложения</h2><p>Примечание В качестве примера рассматривается простое Node-приложение. Представленные здесь принципы могут быть легко адаптированы к другим языкам программирования, например, Python, Go или .NET Core.</p><p>Создаем директорию проекта и в терминале перемещаемся в нее. Выполняем команду:</p><p>На вопрос о точке входа (entry point) вводим server.js и на вопрос о тестовой команде (test command) отвечаем jasmine-node spec . Остальные вопросы можно пропустить, оставив значение по умолчанию. По завершении работы этой команды будет создан файл package.json, который должен выглядеть примерно так:</p><p>Наше приложение будет использовать Express JS. Установим пакет командой:</p><p>Теперь создаем файл server.js, который будет содержать следующий код:</p><p>В строке 4 мы импортируем модуль primes.js, который содержит логику, позволяющую определить, является ли данное число простым. Таким образом, нужно добавить в проект файл primes.js со следующим содержимым:</p><h2>Добавляем Dockerfile</h2><p>Чтобы иметь возможность упаковать наше приложение в Docker-контейнер, нам нужно добавить Dockerfile в проект. Содержимое этого файла должно выглядеть так:</p><p>Обратите внимание, что в строке 3 мы устанавливаем jasmine-node, который нужен для запуска тестов. Также мы открываем не только порт 3000, но и порт 5858. Последний будет использоваться для присоединения отладчика. Также обратите внимание на то, что мы сначала копируем package.json в образ и запускаем npm install, и только после этого копируем оставшуюся часть папки приложения. Это помогает нам оптимизировать сборку Docker-образа.</p><h2>Запуск приложения в контейнере</h2><p>Теперь давайте соберем Docker-образ нашего приложения. Выполним команду:</p><p>Примечание  Не забудьте указать точку в конце команды.</p><p>Теперь мы можем получить контейнер из этого образа:</p><p>Мы должны увидеть длинный ID (хеш-код), который выводится в терминал. Чтобы повторно убедиться, работает ли контейнер, мы можем использовать команду docker ps, и должны увидеть следующее:</p><p><a href="https://media.tproger.ru/uploads/2017/08/testing-and-debugging-a-containerized-node-application-1.png"></a></p><p>Если по какой-либо причине контейнер не создался, мы можем просмотреть логи создания командой docker logs my-app:</p><figure><img src="https://media.tproger.ru/uploads/2017/08/testing-and-debugging-a-containerized-node-application-2.png" alt="" /></figure><h2>Добавляем тесты</h2><p>Для тестирования мы будем использовать Jasmine. Мы можем поставить его глобально на нашей машине, но зачем это делать, если у нас есть контейнер? В данной статье продемонстрирована глобальная установка Jasmine, но вы можете самостоятельно установить Jasmine в контейнер.  Давайте установим:</p><p>Теперь настроим несложный тест. Создайте папку spec и добавьте в нее файл primes-spec.js со следующим содержимым:</p><p>Здесь не будет описана логика Jasmine. Вы можете обратиться к подробной <a href="http://jasmine.github.io/">документации</a>, чтобы разобраться с этим.</p><p>Как только мы определили тест, выполним эту команду в терминале:</p><p>Эта команда вызывает Jasmine-node, который мы определили в package.json. Вывод будет примерно такой:</p><figure><img src="https://media.tproger.ru/uploads/2017/08/testing-and-debugging-a-containerized-node-application-3.png" alt="" /></figure><p>Также мы можем добавлять новые тесты в приложение. Для этого нам нужно добавить модуль require:</p><p>Теперь добавьте файл с именем server-spec.js в папку spec. Он должен иметь такое содержание:</p><p>Теперь мы можем снова запустить все тесты: npm test.</p><p>Давайте запустим тест в контейнере. Для этого используется docker-compose. Добавим файл docker-compose.test.yml в проект:</p><p>Этот yaml-файл содержит инструкции по созданию образа контейнера с использованием Dockerfile, открытии порта 3000 и сопоставлении его с портом 3000 на хосте. Наконец, переопределяем значение entrypoint. Теперь в терминале введите следующую команду:</p><p>Это создаст образ Docker и запустит контейнер с использованием этого образа с переопределенной точкой входа. Если все работает правильно, мы должны увидеть такой вывод в терминале:</p><figure><img src="https://media.tproger.ru/uploads/2017/08/testing-and-debugging-a-containerized-node-application-4.png" alt="" /></figure><p>Здесь создается Docker-контейнер и выполняются все тесты. Тесты, которые прошли успешно, возвращают код 0. Мы можем остановить тестирование командой:</p><h2>Отладка приложения</h2><p>Мы научились выполнять автоматические тесты приложений. Но что насчет отладки? Ниже будет показано, как проходить код по строкам и проверять значения переменных.</p><p>Примечание В данном примере используется Visual Studio Code. Но эти действия можно совершить в большинстве современных редакторов.</p><p>Для начала нам нужно узнать, на каком IP-адресе находится хост Docker. Выполним команду:</p><p>Добавим в проект файл docker-compose.debug.yml со следующим содержимым:</p><p>Подобно файлу docker-compose для тестирования, мы используем Dockerfile для создания образа, открываем порт 3000 и порт 5858, сопоставляем их с теми же портами на хосте. Наконец, мы переопределяем точку входа node --debug = 5858 server.js. То есть запускаем узел в режиме отладки, прослушивая порт 5858. Мы можем начать сеанс отладки, используя эту команду:</p><p>В качестве последнего шага нам необходимо настроить Visual Studio Code для присоединения к Node-приложению, запущенному в контейнере. Добавим папку .vscode в наш проект. Внутри этой папки мы добавляем файл launch.json.</p><figure><img src="https://media.tproger.ru/uploads/2017/08/testing-and-debugging-a-containerized-node-application-5.png" alt="" /></figure><p>Содержимое файла должно быть следующим:</p><figure><img src="https://media.tproger.ru/uploads/2017/08/testing-and-debugging-a-containerized-node-application-6.png" alt="" /></figure><p>Обратите внимание на раздел с именем Attach. Вы должны убедиться, что в поле address командой docker-machine ip default указан IP-адрес вашего Docker-хоста.<br />Как только была добавлена конфигурация запуска, мы можем щелкнуть по кнопке отладки. Убедитесь, что выбрана настройка Attach, а затем нажмите кнопку запуска.</p><p>Теперь добавьте точку останова в строку 7 файла server.js. Откройте браузер и перейдите к 192.168.99.100:3000 (замените IP-адрес своим, если у вас другой). Отладчик должен остановиться в строке 7:</p><figure><img src="https://media.tproger.ru/uploads/2017/08/testing-and-debugging-a-containerized-node-application-7.png" alt="" /></figure><p>В окне отладки мы видим всю отладочную информацию:</p><figure><img src="https://media.tproger.ru/uploads/2017/08/testing-and-debugging-a-containerized-node-application-8.png" alt="" /></figure><h2>Итог</h2><p>Мы научились тестировать и дебажить приложения внутри Docker-контейнера. Преимущество этого метода в том, что нам не нужно загрязнять компьютер библиотеками и фреймворками для поддержки тестирования и отладки.</p>]]></content:encoded>
    </item>
    <item>
      <title>В Firefox 52 Developer Edition добавили новый JS-отладчик</title>
      <link>https://tproger.ru/news/new-mozilla-js-debug-in-devprev</link>
      <comments>https://tproger.ru/news/new-mozilla-js-debug-in-devprev?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Пётр Соковых]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/new-mozilla-js-debug-in-devprev</guid>
      <description><![CDATA[<p>Mozilla заменила отладчик JavaScript на базе XUL: прежняя архитектура требовала серьёзных усилий даже для мелких изменений, поэтому его переписали.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/new-mozilla-js-debug-in-devprev">В Firefox 52 Developer Edition добавили новый JS-отладчик</a>»</p>]]></description>
      <category><![CDATA[JavaScript]]></category>
      <category><![CDATA[Open Source]]></category>
      <category><![CDATA[Веб-разработка]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 29 Nov 2016 15:18:09 GMT</pubDate>
      <content:encoded><![CDATA[<p>Не так давно мы <a href="https://tproger.ru/news/new-mozilla-js-debugger/">писали</a> о том, что Mozilla работает над новым отладчиком для JavaScript. На днях <a href="http://forum.mozilla-russia.org/viewtopic.php?id=70953">была выпущена</a> Firefox 52 Developer Edition, которая уже использует его вместо старой версии, и статья, описывающая встроенный отладчик на Mozilla Developer Network, <a href="https://developer.mozilla.org/en-US/docs/Tools/Debugger">была переписана</a> под новую версию. Рассказываем, в какой стадии готовности находится новый продукт и зачем отладчик вообще надо было переписывать.</p><h4>Прежние технологии устарели</h4><p>Предыдущий отладчик базировался на XML User Interface Language (<a href="https://ru.wikipedia.org/wiki/XUL">XUL</a>) — собственной разработке Mozilla. Со временем стало ясно, что архитектура приложения построена так, что даже малейшие изменения отладчика требуют серьёзных усилий. В результате его было решено переписать с использованием <a href="https://en.wikipedia.org/wiki/React_(JavaScript_library)">React</a> и state-контейнеров <a href="https://github.com/rajdee/redux-in-russian">Redux</a>. Новый отладчик разбит на модули, которые удобно тестировать и поддерживать.</p><p>От XUL же Mozilla стремится избавиться как можно скорее. В настоящий момент все дополнения для Firefox используют именно его, однако начиная с версии 51 (стабильный релиз намечен на 24 января 2017) у разработчиков появится возможность использовать в качестве альтернативы API <a href="https://wiki.mozilla.org/WebExtensions">WebExtensions</a>. Постепенно возможности использования XUL будут урезаться, и к концу 2017 года в Firefox уже не будут поддерживаться дополнения, базированные не на WebExtensions. Хорошая новость в том, что благодаря этому все дополнения будут совместимы с браузером Chrome.</p><h4>Захват новых рынков?</h4><p>В отличие от старого отладчика, новый может использоваться как самостоятельный продукт, Firefox ему не нужен. Уже сейчас в качестве экспериментальной возможности отладчик поддерживает работу с Chrome и Node.js.</p><h4>Но всё же пока сыровато…</h4><p>Как отмечают пользователи в комментариях <a href="https://www.reddit.com/r/programming/comments/5fccnr/firefox_52_updates_debugger_but_some_old_features/?st=IW2NQZXB&amp;sh=95c60dac">на reddit</a>, до стабильной и удобной в использовании версии отладчику пока ещё далеко. Так, например, в нём отсутствует следующий необходимый любому JS-разработчику функционал:</p><ul><li><a href="https://developer.mozilla.org/en-US/docs/Tools/Debugger/How_to/Break_on_a_DOM_event">остановка по событиям</a> с элементами страницы;</li><li><a href="https://developer.mozilla.org/en-US/docs/Tools/Debugger/How_to/Highlight_and_inspect_DOM_nodes">подсветка и исследование</a> элементов страницы;</li><li><a href="https://developer.mozilla.org/en-US/docs/Tools/Debugger/How_to/Examine,_modify,_and_watch_variables">Проверка, изменение, и отслеживание переменных</a>;</li><li><a href="https://developer.mozilla.org/en-US/docs/Tools/Debugger/How_to/Black_box_a_source">black box a source</a> — сокрытие части исходного кода (например, библиотечного);</li><li>поиск по всем файлам;</li><li>переход к указаной строке;</li><li>фильтрация отображаемых переменных.</li></ul><p>Разумеется, в последующих выпусках все эти возможности планируется добавить, но пока отладчик Mozilla совсем не конкурентоспособен. Стоит помнить, однако, что актуальная версия Firefox сейчас — 50.0.1, а релиз 52-й версии назначен на март 2017 года — мы надеемся, что к тому времени отладчик будет выглядеть более привлекательно.</p><p>Скачать Firefox 52 Developer Edition можно с <a href="https://www.mozilla.org/en-US/firefox/channel/#aurora">официального сайта</a>, а посмотреть исходный код отладчика — на <a href="https://github.com/devtools-html/debugger.html">GitHub</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>Баг, который нельзя было исправить</title>
      <link>https://tproger.ru/translations/unfixable-bug</link>
      <comments>https://tproger.ru/translations/unfixable-bug?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Никита Мингалеев]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/translations/unfixable-bug</guid>
      <description><![CDATA[<p>Красный куб не появлялся на карте гонок, а отладчик к фрагментному шейдеру не применить — история поиска ошибки в графическом программировании.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/translations/unfixable-bug">Баг, который нельзя было исправить</a>»</p>]]></description>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[Компьютерная графика]]></category>
      <category><![CDATA[Переводы]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 24 Nov 2016 14:27:33 GMT</pubDate>
      <content:encoded><![CDATA[<p>Во время обучения в университете свое свободное время я тратил на создание своей игры — гонок. Я создал карту, нарисовал текстуры, создал водную поверхность с отражениями и преломлениями.</p><p>Следующим шагом было добавление машины. Здесь начались проблемы. Перед созданием красивой модели я решил начать с малого — с куба. Простой красный куб был создан и помещен на поверхность. Я запустил игру, но ничего не произошло. Куба не было. Чтобы куб было проще найти, я поместил его в центр карты, но его опять там не оказалось.</p><p>В программировании графики есть одна интересная вещь — обычно очень сложно найти источник ошибки. Нельзя применить отладчик к фрагментному шейдеру или посмотреть логи. Остается только изменять параметры, в надежде обнаружить ошибку.</p><p>После внимательного изучения своего кода я начал играться с параметрами. Сначала я поменял цвет куба с красного на белый и перезапустил игру. И знаете что? Маленький белый куб красовался на земле. Может быть я перепутал красный, зеленый и голубой каналы с альфа-каналом, задающим прозрачность? Я снова проверил, но ничего не нашел. Я поменял цвет на голубой, куб остался. Вернулся к красному. Куб исчез.</p><p>Это было странно. Почему не видно красный куб? Я проверил фрагментный шейдер. Я проверил режимы рендеринга. Я даже проверил настройки шаблона. Всё было хорошо. Но почему тогда мой куб не видно?</p><p>Я сделал его опять красным, и знаете что? Он появился! Я вернулся в самое начало, но теперь куб было видно! Ошеломленный, я отвел взгляд от монитора. Когда я посмотрел обратно, он опять исчез. Потом появился. Потом опять исчез. И тут меня осенило.</p><p>Куб был там все это время. Ошибка была не в программном или аппаратном обеспечении. И даже не в окружающем меня пространстве. Причина, по которой я не мог видеть красный куб на зеленом фоне, оказалась простой — я дальтоник, и путаю красный цвет с зеленым.</p>]]></content:encoded>
    </item>
    <item>
      <title>Mozilla представила новый отладчик для JavaScript, доступный для использования в Chrome и Node.js</title>
      <link>https://tproger.ru/news/new-mozilla-js-debugger</link>
      <comments>https://tproger.ru/news/new-mozilla-js-debugger?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Пётр Соковых]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/new-mozilla-js-debugger</guid>
      <description><![CDATA[<p>Отладчик Mozilla построен на компонентах React и state-контейнере Redux вместо XUL, из-за которого обновления старого дебаггера давались тяжело.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/new-mozilla-js-debugger">Mozilla представила новый отладчик для JavaScript, доступный для использования в Chrome и Node.js</a>»</p>]]></description>
      <category><![CDATA[JavaScript]]></category>
      <category><![CDATA[Open Source]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Sun, 18 Sep 2016 19:32:46 GMT</pubDate>
      <content:encoded><![CDATA[<p>На этой неделе Mozilla <a href="http://www.infoworld.com/article/3121244/javascript/mozilla-relaunches-javascript-debugger-as-part-of-tools-transition-plan.html">представила</a> новый отладчик для JavaScript. Наша редакция постаралась разобраться, чем он отличается от старого, и почему это здорово.</p><h4>Новые технологии и простота изменений</h4><p>Одна из причин выпуска нового дебаггера — сложности с выпуском обновлений для старого. Причиной этому является использование в нём XML User Interface Language (<a href="https://ru.wikipedia.org/wiki/XUL">XUL</a>), который в итоге сделал добавление даже малозначительных изменений непростым делом. В новой версии было решено использовать более современную архитектуру, основанную на компонентах <a href="https://en.wikipedia.org/wiki/React_(JavaScript_library)">React</a> и state-контейнере <a href="https://github.com/rajdee/redux-in-russian">Redux</a>. В итоге новый отладчик разбит на множество модулей, которые легко поддерживать, дорабатывать и тестировать.</p><h4>Возможность использования без Firefox</h4><p>Mozilla планирует, в первую очередь, использовать дебаггер в браузере Firefox (и отладчик уже включён в <a href="https://nightly.mozilla.org">ночные сборки</a>). Однако использование новых технологий, которые поддерживаются везде (в отличии от XUL, который был разработан Mozilla и фактически только ими и поддерживался), позволило добавить в отладчик поддержку работы с Chrome и даже Node.js (сейчас это является экспериментальной возможностью).</p><h4>Удобный интерфейс</h4><figure><img src="https://media.tproger.ru/uploads/2016/09/debuggerhtml-interface-1024x649.png" alt="" /></figure><p>Интерфейс отладчика разделён на три основные части: панель с деревом проекта, панель редактора и вертикальное меню справа. Дерево проекта отображает все части проекта, которые отлаживаются в настоящий момент. Панель редактора отображает код, который рассматривается в настоящий момент, и позволяет устанавливать точки остановки (breakpoints). Меню справа позволяет просматривать точки остановок, которые назначены в настоящий момент, просматривать стек вызовов и список переменных.</p><h4>Свободное программное обеспечение</h4><p>Код отладчика доступен <a href="https://github.com/devtools-html/debugger.html">на GitHub</a> и распространяется по свободной лицензии Mozilla Public License v2.0.</p><p>Больше технических деталей вы можете узнать из <a href="https://hacks.mozilla.org/2016/09/introducing-debugger-html/">поста</a> Брайана Кларка (технического менеджера Mozilla) или из документации в <a href="https://github.com/devtools-html/debugger.html">репозитории</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>Отлаживай программы, как настоящий сыщик</title>
      <link>https://tproger.ru/links/debug-like-holmes</link>
      <comments>https://tproger.ru/links/debug-like-holmes?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Типичный программист]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/links/debug-like-holmes</guid>
      <description><![CDATA[<p>Поиск ошибки похож на работу следователя: собрать косвенные улики, выдвинуть гипотезу, поставить эксперимент, доказать вину и устранить причину.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/links/debug-like-holmes">Отлаживай программы, как настоящий сыщик</a>»</p>]]></description>
      <category><![CDATA[Советы]]></category>
      <category><![CDATA[Отладка]]></category>
      <category><![CDATA[Интересные ссылки]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 06 Oct 2015 19:40:21 GMT</pubDate>
      <content:encoded><![CDATA[<p>Если вы всегда мечтали стать сыщиком — искать улики, проверять гипотезы и искать виновного — но, почему-то, стали программистом — не отчаивайтесь!</p><p>Отладка программ <a href="https://www.getdonedone.com/debugging-like-a-detective/">очень похожа</a> на работу следователя. Выследить ошибку по косвенным признакам, поставить эксперимент, доказать вину и устранить. Программист — как Шерлок Холмс!</p><blockquote><i>Прим. редакции.:</i> в 2004 году вышла отличная книга Debugging by Thinking: A Multidisciplinary Approach (HP Technologies), в которой описываются этот и многие другие «стили» отладки.</blockquote>]]></content:encoded>
    </item>
  </channel>
</rss>