Потоковые возможности.NET - действительно ли тест CanXXX безопасен?

при реальной необходимости в решении, Вы могли бы интересоваться руткитом DR, который выполняет просто это, http://www.immunityinc.com/downloads/linux_rootkit_source.tbz2 , статья об этом здесь http://www.theregister.co.uk/2008/09/04/linux_rootkit_released/

10
задан stakx supports GoFundMonica 18 May 2013 в 19:14
поделиться

5 ответов

Не зная внутреннего устройства объекта, вы должны предположить, что свойство «flag» слишком изменчиво, чтобы полагаться на него при изменении объекта в несколько потоков.

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

Чтобы уточнить, интерфейс ICollection в .NET имеет свойство IsReadOnly, которое предназначено для использования в качестве индикатора того, поддерживает ли коллекция методы для изменения своего содержимого. Как и потоки, это свойство может измениться в любое время и вызовет выброс InvalidOperationException или NotSupportedException.

Обсуждения вокруг этого обычно сводятся к следующему:

  • Почему вместо интерфейса IReadOnlyCollection нет? NotSupportedException - хорошая идея.
  • Плюсы и минусы наличия "режимов" по сравнению с отдельными конкретными функциями.

Режимы редко бывают полезными, поскольку вы вынуждены иметь дело с более чем одним «набором» поведения; иметь что-то, что может переключать режимы в любое время, значительно хуже, так как ваше приложение теперь также должно иметь дело с более чем одним «набором» поведения. Однако то, что можно разбить что-то на более незаметные функциональные возможности, не обязательно означает, что вы всегда должны это делать, особенно когда разбиение на части никак не снижает сложность поставленной задачи.

Мое личное мнение таково, что вы должны выберите шаблон, наиболее близкий к ментальной модели, которую, по вашему мнению, поймут потребители вашего класса. Если вы единственный потребитель, выберите ту модель, которая вам больше нравится. В случае Stream и ICollection, Я думаю, что их единое определение гораздо ближе к ментальной модели, созданной годами разработки подобных систем. Когда вы говорите о потоках, вы говорите о файловых потоках и потоках памяти, а не о том, доступны ли они для чтения или записи. Точно так же, когда вы говорите о коллекциях, вы редко относитесь к ним с точки зрения «возможности записи».

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

повторно читаемый или записываемый. Точно так же, когда вы говорите о коллекциях, вы редко относитесь к ним с точки зрения «возможности записи».

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

повторно читаемый или записываемый. Точно так же, когда вы говорите о коллекциях, вы редко относитесь к ним с точки зрения «возможности записи».

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

3
ответ дан 4 December 2019 в 01:31
поделиться

Из вашего вопроса и всех последующих комментариев, я предполагаю, что ваша проблема связана с ясность и «правильность» заявленного договора. Заявленный контракт - это то, что находится в онлайн-документации MSDN.

Вы указали, что в документации чего-то не хватает, что заставляет делать предположения о контракте. В частности, поскольку ничего не сказано о непостоянстве свойства читаемости потока,

1
ответ дан 4 December 2019 в 01:31
поделиться

Хорошо, вот еще одна попытка, которая, надеюсь, будет более полезной, чем мой другой ответ ...

К сожалению, MSDN не дает никаких конкретных гарантий относительно того, как CanRead ] / CanWrite / CanSeek может изменяться со временем. Я думаю, было бы разумно предположить, что если поток доступен для чтения, он будет оставаться доступным для чтения до тех пор, пока он не будет закрыт - и то же самое будет справедливо для других свойств

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

Это должно помочь во всех случаях, кроме самых патологических. (Потоки в значительной степени предназначены для того, чтобы вызвать хаос!) Добавление этих требований к существующей документации - это теоретически критическое изменение, хотя я подозреваю, что 99,9% реализаций уже будут им подчиняться. Тем не менее, это, возможно, стоит предложить на Connect .

Теперь, что касается обсуждения между использованием «основанного на возможностях» API (например, Stream ) и интерфейса - основанный на одном ... фундаментальная проблема, которую я вижу, заключается в том, что .NET не предоставляет возможности указать, что переменная должна быть ссылкой на реализацию более чем одного интерфейса. Например, я не могу написать:

public static Foo ReadFoo(IReadable & ISeekable stream)
{
}

Если это допускает это, это может быть разумным - но без этого вы получите взрыв потенциальных интерфейсов:

IReadable
IWritable
ISeekable
IReadWritable
IReadSeekable
IWriteSeekable
IReadWriteSeekable

Я думаю, что это сложнее, чем текущая ситуация - хотя я думаю, что поддержал бы идею только IReadable и IWritable в дополнение к существующим ] Класс Stream . Это упростило бы клиентам декларативное выражение того, что им нужно.

С Контрактами кода API могут объявлять, что они предоставляют и что им требуется, по общему признанию:

public Stream OpenForReading(string name)
{
    Contract.Ensures(Contract.Result<Stream>().CanRead);

    ...
}

public void ReadFrom(Stream stream)
{
    Contract.Requires(stream.CanRead);

    ...
}

I не знаю, насколько статическая проверка может помочь в этом - или как она справляется с тем фактом, что потоки действительно становятся нечитаемыми / не записываемыми, когда они закрываются.

является более запутанным, чем текущая ситуация - хотя я думаю, что поддержал бы идею только IReadable и IWritable в дополнение к существующему Stream учебный класс. Это упростило бы клиентам декларативное выражение того, что им нужно.

С Контрактами кода API могут объявлять, что они предоставляют и что им требуется, по общему признанию:

public Stream OpenForReading(string name)
{
    Contract.Ensures(Contract.Result<Stream>().CanRead);

    ...
}

public void ReadFrom(Stream stream)
{
    Contract.Requires(stream.CanRead);

    ...
}

I не знаю, насколько статическая проверка может помочь в этом - или как она справляется с тем фактом, что потоки действительно становятся нечитаемыми / не записываемыми, когда они закрываются.

сложнее, чем текущая ситуация - хотя я думаю, что поддержал бы идею только IReadable и IWritable в дополнение к существующему Stream учебный класс. Это упростило бы клиентам декларативное выражение того, что им нужно.

С Контрактами кода API могут декларировать, что они предоставляют и что им требуется, по общему признанию:

public Stream OpenForReading(string name)
{
    Contract.Ensures(Contract.Result<Stream>().CanRead);

    ...
}

public void ReadFrom(Stream stream)
{
    Contract.Requires(stream.CanRead);

    ...
}

не знаю, насколько статическая проверка может помочь в этом - или как она справляется с тем фактом, что потоки действительно становятся нечитаемыми / не записываемыми, когда они закрываются.

4
ответ дан 4 December 2019 в 01:31
поделиться

stream.CanRead просто проверяет, имеет ли нижележащий поток возможность чтения. Он ничего не говорит о том, возможно ли фактическое чтение (например, ошибка диска).

Нет необходимости перехватывать NotImplementedException, если вы использовали какой-либо из классов * Reader, поскольку все они поддерживают чтение. Только * Writer будет иметь CanRead = False и выбросить это исключение. Если вы знаете, что поток поддерживает чтение (например, вы использовали StreamReader), IMHO нет необходимости делать дополнительную проверку.

Вам все равно нужно перехватывать исключения, поскольку любая ошибка во время чтения вызовет их (например, ошибка диска).

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

1
ответ дан 4 December 2019 в 01:31
поделиться

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

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

Это интересная философская проблема.

РЕДАКТИРОВАТЬ: Решая вопрос о том, полезны ли CanRead и т. Д., Я считаю, что они все еще полезны - в основном для проверки аргумента. Например, то, что метод принимает поток, который он захочет прочитать в какой-то момент, не означает, что он хочет прочитать его прямо в начале метода, но именно там в идеале должна выполняться проверка аргумента. Диски выходят из строя или заполняются, сети разрушаются и т. Д. Эти вещи действительно происходят в реальной жизни, поэтому вам всегда нужно кодировать таким образом, чтобы выдержать сбой (или сознательно игнорировать проблему, если она не работает). действительно имеет значение).

Если ваш код может действовать правильно в случае сбоя диска, скорее всего, он сможет пережить переход FileStream из режима записи в режим запрета записи.

Если ] Stream действительно имеет твердые контракты, они должны быть невероятно слабыми - нельзя использовать статическую проверку, чтобы доказать, что ваш код всегда будет работать. Лучшее, что вы могли сделать, это доказать, что он поступил правильно перед лицом неудачи.

Я не верю, что Stream скоро изменится. Хотя я, конечно, согласен с тем, что это можно было бы лучше задокументировать, я не Я не принимаю идею, что он «полностью сломан». Он был бы более сломанным, если бы мы не могли использовать его в реальной жизни ... и если бы он мог быть более сломанным, чем сейчас, он логически не полностью . 1253] У меня есть гораздо более серьезные проблемы с фреймворком, такие как относительно плохое состояние API даты / времени. В последних двух версиях они стали намного лучше, но им по-прежнему не хватает многих функций (скажем) Joda Time . Отсутствие встроенных неизменяемых коллекций, плохая поддержка неизменяемости в языке и т. Д. - это реальные проблемы, которые вызывают у меня настоящие головные боли. Я'

0
ответ дан 4 December 2019 в 01:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: