Wlad писал(а):
Прочитал два раза весь "корпус" ваших последних N сообщений с иллюстративными примерами.
Вообще не понял, о чём душевная боль.
Боли никакой нет, скорее, наоборот -- в реальной практике на императиве есть "расслабуха" (однако, не всегда) из-за игнорирования или пренебрежения некоторыми положениями структурного программирования, в том числе и там, где в языке даже введён цикл Дейкстры.
Вот свежий пример здесь на форуме:
https://forum.oberoncore.ru/viewtopic.php?f=22&t=6402#p108074Код:
...
(** Usage: ConsoleUtils.ReplaceStringInFile --old="old string" --new="new string" <Input file> [<Ouput file>] *)
PROCEDURE ReplaceStringInFile*(context: Commands.Context);
VAR
bOptionsOk, bIgnoreCase: BOOLEAN;
options: Options.Options;
aOldPat, aNewPat: ARRAY 256 OF CHAR;
aFileNameIn, aFileNameOut: Files.FileName;
strContent: String;
buffer: Strings.Buffer;
nRead, nReplaced: LONGINT;
BEGIN
NEW(options);
options.Add("o", "old", Options.String);
options.Add("n", "new", Options.String);
options.Add("s", "silent", Options.Flag);
options.Add("c", "case", Options.Flag); (* case sensitive *)
bOptionsOk := options.Parse(context.arg, context.out) &
options.GetString("old", aOldPat) & options.GetString("new", aNewPat);
IF bOptionsOk THEN
context.arg.SkipWhitespace();
context.arg.String(aFileNameIn);
bOptionsOk := aFileNameIn # ""
END;
bSilent := options.GetFlag("silent");
bIgnoreCase := ~options.GetFlag("case");
IF ~bOptionsOk THEN
Message(context.out, CRLF + "Required parameters not provided. Usage:" + CRLF +
'ConsoleUtils.ReplaceStringInFile --old="old string" --new="new string" <Input file> [<Ouput file>]' + CRLF)
ELSE
context.arg.SkipWhitespace();
context.arg.String(aFileNameOut);
strContent := ReadFile(context.out, aFileNameIn, nRead);
IF strContent # NIL THEN
Message(context.out, 'File "' + aFileNameIn + '" opened, ' + nRead + ' bytes read.' + CRLF);
buffer := StringReplace(strContent^, aOldPat, aNewPat, bIgnoreCase, nReplaced);
Message(context.out, nReplaced + ' occurences of pattern "' + aOldPat + '" found.' + CRLF);
IF aFileNameOut # "" THEN
WriteFile(context.out, aFileNameOut, buffer.GetString()^, 0, buffer.GetLength() - 1)
ELSE
WriteFile(context.out, aFileNameIn, buffer.GetString()^, 0, buffer.GetLength() - 1)
END
END
END
END ReplaceStringInFile;
...
Выше есть "склейка" этапов через "защиту" с переменной "bOptionsOk". Можит быть частично защита есть избыточная, но в результате меньше вложенности if-ов, без досрочных return и т.д., плюс явно вырисовывается линейное следование этапов (видимо, установка переменных bSilent и bIgnoreCase также должна быть под защитой в зависимости от результатов операции options.Parse(...) с целью явно выразить предполагаемые намерения (да и меньше действий при неуспехе защиты), даже если options.GetFlag в любом случае возвращает какой-то логический результат. Т.е. возможна некая перестройка алгоритма, в результате может оказаться избыточность проверок по bOptionsOk. Но не принципиально, без буквоедства, рассматрение по сути лишь в общих чертах).
И наблюдается традиционная "монадная" and-склейка вида:
bOptionsOk := options.Parse(context.arg, context.out) &
options.GetString("old", aOldPat) & options.GetString("new", aNewPat);
Причём обычно даже базовые интерфейсы процедур, как GetString выше, целенаправленно задаются в стиле булевой функции (логический результат) с дополнительными выходами через изменяемые параметры для удобства применения в логических выражениях.
"Каноническое" же структурное программирование требует разделения операций на "команды" (операции по изменению состояния) и "вопросы" (функции-предикаты без побочных эффектов, опрашивающие состояние), следование определяется через ";" и т.д. Код выше перестроить можно (разбить на процедуры, не дублировать проверки и пр.), но, в целом, высокая гранулярность изначально связного контекста (который распадается на части) не всегда удобна и т.д. и т.п.
Уверен, что код выше есть традиционная (широко распространённая) рутинная практика (особенно в массивном коде), которая имеет некие расхождения с методологией (идеализированной).
И выше в теме были методологические альтернативы (с практикой). Смогут ли они заменить или дополнить рутинную "рукопашную простоту" -- отдельный вопрос (материалы и собраны для того, чтобы посмотреть, пощупать, оценить ...).