среда, 7 декабря 2022 г.

[prog.c++] Написал функцию с десятью(!) аргументами...

...и понимаю, что ничего хорошего в этом нет, но и лучшего решения не придумывается.

Вот как это выглядит:

Мое чувство прекрасного ущемлено и требует сатисфакции, но ничего лучше не придумывается :(

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

Была мысль посмотреть в сторону builder pattern. Но в C++ этот самый builder будет многословным. Плюс к тому придется делать проверки а все ли обязательные параметры заданы (а они все обязательные). Что негативно скажется на объеме builder-а. Посему не вариант.

Видимо, следует объединить несколько аргументов в разные структуры. Скажем, argv_0, python_log_collector, py_config и python_lib_path в одну, а ***_arena, params, shutdown_notificator и ***_interaction_points в другую. Но все равно это будет вести к распуханию вспомогательного кода, причем особой пользы от этого вспомогательного кода на данный момент не будет. Разве что это окажется задел на перспективу.

В общем к чему я это: рекомендации лучших собаководов о том, какой код clean, а какой нет, -- это, конечно, хорошо. Пока не сталкиваешься с суровой реальностью ;) В которой не знаешь как сделать лучше, а тратить время на эстетические изыски не вариант.

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

[prog.python.wtf] Понадобилось мне давеча разобраться с Python-овским io... И как-то оно что-то неожиданно непонятно. Вот совсем

В C++ приложение встраивается Python чтобы исполнять Python-вский скрипт прямо внутри приложения. Потребовалось сделать так, чтобы все, что Python-овский скрипт печатает в sys.stdout, отправлялось в C++ную часть.

Стал разбираться с Python-овским io.

Несколько раз проштудировал описание io в стандартной документации.

Мало что понял.

Что удивило. Т.к. пока читаешь, то вроде бы и буквы все понятные, и в слова понятные они складываются. А вот что к чему и почему... Все никак.

Гуглил, читал Stackoverflow, много думал :)

Но просветление не приходило.

Даже в исходники CPython заглянул, чтобы понять, как же вся эта кухня с IOBase, RawIOBase, BufferedIOBase и TextIOBase работает.

В общем, пришел к выводу, что мне нужен стандартный io.TextIOWrapper. В конструктор ему передается экземпляр стандартного io.BufferedWriter. А уже в конструктор io.BufferedWriter в качестве параметра raw передается экземпляр моего класса, наследника io.RawIOBase. Что-то вроде: