Массовая обертка функций
От: Nikolay_P_I  
Дата: 09.03.10 06:55
Оценка:
Понадобилось тут сделать пуленепробиваемую программу. То есть — что-бы при пропадании сети и файловые операции и операции с базами данных не вываливались по ошибке, а пытались исполнится еще минуту.

Собственно, ЧТО делать — понятно — обернуть все нужное в try/catch со счетчиками и выдавать исключения вида "В течении минуты не удалось".

Не понятно — КАК делать. Поскольку таких операций много — оборачивать каждый File.Move, XmlDocument.Load и dbCommand.ExecuteReader и муторно и ведет к многим ошибкам, свойственным методу copy-paste. С базами данных еще проблема, что простейшие операции оборачивать нет смысла — там всю транзакцию надо обернуть, а такие сложные функции могут одна из другой вызываться.

Вообщем — подскажите, пожалуйста, есть ли какой способ универсально обернуть кучу функций в одинаковый код ?
Re: Массовая обертка функций
От: _FRED_ Черногория
Дата: 09.03.10 07:15
Оценка: 3 (1)
Здравствуйте, 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.
Re: Массовая обертка функций
От: alexsoff Россия  
Дата: 09.03.10 07:19
Оценка:
Здравствуйте, Nikolay_P_I, Вы писали:

N_P>Вообщем — подскажите, пожалуйста, есть ли какой способ универсально обернуть кучу функций в одинаковый код ?

Да, есть уже обсуждалось (в поиск). Можно использовать аспектно-ориентированное программирование, тот же PostSharp здесь.
Re[2]: Массовая обертка функций
От: Nikolay_P_I  
Дата: 09.03.10 09:05
Оценка:
Здравствуйте, alexsoff, Вы писали:

A>Здравствуйте, Nikolay_P_I, Вы писали:


N_P>>Вообщем — подскажите, пожалуйста, есть ли какой способ универсально обернуть кучу функций в одинаковый код ?

A>Да, есть уже обсуждалось (в поиск). Можно использовать аспектно-ориентированное программирование, тот же PostSharp здесь.

Посмотрел. Нашел немного. И если DuckTyping кажется просто "из пушки по воробьям" при том, что с Emit я знаком поверхностно, то платный PostSharp, модифицирующий сборки — совсем брррр...
Re: Массовая обертка функций
От: Undying Россия  
Дата: 09.03.10 09:11
Оценка: :)
Здравствуйте, Nikolay_P_I, Вы писали:

N_P>Вообщем — подскажите, пожалуйста, есть ли какой способ универсально обернуть кучу функций в одинаковый код ?


Такой вариант устроит?

    public static T ExecuteToSuccess<T>(Func<T> action, TimeSpan timeOut)
    {
      DateTime startTime = DateTime.UtcNow;
      do
      {
        try
        {
          return action();
        }
        catch (Exception ex)
        {
          // логгируем исключение
        }
      }
      while (DateTime.UtcNow - startTime < timeOut);
      throw new Exception("Превышен таймаут");
    }

    bool fileExist = ExecuteToSuccess(() => File.Exists(path), TimeSpan.FromMinutes(1));
Re[2]: Массовая обертка функций
От: _FRED_ Черногория
Дата: 09.03.10 09:17
Оценка:
Здравствуйте, 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.
Re[3]: Массовая обертка функций
От: Undying Россия  
Дата: 09.03.10 09:23
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>А если во время выполнения пользователь время переведёт? А если не вперёд, а назад на сутки?


Значит, он сам себе злобный Буратино. Если есть желание можешь заменить эту проверку на более корректный код, принципиально идея от этого никак не изменится.
Re[2]: Массовая обертка функций
От: Nikolay_P_I  
Дата: 09.03.10 09:26
Оценка:
Здравствуйте, _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 достаточно высокоуровнева, что надо открывает и закрывает, наружу не влияет.
Re[3]: Массовая обертка функций
От: alexsoff Россия  
Дата: 09.03.10 09:38
Оценка: +1
Здравствуйте, Nikolay_P_I, Вы писали:

Зачем оборачивать File.Move и логику работы с базами данных на логику повторения? Если скажем File.Move выбросит UnauthorizedAccessException, сколько не вызывай раз, от этого прав у процесса не прибавиться.
На мой взгляд логика повторения важна в особых случаях, например при передачи данных по сети.
Re[3]: Массовая обертка функций
От: _FRED_ Черногория
Дата: 09.03.10 09:54
Оценка:
Здравствуйте, 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.
Re[4]: Массовая обертка функций
От: Nikolay_P_I  
Дата: 09.03.10 10:12
Оценка:
Здравствуйте, alexsoff, Вы писали:

A>Зачем оборачивать File.Move и логику работы с базами данных на логику повторения? Если скажем File.Move выбросит UnauthorizedAccessException, сколько не вызывай раз, от этого прав у процесса не прибавиться.

A>На мой взгляд логика повторения важна в особых случаях, например при передачи данных по сети.

А оно и есть "передачи данных по сети" — в случае, когда File.Move("\\server1\file1", "\\server2\file1");

Учитывать же все типы исключений — это те еще горы работы. Проще так. Потом, если припрет, можно будет и учесть.
Re[4]: Массовая обертка функций
От: Nikolay_P_I  
Дата: 09.03.10 10:22
Оценка:
Здравствуйте, _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 функции (добавить, изменить, удалить), да еще несколько штук на перегрузку. Вот и считайте — сколько придется изменять
Re[2]: Массовая обертка функций
От: Nikolay_P_I  
Дата: 09.03.10 10:24
Оценка:
Здравствуйте, Undying, Вы писали:

N_P>>Вообщем — подскажите, пожалуйста, есть ли какой способ универсально обернуть кучу функций в одинаковый код ?

U>Такой вариант устроит?

Спасибо, попробую применить.
Re[5]: Массовая обертка функций
От: alexsoff Россия  
Дата: 09.03.10 10:33
Оценка:
Здравствуйте, Nikolay_P_I, Вы писали:


N_P>горы работы.

Вот как раз, чтобы не было горы работы и копипаста, придумумали аспектно ориентированное программирование, например с пост шарпом (там кстати есть бесплатная версия), вы описываете аспект с логикой при возникновении в методе исключения и приписываете соответствующий атрибут в нужный метод и все.
Re[5]: Массовая обертка функций
От: _FRED_ Черногория
Дата: 09.03.10 10:45
Оценка:
Здравствуйте, 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>А если во время выполнения пользователь время переведёт? А если не вперёд, а назад на сутки?


айс?
Re[4]: Массовая обертка функций
От: Undying Россия  
Дата: 09.03.10 11:25
Оценка:
Здравствуйте, Аноним, Вы писали:

А>айс?


А Stopwatch точно безопасно использовать?

А то в библиотечке которой я пользуюсь, есть класс 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 можно использовать смело?
Re[5]: Массовая обертка функций
От: Codechanger Россия  
Дата: 09.03.10 11:53
Оценка:
По идее, если функций действительно много, можно использовать такой инструмент, как PolicyInjection из Enterprise library.Опять же, не надо функции корежить.
Re[5]: Массовая обертка функций
От: Аноним  
Дата: 09.03.10 13:27
Оценка: 1 (1)
Здравствуйте, Undying, Вы писали:

U>А Stopwatch точно безопасно использовать?

ну вообще-то проблем не вижу, разве что период времени будет слишком велик для long + нужно учесть, что этот самый период в тиках (во внтуренностях реализации!), а тики равны частоте проца. под тиками здесь подразумеваю не Elapsed.Ticks.


U>А то в библиотечке которой я пользуюсь, есть класс SafeStopwatch с таким шаманством:

U>
U>        public TimeSpan Elapsed
U>        {
U>            get 
U>            {
U>                if (Math.Abs(innerWatch.Elapsed.Ticks - (DateTime.UtcNow - startUTC).Ticks) < 160000)
U>                  return innerWatch.Elapsed;
U>                else
U>                  return (DateTime.UtcNow - startUTC);
U>            }
U>        }
U>


U>Вроде писали библиотечку весьма квалифицированные люди, соответственно это шаманство по идее имеет смысл, но какой не знаю. Или все-таки Stopwatch можно использовать смело?

не ясно откуда взялась эта константа, но предположу что сие для ситуаций где недоступен high-resolution performance counter.
Re[3]: Массовая обертка функций
От: Кондор Россия  
Дата: 09.03.10 13:38
Оценка: -1
_FR>А если во время выполнения пользователь время переведёт? А если не вперёд, а назад на сутки?
Ну и дурак ваш пользователь! Его за такие действия судьба накажет
ДДТ!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.