Проблема там описана излишне обобщенно. Ну вот, например, там написано: «Нередко бывают случаи когда обрывается связь с сетью». Что значит фраза «обрывается связь с сетью»? IP пакет не дошел? Дак это TCP/IP разруливает. Или в течении длительного времени были потеряны все IP пакеты и TCP/IP пришел к выводу, что связи нет? Ну тогда нет смысла долбиться повторно вызывая операцию, делая вид, что мы умнее тех, кто реализовывал TCP/IP. Если реализация TCP/IP считает, что связи нет, то значит её действительно нет.
«иногда сервер перестает отвечать» — ок, это уже ближе к делу. В данном случае мы имеем дело с кривым сервером. Если мы не имеем доступа к самому серверу, то кривость сервера можно попытаться разрулить другой кривостью на стороне клиента. Допустим, при обращении к серверу, когда он лежит вылетает исключение ServerDownException. В этом случае в цикле с повторным выполнением операции надо писать не catch(Exception...), а catch(ServerDownException ...)
То, что вы предлагаете обрабатывать все типы исключений, OutOfMemory, StackOverflow, ThreadAbortException в программе чуть сложнее «Hello, world» называется никак иначе как «из пушки по воробьям».
А где я предлагал обрабатывать OutOfMemory и прочие? Обрабатывать надо только те исключения, которые мы ожидаем. В случае с сетью вообще ничего не надо обрабатывать в backend коде, а UI пусть (если он есть) красивый меседжбокс нарисует. Если очень хочется можно автоконнект в UI сделать. А поддержкой надежности пусть занимается TCP/IP. Если же у нас есть кривой сервер, который сам по себе то работает, то не работает, то для него можно сделать костыль (и ловить там не любой Exception, а конкретный, именно тот, который прилетает, когда сервер обычно недоступен). Но возводить этот кривой костыль в ранг паттерна — это слишком.
Или еще веселый вариант: при обращении по сети удаленный хост недоступен и мы получаем исключение TimeOutException через время t (допустим 30 секунд). Соответственно при применении вышеописанного решения пользователь будет ждать в 5 раз больше — 2.5 минуты.
>> catch (Exception ex)
А если это было исключение, не связанное с сетью? Может это OutOfMemory? Или StackOverflow? Или ThreadAbortException? А может просто программа криво написана? А что если каждый вызов делегата приводит к сайд-эффектам?
Часто требуется, чтобы некотороая абстракция выставляла наружу стратегию синхронизации, которую надо использовать при работе либо с данной абстракцией, либо с некоторыми связанными сущностями. Подобную стратегию синхронизации удобно описывать в виде следующего интерфейса:
public interface IGuard
{
IDisposable Aquire();
}
Могут быть, например, следующие реализации данного интерфейса:
MutexGuard — захватить объект может только один поток
ReaderGuard — при захвате данного гарда предоставляется доступ на чтение
WriterGuard — при захвате данного гарда предоставляется доступ на запись
NotSynchronizingGuarg — гард, который ничего не делает
При этом клиентский код будет выглядеть всегда одинаково. Ему безразлично, какая именно стратегия синхронизации используется:
Что-то я не понимаю Вашей логики. Сначала Вы пишете: «Ну правооблладатель же отбил затраты, почему он еще денег хочет?» А потом пишете, что «а это не важно отбил или не отбил». Эти два аргумента взаимоисключают друг друга. Если пользоваться аргументом, «не важно», то тогда соответствующую часть фразы из первого аргумента надо выкинуть и получится: «почему правообладатель хочет денег?» Вопрос риторический…
Вы сразу можете ответить, что такое «порты транспортных протоколов модели взаимодействия открытых систем» и какие используются вашим ноутбуком или настольным компьютером?
У каждой игры на коробке пишут системные требования: Операционная Система, Звуковая карта, Наличие постоянного подключения к интернету и т.д. Почему народ не возмущается, что пользователям Linux, добросовестно купившим игру, ставят искусственные препятствия в виде Windows?
Это несравнимые вещи.
Во-первых, вокруг lineage2 крутились большие деньги и был существенный стимул её ломать.
Во-вторых, lineage2 — это очень долгоживущий проект и есть смысл делать в него «длительные инвестиции». Нет смысла несколько лет писать полноценный эмулятор сервера, потому что к тому времени, как ты его допишешь, уже выйдет новая версия игры (при условии, что это правильно сделанный сервер)
В-третьих в свободном доступе был украденный официальный сервер lineage2, со всеми скриптами в открытом виде и готовый для реверс-инжиниринга.
Проблема там описана излишне обобщенно. Ну вот, например, там написано: «Нередко бывают случаи когда обрывается связь с сетью». Что значит фраза «обрывается связь с сетью»? IP пакет не дошел? Дак это TCP/IP разруливает. Или в течении длительного времени были потеряны все IP пакеты и TCP/IP пришел к выводу, что связи нет? Ну тогда нет смысла долбиться повторно вызывая операцию, делая вид, что мы умнее тех, кто реализовывал TCP/IP. Если реализация TCP/IP считает, что связи нет, то значит её действительно нет.
«иногда сервер перестает отвечать» — ок, это уже ближе к делу. В данном случае мы имеем дело с кривым сервером. Если мы не имеем доступа к самому серверу, то кривость сервера можно попытаться разрулить другой кривостью на стороне клиента. Допустим, при обращении к серверу, когда он лежит вылетает исключение ServerDownException. В этом случае в цикле с повторным выполнением операции надо писать не catch(Exception...), а catch(ServerDownException ...)
Если надо быстро напедалить говнокода?
А где я предлагал обрабатывать OutOfMemory и прочие? Обрабатывать надо только те исключения, которые мы ожидаем. В случае с сетью вообще ничего не надо обрабатывать в backend коде, а UI пусть (если он есть) красивый меседжбокс нарисует. Если очень хочется можно автоконнект в UI сделать. А поддержкой надежности пусть занимается TCP/IP. Если же у нас есть кривой сервер, который сам по себе то работает, то не работает, то для него можно сделать костыль (и ловить там не любой Exception, а конкретный, именно тот, который прилетает, когда сервер обычно недоступен). Но возводить этот кривой костыль в ранг паттерна — это слишком.
«Что тут думать — прыгать надо!»
А если это было исключение, не связанное с сетью? Может это OutOfMemory? Или StackOverflow? Или ThreadAbortException? А может просто программа криво написана? А что если каждый вызов делегата приводит к сайд-эффектам?
>>throw ex;
Прощай callstack
Часто требуется, чтобы некотороая абстракция выставляла наружу стратегию синхронизации, которую надо использовать при работе либо с данной абстракцией, либо с некоторыми связанными сущностями. Подобную стратегию синхронизации удобно описывать в виде следующего интерфейса:
Могут быть, например, следующие реализации данного интерфейса:
MutexGuard — захватить объект может только один поток
ReaderGuard — при захвате данного гарда предоставляется доступ на чтение
WriterGuard — при захвате данного гарда предоставляется доступ на запись
NotSynchronizingGuarg — гард, который ничего не делает
При этом клиентский код будет выглядеть всегда одинаково. Ему безразлично, какая именно стратегия синхронизации используется:
Это с бампером или без?
Я сразу могу ответить: 42
Во-первых, вокруг lineage2 крутились большие деньги и был существенный стимул её ломать.
Во-вторых, lineage2 — это очень долгоживущий проект и есть смысл делать в него «длительные инвестиции». Нет смысла несколько лет писать полноценный эмулятор сервера, потому что к тому времени, как ты его допишешь, уже выйдет новая версия игры (при условии, что это правильно сделанный сервер)
В-третьих в свободном доступе был украденный официальный сервер lineage2, со всеми скриптами в открытом виде и готовый для реверс-инжиниринга.
Статья 273. Создание, использование и распространение вредоносных программ для ЭВМ