Прокинуть типы из подмодуля

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Прокинуть типы из подмодуля

Сообщение Дож » 22.01.2015 16:57:14

Есть несколько модулей A1, A2, A3, …, в каждом из них объявлен тип TFoo. Есть модуль B, он по некоторой сложной логике на IFDEF'ах в зависимости от платформы, пользовательских настроек и режима компиляции подключает ровно один из этих модулей, например:
Код: Выделить всё
unit B;

interface

uses
{$IF Defined(WINDOWS) and not Defined(Blablabla)}
  {$IF Defined(CPU32)}A1,{$ELSE}A2,{$ENDIF}
{$ELSEIF Defined(Blbalbla) or Define()}
  A3,
{$ELSEIF}
и т.д.

Модуль B является надстройкой над A, он активно использует TFoo и должен предоставить этот тип внешнему код. Так как сложная логика реализована в одном месте модуля B, (1) внешний код подключает только B, и никакой из A, (2) в модуле B мы не можем знать какой из A подключён и использовать его точное имя.

Вопрос 1: как объявить тип TFoo в B для внешнего кода? Я сейчас делаю как-то так и это работает:
Код: Выделить всё
type
  ImplTFoo = TFoo;
  TFoo = ImplTFoo;

Интересно можно ли лучше.

Вопрос 2: пусть TFoo является перечислимым типом TFoo = (Bar, Baz, Bal). Если мы решили предыдущую проблему, то как из внешней программы правильно получать доступ к Bar, Baz, Bal (и возможно ли это)? Можно ли для внешнего кода объявить Bar, Baz, Bal, не прописывая константы-синонимы для каждого значения?
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: Прокинуть типы из подмодулей

Сообщение zub » 22.01.2015 17:02:45

>>Вопрос 2
TFoo.Bar, TFoo.Baz, TFoo.Bal
?
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26

Re: Прокинуть типы из подмодулей

Сообщение Дож » 22.01.2015 17:15:11

zub писал(а):>>Вопрос 2
TFoo.Bar, TFoo.Baz, TFoo.Bal
?

Ответ принят, спасибо.
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: Прокинуть типы из подмодуля

Сообщение zub » 22.01.2015 18:35:50

по 1
если TFoo в A1, A2, A3, … определен одинаково, то выкинуть TFoo в отдельный A0 и заюзать его в B
если TFoo в A1, A2, A3, … отличается, то смысла в таком разделении вообще нет, т.к. "платформозависимый" тип вылазит в "платформонезависимый" модуль не должен
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26

Re: Прокинуть типы из подмодуля

Сообщение Дож » 23.01.2015 00:54:36

zub писал(а):по 1
если TFoo в A1, A2, A3, … определен одинаково, то выкинуть TFoo в отдельный A0 и заюзать его в B
если TFoo в A1, A2, A3, … отличается, то смысла в таком разделении вообще нет, т.к. "платформозависимый" тип вылазит в "платформонезависимый" модуль не должен

Скажем так, объект TFoo в интерфейсной части почти одинаков в модулях, за исключением, что в некоторых вариантах не все методы есть. В реализации различен.

Дело ещё в том, что у меня в практической задаче будет некий MultiA со своим TFoo, который cможет в RunTime'е переключаться между несколькими TFoo из различных A :) Поэтому мне реально нужно несколько различных реализации TFoo.
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: Прокинуть типы из подмодуля

Сообщение zub » 23.01.2015 01:30:04

>>Скажем так, объект TFoo в интерфейсной части почти одинаков в модулях, за исключением, что в некоторых вариантах не все методы есть
Т.е. это класс. Ну тогда просится TAbstractFoo с общими методами в A0, в A1, A2, A3 его наследники со своей реализацией. Общение B c Ax методами TAbstractFoo
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26

Re: Прокинуть типы из подмодуля

Сообщение Дож » 23.01.2015 16:15:58

zub писал(а):>>Скажем так, объект TFoo в интерфейсной части почти одинаков в модулях, за исключением, что в некоторых вариантах не все методы есть
Т.е. это класс. Ну тогда просится TAbstractFoo с общими методами в A0, в A1, A2, A3 его наследники со своей реализацией. Общение B c Ax методами TAbstractFoo

Если я так сделаю, то (1) появится дополнительный модуль с TAbstractFoo, его нужно будет писать и поддерживать (2) программа, использующая нереализованные методы, будет компилироваться (!) и падать при вызове Abstract Method с невнятной для юзера ошибкой (3) т.к. будут виртуальные методы вместо статических — ухудшится производительность, притом что виртуальные методы не нужны (4) обычный Smart Linking (без WPO) не сможет удалить из кода никакие виртуальные методы TFoo — а значит в конечный код попадут те, что никогда не используются и увеличится размер итогового файла.

Внимание вопрос: почему Вам так просится написать TAbstractFoo, если это ухудшение абсолютно по всем фронтам (разработка, качество, производительность и размер)?
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: Прокинуть типы из подмодуля

Сообщение Vapaamies » 23.01.2015 17:15:27

Мне кажется, что у вас нетривиальная задача с декомпозицией, и решить ее, не вникая в детали, не удастся. Не для форума тема, короче.

Обратил внимание, что некоторые участники форума добровольно записались в тролли и теперь пытаются убедить авторов тем, что они дураки, и так задачи вообще не решают. Чуть было не слили тему про LDAP, но ее удалось вытащить на конструктив.
Аватара пользователя
Vapaamies
постоялец
 
Сообщения: 292
Зарегистрирован: 24.07.2012 22:37:59
Откуда: Санкт-Петербург

Re: Прокинуть типы из подмодуля

Сообщение zub » 23.01.2015 17:25:37

1 - это просто класс с набором абстрактных методов. общих и необходимых для взаимодействия B с Ax, какие могут быть трудности с поддержкой?
2 - ненадо создавать TAbstractFoo, надо создавать TFoo и передавать его из Ax в B. В ничего не знает о TFoo и работает с ним как будьто это TAbstractFoo. Посмотрите как в лцл устроена работа с виджесетами
3 - нужны, что за задача такая что виртуальный метод даст заметный проигрышь статическому? на деле этим можно пренебречь
4 - из пушки по воробъям, как собственно 3. Если это критично, то нечего использовать классы вообще, юзайте процедуры

>>Внимание вопрос: почему Вам так просится написать TAbstractFoo
Потому что это вполне рабочее и часто применяемое решение. Eсли 3 и 4 действительно важны, а не просто "перестраховка" то имхо классы юзать вообще не стоит. с другой стороны с учетом
>>Дело ещё в том, что у меня в практической задаче будет некий MultiA со своим TFoo, который cможет в RunTime'е
>>переключаться между несколькими TFoo из различных A :)
От "виртуальности" никуда дется неполучится, либо классы с виртуальными методами, либо какойнибудь костыль с эмуляцией виртуальности обычными процедурами и тогда всеравно 3 и 4 никуда не денутся

вывод надуман, по всем фронтам какраз будет улучшение.
а вот вещи типа
Код: Выделить всё
type
  ImplTFoo = TFoo;
  TFoo = ImplTFoo;

это точно ничего хорошего не принесет

Vapaamies
креститесь когда кажется.
>>Не для форума тема, короче.
Что в задаче необычного? Другое дело что постоянно меняются условия, сначала перичислимое, потом класс, потом отказ от виртуальности...
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26

Re: Прокинуть типы из подмодуля

Сообщение Vapaamies » 23.01.2015 18:33:03

zub писал(а):От "виртуальности" никуда дется неполучится, либо классы с виртуальными методами, либо какойнибудь костыль с эмуляцией виртуальности обычными процедурами и тогда всеравно 3 и 4 никуда не денутся

Мне кажется, что у автора там какие-то вариативные данные, достаточно изолированные с точки зрения наследования. Нужно больше инфы, согласен. Возможно, что это задача не для наследования, а для обобщения, пусть даже и в вырожденном виде.
Аватара пользователя
Vapaamies
постоялец
 
Сообщения: 292
Зарегистрирован: 24.07.2012 22:37:59
Откуда: Санкт-Петербург

Re: Прокинуть типы из подмодуля

Сообщение Дож » 23.01.2015 18:52:39

1 - это просто класс с набором абстрактных методов. общих и необходимых для взаимодействия B с Ax, какие могут быть трудности с поддержкой?

Трудностей нет, а поддерживать (следить за актуальностью) нужно, что само по себе минус. Лучше не иметь то, что нужно поддерживать, если оно не приносит пользу. Пользу в TAbstractFoo я пока не вижу — и это я говорю не фигурально, я действительно не понимаю чем оно помогает.

Я понимаю зачем нужны абстрактные классы при использовании наследования и виртуальных методов по назначению (когда мы пишем общий код, работающий с разными типами потомков).
2 - ненадо создавать TAbstractFoo, надо создавать TFoo и передавать его из Ax в B. В ничего не знает о TFoo и работает с ним как будьто это TAbstractFoo.

Я говорил про «в некоторых вариантах не все методы есть». Если TAbstractFoo содержит абстрактные методы, которые могут быть не реализованы в TFoo, то это может привести к падающей в реалтайме программе. Или мы говорим про разное? Поправьте.
3 - нужны, что за задача такая что виртуальный метод даст заметный проигрышь статическому? на деле этим можно пренебречь

Пишу для себя фреймворк :) Программа использует фреймворк и не думает о платформах и внешних библиотеках, фреймворк внутри использует правильное в зависимости от настроек компиляции api. Хочу высокий уровень без потерь преимуществ низкого — концептуально это возможно.

Не для того я компиляторами пользуюсь, чтобы на производительность забивать.
4 - из пушки по воробъям, как собственно 3. Если это критично, то нечего использовать классы вообще, юзайте процедуры

Я использую object'ы и обычные методы можно считать обычными процедурами.

zub писал(а):а вот вещи типа
Код: Выделить всё
type
  ImplTFoo = TFoo;
  TFoo = ImplTFoo;

это точно ничего хорошего не принесет

Я хочу простую вещь модульного программирования! :) Внутри B пробросить наружу тип, который видит сам B. Концептуально вещь элементарная и весьма естественная. Я был бы рад другому способу это сделать, советуйте.

Ответ в стиле «это сделать невозможно, поэтому переделывайте всю архитектуру и смиритесь с другими недостатками» очень грустный, не правда ли?

Что в задаче необычного? Другое дело что постоянно меняются условия, сначала перичислимое, потом класс, потом отказ от виртуальности...

Чтобы меня правильно поняли: я изначально дал минимальную информацию, чтобы задать вопрос, но мне дают советы, выходящие за рамки поставленного вопроса, и чтобы объяснить чем мне советы не подходят, приходится расширять условие задачи и объяснять мою мотивацию. Я могу сформулировать общую задачу целиком, если хотите.

Мне кажется, что у вас нетривиальная задача с декомпозицией, и решить ее, не вникая в детали, не удастся. Не для форума тема, короче.

В том-то и дело, что нет, всё очень плоско и тривиально. Для решения моих проблем не хватает сущих досадных мелочей! Например, вменяемого пробрасывания типов.
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: Прокинуть типы из подмодуля

Сообщение Vapaamies » 23.01.2015 19:33:01

Из описания я так и не понял, есть ли в коде B объявление типа:
Код: Выделить всё
type
{$IFDEF A1}
  TFoo = A1.TFoo;
{$ENDIF}
{$IFDEF A2}
  TFoo = A2.TFoo;
{$ENDIF}
{$IFDEF A3}
  TFoo = A3.TFoo;
{$ENDIF}

Типы ведь тоже можно указывать через точечное имя, где до точки -- имя модуля.
Аватара пользователя
Vapaamies
постоялец
 
Сообщения: 292
Зарегистрирован: 24.07.2012 22:37:59
Откуда: Санкт-Петербург

Re: Прокинуть типы из подмодуля

Сообщение Дож » 23.01.2015 19:37:38

Это вариант, да.
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: Прокинуть типы из подмодуля

Сообщение zub » 23.01.2015 20:37:30

Дож писал(а):Трудностей нет, а поддерживать (следить за актуальностью) нужно, что само по себе минус. Лучше не иметь то, что нужно поддерживать, если оно не приносит пользу. Пользу в TAbstractFoo я пока не вижу — и это я говорю не фигурально, я действительно не понимаю чем оно помогает.

Нужно хорошо продумать набор методов, дабы избежать внесения изменений по любому чиху. Плюс подхода простой - вы имеете минимум внутренних зависимостей в программе. Т.е. если вы в другом проекте сделаете uses B; это притянет только B и A0 который кода никакого не несет, только описание абстрактного интерфейса взаимодействия B c какойто реализацией чегото. В случае с "пробросом" Подтянется и B и какаято реализация из Ax. И если злоупотребить "пробросами" то от модульности не останется и следа - uses чтото_мелкое_из_фреймворка подтянет весь фреймворк
Дож писал(а):Я говорил про «в некоторых вариантах не все методы есть». Если TAbstractFoo содержит абстрактные методы, которые могут быть не реализованы в TFoo, то это может привести к падающей в реалтайме программе. Или мы говорим про разное? Поправьте.

Скажите как в варианте с пробросом B взаимодействует с разными реализациями TFoo? Помоему тут 2 рарианта: либо есть какойто минимальный публичный набор методов и отличия скрыты, либо внутренняя реализация B подтягивается под конкретный TFoo ифдефами. Первый подсказывает прилепить TAbstractFoo, а второй говорит о полном отсутствии "модульности"
Дож писал(а):Я использую object'ы и обычные методы можно считать обычными процедурами.

Я тоже предпочитаю обжекты. Думаю в рамках этого топика можно считать обжект=класс, их отличия на суть вопроса не влияют.
Дож писал(а):Я хочу простую вещь модульного программирования! :) Внутри B пробросить наружу тип, который видит сам B. Концептуально вещь элементарная и весьма естественная. Я был бы рад другому способу это сделать, советуйте.

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

Ну хоть не целиком, но какуюто минимальную специфику можно.
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26

Re: Прокинуть типы из подмодуля

Сообщение Mirage » 23.01.2015 23:56:31

А чем плохо решение, уже в общем-то применяемое.
Непонятно, зачем в Ax называть тип так же, поэтому имеет смысл там назвать его TXXXImpl:
Код: Выделить всё
type TFoo = TFooImpl


Чтобы предлагать другие варианты надо знать чем этот плох. Так, на первый взгляд, вроде ничем.
Mirage
энтузиаст
 
Сообщения: 881
Зарегистрирован: 06.05.2005 20:29:07
Откуда: Russia


Вернуться в Free Pascal Compiler

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

Сейчас этот форум просматривают: Google [Bot] и гости: 1

Рейтинг@Mail.ru