пятница, 14 июля 2023 г.

[prog.c++] Тяпничное, излишне эмоциональное, о наболевшем...

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

  • приложения для конечного пользователя, где нужно было бы искать сторонние готовые библиотеки, и затем комбинировать их чтобы решить прикладную задачу, за 300k RUB, или
  • библиотеки, закрывающей какую-то предметную область (условно: MQTT, UPnP, TURN и т.д., и т.п.) за 150k RUB

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

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

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

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

И да, озвученное выше можно считать публичной офертой 😉


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

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

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

Фраза эта врезалась мне в память и чем больше мне приходится разбираться с чужим кодом, тем чаще ее вспоминаю и все чаще задаюсь вопросом: "Если везде отличные C++ специалисты, то почему я постоянно сталкиваюсь с говнокодом?"

Ну реально: неумение писать вменяемые комментарии (а то и отсутствие комментариев как класса), функции по несколько сотен строк, дублирование кода и копипаста, недоделки, да и просто откровенные баги, которые либо проморгали, либо можно было вообще не допускать, если писать на нормальном C++ по рекомендациям "лучших собаководов"... Может это мне, конечно, так везет. Но кажется, что такое сплошь и рядом. Задолбало неимоверно.


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

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

Во-первых, есть большой соблазн спросить: "А вы мой код на GitHub-е смотрели? Ну и как впечатления? Все еще есть необходимость спрашивать меня про виртуальный деструктор? Чего не хватило, что не понравилось?"

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

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

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

Но, блин, почему-то постоянно в глаза бросаются вещи, вроде вот таких:

class Manager {
  using WorkerMap = std::map<std::string, WorkerSharedPtr>;
  WorkerMap workers_;
  ...
  void addWorker(const std::string & id, WorkerSharedPtr worker) {
    // An old worker with the same ID has to be removed.
    auto old_worker_it = workers_.find(id);
    if(old_worker_it != workers_.end())
      workers_.erase(old_worker_it);
    ...
  }
  ...
};

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

// An old worker with the same ID has to be removed.
workers_.erase(id);

Как бы и особого криминала нет, и вызов std::map::erase(const Key &) наверняка раскрывается под капотом в эти самые три строчки. Но блин, зачем на ровном месте объем кода раздувать? 🙁

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

четверг, 13 июля 2023 г.

[prog.c++] И вот ради этого C++ становится все сложнее и сложнее?

Простите, но у меня бомбануло. Только что узнал, что в C++20 стало можно писать вот так:

std::vector pointsScored {27, 41, 32, 23, 28};

for (typedef int Points; Points points : pointsScored) {
    std::cout << "Jokic scored " << points << '\n';
}

А в C++23 исправили просчет, допущенный в C++20: разрешили кроме typedef-а в подобных конструкциях применять using:

std::vector pointsScored {27, 41, 32, 23, 28};

for (using Points = int; Points points : pointsScored) {
    std::cout << "Jokic scored " << points << '\n';
}

Хвала всевышнему, уж теперь-то заживем! (Это горький сарказм, если что)

Да уж. Написать по старинке, т.е.:

std::vector pointsScored {27, 41, 32, 23, 28};

{
    using Points = int;
    for (Points points : pointsScored) {
        std::cout << "Jokic scored " << points << '\n';
    }
}

было не судьба, нужно было язык усложнять еще больше.

Верной дорогой, блин... :(

вторник, 11 июля 2023 г.

[prog.c++] Ну как так то?

Прошу прощения за эмоциональность, но был сегодня сильно удивлен и несколько раздосадован.

Началось все с того, что разыскивая информацию про NAT/STUN/UPnP/port-forwarding и иже с ними, наткнулся на проект pjsip. Был приятно удивлен тому, насколько приятно он оформлен в плане количества документации. Не берусь судить о ее качестве, т.к. смотрел сильно мельком и по диагонали. Но первое впечатление: внушаить!

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

понедельник, 10 июля 2023 г.

[prog.c++] Ахиллесова пята vcpkg и conan

Очень хорошо, конечно, что для C++ появились продвинутые системы управления зависимостями, вроде vcpkg и conan. Я сейчас без сарказма и иронии: в проекте для текущего заказчика используется vcpkg и это оказалось просто спасением, ибо заниматься поддержкой сборки FFMPEG/SDL на разных платформах это тот еще геморрой. А в vcpkg из коробки, берешь и пользуешься.

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

Но у vcpkg и conan есть один фатальный недостаток, имхо, настоящая ахиллесова пята.

Обе эти системы централизованы в том смысле, что пакеты и версии пакетов в них появляются не просто так. В vcpkg нужно подготовить PR, который как-то проверяется, затем включается в основную ветку vcpkg. В conan, насколько я понимаю, аналогичная система (по крайней мере для попадания в conan.io/center).

При этом сроки принятия PR могут варьироваться в широких пределах. Например, мы зафиксировали SObjectizer v.5.8.0 еще 30-го июня. Тогда же были подготовлены и PR для vcpkg/conan. Но они так до сих пор не были приняты.

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

Но, с другой стороны, представим себе, что в неком пакете обнаружилась критически важная проблема, эту проблему исправили, выкатили PR для vcpkg/conan и... И потом приходится ждать неделю(!!!), а то и больше, чтобы изменения были приняты.

И еще один момент: ну хорошо, пока там 1500 пакетов, тестирование и сборка на стороне vcpkg/conan может казаться оправданной (хотя там же не производится полного прогона всех тест-кейсов, которые есть в проекте). Но что будет, когда пакетов станет 3000? А когда 10000? В общем, мне кажется, что этот подход не масштабируется.

Так что я продолжаю придерживаться мнения, что C++ нужна единая система управления зависимостями (какой-то де-факто стандарт), но эта система должна быть либо вообще server-less (т.е. чтобы не было единого централизованного репозитория пакетов), либо этот репозиторий должен быть совсем минималистичным и внесение изменений в него должно быть простым и быстрым (по типу того, как это происходит в RubyGems).