Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];

Вниз

О стиле "неубиваемого" кода.   Найти похожие ветки 

 
Дмитрий С ©   (2012-06-27 00:28) [0]

Предлагаю похолливарить на следую тему:
Есть, к примеру некая функция. Внутри нее множество вызовов, результат каждого из которых нужно проверять.
Способ с исключениями и try finally я хочу исключить сразу, но не потому что он плох, а потому что, хочу обсудить два других варианта (в том языке для которого я интересуюсь не принято try finally).

И так вариант первый:
- Вложенные условия.

if foo() = 0 then
begin
 file = file_open(...);
 if file <> 0 then
 begin
   ... // штук 10 вложений
   result = "ok";
   ...
   file_close(file);
 end else begin
   result = "CANNOT_OPEN_FILE";
 end;
end else begin
 result = "FOO_FAILED";
end;


И другой:
- С выходом.

label exit_point;

file = 0;

if foo() <> 0 then
begin
 result = "FOO_FAILED";
 goto exit_point;
end;

file = file_open(...);
if file = 0 then
begin
 result = "CANNOT_OPEN_FILE";
 goto exit_point;
end;

... // штук 10 подобных вызовов

exit_point:
if file <> 0 then close_file(file);


Собственное интересует ваше мнение о том и другом.

P.S. Вариант "Не писать такие большие функции" не предлагать. Иногда надо.


 
antonn ©   (2012-06-27 00:52) [1]

а в чем "холливарность"?


 
Jeer ©   (2012-06-27 01:31) [2]


> Собственное интересует ваше мнение о том и другом.


Мнение простое - делай как тебе удобнее и понятнее, лишь бы работало.


 
Германн ©   (2012-06-27 01:33) [3]


> Собственное интересует ваше мнение о том и другом.
>

Я предпочитаю второй вариант. (Для тех двух других языков, которыми я занимался довольно плотно :).


 
Германн ©   (2012-06-27 01:39) [4]


> antonn ©   (27.06.12 00:52) [1]
>
> а в чем "холливарность"?

Автору только кажется, что тут возможен холивар. Имхо, из-за использования goto, что для Паскаля считается дурным тоном.


 
Ega23 ©   (2012-06-27 03:57) [5]

На TSQL я второй вариант практически всегда использовал.
Да и в других случаях при отсутствии finally - тоже также поступил бы, скорее всего.
"Холиварность" - сомнительная, ИМХО, писать надо так, как тебе удобнее.


 
tesseract ©   (2012-06-27 08:25) [6]


> file = file_open(...);
> if file = 0 then
> begin
>  result = "CANNOT_OPEN_FILE";
>  goto exit_point;
> end;


Goto ? Эцих с гвозьдями!


file = file_open(...);
if file <> 0 then


Понятнее как-то так :

var sUserMsg :string;
file = file_open(...);
If not CheckFileOpenResult(file,sUserMsg) then  Exception.Create(sUserMsg);


 
Ega23 ©   (2012-06-27 08:29) [7]


> Goto ? Эцих с гвозьдями!


Почему?


 
Омлет ©   (2012-06-27 08:30) [8]

> в том языке для которого я интересуюсь не принято try finally

Ну так яви название языка.


 
И. Павел ©   (2012-06-27 08:46) [9]

> в том языке для которого я интересуюсь не принято try finally

Уж не ABAP ли? По моему это один из немногих современных языком, который упорно не хочет выбираться из эпохи диско :)


 
Думкин ©   (2012-06-27 08:50) [10]

Ну, на Х++ try catch только. finally нет.


 
Омлет ©   (2012-06-27 09:17) [11]

"не принято" != "нет"


 
Sha ©   (2012-06-27 09:23) [12]

Когда вложений мало (до 3-4) - первый.
Много или сложные IFы - второй. Главное выбрать единый стиль написания выхода по ошибке и формирования кода ошибки.


 
Думкин ©   (2012-06-27 09:24) [13]

Это понятно. Но сама фраза странная "не принято". Над принимать ставки на то, что именно вкладывал автор в эти поэтичные строки.


 
Cobalt ©   (2012-06-27 09:28) [14]

может, это PHP?


 
Омлет ©   (2012-06-27 09:37) [15]

> может, это PHP?

Там нет finally.


 
oxffff ©   (2012-06-27 10:31) [16]


> И. Павел ©   (27.06.12 08:46) [9]
> > в том языке для которого я интересуюсь не принято try
> finally
>
> Уж не ABAP ли? По моему это один из немногих современных
> языком, который упорно не хочет выбираться из эпохи диско
> :)


Не надо ля-ля.
В ABAP есть структурная обработка исключений.


 
И. Павел ©   (2012-06-27 10:51) [17]

> В ABAP есть структурная обработка исключений.

Есть, я и не писал, что нет. Но операторы (например, SELECT) возвращают результат своего выполнения через флаг...


 
Компромисс ©   (2012-06-27 11:02) [18]

Разделение на функции поможет

f = openFile(file);
if(f == 0){
 ...
 return;
}
processingResult = processFile(f);
closeFile(f);

в processFile будет
if foo() <> 0 then
 return "FOO_FAILED";
end;
...
... // штук 10 подобных return;


 
tesseract ©   (2012-06-27 11:09) [19]


> в processFile будет
> if foo() <> 0 then
>  return "FOO_FAILED";
> end;


Лучше всё таки выдавать ошибку по GetLastError. Таки правильнее.


 
oxffff ©   (2012-06-27 11:17) [20]


> И. Павел ©   (27.06.12 10:51) [17]
> > В ABAP есть структурная обработка исключений.
>
> Есть, я и не писал, что нет. Но операторы (например, SELECT)
> возвращают результат своего выполнения через флаг...


Если ты про OPEN SQL. То не только через SY-SUBRC.
Он еще может вываливаться в исключение.
Например CX_SY_OPEN_SQL_DB.


 
oxffff ©   (2012-06-27 11:20) [21]

По теме.
Использую и тот и другой варианты.


 
Компромисс ©   (2012-06-27 11:30) [22]


> Лучше всё таки выдавать ошибку по GetLastError. Таки правильнее.


Конечно. Но только если GetLastError применим. Может, человек на PHP каком-нибудь работает...
Еще правильнее try-finally использовать.
Если в языке есть try-finally, то его нужно использовать всегда, когда есть смысл. На моду нельзя ориентироваться, это не одежда :-)
Если только "мода" не вызвана тем, что try-finally не всегда правильно работает из-за багов в реализации языка.


 
Компромисс ©   (2012-06-27 11:42) [23]

Чем мне не нравятся оба варианта автора, так это тем, что чем больше if, тем хуже читабельность. В первом случае отступы  могут стать гигантскими, во втором случае метка окажется через N страниц от первого if.


 
RWolf ©   (2012-06-27 11:45) [24]

Компромисс ©   (27.06.12 11:42) [23]

это естественный ограничитель длины функции )


 
tesseract ©   (2012-06-27 11:48) [25]


> Еще правильнее try-finally использовать.


А причем тут try..finally и выдача грамотных сообщений об ошибке? Raise можно преспокойно сделать с API-шной FormatMessage  и вызвать исключение с читабельной ошибкой.


 
Плохиш ©   (2012-06-27 11:54) [26]


> Дмитрий С ©   (27.06.12 00:28)  

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


 
Компромисс ©   (2012-06-27 12:01) [27]


> А причем тут try..finally и выдача грамотных сообщений об
> ошибке?


Я к тому, что если уж автора учить, то неиспользование try-finally - более грубая ошибка, чем неиспользование GetLastError.


> Raise можно преспокойно сделать с API-шной FormatMessage
>  и вызвать исключение с читабельной ошибкой.


Я сейчас на яве работаю, мне FormatMessage кажется неправильным, потому как с локализацией тяжело будет. Только код сообщения об ошибке, никаких текстов ошибок в программе.


 
tesseract ©   (2012-06-27 12:13) [28]


> Я сейчас на яве работаю, мне FormatMessage кажется неправильным,
>  потому как с локализацией тяжело будет.


Вообще она юникодовая. В WinAPI.


 
Компромисс ©   (2012-06-27 12:20) [29]

tesseract ©   (27.06.12 12:13) [28]

Замечательно.
1) Можно текст сообщения об ошибке заменить, не перекомпилируя приложение?
2) Можно добавить новый поддерживаемый язык, не перекомпилируя приложение?

Только не надо в каждый raise добавлять параметр для FormatMessage, неправильно это.

raise должен использовать код типа "file.not.found",  а уже самый верхний обработчик ошибок должен подставлять нужное значение текста ошибки в зависимости от кода ошибки и от языка пользователя.


 
DVM ©   (2012-06-27 12:26) [30]


> GetLastError


> FormatMessage

Win32Check не проще?


 
Дмитрий С ©   (2012-06-27 13:11) [31]


>  Может, человек на PHP каком-нибудь работает...

Вот-вот. В нем и finally нет, реализация функций убогая (для скриптового языка)


> во втором случае метка окажется через N страниц от первого
> if.

Ну это да. Но по названию метки понятно что это за метка да и раз посмотреть можно что там внизу.


> то неиспользование try-finally - более грубая ошибка,

Ну нет finally в языке, что сделаешь то, да и большинство функций не генерируют исключения. А некоторые еще и ошибку через одно место возвращают.


>  Только код сообщения об ошибке, никаких текстов ошибок
> в программе.

Т.е. пользователю нужно будет связываться с поддержкой или утомительно читать хелп, чтобы понять что за ошибка номер 42, вместо того, чтобы хоть как то натолкнуть его на мысль в чем может быть дело?


 
Компромисс ©   (2012-06-27 13:47) [32]


> Т.е. пользователю нужно будет связываться с поддержкой или
> утомительно читать хелп, чтобы понять что за ошибка номер
> 42, вместо того, чтобы хоть как то натолкнуть его на мысль
> в чем может быть дело?


Нет. Код генерирует ошибку с кодом file.not.found и параметром, установленным в имя файла, ошибка в конце концов передается  функции, которая находит текст сообщения по ошибке в файле errors.properties:
file.not.found=Cannot find file with name %s
Точнее, если у пользователя текущая локаль ru_ru, то сначала происходит поиск файла error_ru_RU.properties, потом errors_ru.properties и только потом errors.properties


 
tesseract ©   (2012-06-27 14:14) [33]


> 1) Можно текст сообщения об ошибке заменить, не перекомпилируя
> приложение?
> 2) Можно добавить новый поддерживаемый язык, не перекомпилируя
> приложение?


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


> Точнее, если у пользователя текущая локаль ru_ru, то сначала
> происходит поиск файла error_ru_RU.properties


ИМХО BerkleyDB базы всё-таки практичнее при большом количестве сообщений.


 
Компромисс ©   (2012-06-27 14:41) [34]


> ИМХО BerkleyDB базы всё-таки практичнее при большом количестве
> сообщений.
>


Можно использовать несколько файлов для иерархического разделения. Держать все в одном месте неправильно ИМХО, даже если БД справляется. Сначала искать в mySuperFormErrors, потом в mySuperModuleErrors, потом в commonErrors, потом в errors. Таким образом можно перекрыть file.not.found.error для некоторого модуля/формы.


 
ProgRAMmer Dimonych ©   (2012-06-27 20:51) [35]

> [31] Дмитрий С ©   (27.06.12 13:11)
> >  Может, человек на PHP каком-нибудь работает...
> Вот-вот. В нем и finally нет, реализация функций убогая
> (для скриптового языка)

finally, если очень нужно, можно переписать на catch"ах. Специфика PHP, IMHO, в нескольких вещах:
1. Освобождение памяти автоматическое, finally в большинстве случаев как бы и не нужен.
2. Если исключение произошло - это либо пользовательское исключение, либо признак логической ошибки в скрипте.
2.1. Если программист сам его бросил - значит, где-то сверху он его должен ждать и это будет именно catch (возможно, с последующим throw).
2.2. Если программист исключения не ждёт - значит, он не учитывает какой-то ситуации => анализ задачи выполнен не полностью => скрипт нужно допиливать.
2.3. В обоих случаях пользователя достаточно просто уведомить, что что-то пошло не так. Реализовывать многоуровневую логику обработки исключения по finally просто неактуально.


 
ProgRAMmer Dimonych ©   (2012-06-27 20:51) [36]

P.S. Хотелось бы подробнее про убогость функций, но оффтоп :)


 
Владислав ©   (2012-06-27 22:32) [37]

За 10-летнюю практику ни разу не возникла необходимость выбирать из первого или второго варианта. Когда появляется желание выбрать, я переписываю код.

«P.S. Вариант "Не писать такие большие функции" не предлагать. Иногда надо.»

Как раз этот вариант и предлагаю. В 99,99 % это вариант сделать более понятный и простой код.


 
Rouse_ ©   (2012-06-27 23:17) [38]

С учетом что нет SEH, второй более читабелен, более того еще читабельней станет, если goto на return заменить c финализацией


 
zzz   (2012-06-28 05:32) [39]

Не согласен, что для паскаля goto это нонсенс. Да! не нужно им злоуотреблять. Но тем неменее иногда для удочитаемости и реализации легче сделать goto, чем городить "пирамиду" из фиг знает чего.

Это к посту где-то сверху...


 
Дмитрий С ©   (2012-06-28 16:04) [40]

было бы здорово, если бы из try finally можно было выйти с помощью break. Чтобы смысл был примерно такой:
try
 repeat

 until true;
finally
...


> P.S. Хотелось бы подробнее про убогость функций, но оффтоп
> :)

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



Страницы: 1 2 вся ветка

Форум: "Прочее";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.55 MB
Время: 0.053 c
2-1337537332
petvv
2012-05-20 22:08
2013.03.22
HEX в DateTime


15-1334867402
Юрий
2012-04-20 00:30
2013.03.22
С днем рождения ! 20 апреля 2012 пятница


2-1343717574
AV
2012-07-31 10:52
2013.03.22
Поток, организация проверки раз в секунду PostThreadMessage


15-1343236383
alexdn
2012-07-25 21:13
2013.03.22
Шрифт


15-1336034354
ZeroDivide
2012-05-03 12:39
2013.03.22
Delphi перестала работать комбинация Ctrl+Shift+стрелки,





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский