Что говорит за и что против наличия классов InputStream и OutputStream (и произведения от них класса Stream), если язык позволяет множественное наследование?
Здравствуйте, igna, Вы писали:
I>Что говорит за
Здравый смысл.
I>и что против
Глупость.
I>наличия классов InputStream и OutputStream (и произведения от них класса Stream), если язык позволяет множественное наследование?
И еще нужно выделить InputRandomStream и OutputRandomStream
И иерархия должна быть примерно такой
Здравствуйте, igna, Вы писали:
I>Что говорит за и что против наличия классов InputStream и OutputStream (и произведения от них класса Stream), если язык позволяет множественное наследование?
Аргументация простая: Input/Output — это спецификация для пользователей классов. Функция, получающая InputStream на вход ни при каких условиях не сможет что-то записать в поток. Примерный аналог const-спецификации для параметра.
То же самое справедливо и для Output: отдавая куда OutputStream, мы уверены, что пользователь только запишет что-то туда, но не прочёт.
В общем, ключевое слово — специфицирование.
<< Под музыку: Песни индейцев Боливии. Звуки Анд. Inti Raumi (Chuntunqui) >>
<< При помощи Януса: 1.2.0 alpha rev. 650 >>
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Здравствуйте, igna, Вы писали:
I>Что говорит за и что против наличия классов InputStream и OutputStream (и произведения от них класса Stream), если язык позволяет множественное наследование?
Против — плохой дизайн.
Как правило Stream не гарантирует одновременно возможность чтения и записи в него. Для спецификации этого добаляют методы типа: IsReadable/IsWritable. Добавление метода IsReadable в InputStream достаточно нелепое решение. Однако, недобавление такового ведет к нарушению контракта, т.к. теоритически доступный для чтения поток, может стать недоступным практически.
Здравствуйте, igna, Вы писали:
I>Что говорит за и что против наличия классов InputStream и OutputStream (и произведения от них класса Stream), если язык позволяет множественное наследование?
Создавать Stream как расширение InputStream и OutputStream — безумие.
1) В одних задачах нужен объект отвечающий только за чтение, а в других задачах нужен объект отвечающий только за запись. Каков смысл создавать третий объект умеющий и читать и писать одновременно если можно вместо него использовать первые два объекта, которые и уже есть?
2) Есть паттерн проектирования Carrier-Rider-Mapper.
Carrier — носитель информации.
Rider — это либо считыватель (Reader) либо записыватель (Writer) информации из/в Carrier.
Mapper — это либо сканер (Scanner) либо форматтер (Formatter) — преобразователи форматов данных.
Может быть много разных сканеров, каждый из которых соединяется по заранее установленному интерфейсу со считывателем.
Может быть много разных форматтеров, каждый из которых соединяется по заранее установленному интерфейсу с записывателем.
Может быть много разных носителей информации, каждый из которых предлагает одни и теже считыватели и записыватели информации из/в себя.
Из-за того, что интерфейсы подключения Reader->-Scanner и Writer-<-Formatter жестко определены, можно использовать разные мапперы с разными райдерами — это победа над геометрической прогрессией количества классов объектов, которые были бы нужны в противном случае. Поэтому объединение классов Reader и Writer в один класс — безумство.
In terms of design patterns, the Carrier-Rider-Mapper pattern solves the problem of flexible and convenient access to a data carrier, however it is implemented. It can be regarded to consist of two simpler and very basic design patterns: the separation of one object into several objects to allow many-to-one relations; and the separation of one object into two objects to allow for independent extensibility:
Split an abstraction into two interfaces if several clients may access an instance simultaneously, and if independent state may have to be managed for every client.
Split an abstraction into two interfaces, if it needs to be extended independently in two different dimensions.
The Carrier-Rider-Mapper separation goes back to a research project ["Insight ETHOS: On Object-Orientation in Operating Systems"; Clemens Szyperski; vdf, Zьrich, 1992, ISBN 3 7281 1948 2] predating BlackBox. This project used several design patterns and design rules (e.g., avoidance of implementation inheritance) that are also described in Design Patterns. In the Design Patterns terminology, a Rider-Mapper combination (or Carrier-Mapper combination if there is no rider) forms a bridge pattern.
Здравствуйте, Сергей Губанов, Вы писали:
СГ>2) Есть паттерн проектирования Carrier-Rider-Mapper. СГ>Carrier — носитель информации. СГ>Rider — это либо считыватель (Reader) либо записыватель (Writer) информации из/в Carrier. СГ>Mapper — это либо сканер (Scanner) либо форматтер (Formatter) — преобразователи форматов данных. СГ>
СГ>Может быть много разных сканеров, каждый из которых соединяется по заранее установленному интерфейсу со считывателем. СГ>Может быть много разных форматтеров, каждый из которых соединяется по заранее установленному интерфейсу с записывателем. СГ>Может быть много разных носителей информации, каждый из которых предлагает одни и теже считыватели и записыватели информации из/в себя.
Интересная мысль. Было бы любопытно глянуть на список методов каждого класса.
В этом примере мапперы хоть и коннектятся к самой модели, но работают с ней посредством её райдеров. В принципе, более универсальным было бы сделать мапперы коннектящиеся только к райдерам.
Вот объясни мне пожалуйста почему создатели черной коробки привязали RandomInputStream и RandomOutputStrem к файлам?
Особенно смешно это выглядит на фоне твоих громких заявлений о безумном дизайне и развязки модели и пользователей.
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Сергей Губанов wrote: > K> Интересная мысль. Было бы любопытно глянуть на список методов каждого > класса. > Фрагменты интерфейсов модулей BlackBox > <http://www.oberon.ch/blackbox.html> (работа с документами):
В морг.
Во-первых, нет разделения между типами входных данных (покажите мне
SetPos на сокете).
Во-вторых, дизайн записывальщиков/читальщиков — неудачный. Как мне
установить кодировку, например?
Тут лучше всего посмотреть на Java. Для чтения там есть потоки
ввода-вывода, причем их можно комбинировать.
То есть можно произвольным образом комбинировать потоки, получая при это
огромную гибкость. Потоки при этом работают на уровне бинарных данных,
без какой-либо их интерпретации.
Дальше идут уже манипуляторы, которые работают над потоками. Например,
InputStreamReader:
Как показывает практика, эта абстракция замечательно подходит для
большинства случаев.
Однако, в дизайне Java-потоков тоже есть проблемы.
В интерфейсе потока присутствуют методы reset, mark, available и т.п. Я
бы заменил их одним методом "Object getSource()", который бы возвращал
объект "источник" (кто сказал слово "generic"?). У источника можно было
бы спрашивать интерфейсы: Seeakable (для источников произвольного
доступа), Lockable (для поддерживающих блокировку объектов),
MemMapCapable (для файлов, которые можно отображать в память) и т.п.
Здравствуйте, WolfHound, Вы писали:
WH>Вот объясни мне пожалуйста почему создатели черной коробки привязали RandomInputStream и RandomOutputStrem к файлам?
Что? Где Вы там увидели RandomInputStream и RandomOutputStrem?
Здравствуйте, Сергей Губанов, Вы писали:
WH>>Вот объясни мне пожалуйста почему создатели черной коробки привязали RandomInputStream и RandomOutputStrem к файлам?
СГ>Что? Где Вы там увидели RandomInputStream и RandomOutputStrem?
Сравни это с тем что я процитировал
interface IInputStream
{
int ReadBytes(byte[] buf, int start, int count);
}
interface IOutputStream
{
int WriteBytes(byte[] buf, int start, int count);
}
interface IInputRandomStream : IInputStream
{
long Position { get; set; }
}
interface IOutputRandomStream : IOutputStream
{
long Position { get; set; }
}
ReadByte/WriteByte и eof избыточны
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Сергей Губанов wrote: > C>Во-первых, нет разделения между типами входных данных (покажите мне > SetPos на сокете). > Где Вы там увидели сокеты?
Это я к тому, что эта архитектура ввода-вывода не подходит для других
целей кроме чтения файлов. А вот потоки прекрасно подходят.
Здравствуйте, Cyberax, Вы писали:
>> Где Вы там увидели сокеты?
C>Это я к тому, что эта архитектура ввода-вывода не подходит для других C>целей кроме чтения файлов.
Архитектура говорите не подходит, ну-ну...
C> А вот потоки прекрасно подходят.
Здравствуйте, Сергей Губанов, Вы писали:
СГ>И что мешает написать в точности тоже самое для моего примера?
Вот и я спрашиваю что мешало великим гениям создавшим черную коробку правильно спроектировать интерфейсы системы?
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, Сергей Губанов, Вы писали:
СГ>Архитектура говорите не подходит, ну-ну...
Именно. Тебе пора наконец понять что оберон создавали простые смертные люди которые тоже могут ошибаться. И в данном случае они ошиблись.
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн