пятница, 31 июля 2026 г.

[prog.thoughts] Так как же ИИ может изменить профессию "программист"?

Попробую подвести итог начатых ранее размышлений.

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

Во-первых, это экономическая и политическая обстановка в мире. Если не будет какого-то катаклизма, сравнимого с Первой или Второй Мировыми войнами, если мировая экономика выберется из кризиса и вернется экономический рост, то у программистов в целом все будет ОК. Будет работа, которая, наверняка, сильно изменится. Но эта самая работа хотя бы будет. А вот если мир скатится во что-то вроде Великой Депрессии в США 1930-х годов, или периода Веймарской республики начала 1920-х годов, то увы. Всем будет очень и очень не очень. В том числе и программистам. А может быть программистам как раз в первую очередь.

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

Еще, конечно же, интересный вопрос в том, до какого уровня качества этот самый ИИ в итоге дойдет. Пока все говорят (говорят!), что ИИ с каждой новой версией становится все лучше и лучше. Хотя внешней публике и не видно во что (по деньгам инвесторов) эти улучшения обходятся.

А то ведь может оказаться, что с ИИ такая же ситуация, как с аудиофилией: очень несложно и совсем не дорого дойти до 90% от теоретически возможного качества звука. Зато стоимость каждого следующего процента качества возрастает в геометрической прогрессии. Может и с ИИ так? Может мы еще даже до 90% не дошли. И каждая следующая ступень качества, когда модели будут выдавать более точные решения и меньше галлюцинировать, будет обходиться на порядок дороже предыдущей. Чтобы в итоге стало не выгодно вкладывать деньги в повышение этого самого качества.

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

Думаю, что тогда наша профессия изменится. Быстро и бесповоротно.

Но не исчезнет.

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

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

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

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

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

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

четверг, 30 июля 2026 г.

[prog.thoughts] Надобность в "инфраструктурниках" из-за того, что людям приходилось писать код самим

Продолжу то, что начал ранее.

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

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

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

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

Получается, что чем более сложную задачу нам нужно решить, тем большим количеством более мощных абстракций мы должны располагать. Будь то языковые конструкции (вроде классов или шаблонов/дженериков) или библиотеки готовых "компонентов". А воплощение в жизнь подобных абстракций -- это именно что работа инфраструктурных программистов. Кто-то из инфраструктурщиков развивает языки программирования для того, чтобы поднять уровень и дать возможность выражать в коде все более и более сложные вещи, при этом обеспечивая и надежность, и удобство (если не брать в рассмотрение C++, конечно же). Кто-то пишет библиотеки и фреймворки. Кто-то создает вспомогательные инструменты вроде flex/bison или ANTLR.

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

Или может быть лучше сказать "получали"?

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

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

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

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

Это люди могли набить шишки на return -1, прийти к выводу, что исключения надежнее, потом собрать кучу граблей с исключениями, прийти к выводу, что нужен симбиоз, изобрести синтаксис `?` в Rust и try в Swift...

Чтобы в итоге этих самых людей заменил ИИ, который будет генерить простыни Go-шного кода с примитивнейшим `if err != nil` ничуть не страдая от того, что это и многословно, и отвлекает внимание, и не обеспечивает достаточной надежности.


Продолжение.

среда, 29 июля 2026 г.

[prog.thoughts] Мое деление программистов на "прикладных" и "инфраструктурных"

Чтобы продолжить рассуждения о том, как ИИ может повлиять на будущее профессии "программист" (начатые здесь и продолженные здесь) придется озвучить одну из классификаций программистов, которой придерживаюсь в последние годы.

Прикладные программисты делают то, что нужно пользователю. Причем не важно, о каком именно продукте идет речь -- это может быть какая-то сделанная на коленке под заказ система складского учета для провинциальной конторы "Рога и Копыта", пакет Microsoft Office или же сервер реляционной СУБД. Суть в том, что есть продукт, есть требования к нему, есть список фич, которые нужно выкатить, есть сроки, есть бюджеты, есть обязательства и т.д., и т.п. И появляется конкретный продукт для конкретного пользователя именно благодаря труду прикладных программистов.

Инфраструктурные программисты делают инструменты, которые используют прикладные программисты в своей работе. Самыми яркими примерами таких инструментов являются фреймворки и библиотеки. Как общего назначения (вроде Qt, JDK или .NET Framework), так и какие-то специализированные, заточенные под конкретный проект.

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

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

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

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

Яркий пример, демонстрирующий разность в подходах, довелось увидеть буквально пару дней назад в докладе «Опыт перехода проекта „Авито.Доставка“ с Java на Go» / Илья Лапин, Сергей Поляков (Avito), который мне YouTube зачем-то подсунул в рекомендациях (но оказалось довольно любопытно, благо доклад короткий и толковый):

Суть в том, что на момент доклада (2018-й год) в стандартной библиотеке Go (как и в самом языке) не было такого понятия как "множество" (оно же Set). Понятие "словарь" встроенное в сам язык было (в виде штатного типа map), а вот "множества" -- нет.

Прикладной программист: ну OK, раз нет "множества", то сойдет и "словарь", просто в качестве значения для ключа будет использоваться экземпляр пустой структуры. Не, ну а чё, работает же.

Тогда как инфраструктурный программист от подобного впадает в ступор. Типа: "а почему этот самый Set нельзя было взять и сделать?" 😉

PS. Убедительная просьба не воспринимать этот текст как попытку ранжирования программистов по их качеству. Типа "прикладные" программисты -- не настоящие программисты вовсе, тогда как "инфраструктурные" -- соль профессии и настоящая илитарная илита. Как раз жизнь учит тому, что все программирование живет и зарабатывает исключительно благодаря "прикладным" программистам, тогда как "инфраструктурые" являются всего лишь обслуживающим персоналом (но без этого обслуживающего персонала тоже нельзя).


Продолжение.

вторник, 28 июля 2026 г.

[prog.thoughts] И еще одна мысль про влияние ИИ на программирование

Навеяно вот этой статьей: Английский вместо кода

Когда я приходил в профессию на программиста возлагались следующие задачи:

  • выяснить что именно нужно сделать (здесь подразумевается общение с заказчиком и умение сформировать более-менее адекватное ТЗ по результатам этого общения);
  • решить как именно это будет сделано (архитектура, алгоритмы, сторонние библиотеки, форматы данных и вот это вот все);
  • воплотить решение в коде (чистый, работающий, тестируемый, сопровождаемый код и вот это вот все);
  • протестировать сделанное.

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

Никаких бизнес-аналитиков и тестировщиков в то время в наших палестинах еще не существовало как класса, появилось все это лет на 5-10 позже (хотя на Западе, как я слышал, к началу 1990-х все это уже было). Ну да не суть.

Суть же в том, что для некоторых настоящее программирование заключалось прежде всего в "воплотить решение в коде" + (кому-то в больше степени, кому-то в меньшей) "решить как именно сделать" и "протестировать сделанное" (иногда в формулировке "заставить это все работать в конце-то концов!"). А общение с заказчиком и формирование ТЗ было худшим из периодов и настоящим наказанием.

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

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

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

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

Как по мне, так это уже и не программирование вовсе.

понедельник, 27 июля 2026 г.

[prog.thoughts] Подумалось тут про ИИ и будущее программирования...

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

В связи с этим подумалось, что наступает золотая эпоха тех специалистов, которые были вынуждены программировать ну хоть как-то. Вроде физиков, химиков и биологов, которым нужно было делать вычислительные эксперименты, для чего приходилось осваивать программирование хотя бы в минимальной степени. В лучшем случае на Python или Pascal, но скорее на Fortran, а в особо запущенных случаях и на С++.

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

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

суббота, 25 июля 2026 г.

[prog.c++.multithreading] Сломал себе мозг пытаясь понять что не нравится thread sanitizer-у

Upd. Похоже, что проблема сперва была в том, что SO-5 подключался в проект через vcpkg и когда проект компилировался с TSan, то линковался SO-5, собранный без TSan. А когда я включил исходники SO-5 в сам проект, чтобы все компилировалось с одинаковыми ключами, то ошибся с порядком команд в CMakeLists.txt и при компиляции SO-5 опции для TSan не учитывались. Если же собрать и SO-5, и остальной проект с одинаковыми опциями, то данной проблемы не возникает (пока?).

В текущем проекте thread sanitizer периодически выдает предупреждение о data race на фрагменте, который относится к SObjectizer-у.

Самое плохое то, что:

  • я не понимаю в чем именно thread sanitizer видит проблему. Соответственно, неизвестно, является ли срабатывание TSan-а ложно позитивным или же есть реальная ошибка, которую следует исправить;
  • мне не удается повторить такую же ситуацию в тестах для самого SO-5. Т.е. в рамках проекта TSan диагностику выдает, а в мелких тестах, которые пытаются повторить тот же сценарий -- нет. Ни в какую. Что сильно затрудняет разбирательства и поиск обходных путей.

Что здесь происходит:

Агент на нити T7 отсылает сообщение GiveMeTask агенту-координатору, который работает на нити T3.

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

В это же время на нити T7 завершается процедура отсылки сообщения.

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

Экземпляр сообщения GiveMeTask создается на нити T7. Указатель на этот экземпляр хранится на нити T7 внутри объекта intrusive_ptr_t.

На нити T3 внутри execution_demand_t так же есть свой объект intrusive_ptr_t который хранит указатель на этот же экземпляр GiveMeTask.

Т.е. на двух нитях есть два разных intrusive_ptr_t, которые хранят в себе указатель на один и тот же объект GiveMeTask.

При этом счетчик ссылок на GiveMeTask хранится в самом объекте GiveMeTask. Класс GiveMeTask наследуется от so_5::message_t:

struct GiveMeTask final : public so_5::message_t
{
    const so_5::mbox_t _workerMbox;

    GiveMeTask(so_5::mbox_t workerMbox)
        : _workerMbox{ std::move(workerMbox) }
    {}
};

А so_5::message_t наследуется от so_5::atomic_refcounted_t:

class message_t : public atomic_refcounted_t
    {
        ...
    };

В so_5::atomic_refcounted_t счетчик ссылок хранится в виде std::atomic. Т.е. операции инкремента-декремента количества ссылок происходят атомарно и не нуждаются в дополнительной синхронизации.

Получается, что на нити T7 создается новый экземпляр GiveMeTask, указатель на него сохраняется в локальном объекте intrusive_ptr_t и счетчик ссылок на GiveMeTask выставляется в 1.

На нити T7 вызывается send для GiveMeTask и формируется execution_demand_t для агента-координатора. Внутри execution_demand_t создается свой intrusive_ptr_t и счетчик ссылок для GiveMeTask получает значение 2.

Затем на нити T3 происходит обработка GiveMeTask, после чего начинается разрушение execution_demand_t и его содержимого (в том числе и второго intrusive_ptr_t).

Но чуть раньше на нити T7 происходит разрушение своего intrusive_ptr_t после чего счетчик ссылок в GiveMeTask опускается до 1.

А уже после этого на нити T3 счетчик ссылок на GiveMeTask обнуляется и происходит разрушение объекта GiveMeTask.

Происходят действия именно в этом порядке. Если бы сперва полностью разрушился execution_demand_t на нити T3 и лишь после этого началось уничтожение intrusive_ptr_t на нити T7, то деструктор GiveMeTask вызвался бы на нити T7, а не на нити T3.

Т.е. с моей точки зрения здесь все OK. Но TSan видит data race. А я не понимаю про какой data race идет речь.

Под катом выхлоп от TSan в текстовом виде.

среда, 22 июля 2026 г.

[prog.flame] Узнал давеча о переписывании какого-то Bun с какого-то Zig на какой-то Rust :)

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

Некий проект Bun (говорят, что это какой-то очень и очень быстрый инструментарий для JavaScript, включая и виртуальную машину) внутри Antropic-а переписали с Zig на Rust посредством нескольких десятков параллельно работавших в течении 11 дней агентов: https://bun.com/blog/bun-in-rust

На рассказ об этой процедуре среагировал разработчик языка Zig и высказался в том духе, что баба с возу кобыле легче переписали на Rust и славно, а то эти Bun-овцы уже изрядно задолбали дискредитацией всего Zig-а низким качеством своего кода: https://andrewkelley.me/post/my-thoughts-bun-rust-rewrite.html

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

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

fn foo(a_ptr: SharedPtr(TCPSocket)) !void {
  const a: *TCPSocket = a_ptr.get();
  defer a_ptr.deref();

  const b = try do_something_with_a(a);
  defer b.deref();

  // ...
}

Поскольку я не знаю Zig, то очень интересно, а это прям идиоматический код и лучше на Zig уже не получится? Или же это откровенный говнокод, низкое качество которого очевидно даже начинающим Zig-ерам?

PS. Так же я не полностью согласен с тезисом, что для C++ надежность кода достигается за счет следования какому-то административно утвержденному code style (как в случае с упомянутым в блог-посте от Bun-овцев Google C++ code style guide). Многие проблемы (вроде контроля времени жизни объектов, находящихся в совместном использовании) должны решаться не соглашениями, а типами (вроде unique_ptr, shared_ptr и т.д.) Но кто я такой, чтобы рассуждать на эту тему? 😉

PPS. А Rust подтверждает свою репутацию языка, на котором ничего нового не пишут, а только переписывают существующее 🤣