Конференция "Прочее" » Как правильно наследоваться от TDataModule?
 
  • Рыбба (14.01.09 10:30) [0]
    Здраствуйте. В Делфи я новичок, так что сильно не пинайте.
    Решил сделать маленький проектик с базами с использованием наследования. Т.е. сделал какой-то каркас, а затем в проекте наследуешься от него. Сделал классы форм - все нормально наследуется и используется.
    Но хочу так же сделать и с TDataModule. Сделал общий датамодуль (TMyDM), а как наследоваться от него? Ведь в классах формы есть ссылки на TMyDM (датасурсы, гриды, вызовы процедур и прочее)?
    Если сделать новый датамодуль (TDM = class(TMyDM)) то придется вручную поменять ссылки на TDM, тогда смысл?

    Подскажите как правильно. Спасибо
  • Кит (14.01.09 10:50) [1]
    File > New > Other...
    [Тут вкладка с именем твоего проекта] > Ищешь твой датамодуль MyDM выбираешь внизу Inherit > Ok

    Усё.
  • Рыбба (14.01.09 12:00) [2]
    Прочитайте внимательней
  • MsGuns © (14.01.09 12:04) [3]
    Если вся (или почти вся) логика обмена с БД инкапсулируется в датамодуль, зачем делать от него наследника ?
    Мне почему-то кажется, что Вам надо реализовать несколько форм, работающих с разными экземплярами одних и тех же объектов связи с БД (как пример, два или более экземпляра одной и той же формы просмотра содержимого одного и того же запроса, но с разными параметрами). Если так, то для каждой формы не нужно создавать датамодуль по "образу и подобию" основого. Надо все объекты (датасеты обычно) располагать в самих формах, а вот некотрый функционал (например, обработка событий датасетов, обработка ошибок, установление соединения с БД и т.д.) реализовать в основном ДМ. Тогда при достаточной автономности интерфейсных модулей (форм, фрэймов и т.д.) Вы получите компактность и унифицированность кода.

    Есть, конечно, и другой способ, позволяющий все же избавить формы от датасетов - но для этого надо в датамодуле предусмотреть списки датасетов и сгородить недетскую логику по разруливанию их при открытиях и закрытиях форм. ИМХО, путь для обычного (не апп-сервера) совершенно неприемлимый, хотя и реализуемый.
  • MsGuns © (14.01.09 12:13) [4]
    Можно, конечно, и пойти тем путем, который, вероятно, выбрали Вы, т.е. каждой сес.. пардон, форме - по сер.. пардон, датамодулю. Но это, ИМХО, очень "раздробит" проектный код, сделав его трудно читаемым, да и вряд ли избавит Вас от кучи лишнего при реализациях "особенностей"

    ИМХО, более одного "базаданного" датамодуля имеет делать только если у Вас, например, более одной БД одновременно либо есть некий кусок (например, объявления классов в объектной БД), стоящий вне физических БД, как бы над ними, но актуальный для физических БД. Либо Вы хотите часть деклараций и реализации вынести из проекта для дальнейшего использования (например, в репозиторий) в других разработках.

    В любом случае не рекомендую без особой надобности использовать более одного датамодуля. Как показывает практика, множество проблем можно решить просто добавив в делфи собственные библиотеки юнитов (по образу и подобию делфишых)
  • Ega23 © (14.01.09 12:15) [5]
    type

     TMySuperPuperMegaForm = class (TForm)
     private
       procedure SetDataModule(Value : TMySuperMegaDataModule);
     public
       property MySuperMegaDataModule : TMySuperMegaDataModule read FMySuperMegaDataModule write SetDataModule;

     end;

    procedure TMySuperPuperMegaForm.SetDataModule(Value : TMySuperMegaDataModule);
    begin
     FMySuperMegaDataModule := Value;
     if Value=nil then Exit;

     Подключаем все контролы и всё остальное...
     ....
    end;

  • Рыбба (14.01.09 12:42) [6]
    [3], [4]
    Спасибо за ответ.
    Расскажу немного.
    На датамодуле-предке (TMyDM) находятся общие процедуры работы с БД, а также расположены компоненты подключения к серверу БД, несколько датасетов для операций с базой (например, для разовых выполнений каких-то запросов) и некоторые невизуальные компоненты. Ну, например, ImageList (который в себе хранит картинки, например, для разных состояний записи - проведен, не проведен, удален и прочее). Или, возможно, набор стилей для грида DevExpress. Соотственно, в некоторых формах есть ссылки, допустим на ImageList. После наследования эти ссылки должны вести не на предка, а на потомка. Во-вторых, в коде есть явное указание датамодуля, например в коде:
    with MyDM.DataSet do begin ... end;


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

    [5] Спасибо за пример. Попробую вечером. А визуально я могу сослаться на property MySuperMegaDataModule в дизайнере форм?
    Еще недостаток этого подхода по-моему: форма должна быть подключена практически везде для видимости. Всем видимый датамодуль как-то привычней... Но это уже, наверное, дело вкуса
  • Медвежонок Пятачок © (14.01.09 12:42) [7]
    Ведь в классах формы есть ссылки на TMyDM

    ну и пусть будут ссылки.
  • Медвежонок Пятачок © (14.01.09 12:47) [8]
    В любом случае не рекомендую без особой надобности использовать более одного датамодуля.

    С наследованием это никак не связано.
    У меня например базовый Dm и сто его наследников для разных библиотек доступа и разных субд.
    Но в приложении единственный экземпляр dm
  • Ega23 © (14.01.09 12:50) [9]

    > А визуально я могу сослаться на property MySuperMegaDataModule
    > в дизайнере форм?


    Ну если наприльником заточить - то пуркуа бы и не па. А смысл?
  • Медвежонок Пятачок © (14.01.09 12:52) [10]
    with MyDM.DataSet do begin ... end;

    with GetMyDataModuleMethod.DataSet do begin ... end;
  • Рыбба (14.01.09 13:02) [11]
    [9] При дизайне проекта в среде. Или всю привязку делать в рантайме?
    [10] А при визуальном проектировании?
  • Ega23 © (14.01.09 13:30) [12]

    > [9] При дизайне проекта в среде. Или всю привязку делать
    > в рантайме?
    > [10] А при визуальном проектировании?


    Я в рантайме делаю. Дизайн-тайм развращает....  :)

    Но можно сделать и для дизайн-тайм.
  • MsGuns © (14.01.09 14:04) [13]
    >Медвежонок Пятачок ©   (14.01.09 12:47) [8]
    >С наследованием это никак не связано.

     А я не нсоветовал наследовать

    >У меня например базовый Dm и сто его наследников для разных библиотек доступа и разных субд. Но в приложении единственный экземпляр dm

    Бога ради. Но я предпочитаю ОБЩИЙ код делать универсальным и выносить его вообще из проектов в библиотеку. Так просто удобнее ИМХО. И не нужно использовать наследование ИМХО оно здесь неуместно.

    >Рыбба   (14.01.09 12:42) [6]

    Ваш пример очень вписывается в "библиотечную схему". Все процедуры и функции библиотеки получают необходимые объекты в виде ссылок параметирами, сам ни к кому не обращаясь напрямую. И их можно (и нужно !) использовать в других "родственных" проектах.
    Если задача (не проект, а проектируемая система в целом) достаточно сложная, то общие алгоритмы, классы и т.д. предпочтительнее разбить на несколько юнитов. Опять же как в делфи :)

    Более того, библиотеки можно использовать и при смене предмета автоматизации, места работы и даже профспецифики :) С датамодулями это сделать сложнее.
  • Медвежонок Пятачок © (14.01.09 14:13) [14]
    Бога ради. Но я предпочитаю ОБЩИЙ код делать универсальным и выносить его вообще из проектов в библиотеку. Так просто удобнее ИМХО. И не нужно использовать наследование ИМХО оно здесь неуместно.

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

    так что "общий код" только в базовом классе.
  • MsGuns © (14.01.09 14:22) [15]
    >Базовый модуль содержит реализацию всей логики бизнес процессов.

    Аналогично для библиотечной технологии

    >Но при этом ничего не знает ни о компонентах доступа, ни о платформе.

    Кхе-кхе, это как ?

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

    А причем тут датамодуль ? На том, что ты пишешь, стоИт делфи, только я что-то не помню, чтоб там использовались датамодули

    >так что "общий код" только в базовом классе.

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

    У меня, кстати, библиотечным образом реализовано куча форм, всякие поиски, фильтры, диалоги и т.д. Так что в проекте не надо никаких форм, датамодулей и т.д. которые пусть они хоть вообще не содержат кода, но все же "тянут" на себя и ресурсы, и время, и утяжеляют проект, добавляя в него доп.файлы (вот не люблю я когда в рабочей папке сотни файлов, и всё !)

    Хотя, кончно, кому поп, кому попадья :)
  • Медвежонок Пятачок © (14.01.09 14:26) [16]
    Кхе-кхе, это как ?

    Обыкновенно. Вся работа идет на уровне TDataSet.
  • MsGuns © (14.01.09 14:29) [17]
    Ты ж сказал "ничего не зная о компонентах" и, тем более "платформе" :)

    "Как понимать тебя, Саид ?" (с)
  • Ega23 © (14.01.09 14:37) [18]

    > Ты ж сказал "ничего не зная о компонентах" и, тем более
    > "платформе" :)


    Всё потомок TDataSet.
  • Медвежонок Пятачок © (14.01.09 14:43) [19]
    Базовый модуль данных ничего не знает о компонетах (bde,ado,fibs,odac etc)
    И про сервер ничего не знает. Это может быть любой сервер или вообще файлы dbase/paradox

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

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

    В переопределенных методах никакой бизнес логики нет, голая техника типа такого

    function CreateSelectSQLComponent(const ASQLText : string; var AComponent : TComponent; AOpen : boolean; const AEditTableName,AkeyFields,AGeneratorName : string) : boolean; overload; override;

    итого: чтобы собрать новую версию на совершенно другом движке и компонентах уходит час - полтора.
 
Конференция "Прочее" » Как правильно наследоваться от TDataModule?
Есть новые Нет новых   [134453   +32][b:0][p:0.001]