воскресенье, 1 ноября 2026 г.

[life.cinema] Очередной кинообзор (2026/10)

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

Фильмы

Фальшивомонетчик (L’affaire Bojarski, 2025). Мне понравилось. Вроде бы и история не самая сложная, но рассказана интересно, плюс воссозданная атмосфера тех лет. Посмотрел с удовольствием.

Надежда (Hopeu, 2026). Очень бодренько. Ну и я смотрел с пиратским матерным переводом, так что было бодренько вдвойне.

Поймать Эль-Чапо (La Captura, 2026). Неожиданно неплохое кино из Мексики. Да, ощущается бюджетность. Да, не хватает экшОна. Но насколько хорошо создателям удалось передать ужас обычных полицейских, оказавшихся в такой ситуации, просто мое почтение.

Тенцинг (Tenzing, 2026). Было бы лучше, если бы хронометраж сократили минут на 20, убрали бы сопли из воспоминаний о тяжелом прошлом главного героя и больше сконцентрировались на том, какими же фантастически тяжелыми были условия первых восхождений на Эверест.

Мятеж (Mutiny, 2026). Классический фильм со Стетхемом в главной роли: очень бодро, очень предсказуемо.

Бегущая (The Runner, 2026). Довольно бодренько и развязка хорошая. Но, во-первых, меня дико бесила операторская работа. Во-вторых, было в фильме несколько ну очень уж фантастических моментов, в которых спасение главной героини выглядело совсем уж сказочным. Что, в сумме, сильно портит впечатление от просмотра.

На краю Оук-стрит (The End of Oak Street, 2026). Глянуть можно, но очень уж по детски и очень уж дешевые спецэффекты.

Любой ценой (By Any Means, 2026). Очень скучное кино. Не смотря на какой-то экшОн и жестокость, рассказанная история не цепляет.

Мотор Сити (Motor City, 2025). Ну очень нудно и затянуто. Немного спасает ситуацию саунд-трек, но только немного. В развязке фильма одного из героев загримировали так убого, что окончательно убили все то хорошее, что в фильме еще было.

Настройщик (Tuner, 2025). Купился на трейлер, думал, что это криминальный триллер, а оказалось, что сопливая мелодрама, местами переходящая в сказочку. Любителям мелодрам может и зайдет, да и музыка в кино шикарная.

Флорист (The Florist, 2026). Очень посредственно даже не смотря на участие хороших в прошлом актеров. Да еще и очень бюджетно.

Мексикали (Mexicaly, 2026). Дешевый боевик с закосом под олдскульность. Сцены рукопашных боев сделаны отлично, все остальное снималось "на сдачу", в особенности перестрелки.

Сериалы

Капкан для монстра (первый сезон, 2026). Неоднозначные впечатления. Главные злодеи угадываются практически сразу. Плюс случаются моменты, в которые хочется воскликнуть "ну что за фигня?!!!" Но, с другой стороны, играют хорошо, история затягивает, какой-то типичной сериальной затянутости не ощущается. В общем, не шедевр, но посмотреть вполне можно.

Число зверя (первый сезон, 2026). Начало было приличным, но затем стали накапливаться разные моментики (вроде проведения обыска с санкцией, но без понятых), которые сильно подпортили итоговое впечатление.

суббота, 31 октября 2026 г.

[prog.c++] Пара слов о stackless короутинах в C++20

По мере продвижения работ по встраиванию C++20 короутин в SObjectizer накапливаю опыт работы с этими самыми короутинами. Пока его еще мало, чтобы составить какой-то адекватный список проблем. У меня вообще нет окончательного мнения о том, кто был автором короутин в C++20 -- гении, безумцы, или гениальные безумцы, или все вместе, или одно из двух. Ну да ладно, пока что озвучу пару вещей, которая меня временами то ли напрягает, то ли вымораживает.


Основной момент -- это конструирование экземпляра promise_type при создании короутины. У promise_type вызывается либо дефолтный конструктор (без параметров), либо же конструктор, куда можно запихнуть все аргументы функции, являющейся короутиной. Т.е. если у нас есть:

task_t my_coro(int a, char * b) {...}

то у task_t::promise_type должен быть либо дефолтный конструктор, либо конструктор вида:

promise_type(int, char *)

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

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

Или вот мне захотелось уметь привязывать task_t к конкретному планировщику, а в прототипе my_coro нет никаких планировщиков -- только int и char*. И все, выдумывай что хочешь.

Что тут можно было бы придумать?

А вот пока не знаю. Для меня вообще stackless короутины -- это странный и непривычный зверь с очень ограниченной областью полезного применения. Пока еще не набил с ними достаточного количества шишек. Поэтому могу только фантазировать.

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

auto r = co_await co_create(allocator, scheduler) socket.connect(ip_address);

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

Может быть в co_create можно было бы предавать и признак того как именно короутина должна стартовать -- энергично или лениво:

auto c = co_create(std::lazy) socket.connect(ip_address);
...
auto r = co_await c;

Но на счет этого не уверен совершенно.


Еще одна штука масштабом сильно помельче, но гораздо более раздражающая.

Метод await_suspend у Awaiter-а может иметь разные типы возвращаемых значений:

  • void. Приостанавливать текущую короутину нужно обязательно;
  • std::coroutine_handle. Нужно возобновить работу указанной короутины. В том числе это может быть и текущая короутина если приостанавливать ее не пришлось;
  • bool. Нужно или не нужно приостанавливать текущую короутину определяется возвращенным значением.

И вот с bool-ом лично у меня постоянные заминки. Ну не могу я запомнить что означает true: приостановить короутину или же нет.

И тут спрашивается: а что мешало вместо bool сделать специальный тип, вроде:

enum class await_suspend_result { suspend, resume };

Т.е. если await_suspend возвращает await_suspend_result::suspend, значит текущую короутину нужно таки заморозить. А если await_suspend_result::resume, то наоборот.

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

суббота, 10 октября 2026 г.

[work;life] СтифСтриму десять лет

Таки нам десять лет. Несколько неожиданно. И в том плане, что дожить до 10 было не просто. И в том плане, что очень уж быстро эти годы пролетели.

Данный пост содержит мою личную рефлексию по данному поводу. И написан он, скорее всего, для меня самого, чтобы было что перечитать через 5, 10, а может быть и 15 лет. Поэтому заранее извиняюсь, если вы не найдете здесь ничего интересного для себя.

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

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

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

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

Пока что на 100% эта цель не достигнута 😉
Тут еще есть над чем работать.

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

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

Во-первых, когда СтифСтрим создавался, мне было уже за 40. И я исходил из того, что это будет моя первая и последняя попытка начать собственное дело. Поэтому не рассматривал для себя опцию "быстро попробуем, если не пойдет, то закроемся и посмотрим в другую сторону". Хотя, наверное, следовало бы. Оглядываясь назад и присматриваясь к чужому опыту понимаю, что одним из важных качеств бизнесмена является умение признавать неудачи, быстро ликвидировать убыточные предприятия и пробовать новые направления. Мне этого умения не хватило. Возможно, компанию имело смысл закрыть где-то в 2019-ом или 2020-ом году, когда все наши первоначальные планы окончательно накрылись медным тазом. Возможно. Но история не знает сослагательного наклонения. Поэтому сегодня СтифСтим отмечает свое десятилетие.

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

В-третьих, я долго не мог понять кому же нужны наши услуги. Только в последние 3-4 года стало окончательно понятно, что это небольшие по размеру компании, в которых от 4-5 до 10-15 разработчиков.

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

Ну да все это дела минувшие. А вот заглядывать в будущее страшновато.

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

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

Поэтому планов на будущее не строю от слова совсем, горизонт планирования буквально 2-3 месяца. И да, я знаю, что с точки зрения бизнеса это неправильно. Но я и так очень и очень многое в своей жизни делал неправильно. Одним неправильным поведением больше, одним меньше. Поэтому живем сегодняшним днем: стараемся качественно выполнять задачи текущего заказчика, выкраиваем время для развития SO-5, надеемся рано или поздно вернуться и к RESTinio.

Как-то так: делай что должно и будь что будет. Ну а я был бы не против через 10 лет написать еще один такой пост.

пятница, 9 октября 2026 г.

[work;life] Уроки из 10 лет ведения собственного бизнеса

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

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

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

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

Ваши проблемы будут с вами 24x7x365. Если не понятно почему, то см. выше про "Никто кроме вас".

Скорее всего вы никто и звать вас никак. Особенно актуально для тех, кто добился более-менее высоких должностей в крупных компаниях с уже сложившейся репутацией. Грубо говоря, когда вы предлагаете покупателю продукт/сервис от HP или IBM, то это одно, но когда вы не имеете за спиной поддержки громкого бренда и продвигаете новый продукт от никому не известной компании "Рога и Копыта", то вы никто и звать вас никак. Очень хорошо, если для старта вы можете воспользоваться старыми связями и покупку вашего продукта/сервиса могут пролобировать те, кто вас уже знает и/или имеет какой-то свой интерес в этом. Но за пределами этого не очень широкого круга старых связей вы никто и звать вас никак. Имя и репутацию нужно строить с нуля.

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

Воронка продаж. Она существует.

Время -- деньги или "time to market really matters". Ваше отношение ко времени и деньгам изменится. Одним из основных вопросов станет "когда продукт станет доступен на рынке?", а каждый день просрочки вы в прямом смысле начнете ощущать собственным кошельком. Соответственно, качество вашего продукта станет всего лишь одним из его свойств. Жизнь показала, что качество стоит очень дорого, мало кто готов за это платить, т.к. платить приходится не только и не столько деньгами, сколько временем, которое не купить и которым никто не располагает в достаточной мере. Ну кроме наемных работников, само собой ;)

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

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

Ничто не вернет времени, которое вы потратили на бизнес, а не на семью. Ничто.

PS. Последний урок, вероятно, самый важный.

вторник, 6 октября 2026 г.

[prog.c++] Пара слов о докладе про переход от акторов к C++20 короутинам

Upd. Обсуждаемый ниже материал появился на Хабре в виде статьи: Корутины в продакшене: как переложить рельсы под идущим поездом. И в комментариях к этой стате выяснилось, что примеры написаны на CAF для того, чтобы не показывать на слайдах реальный код. Поэтому часть того, что было написано ниже, вероятно, неактуально. И, не исключена вероятность, что на самом деле в качестве агентного фреймворка использовался SObjectizer. Однако, никаких подтверждений этому у меня нет.

На Хабре появился отчет "У нас есть «плюсы» дома: о чем говорили на митапе YADRO × C++ Russia", в котором опубликованы видео докладов "Make legacy great again: переводим зрелый проект на С++20-корутины" и "С++20-корутины в KvadraOS: как устроены и зачем внедрялись". Первый из этих докладов я посмотрел и, как разработчик акторного фреймворка для С++, имею что сказать.

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


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

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

auto r1 = subsystem_1.ask_something();
auto r2 = subsystem_2.ask_something(r1.some_data);
auto r3 = subsystem_3.ask_something(r2.some_data);
make_response(r3.some_data);

Будет что-то вида (псевдокод, не привязанный к конкретному C++ному фреймворку):

my_actor.on([&](start_signal) {
  send<ask_something>(subsystem_1).reply_to(my_actor);
});
my_actor.on(subsystem_1, [&](response & r) {
  send<ask_something>(subsystem_1, r.some_data).reply_to(my_actor);
});
my_actor.on(subsystem_2, [&](response & r) {
  send<ask_something>(subsystem_2, r.some_data).reply_to(my_actor);
});
my_actor.on(subsystem_3, [&](response & r) {
  make_response(r.some_data);
});

Поэтому если в вашем распоряжении C++ный акторный фреймворк по типу CAF или SObjectizer и вам нужно писать, в основном, линейный код, то задействовав акторы вы только усложните себе работу.

Акторы будут себя оправдывать в ситуациях, когда вы ожидаете не одно входящее событие, а несколько разных. Т.е. у вас нет сценария "запросили что-то у подсистемы 1 и ждем ответа", а у вас есть сценарий "инициировали несколько действий и далее ждем одно из трех/четырех/пяти/... событий". Вот тогда вы либо превращаете свой код в лапшу через switch-и:

auto msg = receive_message();
switch(msg.type)
{
case event_1: ...; break;
case event_2: ...; break;
case event_3: ...; break;
}

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

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


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

Во-первых, потому, что виденный мной код акторов на CAF -- это лямбда в лямбде верхом на лямбде и лямбдой погоняет.

Во-вторых, потому, что в виденных мной примерах кода на CAF сообщения принято передавать в виде ad-hoc туплов. Все эти туплы приходится выписывать и в декларациях обработчиков сообщений, и в операциях отсылки сообщений. Что требует затем ручной правки всех этих мест в коде если тупл потребовалось изменить (например, добавить еще что-то в отсылаемое сообщение).

В SObjectizer-е принят совсем другой подход. Поэтому код на SObjectizer, надеюсь, чуть более прост и удобен в сопровождении.

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


Отдельный вопрос в том, а акторы в принципе подходят под решение задач, подобных рассмотренной в докладе "Make legacy great again: переводим зрелый проект на С++20-корутины"?

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

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

Поэтому лично я бы при попытке подойти к подобной проблеме с акторами на перевес, попробовал бы сперва продумать схему "один актор на операцию". Т.е. актор для авторизации, один актор для выполнения запросов к БД, один актор для протоколирования и т.д., и т.п.

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

Так же, возможно, акторы были бы вполне уместны даже в схеме "один актор на запрос", но в случае, если у акторов коллбеки могут безопасно и дешево засыпать на синхронных обращениях к другим акторам, не блокируя при этом механизмы диспетчеризации событий в акторном фреймворке. Например, если каждый актор -- это stackfull короутина (fiber, green thread). Тогда актор запросто может заснуть на синхронной операции, а обслуживающий его тред ОС возьмет в работу какого-то другого актора. Но, во-первых, ни CAF, ни SObjectizer подобные акторы не поддерживают. Во-вторых, в докладе отдельно говорится про проблемы, связанные с fiber-ами.


Теперь пара слов о том, а можно ли получить лучшее из двух миров в одном флаконе, т.е. иметь возможность использовать и акторы, и C++20 stackless короутины.

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

Да, думаю, что можно.

И я пытаюсь научить SO-5 этому. Но не могу сказать, когда же это заработает на практике.

Тут нужно понимать одну простую вещь: SObjectizer напрямую не приносит нам денег, мы не зарабатываем ни на продаже SO-5, ни на его техподдержке, ни на обучении, ни на кастомизации SO-5 под чьи-то специфические нужды. SO-5 и RESTinio создают нам репутацию, которая приводит клиентов. Но клиенты платят за решение своих проблем в своем коде. И эти проблемы, в 99% случаев, вообще никак не связаны с SO-5.

Поэтому работы над SO-5 ведутся лишь тогда, когда для этого удается выкроить ресурсы. То, что могло бы занять 2-3 месяца нормальной работы над SO-5 в режиме "полный рабочий день", растягивается, буквально, на год, если получается выкраивать по 10-15 часов в неделю, да и то далеко не всегда. Посему поддержка короутин в SO-5, надеюсь, появится. Но не через неделю, и даже не через месяц, а может и не через два. Увы, такова се ля ви.

По текущему статусу добавления С++20 короутин в SO-5 могу сказать следующее: часть подготовительных работ выполнена. Дело уперлось в такое понятие, как event_handler_method_t. Эта штука предназначена для хранения обработчиков сообщений и сейчас она заточена только под синхронные обработчики. А нужно поддержать еще и асинхронные. И вопрос в том как это сделать.

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

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

понедельник, 5 октября 2026 г.

[comp.notebooks] От 14" ноутбука к 16" и обратно

Поделюсь очень неожиданным для себя самого открытием. В очередной раз на тему ноутбуков. Уж прошу простить мне эту слабость, т.к. в последние 25 лет работаю только на ноутбуках и для меня это инструмент, с которым я живу, наверное, в режиме 10/7, а иногда и 12/7.

Так вот, много лет подряд пользовался небольшими по размеру 13.3" и 14" ноутбуками. Была попытка в 2019-ом пересесть на 15.6", но в итоге эта пятнашка гораздо чаще использовалась (и используется) для обработки фото и просмотра кино, чем для работы, программировал же, в основном, на 14" ноутбуке.

Но постепенно стали накапливаться некоторые проблемы, вызванные как размерами 14" экрана, так и тем, что в современных 13" и 14" ноутбуках производители очень редко делают на клавиатуре отдельные кнопки Insert, PgUp, PgDn, не говоря уже про Home и End:

  • при созвонах в Zoom или Telemost собеседники часто показывали свои экраны. И если на той стороне большой дисплей с разрешением выше 2.5K, масштабируется на твой 14" экранчик, то читаемость заметно ухудшается (даже не смотря на то, что на 14" экране разрешение 2.8K);
  • если заходишь по RDP из Linux-а через Remmina на Windows машину, то качество шрифтов в окне Remmina оставляет желать много лучшего. Причем это проблема именно входа из Linux-а через Remmina, когда вход делаешь с Windows машины, то с качеством все гораздо, гораздо лучше. Но так уж получается, что в основном я работаю на Linux-е 🙁
  • в какой-то момент я стал в vim-е делить окно пополам для того, чтобы в левой части держать один файл (например, .hpp), а в правой части -- другой (.cpp). Тем самым охватывая взглядом фрагменты из разных файлов. На 14" это можно было сделать только очень сильно уменьшив размер шрифта, а работать так долго невозможно, быстро устают глаза;
  • на имевшихся в моем распоряжении 14" ноутбуках не было аппаратных кнопок Insert (привык пользоваться комбинациями Shift+Insert и Ctrl+Insert), Home и End. А на одном из них не было и отдельных клавиш PgUp, PgDn. Что со временем стало сильно раздражать, т.к. невозможно было двигаться по документам (в Word-е или в окне браузера) посредством одной руки. Например, держишь ноутбук на весу левой рукой, а правой пытаешься двигаться по тексту. Или же держишь в правой руке карандаш для записей в тетрадке, а левой выполняешь навигацию по документу (или даже нескольким документам).

В конце 2025-го года все эти факторы накопились + добавилось подозрение, что в 2026-ом новые ноутбуки могут заметно подорожать из-за роста цен на память и SSD. Появилось желание пересесть на 16" ноутбук пока есть возможность закупиться по старым ценам. Что и было сделано в январе 2026-го года.

Сперва был полный восторг. Особенно из-за того, что на 16" была полноценная клавиатура со всеми нужными мне аппаратными кнопками. В какой-то момент мне даже стало казаться, что 16" маловато, надо хотя бы 17.3", а еще лучше 18.4" 🙂

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

И тут я был шокирован тем, что возвращение на 14" не только не было болезненным, но вообще возникло ощущение, что я вернулся домой. Работать на 14", как будто бы, оказалось даже комфортнее, чем на 16".

Полагаю, что сказалось несколько факторов.

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

По RDP заходить на Windows-сервера клиентов приходится лишь изредка. Раньше к этому прибегать приходилось гораздо чаще. А когда делаешь это раз в неделю и всего на пару-тройку минут, то шрифты плохого качества проблемой не являются. Неприятно, но пять минут можно и потерпеть. Да и, как выяснилось, качество шрифтов в Remmina на 16" не сильно лучше, чем на 14".

Делить экран в vim-е на две части по вертикали практически перестал. Оказалось, что даже на 16" при комфортном размере шрифта этот режим далеко не всегда удобен. Тут в очередной раз хочу сказать спасибо тем разработчикам, которые считают, что ограничение на 80 символов в строке -- это пережиток прошлого. У меня на эту тему уже давно нет цензурных слов, поэтому промолчу.

Т.е. на 16" с разрешением 3200x2000 можно сделать шрифт достаточно мелким, чтобы открыть в vim-е два файла по вертикали и текст оставался читаемым. Но долго в таком режиме не поработаешь. Таки уже не молод и глаза быстро уставали, приходилось увеличивать размер символов.

В общем, те причины, по которым состоялся переход на 16", со временем оказались менее актуальными. Возможно, если бы я сменил 14" сразу на 18.4" с 4K матрицей, то эффект был бы более долгосрочным, а с 16" получилось вот так.

Кроме того, сыграл еще один фактор. За долгие-долгие годы программирования привык к режиму "одного окна", т.е. когда практически всю площадь экрана занимает одно текущее окно приложения, а остальные скрыты под ним. Будь то vim, под которым прячется консоль. Или же браузер, под которым прячется vim. Или окно telegram, под которым прячется что-то еще.

Видимо, корни уходят в 1990-е годы, когда я только учился программировать. Происходило это на маленьких алфавитно-цифровых экранах 80x25, да еще в однозадачных ОС (вроде CP/M и MS-DOS). Даже когда появились Windows и OS/2 с возможностью запустить сразу несколько приложений, то на тогдашних 14" ЭЛТ мониторах с разрешением 640x480 или даже 800x600 (хотя это было ну очень круто по тем временам) все равно не было возможности комфортно поделить площадь экрана сразу между несколькими окнами.

Так до сих пор и работаю: в центре основное текущее приложение (как правило, это vim, konsole, браузер или telegram), а из под него выглядывают краешки окон других приложений. И оказывается, что на 14" эти самые краешки отвлекают гораздо меньше, чем на 16".

Похоже, что на 14" режим "одного окна" таки комфортнее, чем на ноутбуках с большей диагональю.

А вот о чем остается только сожалеть при возвращении на 14", так это об отсутствии отдельных клавиш Insert, PgUp, PgDn, Home и End. Такое ощущение, что когда года через 2-3 буду выбирать более мощный и современный ноутбук, то придется смотреть в сторону ThinkPad-ов, на которых все эти кнопки все еще присутствуют. Хоть сам я не большой любитель клавиатур ThinkPad-ов. А особенно не любитель цен на нормальные ThinkPad-ы T-серии 🙂

четверг, 1 октября 2026 г.

[life.cinema] Очередной кинообзор (2026/09)

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

Фильмы

Майк и Ник, Ник и Элис (Mike & Nick & Nick & Alice, 2026). Очень даже неплохо, мне понравилось. Но есть в этом кино некая толика укуренности в хорошем смысле этого слова. Мне такая укуренность зашла, но кому-то наверняка испортит впечатления от просмотра.

Ночной бизнес (The Get Out, 2026). Мне понравилось.

Ограбление на миллион (Verbrannte Erde, 2024). Этот фильм можно посмотреть просто ради того, чтобы увидеть насколько европейское кино отличается от голливудского. А конкретно эта картина, как будто бы, снята в традициях соцреализма перестроечных времен.

Сыграть в ящик (Just Play Dead, 2026). Нормально, можно смотреть, хотя на мой взгляд, с поворотами сюжета авторы перемудрили.

Зараза (Cold Storage, 2025). Как по мне, то неплохая черная комедия. Главное не ждать от кино чего-то серьезного.

Запретный город ("Forbidden City" или "La Città proibita", 2025). На удивление любопытный боевик с мордобоем и тетенькой в роли главного непобедимого бойца. Портит впечатление количество розовых соплей вокруг происходящего, лучше бы экшОна побольше впихнули.

Соперники Амзиа Кинга (или "Гнев улья", The Rivals of Amziah King, 2025). Купился на участие в фильме Мэттью Макконахи, но его роль там оказалась не самой главной. Фильм специфический и, как по мне, несколько странный. Посмотреть можно. По визуальной составляющей, как и по актерской игре, у меня претензий нет. А вот что касается смысла и сюжета, то у меня остались вопросы о том, кто же здесь главный злодей.

Старуха с ножом (Pagwa, 2025). Во-первых, это кино для тех, кто спокойно или положительно относится к корейскому кинематографу. Во-вторых, фильм далеко не шедевр: экшОна маловато, в сюжет лучше не вдумываться вовсе.

Обсессия (Obsession, 2025). Низкобюджетная муть, жалко потраченного времени. Мне кажется, что низкобюджетные ужастики из видеосалонов 1980-х и то были сделаны круче.

Гандикап (2023). Не понял что это было, больше похоже на отечественный ответ "Бегущему человеку" на самых-самых минималках. В общем, можно пройти мимо.

Сериалы

Джентельмены (The Gentelmen, второй сезон, 2026). Отличное продолжение. Мне даже показалось, что второй сезон динамичнее и интереснее первого. Посмотрел с удовольствием. Надеюсь, что будет продолжение.

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

Магазин для киллеров (Killeodeului syopingmol, второй сезон, 2026). Если понравился первый сезон, то смело можно смотреть и второй. Мне зашло, хотя временами фантастичность происходящего была где-то на уровне сказочки для детей.

Холод (первый сезон, 2026). Разочарован, ждал от сериала сильно большего. А выбор Любовь Аксёнова в главной роли, это очевидный для меня мискаст.

Вне категории

Преимущества путешествия поездами (Ventajas de viajar en tren, 2019). Как по мне, так совершенно укуренное кино. Мне такие нравятся. Однако, рекомендовать не могу, т.к. ну очень уж на любителя.

понедельник, 28 сентября 2026 г.

[life.photo] Несколько кадров из прогулки по лесу

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

воскресенье, 27 сентября 2026 г.

[comp.thoughts] Многопроцессорные ноутбуки на ARM-ах. Почему нет?

Уже почти два года с удовольствием пользуюсь 12" планшетом HONOR Pad 9. По Geekbench 7 у него не сказать, чтобы какие-то выдающиеся результаты. Что-то около 800 баллов в однопотоке и чуть больше 2800 баллов в многопотоке. Т.е. формально это откровенно тормознутый по нынешним меркам процессор.

Однако, за два года использования этого планшета для потребления контента (т.е. ролики на YouTube/RuTube/VK, чтение статей на сайтах, просмотр PDF, небольшие правки в Google Docs, простые ответы по email, переписка в Telegram, Yandex.Music в фоне и вот это вот все) никаких тормозов замечено не было. Т.е. с производительностью для обычных повседневных задач у достаточно старого по нынешним временам Snapdragon 6 Gen 1 хватает. И здесь остается только жалеть, что на таком процессоре нет легкого, тихого и долго живущего на одном заряде ноутбука.

Почему раньше не было ноутбуков на ARM-ах из мобильных телефонов понятно: хоть Windows когда-то в 1990-е и начиналась как ОС с поддержкой нескольких типов архитектур, но довольно быстро десктопная версия Windows сконцентрировалась исключительно на x86, а всякие MIPS и Alpha пошли лесом, т.к. рыночек порешал. Этот же рыночек вместе с эффективным менеджментом из Microsoft и Nokia порешал и мобильную Windows CE (или как она там в последние годы своей жизни назвалась).

Тем не менее, мегауспешный переход Apple на свои собственные процессоры подтолкнул Microsoft к портированию десктопной Windows на ARM-ы. И уже года четыре как Windows доступна на ноутбуках с ARM. Например, был вот такой совсем чахлый TCL Book 14 Go на Snapdragon 7C Gen.1, который, по отзывам, был не просто тормозной, а очень тормозной. Возможно, не из-за процессора, а совсем крошечного по нынешним временам объема RAM, но все таки.

Первый блин Windows-ноутбуков на ARM в лице вот таких вот TCL Book 14 Go вышел комом, поэтому дальше эволюция пошла привычным для ИТ способом -- дождались выхода гораздо более мощных Snapdragon X от Qualcomm и пошли клепать не самые дешевые модели с этим новым процессором, большим объемом памяти, крутыми экранами и вот этим вот всем. Т.е. как будто бы основной прицел был в сегмент повыше среднего. Встречаются недорогие ASUS Vivobook-и и Lenovo IdeaPad-ы из среднего сегмента, но там и разновидности Snapdragon X не самые мощные.

Уж не знаю, есть ли какой-то успех у Windows-ноутбуков на ARM, сам пока не отважился на покупку чего-то подобно (хотя, наверное, надо бы рискнуть, чтобы было на чем проверять свои OpenSource разработки). Но давеча задумался вот о чем: а почему не пробуют сделать ARM ноутбуки с несколькими процессорами?

Грубо говоря, почему бы вместо дорогих и горячих Snapdragon X не взять 2-3-4 более старых, но вполне себе годных Snapdgragon 6 Gen 1, как в моем HONOR Pad 9? Пусть каждый из них сидит в своем сокете и располагает собственными 6 или 8 GiB RAM.

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

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

Что-то мне кажется, что не надо.

Смысл же в том, что если сделать ноутбук на одном Snapdragon 6 Gen 1 с 8 GiB RAM, то его ограниченность (как в плане быстродействия, так и в плане доступной памяти) быстро выплывет на поверхность.

Но есть таких процессоров будет уже два, а памяти не 8, а 16, то это уже совсем другая история. А если не 2, а 3 процессора и 24 GiB RAM? Это же еще лучше. Ну а 4-е процессора -- это уже совсем серьезная штука 😀

Любопытно, почему по этому пути не пошли? Что является основным препятствием? Железо или софт?

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

пятница, 25 сентября 2026 г.

[prog.question] А что сейчас понимают под "архитектурой программного обеспечения"?

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

И тут у меня возникает вопрос: а что, собственно, высказыватели этой надежды понимают под "архитектурой"?

Как бы вопрос не праздный, поскольку последние лет 10, а может и побольше, мне приходится, в основном, колупаться в коде: искать проблемы, что-то переписывать, что-то дописывать, что-то выбрасывать и т.д, и т.п. Но уже давно не доводилось заниматься проектированием "по большому", типа того, что здесь у нас будет такая-то СУБД и в ней будет храниться то-то и то-то, здесь у нас будет такой компонент, который с БД будет общаться напрямую, а здесь вот такой компонент, который будет общаться не с БД, а с первым компонентом, а здесь у нас будет вот такой компонент, который будет вот так-то следить за первыми двумя компонентами, а здесь будет еще вот это и вот это... В последние годы если что-то и приходится проектировать, так это небольшие библиотеки или даже отдельные классы, которые упрощают те или иные задачи.

Складывается впечатление, что под "архитектурой ПО" подразумевается рисование квадратиков и связей между ними, как это принято делать на system design interview, где соискателя просят "спроектировать" очередной клон Facebook-а или YouTube.

Если я прав, то непонятно почему кто-то надеется, что ИИ не заберет эту задачу у человека точно так же, как забирает обычное кодирование.

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

понедельник, 14 сентября 2026 г.

[prog.thoughts] Мои личные заморочки с ранними return-ами

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

  • во-первых, это мое личное мнение. Делюсь им, но ни в коем случае не настаиваю на его непогрешимости и, уж тем более, не утверждаю, что оно единственно правильное. Может быть кто-то из прочитавших сочтет его заслуживающим внимания и постарается относиться к return-ам более ответственно, чтобы таким как я было проще читать код;
  • во-вторых, я программирую, в основном, на C++, поэтому ниже будет C++ная специфика. Возможно, сказанное ниже гораздо менее критично для других языков программирования;
  • в-третьих, любой анонимный эксперт c LOR, RSDN или Habr вам убедительно объяснит, что программировать я не умею, да и вообще редкостный дебил. Посему ошибки у меня сплошь и рядом, в том числе и с плюс-минус-единичкой.

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

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

Очевидный пример -- это проверка валидности аргументов функции/метода:

int copy_file(const std::string & src, const std::string & dest)
{
  if(src.empty()) // Ошибка: нет имени источника.
    return errors::empty_src_name;

  if(dest.empty()) // Ошибка: нет имени результата.
    return errors::empty_dest_name;

  ... // Далее уже непосредственно действия по копированию.
}

Этот код, имхо, гораздо понятнее, чем вот такой:

int copy_file(const std::string & src, const std::string & dest)
{
  int result = errors::unexpected_error;

  if(!src.empty())
  {
    if(!dest.empty())
    {
      ... // Далее уже непосредственно действия по копированию.
    }
    else // Ошибка: нет имени результата.
      result = errors::empty_dest_name;
  }
  else // Ошибка: нет имени источника.
    result = errors::empty_src_name;

  return result;
}

Или вот такой:

int copy_file(const std::string & src, const std::string & dest)
{
  int result = errors::unexpected_error;

  if(src.empty()) // Ошибка: нет имени источника.
    result = errors::empty_src_name;
  else if(dest.empty()) // Ошибка: нет имени результата.
    result = errors::empty_dest_name;
  else
  {
    ... // Далее уже непосредственно действия по копированию.
  }

  return result;
}

Еще один простой пример: отказ от выполнения действий, если объект находится в неподходящем состоянии. Допустим, у нас есть класс "Файл" в виде обертки над простым хэндлом, который записывает значения строго в BigEndian представлении. Что-то вроде:

class file_with_big_endian_data
{
  // Хэндл открытого файла. Значение -1 указывает, что файл не был открыт.
  int m_handle;
  ...
public:
  // Методы для записи различных типов значений.
  void write(std::span<const std::uint16_t> what);
  void write(std::span<const std::uint32_t> what);
  void write(std::span<const std::uint64_t> what);
  ...
};

В таком случае каждый метод write может иметь в начале проверку m_handle с ранним return-ом для того, чтобы ничего не делать, если файл не был открыт:

void file_with_big_endian_data::write(
  std::span<const std::uint16_t> what)
{
  if(-1 == m_handle)
    return;

  ... // Запись с перестановкой байт, если это необходимо.
}

Еще один пример подсказали в комментариях на LinkedIn: ранние return-ы для ситуаций, когда компилятор может избавиться от хвостовой рекурсии. Сам пример достаточно игрушечный, но для иллюстрации вполне себе норм. Привожу его в оригинале на Python-е (спасибо пользователю Konstantin Z.):

def classify(n, steps=0):
  if n < 0:
    return "negative"
  if n == 0:
    return f"reached zero in {steps} steps"
  if n == 1:
    return f"almost there, {steps + 1} steps"
  return classify(n - 2, steps + 1)

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

Прежде всего лично мне гораздо удобнее разбирать прикладную логику в виде лесенки if-ов. Т.е. вот это:

if(first-condition)
{
  if(second-condition)
  {
    if(third-condition)
    {
      ... основные действия, ради которых все условия проверялись.
    }
  }
}

изучать гораздо проще, чем вот это:

if(!first-condition)
  return;

if(!second-condition)
  return;

if(!third-condition)
{
  ... основные действия, ради которых все условия проверялись.
}

Видимо это какие-то особенности моего восприятия (или проявления старческого слабоумия). Но лесенка из if-ов как бы сама уводит взгляд к кульминации и сама говорит "если вот это, и вот это, и вот это, то..." Тогда как ранние return-ы эту прямую последовательность к кульминации прерывают.

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

А вот если уходящую вправо лесенку из if-ов переписать в виде нескольких if-ов с return-ами, то лично для меня логика уже меняется и воспринимать замысел автора становится сложнее.

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

Тогда как с ранними return-ами такого критерия нет. Может быть функция на 40 строк, в которой 10 ранних return-ов. По сути это уже говнокод, но без столь явного запаха, как у лесенки из if-ов в 5-6 уровней глубины.

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

int do_something_important(int a, int b)
{
  if(!is_first_arg_valid(a))
    return results::error_code_1;

  if(!is_second_arg_valid(b))
    return results::error_code_2;

  bool need_update_cache = false;
  if(is_specific_arg_combination(a, b))
  {
    const auto cache_id = make_cache_id(a, b);
    if(has_result_in_cache(cache_id))
    {
      take_value_from_cache(cache_id);
      return results::result_from_cache;
    }
    else
      need_update_cache = true;
  }

  int prepare_result = prepare_for_change(a, b);
  if(prepare_result != results::ok)
  {
    if(prepare_result == results::pool_overflow)
    {
      remove_oldest_from_pool();
      prepare_result = prepare_for_change(a, b);
    }
    if(prepare_result != results::ok)
      return prepare_result;
  }

  commit_change(a, b);
  if(need_update_cache)
  {
    const auto cache_id = make_cache_id(a, b);
    const auto cache_update = update_cache_for(cache_id);
    if(cache_update == results::no_resources)
      return results::ok;
    else
      return results::ok_with_warnings;
  }

  return results::ok;
}

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

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

Но помимо чтения подобного кода иногда у меня возникает необходимость временно добавить в подобную функцию трассировку. В простейшем случае это может быть печать "do_something_important started" при входе и "do_something_important completed" при входе.

Когда у нас есть единственный return в конце, то нет ничего проще -- одна печать на входе, вторая на выходе. Но когда return-ов много, то...

...то приходится прибегать к созданию в начале функции объекта, который в своем конструкторе будет печатать "do_something_important started", а в деструкторе -- "do_something_important completed". Для языков, в которых детерминированного вызова конструкторов-деструкторов нет, подойдет та или иная реализация Go-шного defer-а.

Но это не помогает, если строчка с "do_something_important completed" должна содержать еще и какое-то значение (например, возвращаемое значение). Вставлять такую печать перед каждым return-ом ну так себе занятие. Приходится что-то изобретать.

А вот для единственного return-а это не проблема от слова совсем. Тут вообще все тривиально и ничего не нужно изобретать.

Ну и как-то мне с необходимостью делать подобные трассировки регулярно везет. То нужно построить трассу взаимных вызовов. То засечь время работы. Или и то, и другое сразу. Благо в C++ легко делать объекты в RAII-стиле. В какой-нибудь Java сложностей было бы побольше.


Что хочется сказать в завершении.

ИМХО, в современном мире правило "один вход -- один выход" -- это уже какой-то экстремальный экстрим. Непонятно зачем отказываться от ранних return-ов, если они делают код и компактнее, и проще, и надежнее (как элемент defensive programming), и (временами) быстрее (раскрутка хвостовой рекурсии).

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

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

суббота, 5 сентября 2026 г.

[prog.c++] Всегда удивляюсь, когда вижу имена членов класса без суффиксов/префиксов

Данный пост навеян фрагментом кода из свежей статьи на хабре "Анатомия граблей", а именно вот этим фрагментом кода:

class Foo {
    int value;
public:
    Foo(int value) { // параметр затеняет поле class
        value = value; // ничего не делает, присваивает параметр самому себе
    }
};

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

У меня бы было написано так:

class Foo {
    int m_value;
public:
    Foo(int value) { // параметр ничего не затеняет
        m_value = value;
    }
};

И подобная опечатка сразу бы оказалась видна.

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

class Foo {
    int value;
public:
    Foo(int value) { // параметр затеняет поле class
        this->value = value; // ничего не затеняет
    }
};

Тем паче, что обращение this-> зачастую бывает необходимо при написании кода шаблонов (например, когда шаблон класса наследуется от шаблона класса и обращается к унаследованным из базового класса членам/методам).

PS. Самая странная система именования членов классов, которую доводилась видеть, была такой:

class Demo {
public:
  int a; // Открытый член класса без префикса или суффикса.

protected:
  int _b; // А вот защищенные и закрытые члены с префиксом.

private:
  int _c;
};

PPS. Касательно самой статьи "Анатомия граблей": она позиционируется как сборник C++ных граблей из области игростроя. Но практически все из описанного мне доводилось видеть в разнообразных проектах, которые к игрострою не имели никакого отношения. И какие-то из них (вроде выхода за границы статических массивов) не имеют дешевых решений, увы. По поводу же той части статьи, которая касается контроля за ресурсами и ручной работы с malloc/free, то слишком мало конкретики (плюс есть у меня подозрение, что в игрострое собирается публика, которой очень и очень фиолетово качество кода, но не факт, что подозрение верное).

вторник, 1 сентября 2026 г.

[life.cinema] Очередной кинообзор (2026/08)

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

Фильмы

Кривые линии господа ("God's Crooked Lines" или "Los renglones torcidos de Dios", 2021). Однозначно самое интересное из увиденного за последнее время. Некоторые твисты ну очень классные. Правда, чтобы разобраться в том, что же было показано, пришлось гуглить. И результат поисков не то, чтобы меня порадовал, лично я увидел в кино совсем другой сюжет (чисто детективный, без сильной привязки к психиатрии).

Человек-паук: Новый день (Spider-Man: Brand New Day, 2026). Очень круто сделанный очередной кино-аттракцион для любителей супергероев из "вселенной Марвел". Строго для поклонников жанра.

Чокнутые (Riff Raff, 2024). Отличное кино, получил удовольствие от просмотра. Но мои вкусы несколько специфичны, поэтому сразу предупреждаю, что зайдет оно не всем.

Колония (Gunche, 2026). Если понравился "Поезд в Пусан" от этого же режиссера, то можно смотреть и "Колонию".

Замри (Don't Move, 2024). Ничего не ждал, но этот оказался вполне себе добротным фильмом. Далеко не шедевр, но смотреть было интересно и никакого отрицательного послевкусия не осталось.

Соулм8йт (Soulm8te, 2026). В принципе, снято очень даже неплохо. Но все портит абсолютная предсказуемость происходящего на экране.

Шёпот за окном (The Whisper Man, 2026). Хорошие актеры и неплохой сюжет, но когда начинаешь вдумываться в происходящее, то возникает слишком много белых пятнышек, которые непонятно как объяснить. Поэтому невольно задаешься вопросом "а не втирают ли нам здесь какую-то дичь?"

Коллектор ("The Dept Collector" или "Khon Dueat Thuang Khaen", 2026). В принципе неплохой боевик. Местами предсказуемый, местами не очень, местами впадающий в какую-то Санта-Барбару. Но мне показался несколько затянутым.

Последний дом (The Last House, 2026). Даже не смотря на то, что это фантастика, в некоторые моменты настолько не верится, что это напрочь убивает всю идею происходящего на экране и сильно портит впечатление от фильма.

Точка замерзания (Dead of Winter, 2025). Хорошие актеры, хорошо играют. Но в происходящее на экране не верится от слова совсем.

Та, что сбежала: История Кары Робинсон (The Girl Who Escaped: The Kara Robinson Story, 2026). Очень и очень бюджетно, что сказывается как на картинке, так и на актерской игре -- такое впечатление, что играет одна лишь главная героиня, а всех остальных набрали из массовки по объявлению. В общем, можно смело пройти мимо.

Семь снайперов (Seven Snipers, 2026). Редкая фигня не смотря на наличие хороших (в прошлом) актеров. Не тратить на это время ни в коем случае!

Сериалы

Парижская полиция 1910 (Paris Police 1910, 2026). Отличное продолжение отличного сериала.

Убийства в Оре ("Åre Murders" или "The Åremorden", первый сезон, 2025). Не смотря на то, что всего пять небольших по хронометражу серий, типичная сериальная затянутость все равно ощущается. Но именно к детективной составляющей претензий нет, у каждого расследования неожиданная развязка.

Лаки (Lucky, первый сезон, 2026). Ждал много большего, по факту же очень и очень средний уровень, может быть даже пониже среднего. Плюс традиционная сериальная затянутость, пару серий точно можно было бы выбросить.

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

Подразделение специального назначения ("Elite Force" или "G.I.G.N", первый сезон, 2026). Ждешь жесткий боевик про крутых спецназовцев, получаешь какую-то унылую мелодраму.

Фильм вне категории

Майкл (Michael, 2026). Здесь разочаровало все -- начиная от сюжета и даже визуального ряда до попыток станцевать так же, как Майкл Джексон. Такое ощущение, что после Богемской рапсодии и РокетМена захотелось повторить тот же трюк с еще одной музыкальной суперзвездой. И, что самое страшное, это получилось с таким очень и очень никаким фильмом.

пятница, 21 августа 2026 г.

[life.memories] Ответ "А я не знаю" от преподавателя в университете

Посмотрел недавно ролик "Разбираем популярные манипуляции квантовых психологов. Алексей Семихатов и Виктория Шиманская" на YouTube (на RuTube пока нет, но, может быть, появится на этом канале). Очень понравился мне там момент в районе 41-й минуты, когда Семихатов сказал, что роль учителя в том, чтобы показать как вообще можно размышлять над сложной проблемой.

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

Для меня это был шок и разрыв шаблона.

Потому что 10 лет до этого в школе нас натаскивали на то, что ты должен знать. Математические выражения, физические законы, химические формулы, исторические даты и вот это вот все. Ты либо знаешь и молодец, либо не знаешь и "садись, два!"

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

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

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

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

понедельник, 10 августа 2026 г.

[prog.sarcasm] Если долго сидеть на берегу, то можно увидеть как Erlang-еры...

...переписывают свой софт на Rust:

Моя идея о том, чтобы переписать наш Flussonic с Erlang на Rust оказалась совершенно прекрасной и у меня совершенно прекрасные результаты. Захват 10 000 камер на сервер - это прямо скажем серьезный результат, на рынке таких предложений мало.

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

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

Upd.В этой теме на LOR-е еще прекрасное добавилось от Лапшина (это ответ на вопрос уперся ли Erlang в потолок производительности):

Во все потолки, какие можно было.
И производительность, и количество библиотек, и количество людей и всё прочее.
Когда стало ясно, что прийдется самому руками писать QUIC, тут я слегка устал от эрланга.
О перфомансе вида «принять 10 000 камер» и речи не идет, причем если бы не медленный сторадж, новый код можно поковырять и до 20 тыс (просто это не нужно).

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


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

вторник, 4 августа 2026 г.

[life.audiophile] Неожиданно приятное открытие в VE Megatron

Несколько лет назад попал ко мне в руки USB-ЦАП Megatron от Venture Electronics (хороший обзор на него можно посмотреть здесь: YouTube или RuTube). Попасть-то попал, но большую часть времени лежал без дела. По звуку с ним все OK, но требует, зараза, высокоомные наушники. Мои вкладыши на 300ом приходится слушать на минимальной громкости.

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

А вот буквально на днях случайно выяснилось, что по 3.5mm разъему Megatron поддерживает гарнитуру!

И это решило проблему, с которой мне приходилось мириться на протяжении многих месяцев. А именно: на работе я подключаю к компьютеру USB-ЦАП чтобы слушать музыку в наушниках. Но когда возникает необходимость рабочего созвона через какой-то мессенджер или Zoom/Telemost, то приходится переключаться на гарнитуру, которая втыкается в 3.5mm разъем компьютера. И это переключение я регулярно забываю делать. Не говоря уже о том, что сама по себе эта необходимость раздражает.

Но, к счастью, Megatron делает все эти манипуляции ненужными. Достаточно в 3.5mm разъем Megatron-а воткнуть наушники с гарнитурой, в 4.4mm (или 2.5mm) разъем -- наушники для музыки, а сам Megatron по USB подключить к компьютеру. И все. Слушаешь себе спокойно музыку (хоть из локального хранилища, хоть со стримминга), а когда нужно созвониться, то просто берешь другие наушники, подключенные к тому же самому Megatron-у и все.

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

суббота, 1 августа 2026 г.

[life.cinema] Очередной кинообзор (2026/07)

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

Фильмы

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

Стервятники (Vultures или Rapaces, 2025). Тот самый случай, когда от кино вообще ничего не ждешь, а получаешь вполне нормальный фильм. Не шедевр, но крепкий середнячок.

Грязные деньги (Deoreowoon done sondaeji mara, 2023). Если бы не специфика азиатской актерской игры, то был бы крепкий середнячок в стиле криминальной драмы с интересной развязкой.

Кто-то должен умереть (2025). Отличная картинка. Хорошие актеры. Любопытный сюжет. Но авторам не удалось создать атмосферу настоящей реальности -- смотришь на происходящее на экране и не можешь поверить что такое может происходить на самом деле.

Бескрайняя ночь (The Vast of Night, 2019). Если вы любитель артхаусного и фестивального кино, то можете попробовать глянуть. Мне лично не зашло.

Глубокие воды (Deep Water, 2026). Очень и очень бюджетно. Лучше обойти мимо и не тратить свое время.

Смерть Робина Гуда (The Death of Robin Hood, 2026). Унылая тягомотина с непонятным для меня замыслом и невнятным сюжетом.

Сериалы

Во всем виновата она (All Her Faul, первый сезон, 2025). Отличный подбор актеров. Как по мне, так по некоторым ролям попадание 100%. Не самая плохая развязка, хотя к некоторым важным моментам остаются вопросики. Однако, мне показалось, что фильм безбожно растянут. Если бы вместо 8 серий было 4, получилось бы хорошо, а так скучновато.

Я тебя отыщу (I Will Find You, первый сезон, 2026). Актеров хороших собрали. И они играют. Но это единственное хорошее, что есть в сериале. Когда начинаешь вдумываться в сюжет, то оказывается, что нам втирают какую-то дичь.

Минута тишины (первый сезон, 2024). Очень картонные персонажи, очень все шаблонно, местами приторно-елейно. Но в целом не самый плохой сериал.

Побег (Run, первый сезон, 2026). Главным достоинством сериала является то, что в нем всего шесть небольших серий. Для меня главный вопрос -- как историю преступника с несколькими десятками успешных ограблений и двумя побегами из тюрьмы превратили в такую нудную мелодраму. Смотреть можно только ради того, чтобы полюбопытствовать а как же снимают кино в Австралии. Есть здесь какой-то свой стиль, отличный от голливудского.

После Фишера. Инквизитор (2026, это же третий сезон "Фишера"). Редкая муть, смело можно пройти мимо.

Кино вне категории

"Человек кусает собаку" или "Это случается рядом с вами" (C'est arrivé près de chez vous, 1992). Самое необычное кино из тех, что посмотрел за последние несколько лет. Рекомендовать не буду т.к. ну очень уж специфическое. Однако, на фоне сегодняшнего широпотреба выглядит более чем необычно.

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


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