OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Воскресенье, 15 Декабрь, 2019 08:19

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 101 ]  На страницу Пред.  1, 2, 3, 4, 5, 6  След.
Автор Сообщение
 Заголовок сообщения: Re: Моделирование интерфейсов
СообщениеДобавлено: Воскресенье, 18 Декабрь, 2011 20:38 
Аватара пользователя

Зарегистрирован: Пятница, 25 Ноябрь, 2005 18:55
Сообщения: 2272
Откуда: Россия, Нижний Новгород
Архитектурно там просто: структура данных и набор процедур.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Моделирование интерфейсов
СообщениеДобавлено: Воскресенье, 18 Декабрь, 2011 21:22 

Зарегистрирован: Суббота, 20 Март, 2010 21:48
Сообщения: 22
Александр Ильин писал(а):
Когда вы говорите "не эквивалентна", вы имеете в виду только синтаксические отличия (количество параметров в процедуре) или существо дела? Приведите возражения по существу.


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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Моделирование интерфейсов
СообщениеДобавлено: Воскресенье, 18 Декабрь, 2011 23:54 

Зарегистрирован: Понедельник, 30 Июль, 2007 10:53
Сообщения: 1538
Откуда: Беларусь, Минск
Ну вот, допустим, смотрю я на только что реализованный вариант с одним параметром. Как я должен ощутить "важность этого различия"?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Моделирование интерфейсов
СообщениеДобавлено: Понедельник, 19 Декабрь, 2011 01:24 

Зарегистрирован: Суббота, 20 Март, 2010 21:48
Сообщения: 22
Valery Solovey писал(а):
Ну вот, допустим, смотрю я на только что реализованный вариант с одним параметром. Как я должен ощутить "важность этого различия"?


Можно показать этот вариант?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Моделирование интерфейсов
СообщениеДобавлено: Понедельник, 19 Декабрь, 2011 12:20 

Зарегистрирован: Понедельник, 30 Июль, 2007 10:53
Сообщения: 1538
Откуда: Беларусь, Минск
jackbauer писал(а):
Можно показать этот вариант?
С этим потом. Сначала давайте разберёмся с первым вопросом: как увидеть важность/существенность различия?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Моделирование интерфейсов
СообщениеДобавлено: Понедельник, 19 Декабрь, 2011 13:02 
Аватара пользователя

Зарегистрирован: Вторник, 19 Сентябрь, 2006 21:54
Сообщения: 2319
Откуда: Россия, Томск
Valery Solovey писал(а):
С этим потом. Сначала давайте разберёмся с первым вопросом: как увидеть важность/существенность различия?
Ага! Вопрос о критерии. Хороший ход.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Моделирование интерфейсов
СообщениеДобавлено: Среда, 21 Декабрь, 2011 09:04 

Зарегистрирован: Понедельник, 28 Ноябрь, 2005 10:28
Сообщения: 1215
jackbauer писал(а):
В одном случае передается явный указатель на виртуальную таблицу

Почему на виртуальную? На вполне реальную таблицу. :)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Моделирование интерфейсов
СообщениеДобавлено: Суббота, 01 Сентябрь, 2012 23:36 

Зарегистрирован: Суббота, 17 Сентябрь, 2011 16:39
Сообщения: 72
Илья Ермаков писал(а):
Как всегда, есть случаи, когда декомпозиция на части будет как раз лучшим дизайном (а попытка наследовать множественные интерфейсы - недопроектированием), и случаи, когда она уже будет "эмуляцией", а более естественным было бы второе.


Илья, не могли бы Вы привести пару примеров, когда лучше первое, а когда второе, и почему?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Моделирование интерфейсов
СообщениеДобавлено: Воскресенье, 02 Сентябрь, 2012 10:15 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9165
Откуда: Россия, Орёл
Давайте попробуем.

Пусть у нас есть абстрактные интерфейсы чтения и записи двоичных данных. И разные классы, способные хранить двоичные данные (допустим, кольцевой буфер, файл, ещё какой-нибудь буфер, файл в памяти, BLOB, да что угодно).
Ну, самая грубая ошибка проектирования была бы, конечно, реализовать интерфейсы чтения и записи прямо в классе-носителе данных. Ну такую ошибку вряд ли допустит кто-то, кроме студентов, но всё может быть...
Следуя BlackBox-овому паттерну Carrier-Rider-Mappper (точнее, его первой части Carrier-Rider) мы сделаем объекты чтения и записи (riders - объекты доступа), реализующие соотв. интерфейсы, и позволим иметь много объектов доступа к одному носителю. Это несколько похоже на итераторы.
Кроме возможности "быть в разных позициях" одновременно, это даёт возможность разделять полномочия кода - если алгоритм просит только Reader, то он не может получить доступ к носителю на модификацию (правда, в стандартных ББ-шных компонентах можно и через Reader добраться до его носителя, но я лично обычно изолирую).
Далее. У объектов доступа есть возможность позиционирования (некая пара Pos(): INTEGER, SetPos (INTEGER)). Но не все объекты допускают позиционирование (например, буфер поступающих из сети данных с однократным чтением). Решение в рамках интерфейсов - вынести операции позиционирования в отдельный интерфейс Slider - и пусть объекты доступа одних носителей этот интерфейс реализуют, а других - нет.
Но ещё лучше "допроектировать" и сделать этот Slider отдельным объектом, тогда можно, опять же явно декларировать и гарантировать, что некоторый алгоритм - "однопроходный", т.к. он не имеет доступа к Slider-у. Например, он имеет право дописывать с того места, на котором ему дали writer, а модифицировать что-то ещё в буфере - нет.
Особенно актуальны такие вещи, если мы работаем через такие интерфейсы с ОЗУ и разными хранилищами, а не тупо с файлами или сетью...

Нужно отметить, что идею с отделением объекта Slider некогда у нас тут высказал Сергей Губанов.

Живой пример, как это выглядит (с "купюрами", правда):
Код:
DEFINITION SomemylibData;

   TYPE
      Carrier = POINTER TO ABSTRACT RECORD
         (c: Carrier) NewReader (): Reader, NEW, ABSTRACT;
         (c: Carrier) NewWriter (): Writer, NEW, ABSTRACT;
         (c: Carrier) Slider (): Slider, NEW, ABSTRACT
      END;

      Rider = POINTER TO ABSTRACT RECORD END;

      Reader = POINTER TO ABSTRACT RECORD (Rider)
         (r: Reader) Available (): LONGINT, NEW, ABSTRACT;
         (r: Reader) LookBytes (OUT x: ARRAY OF BYTE; beg, len: INTEGER), NEW, ABSTRACT;
         (r: Reader) ReadBytes (OUT x: ARRAY OF BYTE; beg, len: INTEGER), NEW, ABSTRACT;
         (r: Reader) Skip (len: INTEGER), NEW, ABSTRACT
      END;

      Writer = POINTER TO ABSTRACT RECORD (Rider)
         (w: Writer) WriteBytes (IN x: ARRAY OF BYTE; beg, len: INTEGER), NEW, ABSTRACT
      END;

      Slider = POINTER TO ABSTRACT RECORD
         (s: Slider) Length (rider: Rider): LONGINT, NEW, ABSTRACT;
         (s: Slider) PosOf (rider: Rider): LONGINT, NEW, ABSTRACT;
         (s: Slider) SetPos (rider: Rider; pos: LONGINT), NEW, ABSTRACT
      END;

   PROCEDURE CopyBytes (reader: Reader; writer: Writer);

END SomemylibData.


Теперь обратите внимание на важную "фишку". Если Reader и Writer - это объекты доступа, которые создаются (NewReader(), NewWriter()), потому что они должны хранить контекст взаимодействия с носителем - позицию, то любая реализация Slider - это синглтон. Реализация слайдера не имеет состояния, создана в единственном экземпляре, возвращается одна и та же процедурой Slider() для всех носителей некоторого вида. А уже объект доступа, который нужно отпозиционировать, передаётся ей через параметр. Т.е., например, для некоторого модуля, реализующего какие-нить буферы, будет:

Код:
MODULE...

  TYPE
    Slider = POINTER TO RECORD (Data.Slider) END;

  VAR slider: Slider;

  PROCEDURE (buf: Buffer) Slider (): Slider;
  BEGIN
  RETURN slider
  END Slider;

BEGIN
  NEW(slider)
END ...


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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Моделирование интерфейсов
СообщениеДобавлено: Воскресенье, 02 Сентябрь, 2012 10:29 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9165
Откуда: Россия, Орёл
Если раньше я высказал мнение, что в некоторых случаях это не выгодно, а всего лишь "эмуляция множественных интерфейсов", то последнее время, после того, как пришлось пореализовывать архитектуры такого типа, я склоняюсь к тому, что никакая это не "эмуляция", а просто более явный способ их реализовывать. Интерфейс, фактически, реализуется через отдельный объект - и это позволяет иметь POINTER TO ИНТЕРФЕЙС, т.е. разделять полномочия кода и проч. Что мы получаем при более высокоуровневом, типа, подходе, с интерфейсами и их множественным наследованием: то же самое внутри, спрятано от программиста, и наверняка кто-нибудь где-нибудь уже начал изобретать новый язык, где можно делать POINTER TO ИНТЕРФЕЙС и разделять полномочия... :) Сначала спрячем, а потом накручиваем сверху эмуляцию - прямо как функциональщики спрятали последовательность действий, а потом вводят монады и проч.

Одно может оставаться неясным: как мы можем заставить любой попавший к нам в руки объект отдать любой интересующий нас интерфейс (или проверить, что он его имеет). В паре с паттерном HandleMsg и это возможно.

Пусть наши объекты расширяют некоторый базовый тип, имеющий процедуру HadnleMsg (VAR rec: ANYREC).

У нас есть модуль, в котором определён интерфейс:
Код:
DEFINITION M;

  TYPE
    Interface = POINTER TO ABSTRACT RECORD
       ....
    END;

    GetInterfaceMsg = RECORD
      ifc: Interface
    END;

END M;


К нам в руки попал объект obj. Мы хотим запросить у него интерфейс Interface.
Делаем:
VAR
msg: M.GetInterfaceMsg;
obj.HandleMsg(msg).


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Моделирование интерфейсов
СообщениеДобавлено: Воскресенье, 02 Сентябрь, 2012 12:07 

Зарегистрирован: Суббота, 17 Сентябрь, 2011 16:39
Сообщения: 72
Илья Ермаков писал(а):
Если раньше я высказал мнение, что в некоторых случаях это не выгодно, а всего лишь "эмуляция множественных интерфейсов", то последнее время, после того, как пришлось пореализовывать архитектуры такого типа, я склоняюсь к тому, что никакая это не "эмуляция", а просто более явный способ их реализовывать.


То же самое прочитал и здесь
kemiisto писал(а):
Подробности озвученного подхода от, так сказать, отцов-основателей тут. :wink:

J. Templ. A systematic approach to multiple inheritance implementation писал(а):
Conclusions
It has been shown that independent multiple inheritance can be expressed by multiple application of
single inheritance. Support for multiple inheritance in a programming language does not increase the
expressive power of the language, but simplifies the implementation of structures like twin objects. It also
allows a more efficient implementation which is based on (but does not affect) the implementation of
single inheritance. The efficiency differences between an emulation, the C++ implementation, and our
approach are, however, almost not noticeable. Thus the advantage of multiple inheritance support in a
programming language is purely syntactical.


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

Но при этом оно не позволяет
Илья Ермаков писал(а):
иметь POINTER TO ИНТЕРФЕЙС, т.е. разделять полномочия кода и проч.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Моделирование интерфейсов
СообщениеДобавлено: Воскресенье, 02 Сентябрь, 2012 12:12 

Зарегистрирован: Суббота, 17 Сентябрь, 2011 16:39
Сообщения: 72
Спасибо, многое прояснилось.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Моделирование интерфейсов
СообщениеДобавлено: Воскресенье, 02 Сентябрь, 2012 12:15 

Зарегистрирован: Суббота, 17 Сентябрь, 2011 16:39
Сообщения: 72
Илья Ермаков писал(а):
и наверняка кто-нибудь где-нибудь уже начал изобретать новый язык, где можно делать POINTER TO ИНТЕРФЕЙС и разделять полномочия... :)


Вы не поверите, но я что-то очень похожее набросал в блокноте перед Вашим постом :D


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Моделирование интерфейсов
СообщениеДобавлено: Воскресенье, 02 Сентябрь, 2012 12:25 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9165
Откуда: Россия, Орёл
Ну и хорошо, что всё так понятно :)

Хорошо бы, Дмитрий, из наших с вами сообщений сделать статью в нашу вики.... Блин, у меня времени сейчас нет... Может быть, позже, или кто-нибудь ещё возьмётся...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Моделирование интерфейсов
СообщениеДобавлено: Воскресенье, 02 Сентябрь, 2012 12:34 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9165
Откуда: Россия, Орёл
Ещё отметим такой момент.

Вспомним обероновское ООП, где методы делались полями RECORD-а:

Object = POINTER TO RECORD
Method: PROCEDURE (obj: Object; ....)

Т.е., фактически, виртуальная таблица делалась явной.
Это более мощный подход, чем обычное ООП, но на практике обычные методы оказались очень широко применимыми и удобными.

При наличии "обычных методов" мы можем при необходимости применять идею явной виртуализации, как бы, на новом уровне, имея уже не процедурные переменные, а переменные - ABSTRACT-интерфейсы. Идея явной передачи this-параметра этим интерфейсам сохраняется.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Моделирование интерфейсов
СообщениеДобавлено: Воскресенье, 02 Сентябрь, 2012 15:45 

Зарегистрирован: Суббота, 17 Сентябрь, 2011 16:39
Сообщения: 72
Илья Ермаков писал(а):
Одно может оставаться неясным: как мы можем заставить любой попавший к нам в руки объект отдать любой интересующий нас интерфейс (или проверить, что он его имеет). В паре с паттерном HandleMsg и это возможно.


Разработчики среди недостатков такого подхода отмечают (Design Patterns, 9.4.1 Message Object):
Цитата:
The message handler analyses the messages at runtime with a
WITH-statement. The branches of this WITH statement are
processed sequentially. This is generally slower than a method
call, which is usually implemented by a direct access to a
method table (see Appendix A.12.4).


Насколько критично такое замедление?
Внутренний голос говорит, что <1мс - это не проблема. Но хотелось бы услышать еще мнения.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Моделирование интерфейсов
СообщениеДобавлено: Воскресенье, 02 Сентябрь, 2012 15:56 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9165
Откуда: Россия, Орёл
Операция IS в Обероне выполняется очень быстро, за одно сравнение (так организованы дескрипторы типов).
Последовательный перебор в WITH, конечно, имеет место быть, но 2-3 ветки - то же самое, что IF. Там для 1мс нужно не одну сотню раз WITH-кнуть...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Моделирование интерфейсов
СообщениеДобавлено: Воскресенье, 02 Сентябрь, 2012 15:58 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9165
Откуда: Россия, Орёл
Главное преимущество HandleMsg - можно увязывать компоненты, ничего не знающие друг о друге.
Это такой контролируемый вид динамической типизации, "утиной", в строгом языке.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Моделирование интерфейсов
СообщениеДобавлено: Воскресенье, 02 Сентябрь, 2012 16:04 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9165
Откуда: Россия, Орёл
Дмитрий Грачёв писал(а):
Разработчики среди недостатков такого подхода отмечают (Design Patterns, 9.4.1 Message Object):

Это из Project Oberon?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Моделирование интерфейсов
СообщениеДобавлено: Воскресенье, 02 Сентябрь, 2012 16:08 

Зарегистрирован: Суббота, 17 Сентябрь, 2011 16:39
Сообщения: 72
Илья Ермаков писал(а):
Дмитрий Грачёв писал(а):
Разработчики среди недостатков такого подхода отмечают (Design Patterns, 9.4.1 Message Object):

Это из Project Oberon?


Цитата:
Design Patterns in
Oberon-2 and Component Pascal
translated excerpts from
Objektorientierte Programmierung in
Oberon-2
by
Hanspeter Mössenböck
English translation: Bernhard Treutwein, last c ha nge s :
Authorized translation of Chapter 9 "Entwurfsmuster" of Hanspeter Mössenböck:
Objektorientierte Programmierung in Oberon-2, 3rd Edition, 1998.
Permission granted by Springer, Heidelberg.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 101 ]  На страницу Пред.  1, 2, 3, 4, 5, 6  След.

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
cron
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2005-2019, участники конференции «OberonCore», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Без разрешения участников и ссылки на конференцию «OberonCore» любое воспроизведение и/или копирование высказываний полностью и/или по частям запрещено.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB