вторник, 1 января 2030 г.

О блоге

Более двадцати лет я занимался разработкой ПО, в основном как программист и тим-лид, а в 2012-2014гг как руководитель департамента разработки и внедрения ПО в компании Интервэйл (подробнее на LinkedIn). В настоящее время занимаюсь развитием компании по разработке ПО stiffstream, в которой являюсь одним из соучредителей. Поэтому в моем блоге много заметок о работе, в частности о программировании и компьютерах, а так же об управлении.

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

понедельник, 31 декабря 2029 г.

[life.photo] Характерный портрет: вы и ваш мир моими глазами. Безвозмездно :)

Вы художник? Бармен или музыкант? Или, может быть, коллекционер? Плотник или столяр? Кузнец или слесарь? Владеете маленьким магазинчиком или управляете большим производством? Реставрируете старинные часы или просто починяете примус? Всю жизнь занимаетесь своим любимым делом и хотели бы иметь фото на память?

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

вторник, 18 июня 2024 г.

[prog] Один из признаков того, что с вашим кодом не все в порядке

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

Т.е. если вы видите в кодовой базе что-то вроде:

data_manager::data_manager(
  data_set_id id,
  raw_data_storage_shptr raw_data_storage,
  access_manager_shptr access_manager,
  modification_mode mode,
  logger log)
  : base_type{ id,
      std::move(raw_data_storage),
//     std::move(access_manager)
//     mode
    }
{
//  _id = id;
//  _storage = std::move(raw_data_storage);
//  _access_manager = std::move(access_manager);
  setup_access_manager(std::move(access_manager));
  setup_mode(mode);
  setup_logger(std::move(log));
}

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

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

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

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

Например:

data_manager::data_manager(
  data_set_id id,
  raw_data_storage_shptr raw_data_storage,
  access_manager_shptr access_manager,
  modification_mode mode,
  logger log)
  : base_type{ id,
      std::move(raw_data_storage),
//FIXME(eao197): access_manager и mode должны были бы передаваться
//в base_type, но там временно пришлось убрать такой конструктор.
//Нужно вернуться к передаче access_manager и mode в конструктор
//базового класса после того, как base_type будет отрефакторен.
//     std::move(access_manager)
//     mode
    }
{
  //FIXME(eao197): установка access_manager и mode должна
  //быть со временем перенесена в конструктор base_type.
  setup_access_manager(std::move(access_manager));
  setup_mode(mode);

  setup_logger(std::move(log));
}

PS. Был в моей карьере один случай двухдневного сеанса отладки кода, который до сих пор вспоминается с содроганием. Выглядел этот код как откровенное Г и состоял на 50% вот таких вот закомментированных кусков без всяких пояснений. Причем ладно бы в начале файлов были раскомментированные, актуальные строки, а в конце -- закомментированные, уже не нужные. Так нет, все это было вперемешку. Бррр. Как вспомню, так вздрогну.

воскресенье, 16 июня 2024 г.

[prog.java] Листая старенький айпад или как же похорошела Java за последние 14 лет ;)

Довелось тут давеча вспомнить когда в последний раз программировал на Java. Почему-то думал, что было это в 2012-ом, а оказалось, что в 2010-ом. Интересно сейчас, спустя 14 лет, перечитывать собственные старые впечатления. Особенно вот эти соображения о том, чего лично мне тогда не хватало в Java. И тем забавнее обнаружить, что часть из описанного мной тогда, в современной Java уже есть: это и автоматический вывод типов переменных, и лямбда функции, и try-with-resources.

Как же похорошела Java за эти годы! ;)

Только вот желания программировать на Java как не было, так и нет :)))

PS. Да и с кроссплатформенностью у .NET и C# стало куда как лучше.

вторник, 4 июня 2024 г.

[prog.c++] Полагаю, что не нужно использовать bool-параметры в функциях и методах. Ну вот вообще не нужно.

Когда-то давно прочитал рекомендацию не использовать несколько аргументов функции/метода, если эти аргументы имеют тип bool. Мол, очень тяжело потом разбираться с кодом вида:

do_something(target, true, false, true, logger);

Глядя на такой код более-менее понятно с первого взгляда что означают target и logger. А вот какой смысл несут true, false и еще раз true -- без заглядывания в документацию (если вам повезло и таковая есть вообще) или в реализацию do_something не скажешь.

Рекомендация, кстати говоря, здравая. Но, как по мне, слишком специализированная. Я воспринял ее в более общем виде: нужно избегать идущих подряд аргументов одного типа. Не важно bool это, int, double или string. Когда видишь что-то вроде:

prepare_data(data, 0, 0, 42, 122);

то без плотного знакомства с prepare_data все равно не обойтись.

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

prepare_data(data, default_x, defaut_y, default_w, default_h);

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

prepare_data(data, default_x, defaut_w, default_y, default_h);

Так что если у вас есть возможность пользоваться каким-то из вариантов strong typedef, то лучше им таки пользоваться. Отличная защита от опечаток. Да и в чужой код легче погружаться, когда там в прототипах функций вместо int-ов используются x_coord, y_coord, width и height.

Но вернемся к аргументам типа bool.

За последний год пришел к выводу, что bool в качестве типа параметра -- это вообще ни разу не хорошо.

И вовсе не по тем причинам, которые когда-то описал Мартин Фаулер. А тупо потому, что читать чужой код, в котором раскиданы совершенно неинформативные true и false -- это то еще удовольствие:

auto it = data_cache.get(item_key, true);
...
it = data_cache.validate(it, false);

Когда видишь такой код впервые, то сразу спотыкаешься на true и false, пытаясь выяснить что они означают вообще.

Совсем другое дело, когда используются enum classes и именованные константы:

auto it = data_cache.get(item_key, cache_item_creation::create_if_missed);
...
it = data_cache.validate(it, cache_validation::dont_update_timestamp);

Так что с годами пришел к выводу, что в современном C++ c enum-class bool-аргументы не должны использоваться вообще.


PS. По поводу упомянутого выше Мартина Фаулера. Ну не убеждают меня его доводы. Хотя, если вы не будете использовать bool-параметры под влиянием аргументов Фаулера, то я возражать не буду ;)

суббота, 1 июня 2024 г.

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

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

Фильмы

Артур, ты король (Arthur the King, 2024). Хорошее, доброе, семейное кино. К некоторым местам я бы сильно доколупался бы. Но именно как кино для семейного просмотра, как по мне, так отлично.

Каскадёры (The Fall Guy, 2024). Смотрибельно, но... Во-первых, фильм, как мне показалось, рассчитан на малолетнюю и непритязательную аудиторию. Людям постарше тупо не интересно следить за происходящим. Во-вторых, главным героям, судя по поведению, должно быть лет по 25, а играют их сорокалетние актеры. Это вызывает неслабый диссонанс. В-третьих, гораздо интереснее оказалось смотреть сцены во время финальных титров о том, как проходили съемки трюков.

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

Атлас (Atlas, 2024). Очень предсказуемый и детский фильм. Но красочно снят. Так что на фоне того, что красиво сделанной фантастики в последнее время очень мало, то потраченного времени не жаль. Но далеко не шедевр.

Министерство неджентльменских дел (The Ministry of Ungentlemanly Warfare, 2024). Красочный фантастический комикс для детей младшего школьного возраста. Людям старше 12-13 лет можно не смотреть чтобы не разбить себе лицо фейспалмами.

Сорвать банк (Cash Out, 2024). Очень и очень слабо, как по актерской игре, так и по визуальной составляющей. А уж сценарий так просто днищенское дно.

Сериалы

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

Оффлайн (первый и второй сезоны, 2022-2024). Первый сезон, как по мне, так просто отличный, очень легко смотрится. А вот второй -- это какой-то бред укуренного наркомана. Так что моя рекомендация -- посмотреть только первый сезон и не обращать внимания на продолжение.

Амстердам: Город грехов (Baantjer het Begin, первый сезон, 2019). Начало было многообещающим, но начиная с середины сериал скатился в откровенную посредственность. Не буду ругать, но и рекомендовать не могу.

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

Большая гонка. Ауди против Лянчи (Race for Glory: Audi vs. Lancia, 2024). Странное кино. По нынешним меркам откровенно слабое. Но веет от него какой-то аналоговой теплой ламповостью 1980-х. Настолько, что вспомнилось старое-старое кино 6000 километров страха от 1978-го года, увиденное в далеком детстве. В результате нашел "6000 километров..." на YouTube, пересмотрел, понастольгировал. Мне кажется, что "6000 километров..." намного лучше. Но есть впечатление, что "Ауди против Лянчи" специально делали именно таким, аналоговым и ламповым, под старые фильмы 1980-х о раллийных гонках. Так что не возьмусь давать какую-то оценку.

четверг, 30 мая 2024 г.

[prog.c++] Грустные впечатления от p3086

Недавно в очередной раз наткнулся на библиотеку proxy от Microsoft. Которая разработана в качестве поддержки предложения p3086. Попробовал почитать этот пропозал (2-я ревизия на тот момент). Спектр эмоций оказался широким -- от нехилого пригорания по началу до тихой грусти в итоге. Попытаюсь рассказать почему.

Началось все буквально с первых страниц. Вот на этом фрагменте у меня полыхнуло:

For decades, object-based virtual table has been a de facto implementation of runtime polymorphism in many (compiled) programming languages including C++. There are many drawbacks in this mechanism, including life management (because each object may have different size and ownership), reflection (because it is hard to balance between usability and memory allocation) and intrusiveness. To workaround these drawbacks, some languages like Java or C# choose to sacrifice performance by introducing GC to facilitate lifetime management, and JIT-compile the source code at runtime to generate full metadata.

Т.е. десятилетиями полиморфизм реализовывался на базе привязанных к классам таблиц виртуальных функций и это было плохо, т.к. и временем жизни приходилось озадачиваться, и слишком уж все это было интрузивненько. Поэтому такия языки, как Java и C# решили принести в жертву производительность и пошли на использование GC для управление временем жизни и JIT-генерацию кода во время исполнения.

facepalm.jpg

Ну как бы это помягче сказать.