OberonCore
https://forum.oberoncore.ru/

ABSTRACT RECORD versus EXTENSIBLE RECORD?
https://forum.oberoncore.ru/viewtopic.php?f=23&t=6587
Страница 1 из 1

Автор:  adimetrius [ Пятница, 20 Март, 2020 12:12 ]
Заголовок сообщения:  ABSTRACT RECORD versus EXTENSIBLE RECORD?

Коллеги,

выскажитесь, пож, чем руководствоваться при выборе ABSTRACT RECORD versus EXTENSIBLE RECORD?

Поясню.

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


Я бы сделал так:
Код:
TYPE Type* = POINTER TO EXTENSIBLE RECORD x*, y-, z: ... END;
PROCEDURE (t: Type) P*, NEW, EXTENSIBLE;  (* производные ДОЛЖНЫ вызывать P^ *)

Ну или так, чтобы не полагаться на ^ супервызовы:
Код:
PROCEDURE (t: Type) P2*, NEW, EMPTY;
PROCEDURE P* (t: Type);   (* или PROCEDURE (t: Type) P*, NEW; *)
BEGIN ...; t.P2
END P;


Или все-таки стоит сделать
Код:
TYPE Type* = POINTER TO  ABSTRACT RECORD x*, y-, z: ... END;
StdType = POINTER TO RECORD(Type) ... END;


Какими руководствоваться критериями при выборе?

Автор:  Александр Ильин [ Пятница, 20 Март, 2020 19:59 ]
Заголовок сообщения:  Re: ABSTRACT RECORD versus EXTENSIBLE RECORD?

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

Соответственно, смотрите сами, имеет ли смысл их создавать. Если внутри или вокруг базового типа уже есть некий функционал, который позволяет его создать и осмысленно использовать, пусть этот базовый тип будет EXTENSIBLE. Если вы хотите запретить клиентам создавать экземпляры и хотите, например, чтобы всё создавание происходило внутри вашего модуля (для установки и поддержания каких-то инвариантов времени исполнения), то публикуйте только ABSTRACT тип, а конкретные расширения делайте непубличными. В последнем случае клиент тоже сможет создать свои расширения и передать вам в обход установки инвариантов, но ваши функции смогут их легко идентифицировать проверкой типа и пресечь их работу (трапнуть на предусловии, например).

Автор:  Info21 [ Пятница, 20 Март, 2020 21:42 ]
Заголовок сообщения:  Re: ABSTRACT RECORD versus EXTENSIBLE RECORD?

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

Автор:  adimetrius [ Пятница, 20 Март, 2020 21:58 ]
Заголовок сообщения:  Re: ABSTRACT RECORD versus EXTENSIBLE RECORD?

Info21 писал(а):
Насколько я понимаю, EXTENSIBLE надо избегать.

Я собсно этого и придерживаюсь обычно. Но вот не помню, почему )). Видимо, оч давно придерживаюсь

Почему же надо избегать EXTENSIBLE?

Автор:  adimetrius [ Пятница, 20 Март, 2020 22:01 ]
Заголовок сообщения:  Re: ABSTRACT RECORD versus EXTENSIBLE RECORD?

Александр Ильин писал(а):
Если внутри или вокруг базового типа уже есть некий функционал, который позволяет его создать и осмысленно использовать, пусть этот базовый тип будет EXTENSIBLE.

О, вот это мне понятно, вполне как критерий звучит. Если я прально понял, можно уточнить "...осмысленно использовать без расширения,...

Автор:  Дмитрий Дагаев [ Суббота, 21 Март, 2020 09:48 ]
Заголовок сообщения:  Re: ABSTRACT RECORD versus EXTENSIBLE RECORD?

В Вашем случае (EXTENSIBLE RECORD с наличием EXTENSIBLE методов) нужно избегать потенциальных проблем наследования реализации (хрупкий базовый класс и проч). Применение ABSTRACT эти проблемы снимает.

Но ABSTRACT добавляют проблему повторного использования кода, когда в каждом производном объекте приходится частично дублировать код реализации. Что приводит к необходимости рефакторинга.

Для повторного использования кода лучше применять методы с измененными именами, а не EXTENSIBLE. Но есть ситуация, когда EXTENSIBLE вполне допустимо - когда Вы с этими проблемами управляетесь в одном модуле Module2:
ABSTRACT Module1.Rec -> EXTENSIBLE Module2.Rec -> Module2.RecSpec1, Module2.SpecRec2, ..
При этом Вы должны выводить наружу только Module1.Rec

Автор:  Илья Ермаков [ Суббота, 21 Март, 2020 10:43 ]
Заголовок сообщения:  Re: ABSTRACT RECORD versus EXTENSIBLE RECORD?

Коллеги выше уже разъяснили основное.

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

В отношении классов:
- если проектируете что-то широкого применения, то лучше только ABSTRACT (не закладывать хрупкость, пусть и ценой уменьшения повторного использования).
- если речь о структуре в конкретно вашем приложении (не в переиспользуемом компоненте), то при явной целесообразности можно и EXTENSIBLE, не надо совсем жёсткой догматики.

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

Автор:  Александр Ильин [ Суббота, 21 Март, 2020 14:30 ]
Заголовок сообщения:  Re: ABSTRACT RECORD versus EXTENSIBLE RECORD?

adimetrius писал(а):
Александр Ильин писал(а):
Если внутри или вокруг базового типа уже есть некий функционал, который позволяет его создать и осмысленно использовать, пусть этот базовый тип будет EXTENSIBLE.

О, вот это мне понятно, вполне как критерий звучит. Если я прально понял, можно уточнить "...осмысленно использовать без расширения,...
Да, именно так.

Автор:  Илья Ермаков [ Суббота, 21 Март, 2020 16:36 ]
Заголовок сообщения:  Re: ABSTRACT RECORD versus EXTENSIBLE RECORD?

Да, хорошо сформулировал Александр.

Автор:  Info21 [ Воскресенье, 22 Март, 2020 00:10 ]
Заголовок сообщения:  Re: ABSTRACT RECORD versus EXTENSIBLE RECORD?

Дмитрий Дагаев писал(а):
Но ABSTRACT добавляют проблему повторного использования кода, когда в каждом производном объекте приходится частично дублировать код реализации. Что приводит к необходимости рефакторинга.
Непонятно.

Автор:  Дмитрий Дагаев [ Воскресенье, 22 Март, 2020 09:33 ]
Заголовок сообщения:  Re: ABSTRACT RECORD versus EXTENSIBLE RECORD?

Info21 писал(а):
Дмитрий Дагаев писал(а):
Но ABSTRACT добавляют проблему повторного использования кода, когда в каждом производном объекте приходится частично дублировать код реализации. Что приводит к необходимости рефакторинга.
Непонятно.

Рассмотрим пример Files.File - ABSTRACT тип, который требует реализации.
1. Есть реализация для Windows - HostFiles.File.
2. Есть реализация для Linux - тот же HostFiles.File. Как она сделана? Скопирована реализация для Windows, а потом платформо-зависимый код, отмеченный цветом, изменен А.Ширяевым и др. для Linux. Но остальной код реализации - дублируется, а такого кода очень много.

С дублированием кода в ООП (Фаулер) предлагается бороться рефакторингом. Скажем, возможно было бы создавать (в HostFiles или где-то еще) EXTENSIBLE File реализацию, складывать туда дублируемый код, а платформо-зависимое сводить (в HostFiles) LinFile = RECORD (File)... END.

Автор:  Comdiv [ Воскресенье, 22 Март, 2020 12:39 ]
Заголовок сообщения:  Re: ABSTRACT RECORD versus EXTENSIBLE RECORD?

Дмитрий Дагаев писал(а):
С дублированием кода в ООП (Фаулер) предлагается бороться рефакторингом. Скажем, возможно было бы создавать (в HostFiles или где-то еще) EXTENSIBLE File реализацию, складывать туда дублируемый код, а платформо-зависимое сводить (в HostFiles) LinFile = RECORD (File)... END.

Это можно решить иначе. Files.File может быть даже нерасширяемым типом, который содержит только платформо-неспецифический код, который вызывает, содержащийся в нём экземпляр полностью абстрактного типа, который, в идеале, содержит только минимально необходимый платформо-специфический код.

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

Автор:  Илья Ермаков [ Воскресенье, 22 Март, 2020 12:58 ]
Заголовок сообщения:  Re: ABSTRACT RECORD versus EXTENSIBLE RECORD?

Comdiv писал(а):
Это можно решить иначе. Files.File может быть даже нерасширяемым типом, который содержит только платформо-неспецифический код, который вызывает, содержащийся в нём экземпляр полностью абстрактного типа, который, в идеале, содержит только минимально необходимый платформо-специфический код.


У плюсистов - идиома PIMPL, если не ошибаюсь? (pointer to implementation)?

Автор:  Дмитрий Дагаев [ Воскресенье, 22 Март, 2020 14:09 ]
Заголовок сообщения:  Re: ABSTRACT RECORD versus EXTENSIBLE RECORD?

Comdiv писал(а):
Дмитрий Дагаев писал(а):
С дублированием кода в ООП (Фаулер) предлагается бороться рефакторингом. Скажем, возможно было бы создавать (в HostFiles или где-то еще) EXTENSIBLE File реализацию, складывать туда дублируемый код, а платформо-зависимое сводить (в HostFiles) LinFile = RECORD (File)... END.

Это можно решить иначе. Files.File может быть даже нерасширяемым типом, который содержит только платформо-неспецифический код, который вызывает, содержащийся в нём экземпляр полностью абстрактного типа, который, в идеале, содержит только минимально необходимый платформо-специфический код.

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

Все Вы правильно говорите.

Но я и не утверждал, что EXTENSIBLE - единственное правильное решение. Более того, я говорил, что
Дмитрий Дагаев писал(а):
Для повторного использования кода лучше применять методы с измененными именами, а не EXTENSIBLE. Но есть ситуация, когда EXTENSIBLE вполне допустимо

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

Автор:  adimetrius [ Воскресенье, 22 Март, 2020 16:27 ]
Заголовок сообщения:  Re: ABSTRACT RECORD versus EXTENSIBLE RECORD?

Comdiv писал(а):
Дмитрий Дагаев писал(а):
С дублированием кода в ООП (Фаулер) предлагается бороться рефакторингом. Скажем, возможно было бы создавать (в HostFiles или где-то еще) EXTENSIBLE File реализацию, складывать туда дублируемый код, а платформо-зависимое сводить (в HostFiles) LinFile = RECORD (File)... END.

Это можно решить иначе. Files.File может быть даже нерасширяемым типом, который содержит только платформо-неспецифический код, который вызывает, содержащийся в нём экземпляр полностью абстрактного типа, который, в идеале, содержит только минимально необходимый платформо-специфический код.


Я применил такую схему для модуля Windows, когда делал Тайлер (плиточный интерфейс).
Там, как Д.В. написал: в Windows был только интерфейс, вся реализация в HostWindows, и она совмещала платформо-зависимые и независимые части. Например, к платформо-независимым относится понятие Front и Target окна - это не зависит от Лин-Вин.

Я интуитивно отделил платформо-независимые части и "поднял" их в Windows и, в основном, сделал свободными процедурами, поскольку переопределение или расширение не предусматривается. А для всего платформо-зависимого выделил новый тип WindowBackend, который в Windows только абстрактный интерфейс, а вся реализация в HostWindows. Модуль HostWindows существенно упростился, сократился в 2 раза - легче будет переносить под другие платформы.

Но в этой теме про критерии. И вот вопрос: критерий хорош, предложенный Александром; однако если руководствоваться только им, то TextModels.StdModel вполне можно экспортировать и позволять расширять. Значит надо формальный критерий как-то уточнять или дополнять.

Автор:  Info21 [ Воскресенье, 22 Март, 2020 18:18 ]
Заголовок сообщения:  Re: ABSTRACT RECORD versus EXTENSIBLE RECORD?

Общие куски в HostFiles должны быть реализованы как простые процедуры в Files.
Реализация в HostFiles их использует, и реализация в Linux тоже.

Архитектура ББ в этом смысле недоработана.

Но всё заранее угадать нельзя, поэтому и случается копипаста.
Но это не аргумент для затычек вроде EXTENSIBLE.

Автор:  Дмитрий Дагаев [ Воскресенье, 22 Март, 2020 18:45 ]
Заголовок сообщения:  Re: ABSTRACT RECORD versus EXTENSIBLE RECORD?

Info21 писал(а):
Общие куски в HostFiles должны быть реализованы как простые процедуры в Files.
Реализация в HostFiles их использует, и реализация в Linux тоже.

Архитектура ББ в этом смысле недоработана.

Но всё заранее угадать нельзя, поэтому и случается копипаста.
Но это не аргумент для затычек вроде EXTENSIBLE.

Это - действительно не аргумент.
Это - ответ на Ваш вопрос: прояснить, что ABSTRACT добавляет проблему повторного использования кода. Я прояснил на примере HostFiles - проблема есть, и дело не в том, что кто-то там не угадал.

А аргумент был такой
Цитата:
Но есть ситуация, когда EXTENSIBLE вполне допустимо - когда Вы с этими проблемами управляетесь в одном модуле Module2:
ABSTRACT Module1.Rec -> EXTENSIBLE Module2.Rec -> Module2.RecSpec1, Module2.SpecRec2

Скажу другими словами, что если Вы наследуете от одного абстрактного типа 10 специфических (и еще 20 в уме), то вставка между ними EXTENSIBLE в том же модуле будет оправдана. Ну там, графические объекты Rect, Oval, Circle, Text, Poly... А потом появляются типы Text3D, Rect3D. Один человек будет править этот модуль, проблемы хрупкого базового класса не возникнет.

Является ли EXTENSIBLE единственным возможным решением в этом случае? Нет.

Автор:  Info21 [ Понедельник, 23 Март, 2020 10:26 ]
Заголовок сообщения:  Re: ABSTRACT RECORD versus EXTENSIBLE RECORD?

Не согласен, что добавляет именно ABSTRACT, -- или не понял аргумента.

Оставить EXTENSIBLE для использования внутри модуля, запретив экспорт типов с этим атрибутом, -- лучше, чем оставлять как есть, но сложнее, чем вовсе убрать.

Страница 1 из 1 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/