вторник, 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-параметры под влиянием аргументов Фаулера, то я возражать не буду ;)