Re[4]: Заметка: Компонентная философия и реализация
От: vdimas Россия  
Дата: 05.11.12 09:57
Оценка:
Здравствуйте, AlexRK, Вы писали:


V>>Это не просто COM. Это философия сродни реактивному/агентному программированию, только с помощью КОП. То бишь, это парадигма над парадигмой компонент. )))

V>>На самом деле единственно разумное зерно — это специальные связи компонент. Я когда-то назвал такое "пинами" в аналогичных рассуждениях: http://www.rsdn.ru/forum/philosophy/1676773.1
Автор: vdimas
Дата: 14.02.06


ARK>Спасибо, очень интересная точка зрения. Мне нравится, концептуально очень изящно. Может быть есть какие-то реализации или языки с подобной философией?


Из имеющихся подобных языков — только для разработки аппаратуры. ))
Можно взять Немерле и на нем попробовать сделать подобную библиотеку для софта.
Re[11]: Заметка: Компонентная философия и реализация
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 05.11.12 11:35
Оценка:
Здравствуйте, AlexCab, Вы писали:

AC>Скромно напоминаю: мы обсуждаем компонентную модель(и средства создания компонентов) хоть и похожую на COModel, но всё таки отличающеюся от неё.


Ну так вот отличия именно модели ты так и не смог продемонстрировать, все время скатываешься с модели на детали реализации типа ключевых слов в языке или токенов методов.

AC>>>QueryInterface делает именно запрос, он не выполняет приведение.

AVK>>В чем разница?
AC>Как разница между словами "получить" и "преобразовать". Как бы, похоже, но не то.

Это все софистика, а не ответ на вопрос.

AC>>>А мои мифические connect/disconnect _не_ делают ни запроса, ни приведения. Они делают соединение/разъединение интерфейса.

AVK>>В чем разница?
AC>Например, в процессе: преобразование интерфейса сложнее(состоит из большего числа логических действий) чем получение интерфейса, а подключение интерфейса сложнее чем преобразование.

Это не ответ на вопрос, а игра словами.

AC>Или например, в исходном и конечном состоянии: в первом случае изначально есть один интерфейс, в конце другой; во втором изначально нет ни одного интерфейса(есть только GUID интерфейса), в конце есть интерфейс(в виде таблицы методов); в третьем(для connect) изначально есть имя интерфейса, имя/хендл компонента и первая(экспортируемая) часть реализации интерфейса, в конце есть вторая(импортирования) часть реализации интерфейса, плюс выполнена функция-событие подключения.


Это — детали реализации. К модели это не относится.

AVK>>В момент JIT компиляции она это делает, а не при непосредственном выполнении. Причем уже в IL фигурирует токен метода, а не его метаданные. Метаданные хранятся отдельно. И не читайте русскую википедию, она гадость.

AC>Токен проверяется при каждом вызове?

Я непонятно написал? "В момент JIT компиляции она это делает". При выполнении там обычный статический или виртуальный вызов, как в обычном нативном языке типа С++.
... << RSDN@Home 1.2.0 alpha 5 rev. 66 on Windows 8 6.2.9200.0>>
AVK Blog
Re[12]: Заметка: Компонентная философия и реализация
От: AlexCab LinkedIn
Дата: 05.11.12 12:31
Оценка:
AC>>Скромно напоминаю: мы обсуждаем компонентную модель(и средства создания компонентов) хоть и похожую на COModel, но всё таки отличающеюся от неё.
AVK>Ну так вот отличия именно модели ты так и не смог продемонстрировать, все время скатываешься с модели на детали реализации типа ключевых слов в языке или токенов методов.
AC>>Или например, в исходном и конечном состоянии: в первом случае изначально есть один интерфейс, в конце другой; во втором изначально нет ни одного интерфейса(есть только GUID интерфейса), в конце есть интерфейс(в виде таблицы методов); в третьем(для connect) изначально есть имя интерфейса, имя/хендл компонента и первая(экспортируемая) часть реализации интерфейса, в конце есть вторая(импортирования) часть реализации интерфейса, плюс выполнена функция-событие подключения.
AVK>Это — детали реализации. К модели это не относится.
Где заканчивается модель, и начинаются детали реализации?
Или опиши модель, а я опишу отличия.
Между тем,что я думаю,тем,что я хочу сказать,тем,что я,как мне кажется,говорю,и тем,что вы хотите услышать,тем,что как вам кажется,вы слышите,тем,что вы понимаете,стоит десять вариантов возникновения непонимания.Но всё-таки давайте попробуем...(Э.Уэллс)
Re[13]: Заметка: Компонентная философия и реализация
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 05.11.12 12:35
Оценка:
Здравствуйте, AlexCab, Вы писали:

AC>Где заканчивается модель, и начинаются детали реализации?


А ты сам не в состоянии границу провести? Модель это обязательные контракты компонентной инфраструктуры, идентичные в разных реализациях. То, что от реализации к реализации меняется моделью не является.
... << RSDN@Home 1.2.0 alpha 5 rev. 66 on Windows 8 6.2.9200.0>>
AVK Blog
Re[14]: Заметка: Компонентная философия и реализация
От: AlexCab LinkedIn
Дата: 05.11.12 13:36
Оценка:
AC>>Где заканчивается модель, и начинаются детали реализации?
AVK>А ты сам не в состоянии границу провести? Модель это обязательные контракты компонентной инфраструктуры, идентичные в разных реализациях. То, что от реализации к реализации меняется моделью не является.
Ok, для обсуждаемой модели компонентно-ориентированного программирования, навскидку обязательны(т.е. без этого модель(а точнее любую её реализацию) невозможно будет использовать в полной мере, для разработки ПО, описанными в заметке способами):
1)Компоненты имеющие состояние и поведение.
2)Сборки.
3)Интерфейсы, в таком виде как они описаны выше.
4)Потоки внутри компонентов(упоминашиеся выше).
Остальное, описанное в заметке, будучи реализованным как-то иначе, думаю, существенно не повлияет на основные возможности модели(сборка из компонентов, агентное/реактивное программирование etc.).
Между тем,что я думаю,тем,что я хочу сказать,тем,что я,как мне кажется,говорю,и тем,что вы хотите услышать,тем,что как вам кажется,вы слышите,тем,что вы понимаете,стоит десять вариантов возникновения непонимания.Но всё-таки давайте попробуем...(Э.Уэллс)
Re[15]: Заметка: Компонентная философия и реализация
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 05.11.12 13:56
Оценка:
Здравствуйте, AlexCab, Вы писали:

AC>1)Компоненты имеющие состояние и поведение.

AC>2)Сборки.
AC>3)Интерфейсы, в таком виде как они описаны выше.
AC>4)Потоки внутри компонентов(упоминашиеся выше).

Ну то есть берем дотнет, добавляем к нему простенький фреймворк (в идеале спецязык) и средства реактивного программирования и получаем то что ты хочешь. И это все? В чем новизна идеи?

AC>Остальное, описанное в заметке, будучи реализованным как-то иначе, думаю, существенно не повлияет на основные возможности модели(сборка из компонентов, агентное/реактивное программирование etc.).


Потоки внутри компонентов это и есть вариация на тему реактивного программирования.
... << RSDN@Home 1.2.0 alpha 5 rev. 66 on Windows 8 6.2.9200.0>>
AVK Blog
Re[16]: Заметка: Компонентная философия и реализация
От: AlexCab LinkedIn
Дата: 05.11.12 15:06
Оценка:
AVK>Ну то есть берем дотнет, добавляем к нему простенький фреймворк (в идеале спецязык) и средства реактивного программирования и получаем то что ты хочешь. И это все?
Ну да! Только не .NET, а JVM и, не фреймворк, а полноценный ЯП(например как Scala) с встроенными средствами для реактивного программирования.
AVK> В чем новизна идеи?
В собственно подходе(описанному во второй главе заметки) к программированию в целом, и к созданию и использованию компонентов в частности. А ЯП и рантайм нужны чтобы, для программиста, реализация этого подхода на практике была максимально комфортной и эффективной.
AVK>Потоки внутри компонентов это и есть вариация на тему реактивного программирования.
Нет, эти потоки (выполнения) для агентного программирования. Для реактивного — потоки значений с возможностью организации очередей между компонентами.
Между тем,что я думаю,тем,что я хочу сказать,тем,что я,как мне кажется,говорю,и тем,что вы хотите услышать,тем,что как вам кажется,вы слышите,тем,что вы понимаете,стоит десять вариантов возникновения непонимания.Но всё-таки давайте попробуем...(Э.Уэллс)
Re[10]: Заметка: Компонентная философия и реализация
От: vdimas Россия  
Дата: 05.11.12 16:10
Оценка: 4 (1)
Здравствуйте, AlexCab, Вы писали:

AC>1)Грубо говоря(так как это может быть реализовано и без всяких таблиц методов), подключающийся компонент передаёт другому таблицу экспортируемых методов и получает от другого таблицу импортируемых(экспортируемых другим) методов, т.е. компоненты обмениваются таблицами(а не один передаёт другому как в COM).


Сократи содержимое обоих таблиц до 1-го вхождения, и получишь базовую модель для реактивного программирования. )

То бишь, в одном интерфейсе будет всего один сигнал. Итого, у компонента будет не много сигналов на каждый интерфейс, а много интерфейсов, где в каждом всего 1 сигнал. Но! Подобные интерфейсы должны быть в виде экземпляров, а не в виде уникальных контрактов... Ууупс!!! )) Поэтому модель контрактов современного ООП на реактивное программирование ни разу не ложится — слишком высока связанность для этого.

Тут правильно сказали, что можно смотреть идеологию DirectShow. Что удобно в такой архитектуре — развязываются руки в относительно подключений компонент друг к другу. Почему? Из-за того, что кол-во сигналов обычно невелико, т.е., имея в базисе сигналы (т.е. ориентируя архитектуру на сигналы, вернее на топологию их прохождения), мы получаем очень и очень низкую связанность компонент при всё еще существующей типобезопасности.
Re[8]: Заметка: Компонентная философия и реализация
От: vdimas Россия  
Дата: 05.11.12 17:18
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Притом, что это семантический эквивалент QueryInterface.


Не совсем. Это семантический эквивалент на механику вокруг IConnectionPoint/IConnectionPointContainer, а так же их IDispatch-эквивалент. Это аналог джавовских листенеров событий. Всё это "красиво" встроено в язык VB/VBA, но в С++, Джаве и дотнете аналогичное только ручками.


AC>> Оно лишь, даёт возможность скрыть/показать часть полей объекта.


AVK>Приведение к интерфейсу к полям вообще никакого отношения не имеет — интерфейс поля не содержит, только методы. И операция приведения семантически означает запрос определенного контракта с контролем его наличия. Т.е. ровно то же самое, что делает QueryInterface и твои мифические connect/disconnect. Причем этот вариант существенно более гибок, так как не требует реактивности в обязательном порядке (но при этом вполне позволяет ее реализовать при желании — можешь посмотреть на Reactive Extensions в дотнете для примера).


Дык, реактивность требует некоторой поддержки. Например, VB превращает листенеры в нечто гораздо более "реактивное" за счет упрятанной в язык всей механики. В итоге, можно оперировать контрактами обратного вызова "поэлементно", т.е. так, как будто бы каждый callback независим от других.


AC>>К тому же каждый будет реализовывать это всё по своему, в общем будет адъ и погибель, и компонентное будущее та и не наступит.

AVK>Проснись, все что ты хочешь уже есть.

Оно есть в ООП, ес-но. Но нет поддержки в мейнстриме.
Re[11]: Заметка: Компонентная философия и реализация
От: AlexCab LinkedIn
Дата: 05.11.12 17:27
Оценка:
Здравствуйте, vdimas, Вы писали:
AC>>1)Грубо говоря(так как это может быть реализовано и без всяких таблиц методов), подключающийся компонент передаёт другому таблицу экспортируемых методов и получает от другого таблицу импортируемых(экспортируемых другим) методов, т.е. компоненты обмениваются таблицами(а не один передаёт другому как в COM).
V>Сократи содержимое обоих таблиц до 1-го вхождения, и получишь базовую модель для реактивного программирования. )
Можно определить интерфейс с одним импортируемым и одним экспортируемым методом, но, думаю, запрещать определять больше методов не очень хорошая идея.
V>То бишь, в одном интерфейсе будет всего один сигнал. Итого, у компонента будет не много сигналов на каждый интерфейс, а много интерфейсов, где в каждом всего 1 сигнал. Но! Подобные интерфейсы должны быть в виде экземпляров, а не в виде уникальных контрактов... Ууупс!!! ))
Много интерфейсов — плохо. Это почти тоже самое что ООП, в котором много методов. В КОП, одна из главных задач интерфейсов — упорядочивание и упрощение связей компонентов(а значит и системы в целом). Что достигается объединением логически связынных методов и полей в один интерфейс, и запретом доступа к ним, если компонент не поддерживает данный интерфейс и интерфейс не подключён, в отличии от ООП где любой объект в любое время может вызывать любой метод другого объекта.
К тому же станет невозможно писать в ООП стиле, что сделает переход к компонентному программированию сложнее для программистов.
V>Поэтому модель контрактов современного ООП на реактивное программирование ни разу не ложится — слишком высока связанность для этого.
Раскрой пожалуйста мысль.
V>Тут правильно сказали, что можно смотреть идеологию DirectShow. Что удобно в такой архитектуре — развязываются руки в относительно подключений компонент друг к другу. Почему? Из-за того, что кол-во сигналов обычно невелико, т.е., имея в базисе сигналы (т.е. ориентируя архитектуру на сигналы, вернее на топологию их прохождения), мы получаем очень и очень низкую связанность компонент при всё еще существующей типобезопасности.
Т.е. один пин должен мочь принимать несколько типов сигналов?
Между тем,что я думаю,тем,что я хочу сказать,тем,что я,как мне кажется,говорю,и тем,что вы хотите услышать,тем,что как вам кажется,вы слышите,тем,что вы понимаете,стоит десять вариантов возникновения непонимания.Но всё-таки давайте попробуем...(Э.Уэллс)
Re[9]: Заметка: Компонентная философия и реализация
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 05.11.12 17:35
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Не совсем. Это семантический эквивалент на механику вокруг IConnectionPoint/IConnectionPointContainer


По заявлениям ТС, реактивность не есть обязательный признак. Так что нет.

V>, а так же их IDispatch-эквивалент. Это аналог джавовских листенеров событий. Всё это "красиво" встроено в язык VB/VBA, но в С++, Джаве и дотнете аналогичное только ручками.


Аналогичное что? С шарпе IConnectionPoint превращается в обыкновенное событие. При желании можно завернуть в IObservable.

V>Дык, реактивность требует некоторой поддержки


Какой?
... << RSDN@Home 1.2.0 alpha 5 rev. 66 on Windows 8 6.2.9200.0>>
AVK Blog
Re[7]: Заметка: Компонентная философия и реализация
От: vdimas Россия  
Дата: 05.11.12 17:35
Оценка: 1 (1)
Здравствуйте, AlexCab, Вы писали:

AC>От сюда:

AC>

AC>Глобальное состояние системы хранится во всех функциях и вытекает изо всех функций.


Более точно состояние в ФП хранится в локальных переменных по всему стеку вызова. То бишь, в состояние в ФП входит состояние стека и положение указателя команд.
ООП/императив отличается тем, что состояния делят на целевые и промежуточные. Проектирую обычно только целевые состояния, а проходы по промежуточным стараются делать как можно более безопасными (в идеале — транзакционными). В этом смысле в ФП все состояния — промежуточные. ))
Re[4]: Заметка: Компонентная философия и реализация
От: Miroff Россия  
Дата: 05.11.12 18:45
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>Среднестатистическое програмирование может радикально измениться.


Как именно оно изменится? 99% кодеров как клали на производительность, так и продолжат класть.
Re[5]: Заметка: Компонентная философия и реализация
От: AlexRK  
Дата: 05.11.12 19:00
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Из имеющихся подобных языков — только для разработки аппаратуры. ))

V>Можно взять Немерле и на нем попробовать сделать подобную библиотеку для софта.

Понял.

Подумалось еще вот что. А как в вашей модели дело обстоит с приемом сигналов в произвольные моменты времени? По идее, компонент может применяться в многопоточном окружении (он сам не знает, где применяется, поэтому рассчитывает на худшее). Получается, внутри будет куча всяких локов и прочих синхронизаций? Или же состояния у компонента вообще не может быть в принципе, и каждый выход — просто функция от всех входов? (Наверное, так и есть. )
Re[12]: Заметка: Компонентная философия и реализация
От: vdimas Россия  
Дата: 06.11.12 13:35
Оценка:
Здравствуйте, AlexCab, Вы писали:

AC>>>1)Грубо говоря(так как это может быть реализовано и без всяких таблиц методов), подключающийся компонент передаёт другому таблицу экспортируемых методов и получает от другого таблицу импортируемых(экспортируемых другим) методов, т.е. компоненты обмениваются таблицами(а не один передаёт другому как в COM).

V>>Сократи содержимое обоих таблиц до 1-го вхождения, и получишь базовую модель для реактивного программирования. )
AC>Можно определить интерфейс с одним импортируемым и одним экспортируемым методом, но, думаю, запрещать определять больше методов не очень хорошая идея.

Нужен всего один метод. Идея нормальная — ведь в отсутствии таблицы получишь уменьшение косвенности на 1 (если сам делаешь рантайм).
Одна сторона (выходная) этот метод вызывает, другая сторона — подставляет функтор (пин) для вызова.

V>>То бишь, в одном интерфейсе будет всего один сигнал. Итого, у компонента будет не много сигналов на каждый интерфейс, а много интерфейсов, где в каждом всего 1 сигнал. Но! Подобные интерфейсы должны быть в виде экземпляров, а не в виде уникальных контрактов... Ууупс!!! ))

AC>Много интерфейсов — плохо. Это почти тоже самое что ООП, в котором много методов.

Это если смотреть на интерфейсы как на типы. А ты смотри на них как на экземпляры. И тогда пусть их будет хоть сотни — это не мешает ни чему.

AC>В КОП, одна из главных задач интерфейсов — упорядочивание и упрощение связей компонентов(а значит и системы в целом). Что достигается объединением логически связынных методов и полей в один интерфейс, и запретом доступа к ним, если компонент не поддерживает данный интерфейс и интерфейс не подключён, в отличии от ООП где любой объект в любое время может вызывать любой метод другого объекта.


Мммм... сорри, но вынужден отослать к OLE/ActiveX. В реальности, никакого упрощения НЕТ.
1. Обычно интерфейсы не самодостаточны, а взаимодействуют со многими другими интерфейсами, если посмотреть на протокол некоей системы целиком. И тут начинает вылазить кривизна интерфейсов как типов:
2. "Вхождения" многих интерфейсов пересекаются, то бишь ф-ии/кортежи, составляющие интерфейсы, порой дублируют друг друга.
3. Интерфейсы служат тормозом к развитию. Для добавления новых членов в кортеж ф-ий, составляющих интерфейс, тупо создают новый IOldName2 или IOldNameEx и т.д., что не требуется в случае наличия необходимых "пинов".

И да. Никто тебе не запрещает делать "мета/пины", т.е. те, которые выдают как результат компоненты (кортежи других пинов). В общем, по мне проблема интерфейсов в КОП — в их уникальности, т.к. сейчас интерфейс равен типу в языке, что провоцирует на сильную связанность и дублирование содержимого интерфейсов. Нужна экземплярность.

Вот пример из электроники:
— многие пины у совершенно разных компонент совместимы друг с другом.
— когда речь о функциональности, то компонент целиком отвечает за функциональность (контракт на поведение). Т.е. реализация компонент разная, контракт один.

А что мы имеем сейчас? Сейчас контракт обслуживает сугубо интерфейсную (стыковочную) часть дизайна, а не поведенческую. То бишь, происходит ровно наоборот, под один и тот же интерфейс мы подставляем разные компоненты именно для целей разного их поведения. Ну дык! Давай те же перестанем делать вид, буд-то не понимаем этого, т.е. давайте оставим типизированный контракт сугубо для целей "стыковки" компонент, а не для целей управления семантикой... бо это ересь, т.к. компилятор не в состоянии контроллировать правильность семантики реализованного контракта. И чего тогда париться относительно "сложных" интерфейсов? Семантику пусть задают сами компоненты, а максимально простые интерфейсы пусть обеспечивают наименьшую связанность. Один метод в интерфейсе — меньше не бывает. ))

Еще пример разрыва в логике при реализации КОП сверху ООП: для того, чтобы вызвать совместимый с ранее известным некий сигнал (например, в электронике пусть будет тактовый сигнал), нам необходимо знать тип целого большого интерфейса!!! ОК, пусть система типов предлагает как вариант позвать еще один некий известный нам чуть более общий интерфейс ITactable... А что делать если у нас два тактовых входа? Ууупс???


AC>К тому же станет невозможно писать в ООП стиле, что сделает переход к компонентному программированию сложнее для программистов.

V>>Поэтому модель контрактов современного ООП на реактивное программирование ни разу не ложится — слишком высока связанность для этого.
AC>Раскрой пожалуйста мысль.

ИМХО, чем мощнее кортеж ф-ий, составляющих контракт, тем менее гибко его применение. Или раскрыть термин "высокая/низкая связанность"?

V>>Тут правильно сказали, что можно смотреть идеологию DirectShow. Что удобно в такой архитектуре — развязываются руки в относительно подключений компонент друг к другу. Почему? Из-за того, что кол-во сигналов обычно невелико, т.е., имея в базисе сигналы (т.е. ориентируя архитектуру на сигналы, вернее на топологию их прохождения), мы получаем очень и очень низкую связанность компонент при всё еще существующей типобезопасности.

AC>Т.е. один пин должен мочь принимать несколько типов сигналов?

Нет, один пин обслуживает один тип сигнала. Просто не должно быть ограничений на конкретный тип этого сигнала.

Ну и синтаксис соединения и маппинга портов хотелось бы максимально простой:
component C1 {
  in X : int;
  var Z : int;
    
  out Y : int = X * Z;

  C1(z : int) : Z(z) {}
};

component C2 {
  in X : int;
  out Y : int;
  var c1 : C1;

  C2(z : int) : C1(z) {
    X => c1.X;
    c1.Y => Y;
  }
};

component Main {
  out Ya, Yb : int;
  in X : int;
  var a, b : C2;

  Main() : a(42), b(43) {
    X => a.X;
    a.Y => Ya;
    X => b.X;
    b.Y => Yb;
  }
}


===========
Я нечто подобное ковыряю на досуге... Периодически встают разного рода вопросы конфликта синтаксиса...
Re[13]: Заметка: Компонентная философия и реализация
От: AlexRK  
Дата: 06.11.12 14:04
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Вот пример из электроники:

V>- многие пины у совершенно разных компонент совместимы друг с другом.
V>- когда речь о функциональности, то компонент целиком отвечает за функциональность (контракт на поведение). Т.е. реализация компонент разная, контракт один.

V>А что мы имеем сейчас? Сейчас контракт обслуживает сугубо интерфейсную (стыковочную) часть дизайна, а не поведенческую. То бишь, происходит ровно наоборот, под один и тот же интерфейс мы подставляем разные компоненты именно для целей разного их поведения. Ну дык! Давай те же перестанем делать вид, буд-то не понимаем этого, т.е. давайте оставим типизированный контракт сугубо для целей "стыковки" компонент, а не для целей управления семантикой... бо это ересь, т.к. компилятор не в состоянии контроллировать правильность семантики реализованного контракта. И чего тогда париться относительно "сложных" интерфейсов? Семантику пусть задают сами компоненты, а максимально простые интерфейсы пусть обеспечивают наименьшую связанность. Один метод в интерфейсе — меньше не бывает. ))


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

V>Я нечто подобное ковыряю на досуге... Периодически встают разного рода вопросы конфликта синтаксиса...


Какие конфликты, например?
Re[13]: Заметка: Компонентная философия и реализация
От: AlexCab LinkedIn
Дата: 06.11.12 16:09
Оценка:
V>Нужен всего один метод.
Т.е. взаимодействие через интерфейс может быть только однонаправленным?
V>Это если смотреть на интерфейсы как на типы. А ты смотри на них как на экземпляры.
Т.е. компонент может создавать/разрушать свои интерфейсы?
V>И тогда пусть их будет хоть сотни — это не мешает ни чему.
Анализ/отладка системы?
V>1. Обычно интерфейсы не самодостаточны, а взаимодействуют со многими другими интерфейсами, если посмотреть на протокол некоей системы целиком. И тут начинает вылазить кривизна интерфейсов как типов:
Это баг старых вариантов КОП.
V>2. "Вхождения" многих интерфейсов пересекаются, то бишь ф-ии/кортежи, составляющие интерфейсы, порой дублируют друг друга.
В смысле в одном интерфейсе или в нескольких интерфейсах одного компонента?
V>3. Интерфейсы служат тормозом к развитию. Для добавления новых членов в кортеж ф-ий, составляющих интерфейс, тупо создают новый IOldName2 или IOldNameEx и т.д., что не требуется в случае наличия необходимых "пинов".
Т.е. расширение интерфейса компонента будет выполнятся за чёт добавление новых пинов?
V>А что мы имеем сейчас? Сейчас контракт обслуживает сугубо интерфейсную (стыковочную) часть дизайна, а не поведенческую. То бишь, происходит ровно наоборот, под один и тот же интерфейс мы подставляем разные компоненты именно для целей разного их поведения.
по идее(даже в том же COM'е) контракт должен включать не только соглашение о собственно интерфейсе, но и соглашение о семантике интерфейса, в т.ч. и том как дожен "вести" себя владелец интерфейса при взаимодействии через этот интерфейс.
V>Один метод в интерфейсе — меньше не бывает. ))
В модели КОП из заметки, в интерфейсе может быть не одного метода, для случая когда нужно только установить факт подключения/отключения.
V>Или раскрыть термин "высокая/низкая связанность"?
Да.
V>Я нечто подобное ковыряю на досуге... Периодически встают разного рода вопросы конфликта синтаксиса...
Интересно, опиши пожалуйста(лучше с картинками и комментированым псевдокодом), что из себя будет представлять компонент с пинами, каковы возможности пинов и, как будет выполнятся взаимодействие компонентов, в общих чертах.
Между тем,что я думаю,тем,что я хочу сказать,тем,что я,как мне кажется,говорю,и тем,что вы хотите услышать,тем,что как вам кажется,вы слышите,тем,что вы понимаете,стоит десять вариантов возникновения непонимания.Но всё-таки давайте попробуем...(Э.Уэллс)
Re[14]: Заметка: Компонентная философия и реализация
От: vdimas Россия  
Дата: 06.11.12 19:49
Оценка: 1 (1)
Здравствуйте, AlexRK, Вы писали:

ARK>Хм, в таком случае "семантику" для компонента в целом задать будет нельзя.


Её и сейчас задать нельзя. Я потому и предлагаю не делать вид, будто можно.
Семантика пусть задается так, как она сейчас задаётся — вербально. В виде доки или ТЗ на компонент, например. )))

Ну и никто не мешает эти же пины представлять в виде типизированного "разъема", в этом случае "разъем" будет полным аналогом имеющегося на сегодня интерфейса/контракта. Каждый компонент в любом случае будет представлять из себя некий специфический разъем, просто из одних разъемов будет крайне удобно строить другие — в этом цель. Речь лишь о том, кто какие типы "видит". Например, в месте программы, где описывается порт-маппинг (т.е. соединение 2-х пинов), необходимо знать типы (разъемы) обоих компонент, без этого невозможно организовать типобезопасный код. Другое дело, что целевой пин мог придти транзитивно сколь угодно "далеко" через точно такой же порт-маппинг внутри описанных типов. Просто, помимо удобного синтаксиса "стыковки", удобным получается отуствие лишнего уровня косвенности по мере вложения компонент друг в друга. В электронике тоже простое прохождение сигнала по проводу пусть сквозь сколько угодно уровней абстракций дизайна ничего ведь не стоит... А в ООП сейчас стоит и очень некисло...

ARK>Нечто вроде утиной типизации выходит — если набор пинов у двух компонентов подходит, то они эквивалентны.


Да, один можно воткнуть вместо другого. В дотнете можно подать некий функтор (предикат, например) в огромное кол-во библиотечных методов. Надо лишь, чтобы этот функтор отвечал сигнатуре (считай — разъему). Но ведь кроме как коду функтора неизвестно, что этот он делает внутри. Я лишь предлагаю по такому принципу строить дизайн целиком, а не только отдельные библиотечные методы.

==========
Возвращаясь к утиной типизации — в ПО ситуация неплохая, в отличие от, ведь сами сигналы в ПО могут быть куда как более специализированы, чем в электронной области. Никто не мешает в виде сигнала использовать сколько угодно сложный пользовательский тип. Тут (повторюсь к посту рядом) было бы неплохо жестко отличать типы-компоненты от типов-данных. (Отдельная серьезная тема, но которая может потенциально разгрести часть бардака в современном ООП, где данные и объекты замешаны в одну кашу, и в итоге граф-"вычислитель" постоянно трансформируется в ходе работы, что лишает его детерминированности и возможности оптимизаций).

ARK>Т.е. какой-нибудь вентиль с одним входом и одним выходом можно будет легко спутать с другим, по "смыслу" совершенно иным. Хотя хз, может это и не так страшно...


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


V>>Я нечто подобное ковыряю на досуге... Периодически встают разного рода вопросы конфликта синтаксиса...

ARK>Какие конфликты, например?

Да хочется вообще минимализма, т.е. чтобы маппинг портов указывать не отдельно, как я показал, а прямо во время объявления пина/компонента. Ну и я так без фанатизма особо пока...
Стоит задача не столько реализовать некую готовую систему, сколько изобрести синтаксис, который самого удовлетворил бы. )) Компилятор-то потом в какой-нить мейнстримовый язык (или даже байт-код) написать не проблема.
Re[15]: Заметка: Компонентная философия и реализация
От: AlexRK  
Дата: 06.11.12 20:19
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Её и сейчас задать нельзя. Я потому и предлагаю не делать вид, будто можно.

V>Семантика пусть задается так, как она сейчас задаётся — вербально. В виде доки или ТЗ на компонент, например. )))

В мейнстрим-языках нельзя, но в теории можно. Вон в Rust что-то там пытаются на практике сделать с typestate.
Кстати, я там выше спрашивал — в вашей модели, как я понимаю, компоненты принципиально без состояния (каждый выход — функция всех входов)? Т.е. понятие "последовательность вызовов" бессмысленно?

V>Ну и никто не мешает эти же пины представлять в виде типизированного "разъема", в этом случае "разъем" будет полным аналогом имеющегося на сегодня интерфейса/контракта.


Вот тут не очень понял, что выставляется наружу в виде портов — некий набор примитивных типов + можно выставлять другие компоненты?

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


В смысле, выход внутреннего компонента "пробрасывается" напрямую на выход родительского?

V>Никто не мешает в виде сигнала использовать сколько угодно сложный пользовательский тип. Тут (повторюсь к посту рядом) было бы неплохо жестко отличать типы-компоненты от типов-данных.


Ну, данные наверное тоже можно считать примитивными "компонентами".


Подумал сейчас, возникла еще пара соображений.

Во-первых, "возмущение" по вашей системе, возникшее по сигналу извне, будет передаваться не мгновенно (как в теории), а за какое-то время. Что должно произойти, если реакция на прошлое возмущение еще не завершилась, а уже поступил новый сигнал? Завершаем все вычисления или прерываем и начинаем заново? В принципе, можно и так, и так сделать, наверное...

Во-вторых, как должно обстоять дело с обработкой ошибок? Предположим, в компоненте один из выходов задает функцию с ограниченной областью определения. Если функция на входных параметрах не определена, то что делаем? На один выход выставляем "еррор", а на другой — некое дефолтное значение результата? В таком случае можно и забыть проверить первый выход, получается аналог кодов возврата — ответственность на программисте. Либо как вариант — на выходе некий алгебраический тип данных Empty | Some a? Тут другой риск — эти нуллабельные типы будут пролезать во все интерфейсы и засорять их...

Во, и еще вопрос — как вы предполагаете избегать "коротких замыканий"? По идее можно ведь сделать цикл с кучей компонентов в цепочке и не заметить этого.
Re[16]: Заметка: Компонентная философия и реализация
От: vdimas Россия  
Дата: 06.11.12 23:38
Оценка:
Здравствуйте, AlexRK, Вы писали:

V>>Её и сейчас задать нельзя. Я потому и предлагаю не делать вид, будто можно.

V>>Семантика пусть задается так, как она сейчас задаётся — вербально. В виде доки или ТЗ на компонент, например. )))

ARK>В мейнстрим-языках нельзя, но в теории можно.


Да всё-равно не выйдет. Программа целиком и есть семантика.


ARK>Вон в Rust что-то там пытаются на практике сделать с typestate.


Я еще не смотрел, но почему-то уверен, что когда посмотрю, то за пару минут придумаю, как без проблем удовлетворить любой контракт, но при этом нарушить исходную семантику. ))


ARK>Кстати, я там выше спрашивал — в вашей модели, как я понимаю, компоненты принципиально без состояния (каждый выход — функция всех входов)? Т.е. понятие "последовательность вызовов" бессмысленно?


Это зависит от модели расрпостранения сигналов. Если синхронная модель — то последовательность вызовов имеет смысл. Если асинхронная, то тоже имеет, но уже по-другому (реакция лишь на изменения значения, а не на факт поступления 2-в-1-м — сигнала+события).

Я, вообще-то за то, чтобы компоненты могли (при надобности) иметь состояние.

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

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


В электронике такое разделение происходит естественным образом — схема неизменна (до следующей перепрошивки, по крайней мере, если речь о матрице вентилей), но данные (сигналы + состояния ячеек памяти) — изменяемы.

Ну и еще такой момент в предложенной системе — отсутствие гонок. Не может два и более выхода работать на один вход. Иначе это КЗ и компилятор ругается. Скажем так, понять этот момент сразу будет сложновато... Это совсем другие навыки дизайна, чем принятые в ИП сегодня.


V>>Ну и никто не мешает эти же пины представлять в виде типизированного "разъема", в этом случае "разъем" будет полным аналогом имеющегося на сегодня интерфейса/контракта.

ARK>Вот тут не очень понял, что выставляется наружу в виде портов — некий набор примитивных типов + можно выставлять другие компоненты?

Наружу выставляется кортеж пинов. Такой кортеж вполне себе тип.
Насчет выставлять другие компоненты как значения пинов — я соображения уже высказал: это путь к точно такому бардаку, который уже есть де-факто. Боюсь, без понятия "фабрики" не обойтись всё-равно, но использование фабрики весьма специфично — она используется только в момент создания "вычислителя".


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

ARK>В смысле, выход внутреннего компонента "пробрасывается" напрямую на выход родительского?

"Пробрасывается" не значение, а сам пин в момент соединения компонент. Значение потом идёт напрямую от источника к приемнику, игнорируя уровни иерархии дизайна.

Это как делегирование подписывания на событие в дотнете:
public event SomeHandler Event1 {
  add { _field1.Event1 += value; }
  remove { _field1.Event1 -= value; }
}


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


V>>Никто не мешает в виде сигнала использовать сколько угодно сложный пользовательский тип. Тут (повторюсь к посту рядом) было бы неплохо жестко отличать типы-компоненты от типов-данных.

ARK>Ну, данные наверное тоже можно считать примитивными "компонентами".

Хотите об этом поговорить? Я бы с удовольствием. Тут самое время раскатать в блин понятие "ссылочного типа" и его зачастую некорректное применение к типам, отвечающим за данные. И всё потому, что компилятор позволяет что угодно.

ARK>Подумал сейчас, возникла еще пара соображений.

ARK>Во-первых, "возмущение" по вашей системе, возникшее по сигналу извне, будет передаваться не мгновенно (как в теории), а за какое-то время. Что должно произойти, если реакция на прошлое возмущение еще не завершилась, а уже поступил новый сигнал? Завершаем все вычисления или прерываем и начинаем заново? В принципе, можно и так, и так сделать, наверное...

Всю схему "кто-то" должен пересчитывать. Этот кто-то должен раздавать компонентам вычислительные ресурсы. Принцип раздачи может быть очень разный.
Например: каждый пин будет содержать буфер-защелку. Когда на одном (любом) входе компонента будет обнаружено событие подачи сигнала, то компонент будет поставлен в очередь к шедуллеру. Когда до компонента дойдет очередь, то он может пересчитать свои выходы от всех измененных к моменту получения вычислительных ресурсов входов. В этом смысле логический вычислительный поток каждого компонента постоянно сидит в ожидании входных сигналов. Т.е. мы имеем строгую агентную среду, где не может быть гонок внутри компонент.

Логику можно усложнить. Например, реагировать не на факт подачи сигнала, а лишь на изменение входного значения. Если состояния такого автомата будут устойчивы, т.е. значение ф-ии переходов f(s, x) = s, то это будет асинхронный автомат. Кстати, нейронные сети с обратными связями так и работают — у них есть период затухания после возмущений. Как только сеть стабилизируется, т.е. войдет в устойчивое состояние, то вычисления закончены. Прямо отсюда должно быть понятно, как комбинировать программные модели синхронных и асинхронных автоматов. Сигнал об окончании вычислений асинхронного автомата может быть событием для зависимого синхронного.

Кстате, для эрудиции, базовый в схемотехнике RS-триггер — это классический асинхронный автомат, то бишь, автомат, выполненый на "чистых" функциях — логических вентилях. Просто в схеме есть обратные связи. Вот тебе откровение №1 — земля на самом деле круглая ячейка памяти — это чистая ф-ия + обратная связь. ))

Прямо отсюда должно быть понятно, почему я не сильно отличаю императивный и функциональный подход. Подобные устойчивые системы могут быть гораздо более сложными, чем RS-триггер. Могут состоять из кучи абсолютно чистых ф-ий, но при этом обладать изменяемым состоянием. Достаточно в ФП-программе суметь создать, например, циклическую структуру данных — и ву а ля, вот тебе изменяемое состояние из бесконечно считаемых по кругу ф-ий. Текущее устойчивое значение ф-ии на каждом витке вполне можно принять за состояние (как это есть в RS-триггере). Например, в упрощенном виде такая циклическая структура дана в виде монады IO в Хаскеле (при том, что её зацикливание выполняется внешним, по отношению к программе, вычислителем).


ARK>Во-вторых, как должно обстоять дело с обработкой ошибок?


В условиях детерминированной структуры вычислителя — проще простого. Ошибка — это состояние. Исключительных ситуаций не бывает (мы ведь не можем разрушть недостроенный дизайн). Если компонент может сигнализировать об ошибке — пусть у него будет под это специальный пин.

ARK>Предположим, в компоненте один из выходов задает функцию с ограниченной областью определения.


Если речь о зависимых типах, то мы просто не сможем подать на такой входной пин неподходящий выходной. Система типов не даст.


ARK>Во, и еще вопрос — как вы предполагаете избегать "коротких замыканий"? По идее можно ведь сделать цикл с кучей компонентов в цепочке и не заметить этого.


Это цикл, а не короткое замыкание. Короткое замыкание — это когда гонки. А цикл — это очень полезная структура. ))
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.