api design: return code or exception - formal criteria
От: Andrew S Россия http://alchemy-lab.com
Дата: 27.08.09 12:14
Оценка:
Всем привет.

Ситуация следующая — разрабатывается небольшой слой кросс-платформенной абстракции (io, sync, mt etc). В который раз возник вопрос, что в каких ситуациях использовать — исключения и коды возврата ошибок.
Есть ли какие-то формальные критерии, по которым можно решить что в данном случае использовать коды возврата ошибки, в данном — исключения.
Например, взять файловые операции. Тут довольно тонкая ситуация — в некоторых случаях важно ошибки обрабатывать прямо рядом с вызовом, в некоторых — не нужно. Хочется иметь какие-то формальные рекомендации, по которым в большинстве случаев можно было бы принимать подобное решение. "Посмотреть как у других" в данном случае не подходит — просто потому, что у других по-разному.

Рассмотрим, например, ситуацию — критическая секция в терминах win32 и именованный мьютекс. С критической секцией вроде без вариантов — там только исключения, тем более, что бросать она их может только в одном редком кейсе, см msdn. Должен ли мьютекс по аналогии бросать эксепшены (читай, инициализироваться в конструкторе), или же иметь методы Create/Open/Close. Как тогда быть с операциями типа wait, которы могут возвращать довольно много различных кодов, часть из которых обычно анализируется сразу рядом, часть — вызывается необратимые последствия...

Если есть ссылки критерии, best practice или что-нибудь подобное — будет супер.

Спасибо!

PS Свое мнение по данному вопросу у меня имеется В данном случае нужны именно формальные критерии, чтобы каждый конкретный случае не вызывал одинаковых вопросов.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re: api design: return code or exception - formal criteria
От: jazzer Россия Skype: enerjazzer
Дата: 27.08.09 12:44
Оценка: 32 (6)
Здравствуйте, Andrew S, Вы писали:

AS>Всем привет.


AS>Ситуация следующая — разрабатывается небольшой слой кросс-платформенной абстракции (io, sync, mt etc). В который раз возник вопрос, что в каких ситуациях использовать — исключения и коды возврата ошибок.


AS>Если есть ссылки критерии, best practice или что-нибудь подобное — будет супер.


boost.asio

все функции в двух экземплярах, одни бросают, другие (у которых есть параметр boost::system::error_code & ec) — не бросают.
Пример:
iterator resolve(
    const query & q);

iterator resolve(
    const query & q,
    boost::system::error_code & ec);


http://www.boost.org/doc/libs/1_39_0/doc/html/boost_asio/reference/ip__basic_resolver/resolve.html
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[2]: api design: return code or exception - formal criteri
От: Andrew S Россия http://alchemy-lab.com
Дата: 27.08.09 12:50
Оценка:
AS>>Всем привет.

AS>>Ситуация следующая — разрабатывается небольшой слой кросс-платформенной абстракции (io, sync, mt etc). В который раз возник вопрос, что в каких ситуациях использовать — исключения и коды возврата ошибок.


AS>>Если есть ссылки критерии, best practice или что-нибудь подобное — будет супер.


J>boost.asio


J>все функции в двух экземплярах, одни бросают, другие (у которых есть параметр boost::system::error_code & ec) — не бросают.

J>Пример:
J>
J>iterator resolve(
J>    const query & q);

J>iterator resolve(
J>    const query & q,
J>    boost::system::error_code & ec);
J>


J>http://www.boost.org/doc/libs/1_39_0/doc/html/boost_asio/reference/ip__basic_resolver/resolve.html


Ух, сильно. Нужно ли это для каждого метода — вот вопрос. Мое мнение, что для каждого метода это лишнее, и сам же буст этому пример — например, трединг, алгоритмы...
Хочется формальных критериев, когда надо только исключения, когда только результат, когда нужно, например, вот такое раздвонение интерфейса.

Спасибо за мнение, пример наводит на некоторые мысли
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[3]: api design: return code or exception - formal criteri
От: jazzer Россия Skype: enerjazzer
Дата: 27.08.09 16:08
Оценка: 6 (1) +4
Здравствуйте, Andrew S, Вы писали:

AS>Хочется формальных критериев, когда надо только исключения, когда только результат, когда нужно, например, вот такое раздвонение интерфейса.


Имхо, нету таких формальных критериев.
Все зависит от пользователя: для одного неудача — штатная ситуация, а для другого — фатальная ошибка.

Например, должна ли бросать функция открытия файла, если файл не найден?
Если у тебя список файлов, и тебе нужно попробовать их все по порядку и использовать первый нашедшийся, то неудача с одним файлом — это штатный эпизод перебора файлов, а фатальная ошибка — это если вообще ни одного файла нет.
А если у тебя всего лишь одно имя файла, то невозможность его открыть — это фатальная ошибка.
И всё это разнообразие может быть у пользователя в одной функции загрузки конфигов.

Так что правильный путь, имхо — это дать возможность пользователю самому решить, что ему нужно, например, как делает boost.asio (можно и по-другому делать).
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[3]: api design: return code or exception - formal criteri
От: pivcorp Россия  
Дата: 27.08.09 16:28
Оценка: +1
Здравствуйте, Andrew S, Вы писали:

AS>>>Всем привет.


AS>>>Ситуация следующая — разрабатывается небольшой слой кросс-платформенной абстракции (io, sync, mt etc). В который раз возник вопрос, что в каких ситуациях использовать — исключения и коды возврата ошибок.


J>>все функции в двух экземплярах, одни бросают, другие (у которых есть параметр boost::system::error_code & ec) — не бросают.


AS>Ух, сильно. Нужно ли это для каждого метода — вот вопрос. Мое мнение, что для каждого метода это лишнее, и сам же буст этому пример — например, трединг, алгоритмы...

AS>Хочется формальных критериев, когда надо только исключения, когда только результат, когда нужно, например, вот такое раздвонение интерфейса.

Дело в том, что судя по тому что ты озвучил, это библиотека. Причем вещей достаточно низкоуровневых.
Соответственно ты, по идее, не знаешь (и сам об этом говоришь) в каком контексте будешь использовать.
Так что разумно реализовывать оба варианта.
Если ломы делать сразу оба — оттолкнись от проекта для которого в первую очередь эта библиотека пойдет.
Там должна быть стратегия обработки ошибок, делай в первую очередь тот вариант который удачно впишется в неё.
Но делай имея ввиду, что придется делать и второй вариант.


ЗЫ "раздвонение интерфейса" возьму на вооружение
Re[4]: api design: return code or exception - formal criteri
От: Andrew S Россия http://alchemy-lab.com
Дата: 27.08.09 18:21
Оценка:
AS>>Хочется формальных критериев, когда надо только исключения, когда только результат, когда нужно, например, вот такое раздвонение интерфейса.

J>Имхо, нету таких формальных критериев.

J>Все зависит от пользователя: для одного неудача — штатная ситуация, а для другого — фатальная ошибка.

J>Например, должна ли бросать функция открытия файла, если файл не найден?


Вот, вот, примерно это.

J>Если у тебя список файлов, и тебе нужно попробовать их все по порядку и использовать первый нашедшийся, то неудача с одним файлом — это штатный эпизод перебора файлов, а фатальная ошибка — это если вообще ни одного файла нет.


Лучше пример с неименованным мьютексом без секьюрити Там менее очевидно чем с файлом (тем более для файла есть пример — mfc, где как раз сделано более-менее в плане проектирования нормально).

А если с файлом — тогда лучше рассмотреть метод Read или Write. По моим ощущениям, напрмер, в данном случае как раз можно найти некий баланс в виде result code (if success or eof) + exception if failure. Т.е. в 99% юзекейсов покрывается. Так сделано в mfc и, похоже, это довольно неплохой дизайн в таких случаях, хотя раньше я думал иначе . Вот хочется примерно таких рекомендаций, дабы разработчику не надо было думать, что в каких случаях делать, да и все проще, если играть по правилам.

J>А если у тебя всего лишь одно имя файла, то невозможность его открыть — это фатальная ошибка.


С файлами все вообще сложнее — надо делать двухуровневое конструировение, либо делать одноуровневое + порождающую фабрику. Меня больше, повторюсь, интересуют пограничные случаи типа неименованного мьютекса.

J>Так что правильный путь, имхо — это дать возможность пользователю самому решить, что ему нужно, например, как делает boost.asio (можно и по-другому делать).


Но, имхо, не для каждого интерфейса. Либо делать 2 разных интерфейса с возможность move-upgrade одного в другой...
Вот этого бы не хотелось, на самом деле.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[5]: api design: return code or exception - formal criteri
От: Юрий Жмеренецкий ICQ 380412032
Дата: 27.08.09 20:45
Оценка: 5 (3)
Здравствуйте, Andrew S, Вы писали:
...
J>>Так что правильный путь, имхо — это дать возможность пользователю самому решить, что ему нужно, например, как делает boost.asio (можно и по-другому делать).

AS>Но, имхо, не для каждого интерфейса. Либо делать 2 разных интерфейса с возможность move-upgrade одного в другой...

AS>Вот этого бы не хотелось, на самом деле.

Если модификация api невозможна, то можно такие варианты рассмотреть:
// Дано:
result api::f1(); // все nothrow
result api::f2();
result api::f3();

// использование

checked_result r(error_code1 | error_code2);  
r = api::f1();
r = api::f2();
r = api::f3();


Объект checked_result в операторе присваивания проверяет аргумент на присутствие error_code1 или error_code2, и в случае обнаружения кидает исключение. Либо просто использует что-то вроде 'if(FAILED(hr)) throw ...'.

Другой вариант — опять nothrow api, + легкие обертки-функторы:

remove_file remove(std::nothrow); // любые ошибки игнорируются
std::for_each(v.begin(), v.end(), remove);

//...

// not_found трансформируется в исключение, 
// остальные ошибки просто возвращаются.
remove_file remove(not_found);

result r = remove(filename); 
if(r == access_denied)
{
  //...
}
Re[4]: api design: return code or exception - formal criteri
От: TarasKo Голландия  
Дата: 27.08.09 21:26
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Здравствуйте, Andrew S, Вы писали:


AS>>Хочется формальных критериев, когда надо только исключения, когда только результат, когда нужно, например, вот такое раздвонение интерфейса.


J>Имхо, нету таких формальных критериев.

J>Все зависит от пользователя: для одного неудача — штатная ситуация, а для другого — фатальная ошибка.

J>Например, должна ли бросать функция открытия файла, если файл не найден?

J>Если у тебя список файлов, и тебе нужно попробовать их все по порядку и использовать первый нашедшийся, то неудача с одним файлом — это штатный эпизод перебора файлов, а фатальная ошибка — это если вообще ни одного файла нет.
J>А если у тебя всего лишь одно имя файла, то невозможность его открыть — это фатальная ошибка.
J>И всё это разнообразие может быть у пользователя в одной функции загрузки конфигов.

J>Так что правильный путь, имхо — это дать возможность пользователю самому решить, что ему нужно, например, как делает boost.asio (можно и по-другому делать).


Думаю что у функции открытия файла должно быть чего-то типа флагов, например create_if_not_exists.

Я считаю так. Если функция не выполнила пост условия, значит это исключение. Определи постусловие у функции и бросай исключение в случае его не достижения.
Правда тут есть тоже тонкость. Например операция удаления файла. Что делать если этого файла и не было. В этом случае вопрос заключается в том, считать ли это ошибкой предусловия или нет. Является ли наличие файла требованием дл функции удаления файла. Мне больше всего нравится решение когда такие проблемы если они есть разруливаются классами стратегий, ну и соответственно есть какая-то стратегия по умолчанию.
Я за то что б бросать исключения и использовать коды воврата только в крайних случаях.
Re[6]: api design: return code or exception - formal criteri
От: Andrew S Россия http://alchemy-lab.com
Дата: 28.08.09 11:21
Оценка:
J>>>Так что правильный путь, имхо — это дать возможность пользователю самому решить, что ему нужно, например, как делает boost.asio (можно и по-другому делать).

AS>>Но, имхо, не для каждого интерфейса. Либо делать 2 разных интерфейса с возможность move-upgrade одного в другой...

AS>>Вот этого бы не хотелось, на самом деле.

ЮЖ>Если модификация api невозможна, то можно такие варианты рассмотреть:

ЮЖ>
// Дано:
ЮЖ>result api::f1(); // все nothrow
ЮЖ>result api::f2();
ЮЖ>result api::f3();

ЮЖ>// использование

ЮЖ>checked_result r(error_code1 | error_code2);  
ЮЖ>r = api::f1();
ЮЖ>r = api::f2();
ЮЖ>r = api::f3();
ЮЖ>


ЮЖ>Объект checked_result в операторе присваивания проверяет аргумент на присутствие error_code1 или error_code2, и в случае обнаружения кидает исключение. Либо просто использует что-то вроде 'if(FAILED(hr)) throw ...'.


ЮЖ>Другой вариант — опять nothrow api, + легкие обертки-функторы:


Спасибо за ответ.
Да, про это все тоже думалось. В данном случае надо уменьшить бардак в коде, такие подходы его, на мой взгляд, поощряют — появляется куча условий на довольно высоком уровне. В общем, смысл от исключений тогда почти теряется. В общем, от исключений совсем отказываться не хочется, надо просто регламентировать ситуации...
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[6]: api design: return code or exception - formal criteri
От: IROV..  
Дата: 28.08.09 21:09
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>Здравствуйте, Andrew S, Вы писали:

ЮЖ>...
J>>>Так что правильный путь, имхо — это дать возможность пользователю самому решить, что ему нужно, например, как делает boost.asio (можно и по-другому делать).

AS>>Но, имхо, не для каждого интерфейса. Либо делать 2 разных интерфейса с возможность move-upgrade одного в другой...

AS>>Вот этого бы не хотелось, на самом деле.

ЮЖ>Если модификация api невозможна, то можно такие варианты рассмотреть:

ЮЖ>
// Дано:
ЮЖ>result api::f1(); // все nothrow
ЮЖ>result api::f2();
ЮЖ>result api::f3();

ЮЖ>// использование

ЮЖ>checked_result r(error_code1 | error_code2);  
ЮЖ>r = api::f1();
ЮЖ>r = api::f2();
ЮЖ>r = api::f3();
ЮЖ>


ЮЖ>Объект checked_result в операторе присваивания проверяет аргумент на присутствие error_code1 или error_code2, и в случае обнаружения кидает исключение. Либо просто использует что-то вроде 'if(FAILED(hr)) throw ...'.


А что делать если f1 возвращает значение? делать через out параметры? не всегда удобно/красиво
я не волшебник, я только учусь!
Re[7]: api design: return code or exception - formal criteri
От: Юрий Жмеренецкий ICQ 380412032
Дата: 29.08.09 06:52
Оценка:
Здравствуйте, IROV.., Вы писали:

IRO>А что делать если f1 возвращает значение? делать через out параметры? не всегда удобно/красиво


Здесь два варианта:
1) Код ошибки при этом возвращается через out параметры (что встречается редко).
2) Ошибкой считается некоторое состояние возвращаемого значения.

В принципе второй вариант очень похож на вариант с возвратом кода ошибки, разница может быть в том, что коды ошибок фиксированы, а "ошибочное" состояние может зависить от контекста/функции. Если разницы нет, то такой вариант эквивалентен первоначальному.

Дополнительно к этому нужно определить минимальный набор данных, которые надо передавать в объект исключения. В первом случае — наверняка это будет непосредственно код ошибки, во втором — с большей долей вероятности _не_ возвращенное значение, а что-то другое, вроде значения GetLastError из WINAPI.

С обработкой на месте эти два варианта могут выглядеть так:

result r;
value v = api::f(.., &r);
if(r == X)
  throw exception(r);

//...

value v = api::f(...);
if(v == Y)
  throw exception(get_last_error());


Разумеется и такие варианты могут быть актуальными (особенно при единичных вызовах). Вопрос в том, насколько можно их "улучшить" в рамках принятых допущений. Но более концептуальный вопрос — а что считать улучшениями?

Вот например:

// для первого случая
result r;
value v = api::f(.., &r);
ensure(r, r == X);

//...
result r;
value v = api::f(.., &f);
ENSURE(r == X);           // макрос для избавления от первого аргумента

// для второго
value v = api::f(...);
ensure(v == Y);

//...
value v = ensure_not_Y(api::f(...));

//...
value v = api::f(...), THROW_IF(v == Y); // макрос


Что здесь лучше/хуже/удобней/красивей?
Re[3]: api design: return code or exception - formal criteri
От: gear nuke  
Дата: 30.08.09 00:17
Оценка:
Здравствуйте, Andrew S, Вы писали:

AS>вот такое раздвонение интерфейса.


В последней ревизии немного другой подход:
void f(error_code& ec=throws());
здесь
.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[8]: api design: return code or exception - formal criteri
От: jazzer Россия Skype: enerjazzer
Дата: 30.08.09 03:22
Оценка: 1 (1) +1
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>Здравствуйте, IROV.., Вы писали:


IRO>>А что делать если f1 возвращает значение? делать через out параметры? не всегда удобно/красиво


ЮЖ>Здесь два варианта:

ЮЖ>1) Код ошибки при этом возвращается через out параметры (что встречается редко).
ЮЖ>2) Ошибкой считается некоторое состояние возвращаемого значения.
ЮЖ>Что здесь лучше/хуже/удобней/красивей?


Главная проблема с возвращаемыми значениями — это то, что они игнорируются по умолчанию (в отличие от исключений).
Поэтому если код написан безопасно по отношению к исключениям, то у нас есть автоматическая гарантия, что ни одна ошибка не будет пропущена — против лома нет приема, если исключение вылетело, то оно будет лететь, пока его не поймаешь явно.

С возвращаемыми же значениями в варианте два пропустить ошибку легче легкого, ее ведь даже не видно — зовешь себе функции, как будто они все возвращают void.
В этом смысле первый вариант мне кажется лучшим — по крайней мере, ты говоишь явно, что собираешься обрабатывать ошибки без исключений: ты объявляешь переменную с кодом ошибки и потом пихаешь ее во все вызовы, из которых ты не хочешь получить исключение.
Конечно, тут тоже легко пропустить обработать ошибку, особенно при копи-пейсте, но это уже не будет настолько невидимым, как в варианте два — по крайней мере, код ошибки присутствует во всех вызовах явно, и то, что его не обработали — видно.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[9]: api design: return code or exception - formal criteri
От: Юрий Жмеренецкий ICQ 380412032
Дата: 30.08.09 09:13
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Здравствуйте, Юрий Жмеренецкий, Вы писали:


ЮЖ>>Здравствуйте, IROV.., Вы писали:


IRO>>>А что делать если f1 возвращает значение? делать через out параметры? не всегда удобно/красиво


ЮЖ>>Здесь два варианта:

ЮЖ>>1) Код ошибки при этом возвращается через out параметры (что встречается редко).
ЮЖ>>2) Ошибкой считается некоторое состояние возвращаемого значения.
ЮЖ>>Что здесь лучше/хуже/удобней/красивей?

J>Главная проблема с возвращаемыми значениями — это то, что они игнорируются по умолчанию (в отличие от исключений).


Стоп, стоп... мы говорим о другом — об использовании nothrow api.

Я: вот такую конструкцию:

result r = api::f1(...);
if(r == error_code1)
  throw exception(...);

r = api::f2(...);
if(r == error_code1)
  throw exception(...);
 
r = api::f3(...);
if(r == error_code1)
  throw exception(...);


легко можно преобразовать в такую:

checked_result r(error_code1);  
r = api::f1();
r = api::f2();
r = api::f3();


IROV: А что делать если f1 возвращает значение?

Значение здесь — это не то "возращаемое значение" о котором ты говоришь. Это полноценный результат. Во втором варианте, про который я говорил (см. выше) — api::f в общем случае не знает, какое значение клиент воспринимает как исключение. Т.е. функция возвращает строку — а клиента может расценивать пустую(или с некоторым значением) строку как исключительную ситуацию. Здесь для определения ошибка/не ошибка используется внешний по отношению к api::f предикат. В частных случаях, вроде HANDLE из winapi, может существовать предопределенное, "ошибочное" значение (хотя в случае с HANDLE их может несколько).

Собственно и вопрос про лучше/хуже был задан в этом контексте. Например в варианте checked_result как плюсом, так и минусом является сокрытие предиката проверки.

J>Поэтому если код написан безопасно по отношению к исключениям


Это минимальное требование, без которого не стоит связываться с исключениями (имхо).

J>то у нас есть автоматическая гарантия, что ни одна ошибка не будет пропущена — против лома нет приема, если исключение вылетело, то оно будет лететь, пока его не поймаешь явно. С возвращаемыми же значениями в варианте два пропустить ошибку легче легкого, ее ведь даже не видно...


Это уже проблема api — возврат кода ошибки через out параметр...

J>В этом смысле первый вариант мне кажется лучшим — по крайней мере, ты говоишь явно, что собираешься обрабатывать ошибки без исключений: ты объявляешь переменную с кодом ошибки и потом пихаешь ее во все вызовы, из которых ты не хочешь получить исключение.


Ты про какой вариант говоршь? Я предлагал наоборот (поскольку api не кидает исключений) — указанные коды трансформируются в исключения. В вариатнах с ensure — copy-paste ошибка, постусловием должнен быть 'assert(exp)', т.е. 'ensure(v != Y)'. Собственно семантика такой функции/макроса похожа на assert, но она во-первых всегда присутствует в коде, во-вторых кидает исключение. Возможная проблема здесь — передача дополнительных аргументов.

J>Конечно, тут тоже легко пропустить обработать ошибку, особенно при копи-пейсте, но это уже не будет настолько невидимым, как в варианте два — по крайней мере, код ошибки присутствует во всех вызовах явно, и то, что его не обработали — видно.


Уточни, пожалуйста, про какой вариант идет речь, а то я начинаю запутываться.
Re: api design: return code or exception - formal criteria
От: minorlogic Украина  
Дата: 30.08.09 12:42
Оценка: 25 (3)
Совсем формальным критерием может служить ответ на вопрос
"возможно ли дальнейшее выполнение если ..."

Например

1. в конструкторе обертки над мютексом, мы не смогли создать именованный мютекс. В этом случае лучше кинуть ексепшен, потому что объект повиснет в невалидном состоянии. Если этого не делать , то пользователь класса может и забыть проверить валидное создание объекта.


2. Объект поток не смог открыться и вернул напримр false в методе stream.open(), после этого любая попытка прочесть из него или записать должны кидать эксепшены.


Ну и опять же все зависит от сценария использования.
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[2]: api design: return code or exception - formal criteri
От: Andrew S Россия http://alchemy-lab.com
Дата: 30.08.09 15:03
Оценка:
M>Совсем формальным критерием может служить ответ на вопрос
M>"возможно ли дальнейшее выполнение если ..."

Вот, наконец то

Именно про это я и говорил. Примерно то же самое у меня и стоит первым в списке формальных критериев. Но этого мало, в смысле формализма — получается слишком много степеней свободы. Я попытался ограничить, он все равное есть ощущение, что можно и получше...

Спасибо.


M>Например


M>1. в конструкторе обертки над мютексом, мы не смогли создать именованный мютекс. В этом случае лучше кинуть ексепшен, потому что объект повиснет в невалидном состоянии. Если этого не делать , то пользователь класса может и забыть проверить валидное создание объекта.



M>2. Объект поток не смог открыться и вернул напримр false в методе stream.open(), после этого любая попытка прочесть из него или записать должны кидать эксепшены.



M>Ну и опять же все зависит от сценария использования.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re: api design: return code or exception - formal criteria
От: kvser  
Дата: 31.08.09 08:53
Оценка:
Здравствуйте, Andrew S, Вы писали:

AS>Всем привет.


AS>Ситуация следующая — разрабатывается небольшой слой кросс-платформенной абстракции (io, sync, mt etc). В который раз возник вопрос, что в каких ситуациях использовать — исключения и коды возврата ошибок.


Есть еще вариант с передачей в эту библиотеку параметра — ссылки на пользовательскую функцию обработки ошибок, и пусть пользователь решает, что в этом обработчике написать

У самого аналогичная неясность...
Re[2]: api design: return code or exception - formal criteri
От: Юрий Жмеренецкий ICQ 380412032
Дата: 31.08.09 09:31
Оценка: 5 (1)
Здравствуйте, minorlogic, Вы писали:

M>Совсем формальным критерием может служить ответ на вопрос

M>"возможно ли дальнейшее выполнение если ..."

M>Например


M>1. в конструкторе обертки над мютексом, мы не смогли создать именованный мютекс. В этом случае лучше кинуть ексепшен, потому что объект повиснет в невалидном состоянии. Если этого не делать , то пользователь класса может и забыть проверить валидное создание объекта.


Это несколько "искусственный" критерий — так получится что исключения нужно кидать только из конструкторов и операторов. В более обтекаемой форме этот критеририй звучит как невозможность выполнения постусловий. Но с применением такого подхода есть тонкости — он больше подходит при проектировани "сверху вниз" — от требований к реализации. В случае с api/фреймворком ситуация усложняется т.к. набор требований и сценариев использования как правило недостаточно полон.

M>2. Объект поток не смог открыться и вернул напримр false в методе stream.open()


Наличие метода open у потока — это нарушение SRP. Поток это интерфейс, которым могут обладать различные сушности — вот у них такой метод можут существовать. Либо такая сущность может существовать косвенно — вариант с 'stream open_filestream(const string& name)'. Здесь и потенциальных ошибок меньше.

M>после этого любая попытка прочесть из него или записать должны кидать эксепшены.


Можно просто в предусловия вызовов методов добавить произведенный вызов open.

M>Ну и опять же все зависит от сценария использования.

+1
Re: api design: return code or exception - formal criteria
От: jazzer Россия Skype: enerjazzer
Дата: 31.08.09 12:30
Оценка: 3 (2)
Здравствуйте, Andrew S, Вы писали:

AS>PS Свое мнение по данному вопросу у меня имеется В данном случае нужны именно формальные критерии, чтобы каждый конкретный случае не вызывал одинаковых вопросов.


О, я придумал формальный критерий: всегда должны использоваться исключения, потому что они обеспечивают гарантию непродолжения в случае ошибки, не давая програмисту неявно ошибиться.
Отказ от исключений и работа через коды ошибок (в любом виде, будь то возвращаемые значения или out-параметры, как в Boost.Asio) — это ручная оптимизация, которая должна применяться адекватно, как и любая другая оптимизация, т.е. после профилирования и т.п.
Это на уровне приложения.

На уровне библиотеки: поскольку библиотеке неведомо, как она будет применяться, то она должна предоставить оба интерфейса — один для 99% процентов случаев, давая наиболее чистый код пользователя, а другой — для тех мест, где надо все заоптимизировать (иначе пользователю будет неудобно — ему в этих местах придется пользоваться другой библиотекой).
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[2]: api design: return code or exception - formal criteri
От: Andrew S Россия http://alchemy-lab.com
Дата: 31.08.09 17:51
Оценка:
AS>>PS Свое мнение по данному вопросу у меня имеется В данном случае нужны именно формальные критерии, чтобы каждый конкретный случае не вызывал одинаковых вопросов.

J>О, я придумал формальный критерий: всегда должны использоваться исключения, потому что они обеспечивают гарантию непродолжения в случае ошибки, не давая програмисту неявно ошибиться.


Удобство использования страдает. Пример — тот же File.

J>Отказ от исключений и работа через коды ошибок (в любом виде, будь то возвращаемые значения или out-параметры, как в Boost.Asio) — это ручная оптимизация, которая должна применяться адекватно, как и любая другая оптимизация, т.е. после профилирования и т.п.

J>Это на уровне приложения.

J>На уровне библиотеки: поскольку библиотеке неведомо, как она будет применяться, то она должна предоставить оба интерфейса — один для 99% процентов случаев, давая наиболее чистый код пользователя, а другой — для тех мест, где надо все заоптимизировать (иначе пользователю будет неудобно — ему в этих местах придется пользоваться другой библиотекой).


В результате разработчик будет делать как ему удобнее — не проверять коды. Плюсом придется писать кучу апгрейдов из одного интерфейса в другой...
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.