пятница, 15 августа 2008 г.

entern int i;

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

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

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

И вот тут я буду плеваться на Windows. Хотя он и не виноват вовсе, я и на Linux иногда плююсь. :) Наверное мне просто везет на ужасные проекты, которых в нашей фирме великое множество. И мне постоянно приходится их сопровождать.

LoadResourceString(IDS_STRING136,strTemp);
wsprintfA(szTm, strTemp.c_str(), from.wDay, from.wMonth, from.wYear, to.wDay, to.wMonth, to.wYear);


Мало того, что содержимое строки не видно. Но даже если мы перейдем к описанию IDS_STRING136, то мы обнаружим всего лишь...

#define IDS_STRING136 136

Даже если бы у этого идентификатора было бы осмысленное имя - это всеравно ничего не дает, потому что строки нету. Да, можно полезть в ресурсы и выискивать эту строку из сотен других. Не знаю сильно ли это облегчит задачу. Это почти то же самое что описать int i в отдельном файле, может даже хуже. Могу себе представить какие сложности испытывают программисты многоязычных приложений.

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

Похожую проблему видел в одной прошивке, но там это более менее можно понять. Всетаки экономия памяти, всякое разное. Но и там теоретически можно было сделать основной язык в тексте, а дополнительные языки - подставлять при компиляции к примеру. На *nix обеспечить такую подстановку - как два байта подменить. написал скриптик в пять строк и все дела. А проект, к сожалению, был под DOS, чтобы так легко все заменить пришлось бы писать специальную программу. Там сделано просто - файл с 'ресурсами' представлял из себя большой массив, в котором производилось сопоставление идентификатора и строки. Файл для нужного языка выбирался на этапе компиляции статически. Идентификаторы, само собой были отдельно, через enum.

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

1 коммент.:

Анонимный комментирует...

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

1. IDS_STRING136 - нет слов, только чувства... По рукам давать надо.
2. wsprintfA небезопасно. Надо юзать (давно уже) _snprintf/snprintf (еще лучше _sntprintf).
3. Для функций типа LoadResourceString надо указывать строку по умолчанию, еси не нашли строки в ресурсах.
4. Есть еще мелочи, но ладно уж...

Но даже если мы перейдем к описанию IDS_STRING136, то мы обнаружим всего лишь...

#define IDS_STRING136 136

Ну а ты чего ожидал увидеть? Это ид для string resource.

Да, можно полезть в ресурсы и выискивать эту строку из сотен других. Не знаю сильно ли это облегчит задачу
Юзай IDE :-)

Могу себе представить какие сложности испытывают программисты многоязычных приложений.
При правильно написанной локализации - никакой.
Самый примитивный вариант.
MessageBox (..., pTranslate->GetText (MSG_ERROR_File_not_found, _T("File not found"), pTranslate->GetText (MSG_CAPTION_Error, _T("Error"), ...);

Мы почему-то пытаемся главноязычные сообщения подменить безликими малоговорящими идентификаторами.
Ну зачем обобщать? :) Не я, и наверняка не ты... а кто-то.

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

На *nix обеспечить такую подстановку - как два байта подменить. написал скриптик в пять строк и все дела. А проект, к сожалению, был под DOS, чтобы так легко все заменить пришлось бы писать специальную программу.
Я что-то не пойму. Либо произведи замену строк под *nix (или исходники нельзя забрать в *nix?), либо скомпильни утилиты *nix DJGPP.