Строки в отдельном файле.pas
Это может быть неправильным местом для этого вопроса, если не стесняйтесь переместить его. Я пометил как Delphi/Pascal, потому что это то, над чем я работаю в банкомате, но это может относиться ко всему программированию, которое я предполагаю.
В любом случае, я делаю некоторую очистку кода и собираюсь переместить все строки в моей программе в отдельный файл.pas. Есть ли плюсы и минусы в этом? Это даже стоит делать?
Чтобы уточнить: я имею в виду, что я буду создавать отдельный файл, Strings.pas в нем я сделаю все мои текстовые строковые переменные.
бывший
Текущий код
Messages.Add('The voucher was NOT sent to ' + sName+
' because the application is in TEST MODE.');
Messages.Add('Voucher Saved to ' + sFullPath);
Messages.Add('----------------------------------------------------------');
Новый код будет что-то вроде:
Messages.Add(sMsgText1 + '' + sName + '' + sMsgText2 + '' + sFullPath)
Файл Strings.pas будет содержать все строковые данные. Надеюсь, что это имеет смысл
6 ответов
Перенос строк в отдельный файл - хорошая идея! Он держит их вместе и позволит вам легко изменить их при необходимости. Ваш вопрос не говорит о том, что вы хотите их перевести, но централизация поможет этому.
Но, код как:
Messages.Add(sMsgText1 + '' + sName + '' + sMsgText2 + '' + sFullPath)
не лучше чем код как:
Messages.Add('The voucher was NOT sent to ' + sName+
' because the application is in TEST MODE.');
Вы превратили грязный, но читаемый вызов функции в грязный и нечитаемый вызов функции. Со старым кодом (второй фрагмент чуть выше) вы можете прочитать код и примерно увидеть, что будет сказано в сообщении, потому что его много в тексте. С новым кодом вы не можете.
Во-вторых, причина перемещения строк в том, чтобы связать связанные элементы и упростить их замену. Что если вы хотите изменить вышеприведенное сообщение так, чтобы вместо слова "файл 'foo' в пути 'bar'..." было написано "Файл bar\foo is..."? Вы не можете: способ построения сообщений по-прежнему фиксирован и разбросан по всему коду. Если вы хотите изменить несколько сообщений для одинакового форматирования, вам нужно будет изменить множество отдельных мест.
Это будет еще большей проблемой, если ваша цель - перевести ваши сообщения, так как часто перевод требует перефразирования сообщения, а не просто перевода компонентов. (Например, вам нужно изменить порядок подэлементов, включенных в ваши сообщения - вы не можете просто предполагать, что каждый язык представляет собой фразу за фразой в порядке замены.)
Рефакторинг на шаг впереди
Вместо этого я бы предложил более агрессивный рефакторинг вашего кода сообщения. Вы определенно на правильном пути, когда предлагаете перенести свои сообщения в отдельный файл. Но не просто перемещайте строки: перемещайте также и функции. Вместо большого количества Messages.Add('...')
разбросаны по вашему коду, найти общее подмножество сообщений, которые вы создаете. Многие будут очень похожи. Создайте семейство функций, которые вы можете вызывать, чтобы все похожие сообщения были реализованы с помощью одной функции, и если вам нужно изменить формулировку для них, вы можете сделать это в одном месте.
Например, вместо:
Messages.Add('The file ' + sFile + ' in ' + sPath + ' was not found.');
... and elsewhere:
Messages.Add('The file ' + sFileName + ' in ' + sURL + ' was not found.');
иметь единственную функцию:
Messages.ItemNotFound(sFile, sPath);
...
Messages.ItemNotFound(sFileName, sURL);
Ты получаешь:
- Централизованные строки сообщений
- Централизованные функции сообщений
- Меньше дублирования кода
- Более чистый код (без сборки строк при вызове функции, только параметры)
- Проще переводить - обеспечить альтернативную реализацию функций (не забывайте, что простого перевода подстрок может быть недостаточно, вам часто нужно иметь возможность существенно изменить формулировку).
- Четкие описания того, что сообщение в названии функции, например,
ItemNotFount(item, path)
, что приводит к - Более четкий код при чтении
Звучит неплохо:)
Я думаю, что имеет смысл переместить все строковые константы в одну единицу. Это значительно упрощает изменение текста, особенно если вы хотите перевести на другие (человеческие) языки.
Но вместо строк, почему бы вам не сделать то, что я обычно делаю, то есть использовать строку ресурсов. Таким образом, ваши строки могут быть изменены кем-то еще с помощью редактора ресурсов, без перекомпиляции.
unit Strings;
resourcestring
strMsgText1 = 'The voucher was NOT sent to ';
etc...
Но такую строку, вероятно, лучше сделать так:
resourcestring
strVoucherNotSent =
'The voucher was NOT sent to %s because the application is in TEST MODE.';
strVoucherForNHasValueOf =
'The voucher for %s has a value of $%.2f';
Преимущество этого состоит в том, что в некоторых языках размещение и порядок таких замен различаются. Таким образом, переводчик может разместить аргументы там, где это необходимо. Конечно, приложение должно затем использовать Format() для обработки строки:
Messages.Add(Format(strVoucherNotSent, [sName]));
Messages.Add(Format(strVoucherSavedTo, [sFullPath]));
Messages.Add(Format(strVoucherForNHasValueOf, [sName, dblValue]));
Если вы хотите перевести пользовательский интерфейс на разные языки, вам может пригодиться весь текст в одном файле или, возможно, несколько файлов, предназначенных для объявления строковых констант.
Однако, если вы сделаете это изменение без такой сильной мотивации, вы можете просто сделать ваш код трудным для чтения.
Как правило, вы должны спросить, каковы преимущества такого крупного рефакторинга, и если они не являются самоочевидными, то вы вполне можете изменить вещи только ради перемен.
Если вы хотите перевести свое приложение, рассмотрите возможность использования Gnu GetText для Delphi, также известного как dxGetText. Это лучше, чем помещать ваши строки в отдельный файл.pas, потому что он позволяет включать перевод без каких-либо специальных инструментов, без перекомпиляции даже конечными пользователями.
Что ж, консенсус здесь, по-видимому, имеет тенденцию в пользу профи, и я полностью с этим согласен. Неправильное использование строковых литералов может привести к тому, что ваш источник будет строго напечатан.
Одно из преимуществ, которое я до сих пор упускаю, - это возможность повторного использования строк. Хотя это не является прямой выгодой от доставки в другое устройство, оно заключается в перемещении строковых литералов в константы.
Но довольно существенным недостатком является время, необходимое для создания этого отдельного исходного файла. Вы можете рассмотреть возможность реализации этой хорошей практики программирования в следующем проекте. Это полностью зависит от того, достаточно ли у вас времени (например, хобби-проект) или крайнего срока, от того, есть ли у вас следующий проект или нет (например, от студента), или просто от желания заняться какой-то практикой. Как и ответы и комментарии Дэвида Х, как и во всех решениях, которые вы принимаете, вы должны взвешивать выгоды.
Если не считать всех видов причудливых инструментов рефакторинга, которые могут оказать некоторую автоматическую помощь, поймите, что перемещение строковых литералов в другое устройство само по себе не выполняет работу. Как уже ответили Руди и Дэвид М, вам частично придется переписать свой источник. Кроме того, поиск удобочитаемых, коротких и применимых имен констант требует времени. Поскольку во многих комментариях уже говорилось о важности контроля над написанием последовательности, мне нравится думать, что этот же аргумент относится и к самим заменяющим константам.
А что касается ответов на переводы, независимо от того, применимы ли они к OP или нет, перемещение всех ваших исходных строк в отдельный блок - это только часть решения по переводу. Вы также должны позаботиться о дизайнерских строках (т.е. надписях) и совместимости с графическим интерфейсом: более длинный перевод все еще должен уместиться на вашем ярлыке.
Если у вас есть роскошь или необходимость: пойти на это. Но я бы отнес это к следующему проекту.
Я сгруппировал все литералы со строками ресурсов в более старой версии нашей платформы. Я вернулся к этому, поскольку в каркасах вы можете не использовать все строки в каркасе (например, потому что некоторые юниты или группы юнитов не используются, но при сканировании общих каталогов будут показаны все строки в вашем инструменте перевода).
Теперь я снова распределяю их по единицам. Первоначально я начал группировать их, чтобы избежать дубликатов, но в ретроспективе это была меньшая проблема
(*) использование dxgettext на "общих" директориях.