Понадобилось тут сделать пуленепробиваемую программу. То есть — что-бы при пропадании сети и файловые операции и операции с базами данных не вываливались по ошибке, а пытались исполнится еще минуту.
Собственно, ЧТО делать — понятно — обернуть все нужное в try/catch со счетчиками и выдавать исключения вида "В течении минуты не удалось".
Не понятно — КАК делать. Поскольку таких операций много — оборачивать каждый File.Move, XmlDocument.Load и dbCommand.ExecuteReader и муторно и ведет к многим ошибкам, свойственным методу copy-paste. С базами данных еще проблема, что простейшие операции оборачивать нет смысла — там всю транзакцию надо обернуть, а такие сложные функции могут одна из другой вызываться.
Вообщем — подскажите, пожалуйста, есть ли какой способ универсально обернуть кучу функций в одинаковый код ?
Здравствуйте, Nikolay_P_I, Вы писали:
N_P>Понадобилось тут сделать пуленепробиваемую программу. То есть — что-бы при пропадании сети и файловые операции и операции с базами данных не вываливались по ошибке, а пытались исполнится еще минуту. N_P>Собственно, ЧТО делать — понятно — обернуть все нужное в try/catch со счетчиками и выдавать исключения вида "В течении минуты не удалось". N_P>Не понятно — КАК делать. Поскольку таких операций много
Что значит "много"? Сотни? Тысячи?
N_P> — оборачивать каждый File.Move, XmlDocument.Load и dbCommand.ExecuteReader и муторно и ведет к многим ошибкам, свойственным методу copy-paste.
А не приведёт ли к ещё более странным ошибкам "массовая обёртка" без оглядки на то, что функция делает? Можно посмотреть на код, которым предполагается оборачивать вызовы?
N_P>С базами данных еще проблема, что простейшие операции оборачивать нет смысла — там всю транзакцию надо обернуть, а такие сложные функции могут одна из другой вызываться.
А с файлами такого разве быть не может?
N_P>Вообщем — подскажите, пожалуйста, есть ли какой способ универсально обернуть кучу функций в одинаковый код ?
Уверены ли вы, что "универсально обернуть" будет лучше? Чем именно (каким кодом) предполагается оборачивать?
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Nikolay_P_I, Вы писали:
N_P>Вообщем — подскажите, пожалуйста, есть ли какой способ универсально обернуть кучу функций в одинаковый код ?
Да, есть уже обсуждалось (в поиск). Можно использовать аспектно-ориентированное программирование, тот же PostSharp здесь.
Здравствуйте, alexsoff, Вы писали:
A>Здравствуйте, Nikolay_P_I, Вы писали:
N_P>>Вообщем — подскажите, пожалуйста, есть ли какой способ универсально обернуть кучу функций в одинаковый код ? A>Да, есть уже обсуждалось (в поиск). Можно использовать аспектно-ориентированное программирование, тот же PostSharp здесь.
Посмотрел. Нашел немного. И если DuckTyping кажется просто "из пушки по воробьям" при том, что с Emit я знаком поверхностно, то платный PostSharp, модифицирующий сборки — совсем брррр...
Здравствуйте, Undying, Вы писали:
N_P>>Вообщем — подскажите, пожалуйста, есть ли какой способ универсально обернуть кучу функций в одинаковый код ? U>Такой вариант устроит?
U> DateTime startTime = DateTime.UtcNow;
U> do
U> {
U> }
U> while (DateTime.UtcNow - startTime < timeOut);
А если во время выполнения пользователь время переведёт? А если не вперёд, а назад на сутки?
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>А если во время выполнения пользователь время переведёт? А если не вперёд, а назад на сутки?
Значит, он сам себе злобный Буратино. Если есть желание можешь заменить эту проверку на более корректный код, принципиально идея от этого никак не изменится.
Здравствуйте, _FRED_, Вы писали:
N_P>>Понадобилось тут сделать пуленепробиваемую программу. То есть — что-бы при пропадании сети и файловые операции и операции с базами данных не вываливались по ошибке, а пытались исполнится еще минуту. N_P>>Собственно, ЧТО делать — понятно — обернуть все нужное в try/catch со счетчиками и выдавать исключения вида "В течении минуты не удалось". N_P>>Не понятно — КАК делать. Поскольку таких операций много
_FR>Что значит "много"? Сотни? Тысячи?
Элементарных вроде File.Move — десяток-другой всего. С учетом БД, с учетом всяких .BeginTransaction — полсотни будет.
В этом варианте проблемы 2 — 1) куча кода в библиотеках, где его не обернешь и 2) оборачивать операцию высокого уровня "Получить данные из БД" мне кажется грамотнее, чем оборачивать "начать транзакцию в БД".
N_P>> — оборачивать каждый File.Move, XmlDocument.Load и dbCommand.ExecuteReader и муторно и ведет к многим ошибкам, свойственным методу copy-paste.
_FR>А не приведёт ли к ещё более странным ошибкам "массовая обёртка" без оглядки на то, что функция делает? Можно посмотреть на код, которым предполагается оборачивать вызовы?
Ну, СОВСЕМ не смотреть внутрь — моветон, но для кучи функций вида "получить из БД List<чего-то>" предполагается что-то типа
Int32 errorcount = 100;
while(true)
{
try
{
return GetDataFromBD(args);
}
catch(Exception exc)
{
errorcount--;
if (errorcount==0)
{
throw new Exception("Операция GetDataFromBD не удалась за 100 попыток по причине " + exc.Message);
}
Thread.Sleep(1000);
}
}
С поправкой на окультуривание, настройки числа попыток и пр.
GetDataFromBD достаточно высокоуровнева, что надо открывает и закрывает, наружу не влияет.
Зачем оборачивать File.Move и логику работы с базами данных на логику повторения? Если скажем File.Move выбросит UnauthorizedAccessException, сколько не вызывай раз, от этого прав у процесса не прибавиться.
На мой взгляд логика повторения важна в особых случаях, например при передачи данных по сети.
Здравствуйте, Nikolay_P_I, Вы писали:
N_P>>>Не понятно — КАК делать. Поскольку таких операций много _FR>>Что значит "много"? Сотни? Тысячи?
N_P>Элементарных вроде File.Move — десяток-другой всего. С учетом БД, с учетом всяких .BeginTransaction — полсотни будет.
Ерунда. Если придумать принцип (который в любом случае придумывать придётся), то применить его в ручную займёт несколько часов.
N_P>В этом варианте проблемы 2 — 1) куча кода в библиотеках, где его не обернешь и 2) оборачивать операцию высокого уровня "Получить данные из БД" мне кажется грамотнее, чем оборачивать "начать транзакцию в БД".
Естественно. О том и речь — сначала решить что и как оборачивать. Для этого придётся ещё проанализировать вызывающий код. Основное время потратится где-то тут.
N_P>>> — оборачивать каждый File.Move, XmlDocument.Load и dbCommand.ExecuteReader и муторно и ведет к многим ошибкам, свойственным методу copy-paste. _FR>>А не приведёт ли к ещё более странным ошибкам "массовая обёртка" без оглядки на то, что функция делает? Можно посмотреть на код, которым предполагается оборачивать вызовы? N_P>Ну, СОВСЕМ не смотреть внутрь — моветон, но для кучи функций вида "получить из БД List<чего-то>" предполагается что-то типа
Написать один (или несколько, если понадобится) методов, которые что-то такое делают и применить их несколько десятков раз вручную будет быстрее, чем прикручивание какой-либо автоматизации. Это если надо сделать "по-быстрому".
Если надо сделать "по-хорошему" то вопросов намного больше. Например, если мы имеем дело с серверным кодом и будем на нём ждать до минуты, а клиент подключается с таймаутом в десять секунд, то как быть? В общем, если нужно сделать правильно, спрашивать нужно в архитектуре.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, alexsoff, Вы писали:
A>Зачем оборачивать File.Move и логику работы с базами данных на логику повторения? Если скажем File.Move выбросит UnauthorizedAccessException, сколько не вызывай раз, от этого прав у процесса не прибавиться. A>На мой взгляд логика повторения важна в особых случаях, например при передачи данных по сети.
А оно и есть "передачи данных по сети" — в случае, когда File.Move("\\server1\file1", "\\server2\file1");
Учитывать же все типы исключений — это те еще горы работы. Проще так. Потом, если припрет, можно будет и учесть.
Здравствуйте, _FRED_, Вы писали:
N_P>>>>Не понятно — КАК делать. Поскольку таких операций много _FR>>>Что значит "много"? Сотни? Тысячи? N_P>>Элементарных вроде File.Move — десяток-другой всего. С учетом БД, с учетом всяких .BeginTransaction — полсотни будет.
_FR>Ерунда. Если придумать принцип (который в любом случае придумывать придётся), то применить его в ручную займёт несколько часов.
Не понял ? В чем "ерунда" и о чем "принцип" ?
Применить в ручную — Copy-Paste приведенного мной кода дал ДИКОЕ количество ошибок, хотелось-бы их избежать.
N_P>>В этом варианте проблемы 2 — 1) куча кода в библиотеках, где его не обернешь и 2) оборачивать операцию высокого уровня "Получить данные из БД" мне кажется грамотнее, чем оборачивать "начать транзакцию в БД".
_FR>Естественно. О том и речь — сначала решить что и как оборачивать. Для этого придётся ещё проанализировать вызывающий код. Основное время потратится где-то тут.
Нет, функции уже поделены — то что высокоуровневое, торчит из класса работы с БД, то что низкоуровневое — внутри. С файлами — похоже.
N_P>>>> — оборачивать каждый File.Move, XmlDocument.Load и dbCommand.ExecuteReader и муторно и ведет к многим ошибкам, свойственным методу copy-paste. _FR>>>А не приведёт ли к ещё более странным ошибкам "массовая обёртка" без оглядки на то, что функция делает? Можно посмотреть на код, которым предполагается оборачивать вызовы? N_P>>Ну, СОВСЕМ не смотреть внутрь — моветон, но для кучи функций вида "получить из БД List<чего-то>" предполагается что-то типа
_FR>Написать один (или несколько, если понадобится) методов, которые что-то такое делают и применить их несколько десятков раз вручную будет быстрее, чем прикручивание какой-либо автоматизации. Это если надо сделать "по-быстрому".
Нет. Высокоуровневых функций НАМНОГО больше низкоуровневых — вот пример — в БД 5 таблиц, на каждую — 3 функции (добавить, изменить, удалить), да еще несколько штук на перегрузку. Вот и считайте — сколько придется изменять
Здравствуйте, Undying, Вы писали:
N_P>>Вообщем — подскажите, пожалуйста, есть ли какой способ универсально обернуть кучу функций в одинаковый код ? U>Такой вариант устроит?
N_P>горы работы.
Вот как раз, чтобы не было горы работы и копипаста, придумумали аспектно ориентированное программирование, например с пост шарпом (там кстати есть бесплатная версия), вы описываете аспект с логикой при возникновении в методе исключения и приписываете соответствующий атрибут в нужный метод и все.
Здравствуйте, Nikolay_P_I, Вы писали:
N_P>>>>>Не понятно — КАК делать. Поскольку таких операций много _FR>>>>Что значит "много"? Сотни? Тысячи? N_P>>>Элементарных вроде File.Move — десяток-другой всего. С учетом БД, с учетом всяких .BeginTransaction — полсотни будет.
_FR>>Ерунда. Если придумать принцип (который в любом случае придумывать придётся), то применить его в ручную займёт несколько часов.
N_P>Не понял ? В чем "ерунда"
В том, что для этого не требуется "Массовая обертка функций" и всё можно сделать вручную.
N_P>и о чем "принцип" ?
О том, как и какой метод оборачивать. Если это уже извесно, то пройтись вручную будет быстрее и безболезненей.
N_P>Применить в ручную — Copy-Paste приведенного мной кода дал ДИКОЕ количество ошибок, хотелось-бы их избежать.
Какого рода ошибки? Откуда они взялись?
Help will always be given at Hogwarts to those who ask for it.
Re[3]: Массовая обертка функций
От:
Аноним
Дата:
09.03.10 11:06
Оценка:
Здравствуйте, _FRED_, Вы писали:
_FR>
U>> var sw = Stopwatch.StartNew();
U>> do
U>> {
U>> }
U>> while (sw.Elapsed < timeOut);
_FR>
_FR>А если во время выполнения пользователь время переведёт? А если не вперёд, а назад на сутки?
А то в библиотечке которой я пользуюсь, есть класс SafeStopwatch с таким шаманством:
public TimeSpan Elapsed
{
get
{
if (Math.Abs(innerWatch.Elapsed.Ticks - (DateTime.UtcNow - startUTC).Ticks) < 160000)
return innerWatch.Elapsed;
else
return (DateTime.UtcNow - startUTC);
}
}
Вроде писали библиотечку весьма квалифицированные люди, соответственно это шаманство по идее имеет смысл, но какой не знаю. Или все-таки Stopwatch можно использовать смело?
По идее, если функций действительно много, можно использовать такой инструмент, как PolicyInjection из Enterprise library.Опять же, не надо функции корежить.
Здравствуйте, Undying, Вы писали:
U>А Stopwatch точно безопасно использовать?
ну вообще-то проблем не вижу, разве что период времени будет слишком велик для long + нужно учесть, что этот самый период в тиках (во внтуренностях реализации!), а тики равны частоте проца. под тиками здесь подразумеваю не Elapsed.Ticks.
U>А то в библиотечке которой я пользуюсь, есть класс SafeStopwatch с таким шаманством: U>
U>Вроде писали библиотечку весьма квалифицированные люди, соответственно это шаманство по идее имеет смысл, но какой не знаю. Или все-таки Stopwatch можно использовать смело?
не ясно откуда взялась эта константа, но предположу что сие для ситуаций где недоступен high-resolution performance counter.
_FR>А если во время выполнения пользователь время переведёт? А если не вперёд, а назад на сутки?
Ну и дурак ваш пользователь! Его за такие действия судьба накажет