Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 4 819

/ вопрос открыт /

Здравствуйте, товарищи эксперты!
пишу open-source шифрованный форум, который будет выполняться на машинах клиентов и обмениваться зашифрованными ассиметричным шифрованием пакетами по электронной почте.
использую SQLite
вопрос стоит о идеологически верной организации процедур записи и чтения в базу

Приложение:
  1.  
  2. {{code}}
  3. TMessage = class (TObject)
  4. private
  5. f_ID: TID;
  6. protected
  7. function GetID : TID;
  8. procedure SetID (const aValue: TID) : TID;
  9. class function _GetID (const aValue: TID) : TID;
  10. class function _SetID (const aValue: TID) : TID;
  11. public
  12. property ID: TID read GetID write SetID default 0;
  13. end;
  14. {{/code}}
  15.  
  16.  
  17.  


mirt.steelwater Вопрос ожидает решения (принимаются ответы, доступен мини-форум)

Вопрос задал: mirt.steelwater (статус: Посетитель)
Вопрос отправлен: 14 декабря 2010, 15:50
Состояние вопроса: открыт, ответов: 0.


Мини-форум вопроса

Всего сообщений: 19; последнее сообщение — 16 декабря 2010, 14:00; участников в обсуждении: 2.
Вадим К

Вадим К (статус: Академик), 14 декабря 2010, 17:17 [#1]:

вот тут точно не ошибка?
procedure SetID (const aValue: TID) : TID;

непонятно назначение методов
class function _GetID (const aValue: TID) : TID;
class function _SetID (const aValue: TID) : TID;
Галочка "подтверждения прочтения" - вселенское зло.
mirt.steelwater

mirt.steelwater (статус: Посетитель), 14 декабря 2010, 18:27 [#2]:

ну да - я опечатался, процедура не возвращает тип, конечно
procedure SetID (const aValue: TID);
Ⓐ свобода сопротивление солидарность
mirt.steelwater

mirt.steelwater (статус: Посетитель), 14 декабря 2010, 18:31 [#3]:

методы класса _GetID и _SetID нужны для того, чтобы приводить значения свойства в значения полей без создания экземпляра объекта в функциях класса этого объекта - вернусь домой, я приложу весь код.
там что-то вроде такого:
class procedure TMessage.Delete (aDB: TDataBase; const anID: TID);
begin
    query := Format ('DELETE FROM messages WHERE id="%d"',
                     [ _SetID (anID) ]); 
end;
Ⓐ свобода сопротивление солидарность
Вадим К

Вадим К (статус: Академик), 15 декабря 2010, 11:15 [#4]:

Цитата:

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

спрашивается - а смысл??? почему нельзя воспользоваться предыдущими методами? Или для других значений? тогда это ещё может быть как то оправдано. Но не сильно:)

То есть, у Вас в классе есть дубликаты? тогда это можно попробовать решить одним общим наследником. разберем на примере _SetID и SetID.
Как бы Вы не писали код, для этих методов возможно пять вариантов:
- у каждой свой уникальный код. Это плохо. потому что нужно следить за идентичностью методов.
- они являются точной копией друг дружки, за небольшими исключениями. Это не лучше первого варианта.
- оба эти метода вызывают какой то один метод/функцию. Это уже лучше. значительно лучше, но есть ещё излишество.
- классовый метод вызывает неклассовый. Все хорошо, кроме одного - придется создавать объект, а Вы этого не хотите.
- неклассовый метод вызывает классовый метод. Это уже достаточно хорошо. Где то так
procedure TMessage.SetID (const aValue: TID) : TID;
begin
  _SetID(aValue);
end;
 
class procedure TMessage._SetID (const aValue: TID);
begin
  // а тут код преобразования.
end;

Согласитесь - это уже сильно упрощает написание. Но как не хочется каждый раз писать. Поэтому пишем базовый класс, который заключит в себя часть функционала.
    TBase = class (TObject)
    private
        f_ID: TID;
    protected
        function GetID : TID; virtual;
        procedure SetID (const aValue: TID) ; virtual;
        class function _GetID (const aValue: TID) : TID; Virtual; Abstract;
        class procedure _SetID (const aValue: TID); Virtual; Abstract;
    public
        property ID: TID read GetID write SetID default 0;
    end;
////
procedure TBase.SetID (const aValue: TID) : TID;
begin
  _SetID(aValue);
end;
function TBase.GetID : TID;
begin
  result := _GetID;
end;
( я не обещаю, что этот код заработает в 7 делфи и младше, а вот в 2005 и старше должно).

Теперь, когда нужно создать новый класс, просто делается так
type
  TMessage = class(TBase)
  protected    
    class function _GetID (const aValue: TID) : TID; override;
    class procedure _SetID (const aValue: TID); override;
  end;
////
 
 class function TMessage._GetID (const aValue: TID) : TID; abstract;
 begin
 // реализация
 end;
 class procedure TMessage._SetID (const aValue: TID); abstract;
 begin
 // реализация
 end;
Итого, что получается. Два метода написать мы никогда не забудем - их и не нужно писать - они уже есть. Свойство также всегда есть. А два других метода нам не даст забыть компилятор - там есть ключевое слово abstract, которое будет требовать реализацию этого метода. То есть, сплошной плюс.

Что же делать, если в каком то из наследников потребуется неклассовые методы доступа написать как то по особому? никаких проблем. Возле них недаром в базовом классе написано virtual. Поэтому, если нужно нестандартное поведение, мы просто его реализуем, не забывая добавить слово override;

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


P.S. у меня нет возможности проверить этот код. Но идеологически он верен. Скорее всего его придется хорошо доработать напильником под Ваши нужды.
Галочка "подтверждения прочтения" - вселенское зло.
mirt.steelwater

mirt.steelwater (статус: Посетитель), 16 декабря 2010, 11:22 [#5]:

да ведь я так и сделал
проблема только в том, что единственное что я могу определить в базовом классе - это именно операции с идентификатором
а все остальные свойства сущностей в потомках отличаются - и приходится писать 2 метода объекта вызывающих по возможности методы класса. и 2 метода класса, которые стараются не прибегать к созданию временного экземпляра.
Ⓐ свобода сопротивление солидарность
mirt.steelwater

mirt.steelwater (статус: Посетитель), 16 декабря 2010, 11:22 [#6]:

{ ñîîáùåíèå }
{$M+}
    CMessage = class of TMessage;
    PMessage = ^TMessage;
    TMessage = class (TObject)
    private
        f_DB: TSQLiteDatabase;           { îáúåêò áàçû
äàííûõ }
        f_ID: TID;                       { óíèêàëüíûé
èäåíòèôèêàòîð }
        f_TimeStampCreate: DWORD;        { äàòà è âðåìÿ
ñîçäàíèÿ }
        f_TimeStampModify: DWORD;        { äàòà è âðåìÿ
èçìåíåíèÿ }
        f_TimeStampPublic: DWORD;        { äàòà è âðåìÿ
îòïðàâêè }
        f_CategorieID: TID;              {
èäåíòèôèêàòîð
êàòåãîðèè, â êîòîðîé
ðàçìåùåíî ñîîáùåíèå }
        f_Categorie: TCategorie;         { îáúåêò
êàòåãîðèè, â êîòîðîé
ðàçìåùåíî ñîîáùåíèå }
        f_MessageTypeID: TID;            {
èäåíòèôèêàòîð òèïà
ñîîáùåíèÿ }
        f_MessageType: TMessageType;     { îáúåêò òèïà
ñîîáùåíèÿ }
        f_MessageStatusID: TID;          {
èäåíòèôèêàòîð
ñòàòóñà ñîîáùåíèÿ }
        f_MessageStatus: TMessageStatus; { îáúåêò
ñòàòóñà ñîîáùåíèÿ }
        f_AuthorID: TID;                 {
èäåíòèôèêàòîð àâòîðà
ñîîáùåíèÿ }
        f_Author: TOperator;             { àâòîð
ñîîáùåíèÿ }
        f_Subject: String;               { òåìà }
        f_Text: String;                  { òåêñò }
        f_Version: TVERSION_INFO;        { âåðñèÿ
ñîîáùåíèÿ }
    protected
        function GetID : TID;
        function GetTimeStampCreate : TDateTime;
        function GetTimeStampModify : TDateTime;
        function GetTimeStampPublic : TDateTime;
        function GetCategorieID : TID;
        function GetCategorie : TCategorie;
        function GetMessageTypeID : TID;
        function GetMessageType : TMessageType;
        function GetMessageStatusID : TID;
        function GetMessageStatus : TMessageStatus;
        function GetAuthorID : TID;
        function GetAuthor : TOperator;
        function GetSubject : String;
        function GetText : String;
        function GetVersion : TVERSION_INFO;
        function GetHash : String;
 
        procedure SetID (const aValue: TID);
        procedure SetTimeStampCreate (const aValue: TDateTime);
        procedure SetTimeStampModify (const aValue: TDateTime);
        procedure SetTimeStampPublic (const aValue: TDateTime);
        procedure SetCategorieID (const aValue: TID);
        procedure SetCategorie (const aValue: TCategorie);
        procedure SetMessageTypeID (const aValue: TID);
        procedure SetMessageType (const aValue: TMessageType);
        procedure SetMessageStatusID (const aValue: TID);
        procedure SetMessageStatus (const aValue: TMessageStatus);
        procedure SetAuthorID (const aValue: TID);
        procedure SetAuthor (const aValue: TOperator);
        procedure SetSubject (const aValue: String);
        procedure SetText (const aValue: String);
        procedure SetVersion (const aValue: TVERSION_INFO);
 
        class function _GetID (const aValue: TID) : TID;
        class function _GetTimeStampCreate (const aValue: DWORD) : TDateTime;
        class function _GetTimeStampModify (const aValue: DWORD) : TDateTime;
        class function _GetTimeStampPublic (const aValue: DWORD) : TDateTime;
        class function _GetCategorieID (const aValue: TID) : TID;
        class function _GetCategorie (const aValue: TCategorie) : TCategorie;
        class function _GetMessageTypeID (const aValue: TID) : TID;
        class function _GetMessageType (const aValue: TMessageType) : TMessageType;
        class function _GetMessageStatusID (const aValue: TID) : TID;
        class function _GetMessageStatus (const aValue: TMessageStatus) : TMessageStatus;
        class function _GetAuthorID (const aValue: TID) : TID;
        class function _GetAuthor (const aValue: TOperator) : TOperator;
        class function _GetSubject (const aValue: String) : String;
        class function _GetText (const aValue: String) : String;
        class function _GetVersion (const aValue: TVERSION_INFO) : TVERSION_INFO;
 
        class function _SetID (const aValue: TID) : TID;
        class function _SetTimeStampCreate (const aValue: TDateTime) : DWORD;
        class function _SetTimeStampModify (const aValue: TDateTime) : DWORD;
        class function _SetTimeStampPublic (const aValue: TDateTime) : DWORD;
        class function _SetCategorieID (const aValue: TID) : TID;
        class function _SetCategorie (const aValue: TCategorie) : TCategorie;
        class function _SetMessageTypeID (const aValue: TID) : TID;
        class function _SetMessageType (const aValue: TMessageType) : TMessageType;
        class function _SetMessageStatusID (const aValue: TID) : TID;
        class function _SetMessageStatus (const aValue: TMessageStatus) : TMessageStatus;
        class function _SetAuthorID (const aValue: TID) : TID;
        class function _SetAuthor (const aValue: TOperator) : TOperator;
        class function _SetSubject (const aValue: String) : String;
        class function _SetText (const aValue: String) : String;
        class function _SetVersion (const aValue: TVERSION_INFO) : TVERSION_INFO;
    public
        constructor Create (DB: TSQLiteDatabase; anArgs: array of const); overload;
        constructor Create (DB: TSQLiteDatabase; anArgs: array of const; aVersion: TVERSION_INFO); overload;
        constructor Create (DB: TSQLiteDatabase; anArgs: array of const; aVersion: array of const); overload;
        destructor Destroy; override;
 
        class function Load (DB: TSQLiteDatabase; const anID: TID) : TMessage; overload;
        procedure Load; overload;
 
        class function Find (DB: TSQLiteDatabase; const aHash: String) : TID;
 
        class function Save (DB: TSQLiteDatabase; anArgs: array of const) : TID; overload;
        procedure Save; overload;
 
        class procedure Delete (DB: TSQLiteDatabase; const anID: TID); overload;
        procedure Delete; overload;
        class procedure DeleteOnType (DB: TSQLiteDatabase; const aTypeID: TID); overload;
        class procedure DeleteOnType (DB: TSQLiteDatabase; const aTypeName: String); overload;
        class procedure DeleteOnStatus (DB: TSQLiteDatabase; const aStatusID: TID); overload;
        class procedure DeleteOnStatus (DB: TSQLiteDatabase; const aStatusName: String); overload;
        class procedure DeleteOnAuthor (DB: TSQLiteDatabase; const anAuthorID: TID); overload;
        class procedure DeleteOnAuthor (DB: TSQLiteDatabase; const anAuthorName: String); overload;
        class procedure DeleteAll (DB: TSQLiteDatabase; const aCategorieID: TID);
 
        property ID: TID read GetID write SetID default 0;
        property TimeStampCreate: TDateTime read GetTimeStampCreate write SetTimeStampCreate;
        property TimeStampModify: TDateTime read GetTimeStampModify write SetTimeStampModify;
        property TimeStampPublic: TDateTime read GetTimeStampPublic write SetTimeStampPublic;
        property CategorieID: TID read GetCategorieID write SetCategorieID default 0;
        property Categorie: TCategorie read GetCategorie write SetCategorie;
        property MessageTypeID: TID read GetMessageTypeID write SetMessageTypeID default 0;
        property MessageType: TMessageType read GetMessageType write SetMessageType;
        property MessageStatusID: TID read GetMessageStatusID write SetMessageStatusID default 0;
        property MessageStatus: TMessageStatus read GetMessageStatus write SetMessageStatus;
        property AuthorID: TID read GetAuthorID write SetAuthorID default 0;
        property Author: TOperator read GetAuthor write SetAuthor;
        property Subject: String read GetSubject write SetSubject;
        property Text: String read GetText write SetText;
        property Version: TVERSION_INFO read GetVersion write SetVersion;
        property Hash: String read GetHash;
    end;
{$M-}
Ⓐ свобода сопротивление солидарность
mirt.steelwater

mirt.steelwater (статус: Посетитель), 16 декабря 2010, 11:23 [#7]:

{ êàòåãîðèÿ }
{$M+}
    CCategorie = class of TCategorie;
    PCategorie = ^TCategorie;
    TCategorie = class (TObject)
    private
        f_DB: TSQLiteDatabase;               { îáúåêò áàçû
äàííûõ }
        f_ID: TID;                           { óíèêàëüíûé
èäåíòèôèêàòîð }
        f_ParentID: TID;                     {
èäåíòèôèêàòîð ïðåäêà
â ëîãè÷åñêîì äåðåâå
êàòåãîðèé }
        f_Parent: TCategorie;                { ññûëêà íà
ïðåäêà â ëîãè÷åñêîì
äåðåâå êàòåãîðèé }
        f_TimeStampCreate: DWORD;            { äàòà è âðåìÿ
ñîçäàíèÿ }
        f_TimeStampModify: DWORD;            { äàòà è âðåìÿ
èçìåíåíèÿ }
        f_TimeStampPublic: DWORD;            { äàòà è âðåìÿ
îòïðàâêè }
        f_CategorieTypeID: TID;              {
èäåíòèôèêàòîð òèïà
êàòåãîðèè }
        f_CategorieType: TCategorieType;     { îáúåêò òèïà
êàòåãîðèè }
        f_CategorieStatusID: TID;            {
èäåíòèôèêàòîð
ñòàòóñà êàòåãîðèè }
        f_CategorieStatus: TCategorieStatus; { îáúåêò
ñòàòóñà êàòåãîðèè }
        f_AuthorID: TID;                     {
èäåíòèôèêàòîð àâòîðà
êàòåãîðèè }
        f_Author: TOperator;                 { àâòîð
êàòåãîðèè }
        f_Name: String;                      { íàçâàíèå }
        f_Description: String;               { îïèñàíèå }
        f_Version: TVERSION_INFO;            { âåðñèÿ
êàòåãîðèè }
    protected
        function GetID : TID;
        function GetParentID : TID;
        function GetParent : TCategorie;
        function GetTimeStampCreate : TDateTime;
        function GetTimeStampModify : TDateTime;
        function GetTimeStampPublic : TDateTime;
        function GetCategorieTypeID : TID;
        function GetCategorieType : TCategorieType;
        function GetCategorieStatusID : TID;
        function GetCategorieStatus : TCategorieStatus;
        function GetAuthorID : TID;
        function GetAuthor : TOperator;
        function GetName : String;
        function GetDescription : String;
        function GetVersion : TVERSION_INFO;
        function GetHash : String;
 
        procedure SetID (const aValue: TID);
        procedure SetParentID (const aValue: TID);
        procedure SetParent (const aValue: TCategorie);
        procedure SetTimeStampCreate (const aValue: TDateTime);
        procedure SetTimeStampModify (const aValue: TDateTime);
        procedure SetTimeStampPublic (const aValue: TDateTime);
        procedure SetCategorieTypeID (const aValue: TID);
        procedure SetCategorieType (const aValue: TCategorieType);
        procedure SetCategorieStatusID (const aValue: TID);
        procedure SetCategorieStatus (const aValue: TCategorieStatus);
        procedure SetAuthorID (const aValue: TID);
        procedure SetAuthor (const aValue: TOperator);
        procedure SetName (const aValue: String);
        procedure SetDescription (const aValue: String);
        procedure SetVersion (const aValue: TVERSION_INFO);
 
        class function _GetID (const aValue: TID) : TID;
        class function _GetParentID (const aValue: TID) : TID;
        class function _GetParent (const aValue: TCategorie) : TCategorie;
        class function _GetTimeStampCreate (const aValue: DWORD) : TDateTime;
        class function _GetTimeStampModify (const aValue: DWORD) : TDateTime;
        class function _GetTimeStampPublic (const aValue: DWORD) : TDateTime;
        class function _GetCategorieTypeID (const aValue: TID) : TID;
        class function _GetCategorieType (const aValue: TCategorieType) : TCategorieType;
        class function _GetCategorieStatusID (const aValue: TID) : TID;
        class function _GetCategorieStatus (const aValue: TCategorieStatus) : TCategorieStatus;
        class function _GetAuthorID (const aValue: TID) : TID;
        class function _GetAuthor (const aValue: TOperator) : TOperator;
        class function _GetName (const aValue: String) : String;
        class function _GetDescription (const aValue: String) : String;
        class function _GetVersion (const aValue: TVERSION_INFO) : TVERSION_INFO;
 
        class function _SetID (const aValue: TID) : TID;
        class function _SetParentID (const aValue: TID) : TID;
        class function _SetParent (const aValue: TCategorie) : TCategorie;
        class function _SetTimeStampCreate (const aValue: TDateTime) : DWORD;
        class function _SetTimeStampModify (const aValue: TDateTime) : DWORD;
        class function _SetTimeStampPublic (const aValue: TDateTime) : DWORD;
        class function _SetCategorieTypeID (const aValue: TID) : TID;
        class function _SetCategorieType (const aValue: TCategorieType) : TCategorieType;
        class function _SetCategorieStatusID (const aValue: TID) : TID;
        class function _SetCategorieStatus (const aValue: TCategorieStatus) : TCategorieStatus;
        class function _SetAuthorID (const aValue: TID) : TID;
        class function _SetAuthor (const aValue: TOperator) : TOperator;
        class function _SetName (const aValue: String) : String;
        class function _SetDescription (const aValue: String) : String;
        class function _SetVersion (const aValue: TVERSION_INFO) : TVERSION_INFO;
    public
        constructor Create (DB: TSQLiteDatabase; anArgs: array of const); overload;
        constructor Create (DB: TSQLiteDatabase; anArgs: array of const; aVersion: TVERSION_INFO); overload;
        constructor Create (DB: TSQLiteDatabase; anArgs: array of const; aVersion: array of const); overload;
        destructor Destroy; override;
 
        class function Load (DB: TSQLiteDatabase; const anID: TID) : TCategorie; overload;
        procedure Load; overload;
 
        class function Find (DB: TSQLiteDatabase; const aHash: String) : TID;
 
        class function Save (DB: TSQLiteDatabase; anArgs: array of const) : TID; overload;
        procedure Save; overload;
 
        class procedure Delete (DB: TSQLiteDatabase; const anID: TID); overload;
        procedure Delete; overload;
        class procedure DeleteOnType (DB: TSQLiteDatabase; const aTypeID: TID); overload;
        class procedure DeleteOnType (DB: TSQLiteDatabase; const aTypeName: String); overload;
        class procedure DeleteOnStatus (DB: TSQLiteDatabase; const aStatusID: TID); overload;
        class procedure DeleteOnStatus (DB: TSQLiteDatabase; const aStatusName: String); overload;
        class procedure DeleteOnAuthor (DB: TSQLiteDatabase; const anAuthorID: TID); overload;
        class procedure DeleteOnAuthor (DB: TSQLiteDatabase; const anAuthorName: String); overload;
        class procedure DeleteAll (DB: TSQLiteDatabase; const aParentID: TID);
 
        property ID: TID read GetID write SetID default 0;
        property ParentID: TID read GetParentID write SetParentID default 0;
        property Parent: TCategorie read GetParent write SetParent;
        property TimeStampCreate: TDateTime read GetTimeStampCreate write SetTimeStampCreate;
        property TimeStampModify: TDateTime read GetTimeStampModify write SetTimeStampModify;
        property TimeStampPublic: TDateTime read GetTimeStampPublic write SetTimeStampPublic;
        property CategorieTypeID: TID read GetCategorieTypeID write SetCategorieTypeID default 0;
        property CategorieType: TCategorieType read GetCategorieType write SetCategorieType;
        property CategorieStatusID: TID read GetCategorieStatusID write SetCategorieStatusID default 0;
        property CategorieStatus: TCategorieStatus read GetCategorieStatus write SetCategorieStatus;
        property AuthorID: TID read GetAuthorID write SetAuthorID default 0;
        property Author: TOperator read GetAuthor write SetAuthor;
        property Name: String read GetName write SetName;
        property Description: String read GetDescription write SetDescription;
        property Version: TVERSION_INFO read GetVersion write SetVersion;
        property Hash: String read GetHash;
    end;
{$M-}
Ⓐ свобода сопротивление солидарность
mirt.steelwater

mirt.steelwater (статус: Посетитель), 16 декабря 2010, 11:23 [#8]:

как видим за исключением лишь некоторых - свойства не повторяются в классах, описывающих хранимые сущности. и таких классов достаточно много, нет никакого однозначно переходящего всюду параметра, кроме ID. определять все свойства всех классов в базовом неправильно, т.к. это даст доступ из потомков к несуществующим свойствам их сущности.
можно, конечно, определить в общем предке только методы
_GetX, _SetX, GetX, SetX
а в наследниках определять свойства с вызовом соотв. методов и при необходимости их переопределять, но я не уверен, что это правильно - тогда нарушается логическая связь "потомственности" и приводит к "вырождению" потомков в сущности большей общности, чем предок..
Ⓐ свобода сопротивление солидарность
mirt.steelwater

mirt.steelwater (статус: Посетитель), 16 декабря 2010, 11:29 [#9]:

а методы объекта у меня вызывают методы класса - это понятно..
function TMessage.GetTimeStampCreate : TDateTime;
begin
    Result := 0.0;
    try
        Result := _GetTimeStampCreate (f_TimeStampCreate);
    except on E: Exception do
        raise EClass.Create ([self,'GetTimeStampCreate',ERR_TMESSAGE_GET_TIME_STAMP_CREATE,E],
                             ['{6DC3684E-2866-4B9B-9441-3EDCB0A1E15A}']);
    end;
end;
 
procedure TMessage.SetTimeStampCreate (const aValue: TDateTime);
begin
    try
        f_TimeStampCreate := _SetTimeStampCreate (aValue);
    except on E: Exception do
        raise EClass.Create ([self,'SetTimeStampCreate',ERR_TMESSAGE_SET_TIME_STAMP_CREATE,E],
                             ['{0BF909DD-57DA-4DA0-AF5C-2B8A3F287866}']);
    end;
end;
 
class function TMessage._GetTimeStampCreate (const aValue: DWORD) : TDateTime;
begin
    Result := 0.0;
    try
        if ( aValue > 0 ) then
            Result := UnixToDateTime (aValue)
        {else
            raise Exception.Create (ERR_TMESSAGE_INCORRECT_TIME_STAMP_CREATE)};
    except on E: Exception do
        raise EClass.Create ([self,'_GetTimeStampCreate',ERR_TMESSAGE_GET_TIME_STAMP_CREATE,E],
                             ['{777770B1-1D4E-4136-84B7-E2C6783E34C2}']);
    end;
end;
 
class function TMessage._SetTimeStampCreate (const aValue: TDateTime) : DWORD;
begin
    Result := 0;
    try
        if ( aValue > 0 ) then
            Result := DateTimeToUnix (aValue)
        {else
            raise Exception.Create (ERR_TMESSAGE_INCORRECT_TIME_STAMP_CREATE)};
    except on E: Exception do
        raise EClass.Create ([self,'_SetTimeStampCreate',ERR_TMESSAGE_SET_TIME_STAMP_CREATE,E],
                             ['{5AEF918D-857E-4127-8124-0999B547CB63}']);
    end;
end;
Ⓐ свобода сопротивление солидарность
Вадим К

Вадим К (статус: Академик), 16 декабря 2010, 12:00 [#10]:

Цитата:

определять все свойства всех классов в базовом неправильно

логично.
посмотрел реализацию методов *TimeStampCreate
в методе SetTimeStampCreate try-except выглядит немного лишним. Маловероятно, что там будет ошибка - она скорее отловиться методом _SetTimeStampCreate
Если все методы так выглядят - это с ума сойти можно.

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

И есть второй подход. Называется "генератор". Суть в том, что эти все методы очень похожи друг на друга, и проще написать программу, которая будет брать текстовый файл, в котором описана структура (а ещё красивее - прямо с базы структуру брать) и по ней генерировать все эти классы. Так поступают многие "фреймворки" для крутых систем. Более того, делфи позволяет (начиная с 2006 версии вроде) подключать свои компиляторы и преобразователи текста. То есть можно спокойно прям в делфи писать себе структуру, а прекомпилятор вызовет утилиту и преобразует все.
Галочка "подтверждения прочтения" - вселенское зло.
mirt.steelwater

mirt.steelwater (статус: Посетитель), 16 декабря 2010, 12:17 [#11]:

да, я думал над первым предложенным вариантом ранее - он имеет свои плюсы и минусы.
плюсы в том, что нет лишнего кода, есть только функциональный код - изначально именно так у меня и было написано. но при большом размере проекта (и проект теоретически должны улучшать под себя в дальнейшем совершенно незнакомые мне люди, с которыми я смогу общаться максимум на плохом английском) - очень запутанно будет, если не будет методов класса для явных преобразований свойств в поля и полей в свойства. т.е. сейчас мне вроде все понятно - вот время в БД у меня в unix-формате, текст в 16-ричке здесь, а здесь он зашифрован и опять же переведен в 16-ричку, потом я делаю все операции в обратном порядке при загрузке. но если кто-нибудь глянет в бд, увидит 16-ричку, попытается перевести в ASCII или UNICOD - ничего дельного у него не выйдет, т.к. оно зашифровано - и все, он будет долго думать и искать, пока не поймет, что оно шифровалось, будет искать какими ключами оно должно шифроваться и расшифровываться и т.п. -- вообщем нет однотипности в коде в таком случае.

второй вариант меня заинтересовал - не могли бы дать ссылки на что-то похожее?
Ⓐ свобода сопротивление солидарность
Вадим К

Вадим К (статус: Академик), 16 декабря 2010, 13:01 [#12]:

например protobuf (это на самом деле немного больше - там ещё передача данных, но это не важно) - http://code.google.com/intl/uk-UA/apis/protocolbuffers/docs/overview.html для делфи такого пока не встречал...
Галочка "подтверждения прочтения" - вселенское зло.
mirt.steelwater

mirt.steelwater (статус: Посетитель), 16 декабря 2010, 13:17 [#13]:

спасибо
для дельфи вряди получится это реализовать - сделать ассоциативный список методов у класса можно, но код их должен либо подгружаться из библиотеки либо уже должен быть реализован.
можно, конечно, попробовать сделать что-то вроде:
TMetaMethod = function (anArgs: array of const) : LongWord;
TMetaObject = class
private
    f_Methods: TList;
    f_Properties: TList;
protected
    function GetMethodOf (anIndex: String) : TMetaMethod;
    procedure SetMethodOf (anIndex: String; aValue: TMetaMethod);
    //...
public
    Methods [anIndex: String]: TMetaMethod read GetMethodOf write SetMethodOf;
    Properties [anIndex: String]: TMetaProperty read GetPropertyOf write SetPropertyOf;
end;
и хранить в f_Methods указатели на функции, потом их вызывать, добавлять те или иные - в зависимости от типа поля БД и т.п.
но это уж совсем как-то монстроподобно мне видится..
когда то я делал на PHP в таблицах хранил классы, свойства классов, методы классов и объектов, связь потомков и родителей и т.п.
но в дельфи это будет проблематично, вероятно
Ⓐ свобода сопротивление солидарность
Вадим К

Вадим К (статус: Академик), 16 декабря 2010, 13:23 [#14]:

В вышеприведенном коде есть фундаментальная ошибка проектирования - свойства и методы их обрабатывающие - разделены. Нужно делать одну сущность методы+свойство и один потом "массив".
Галочка "подтверждения прочтения" - вселенское зло.
mirt.steelwater

mirt.steelwater (статус: Посетитель), 16 декабря 2010, 13:29 [#15]:

хм.. почему?
Ⓐ свобода сопротивление солидарность
Вадим К

Вадим К (статус: Академик), 16 декабря 2010, 13:32 [#16]:

потому что не нужно плодить сущности без необходимости.
А в целом - в будущем, где то случайно в один массив добавим, а в другой забудем и будет для одного свойства вызываться совсем другой метод. Получаем феерические ошибки:)
Галочка "подтверждения прочтения" - вселенское зло.
mirt.steelwater

mirt.steelwater (статус: Посетитель), 16 декабря 2010, 13:39 [#17]:

ну я их думал по именам связывать как-то
а вообще можно, конечно, объявить свойство вроде такого:
TMetaProperty = packed record
    Name: String;
    Type: Integer; { TVarRec.VType values }
    Value: TVarRec;
    Default: TVarRec;
    Get: TMetaMethod;
    Set: TMetaMethod;
end;
тогда можно и в одном массиве хранить - только нужно будет хранить указатель на структуру и как-то их различать..
Ⓐ свобода сопротивление солидарность
Вадим К

Вадим К (статус: Академик), 16 декабря 2010, 13:49 [#18]:

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

packed тут не нужно. памяти он сильно не уменьшит. а в целом обычно он сказывается на производительности.
Галочка "подтверждения прочтения" - вселенское зло.
mirt.steelwater

mirt.steelwater (статус: Посетитель), 16 декабря 2010, 14:00 [#19]:

спасибо
попробую переделать это в таком варианте
Ⓐ свобода сопротивление солидарность

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 22 февраля 2025, 11:57
Выполнено за 0.07 сек.