понедельник, 2 сентября 2013 г.

Стримы в .NET

Картинка в visio, в pdf.

Ни у кого не возникало мыслей, что System.IO в наших с вами дот нетах проектировали специально, чтобы максимально запутать бедных программистов? Вот я, например, постоянно путаюсь между этими TextReader-ами, StreamReader-ами, StringReader-ами, классами FileStream и System.IO.File и т.п.. Поэтому я решил сделать небольшую шпаргалку для себя, но она может быть полезна и кому-то еще.

Итак, вот она:

image

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

  1. Непосредственно стримы с данными (FileStream, MemoryStream etc): позволяют работать с файлами, сокетами, памятью как с потоком данных бинарных данных
  2. Декораторы (BufferedStream, GZipStream etc): добавляют поведение стримам, типа буферизации или сжатия.
  3. Адаптеры (текстовые – TextReader/Writer и бинарные – BinaryReader/Writer): служат для упрощения чтения специфических данных из стримов, таких как чтение текстовых данных или выкусывание примитивных данных из бинарного потока.
  4. Фасадный класс с набором фабричных методов System.IO.File (на рисунке не показан)

Классы StreamDecorator и DataStream не существуют, их я выделил чтобы проще было показывать "общность" классов.

Класс File является таким себе фасадом и содержит набор вспомогательных методов для чтения/записи и манипулирования файлами, но в данном случае наиболее важными являются следующие фабричные методы:

image

Встроенная поддержка тестируемости

Обратите внимание, что на диаграмме выше кроме классов, работающих со стримами есть еще пара классов (StringReader и StringWriter), которые работают со строками в памяти.

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

Этому подходу следуют многие классы .NET Framework, как XmlReader/XmlWriter, XElement/XDocument и многие другие. По сути, TextReader – является такой себе стратегией, передача которой через конструктор или метод обеспечит как разделение ответственности между классами, так и требуемую тестируемость.

7 комментариев:

  1. Отличная шпаргалка! Большое спасибо!

    ОтветитьУдалить
  2. > System.IO в наших с вами дот нетах проектировали специально, чтобы максимально запутать бедных программистов

    Это точно!

    ОтветитьУдалить
  3. > > System.IO в наших с вами дот нетах проектировали специально, чтобы максимально запутать бедных программистов

    > Это точно!

    Вы еще на Windows Store Application посмотрите и подумайте над любым нетривиальным сценарием (особенно весело с портированием кода с андроидов/обычных форм).

    ОтветитьУдалить
  4. Да уж, с этими стримами всегда путаешься. Кстати, даже не задумывался чем является оказывается класс File — фабрикой )) Больше всего доставило написание адаптеров на стрим, мне кажется разработчики слегка переборщили, лучше бы обошлись интерфейсами. Думаю, они бы так и сделали, если бы выпала возможность перепроектировать весь .NET заново.

    ОтветитьУдалить
  5. @Алексей: Кстати, класс File является скорее фасадом с набором фабричных методов;)

    ОтветитьУдалить