Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2009.08.30;
Скачать: [xml.tar.bz2];

Вниз

WEB <-> Настройки <-> БД   Найти похожие ветки 

 
Пит   (2009-06-30 18:04) [0]

Давно терзают меня измышления на тему WEB-настроек программы, хранения их в БД и кажется, я готов хоть как-то более-менее грамотно описать ситуацию.

В целом, проблема как я понимаю давно рассматриваемая и в некоторых (C#) языках есть средства упрощения данного процесса, а некоторые так и созданы для таких вещей, но рассматривается именно Delphi.

Задача описывается достаточно кратко: в программе есть объекты (сущности, записи - как угодно), у них есть свойства. Хранить эти свойства офлайн нужно в БД. Со стороны пользователя данные сущности настраиваются через WEB.
Собственно, все.

А вот теперь о реализации. Общие проблемы такие:

I) неудобно постоянно разбирать / собирать HTML. Как-то надо автоматизировать, обегчить этот процесс, обеспечить расширяемость и так далее.

II) HTTP протокол текстовый, постоянные конвертации, нужно упрощать процесс.

Более подробно на техническом уровне в чем состоит задача:

1) со стороны сервера формируется HTML-страничка, позволяющая в браузере делать настройки объекта, данная страница пересылается клиенту

Вопрос номер один: кто будет формировать эти странички, позволяющие настраивать объекты?

Это может быть сам объект (его внутренний функционал), какой-то дополнительный внешний код, другие варианты?

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

Сделанные настройки отправляются POST-запросом на сервер. Допустим, серверу это доступно в виде TStrings, имя параметра и его значение (все параметры, напомню, текстовые)

Пример пересылаемых данных для удаления объекта:
action=delete
id=54


Пример для редактирования:
action=edit
id=54
name=Объект номер 54
number=3
...
[свойства объекта]
...


3) сервер обрабатывает полученную информацию: проверяет на корректность, делает соответствующие изменения в БД, изменяет свойства объектов (сущностей) в программе.

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

Что должен уметь функционал - принимать WEB-запросы в виде набора "параметр=значение" и формировать ответ в HTML.


 
Пит   (2009-06-30 18:05) [1]

Вариант 1. Примитивный.

Набор свойств в программе хранится в виде списка на структуры, "ручная" обработка всего и вся

var
 List: TList;   // список свойств
...
function WEBRequest(ParamList: TStrings): string;
var
 id: int64;
begin
 if ParamList["action"] = "add" then
 begin
   if not TryStrToInt64(ParamList["priority"], iPriority) then begin
     Result := "Отсутствует параметр приоритет";
     exit;
   end;
   if (iPriority < 0) or (iPriority > 100) then
   begin
     Result := "Параметр приоритет должен быть в диапазоне 0..100";
     exit;
   end;
   .......
   // сохранение в БД
   INSERT INTO xxx Priority = [iPriority] ...
   // получаем ID получившейся записи
   ID := SELECT ... ;
   // добавление новой сущности в работу
   New(Param);
   Param.ID := ID;
   Param.Priority := iPriority ;
   ...
   List.Add(Param);
 end;
end;


Код ужасен. Приведена только часть кода, которая отвечает за создание нового объекта. А еще есть редактирование, удаление, другие объекты. Да и показана обработка только одного свойства.

Код будет очень избыточным. Проверка на допустимость Priority нужна и в секции редактирования объекта, и в секции добавления нового объекта. И так каждый раз, плюс конвертации постоянные текстовых параметров в нужные типы.

Более-менее сложная иерархия, кода будет килобайты, ну в общем что тут обсуждать.


 
Пит   (2009-06-30 18:05) [2]

Вариант 2. Продвинутый.

Пишется некоторый класс, который обегчает работу с WEB-ом. Параллельно он вынужден инкапсулировать работу с хранилищем данных, иначе от него немного толку.
Для наглядности некоторое описание этого класса:

THTMLDBConfig = class
...
procedure AddProperty(Name, Desc: string; TypeProp: TTypeProp;
     DefValue: string; HTMLMaxLength:integer=-1; HTMLSize: integer=-1;
     CheckBoxLabel:string="");
function AddRecord(ParamList: TStrings; ErrText: PString): boolean;
   function EditRecord(ParamList: TStrings; PKValue: int64;
     ErrText: PString): boolean;
   procedure DeleteRecord(ParamList: TStrings); overload; virtual;
   procedure DeleteRecord(PKValue: int64); overload; virtual;
   function GetHTMLCodeRecord(PKValue: int64): string; overload; virtual;


Пример настройки такого класса:

AddProperty("Name", "Название магазина", tpTextNotEmpty, "", 50, 20);
AddProperty("Priority", cParamRegCodeNum_desc, tpInt, "", 3, 3);


Дело улучшается. Имея такой класс, двумя строчками я даю понять о существовании двух полей. Задаю имена (это как имена POST-данных, так и имена полей в БД), задаю описание поля (по которому класс может генерировать текстовое описание WEB-ошибок), тип поля, другие характеристики, нужные классу.

Соответственно, пример 1 трансформируется:

function WEBRequest(ParamList: TStrings): string;
begin
 if ParamList["action"] = "add" then Result := HTMLDBConfig.AddRecord(ParamList);
end;


Соответственно, на основании заданной структуры (с помощью AddProperty) класс из переданного ParamList проверяет наличие всех нужных параметров, проверят их валидность, пишет их в базу, выдает ошибки в случае чего.

Процедура же GetHTMLCodeRecord в HTML табличном виде выдает форму настройки параметров данной сущности, опять же на основании заданой структуры через AddProperty.

Налицо инкапсуляция работы с WEB и с БД. Но при этом реальный код по работе с сущностью отделен от БД (плохо это? Хорошо?), конечно класс наносит определенные ограничения, а что поделать.

Зато сколько свойств у объекта, столько строчек кода нужно для определения формата вывода в HTML, редактирование, добавления объектов через HTML в БД.
Недостатки возможно в том, что сторонний класс "отнимает" работу с БД у собственно функционального кода.
И при этом получается, что WEB настраивает не сами сущности в программе, а сущности в БД. То есть, допустим, при редактировании объекта класс проверяет и записывает информацию в БД, откуда для применения изменений она уже должна быть считана в программу. Немного, наверное, порочная практика.

Также нужно обеспечивать синхронизацию между работой вспомогательного WEB-DB класса и той части кода, отвечающей за функционал объекта.

В случае использования такого вспомогательного класса вручную остается писать:

- загрузку свойств объекта из БД для работы (для загрузки при старте программы, для загрузки изменений из БД, которые туда сохранил вспомогательный класс)
- сохрание изменившихся свойств объекта в БД


 
Пит   (2009-06-30 18:05) [3]

Дальнейшие улучшения

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

TClient = class
 // функционал
 ...
 // WEB
 function WEBRequest(ParamList: TSTrings): string;
 ...
 // property
 property Priority: integer write SetPriority read FPriority;
...
end;


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

function TClient.WEBRequest(ParamList: TStrings): string;
begin
 if ParamList["action"] = "edit" then
 begin
   Result := THTMLConfigCheck.Request(ParamList) ;
   if Result <> "" then exit;
   Self.Priority := StrToInt(ParamList["priority"]);
   ...
 end;
end;


При этом класс THTMLConfigCheck настраивается аля:

HTMLConfigCheck.AddProperty("priority", "Приоритет клиента", tpInteger);

тем самым он может производить первоначальные проверки и выдавать ошибки. Дополнительная проверка, возможна, допустим через исключения в сетерах. То есть:

procedure TClient.SetPriority(Priority: integer);
begin
 if (Priority < 0 ) or (Priority > 100) then EMy.Create("Ошибка такая то");
 ...
end;


Соответственно, тогда в WEBRequest должна быть "поимка" исключений при присвоении свойств.

Вся проблема усугубляется тем, что нужно соблюдение некоторых юзеро-ориентированных правил для веба:

- если форма заполнена неверно и отправлена - должен вернуться ПЕРЕЧЕНЬ ошибок (а не первая встретившаяся) заполнения формы с повторным выводом неправильно заполненной формы

Есть еще кое-какие фишки, забыл уже ((

В общем, проблема достаточно многогранная, думаю, у кого нет опыта работ таких связок на дельфи сразу во все проблемы просто не въедет. Описать полностью просто сил нету, статью надо писать. Хотелось бы обсудить, возможно кто-то имеет опыт, решал аналогичные проблемы. От мыслей пухнет голова, сделаешь в одном месте красиво - в другом не очень. А хочется красиво везде, без избыточности...

Если у кого идеи есть - высказывайте, я не все описал, по факту могу уже порассуждать чем плохо, хорошо, в чем затык...


 
test ©   (2009-06-30 18:12) [4]

В Java давно на этот счет сделали DAO DB суть в том что класс отвечает за таблицу(связку таблиц), ты оперируеш обьектами, обьектами уже сами занимаются SQL DML и Select"ом.


 
test ©   (2009-06-30 18:13) [5]

Там этот момент облегчен тем что удалять ничего не надо сервер сам узнает своих.))


 
Пит   (2009-06-30 18:32) [6]


> В Java давно на этот счет сделали DAO DB

круто


> класс отвечает за таблицу(связку таблиц), ты оперируеш обьектами,
>  обьектами уже сами занимаются SQL DML и Select"ом.

какая пользова от этого в дельфи, можно повторить алгоритм? Как это реализовано все принципиально, очень хотелось бы на элементарном примере.


 
sniknik ©   (2009-06-30 18:33) [7]

много букв.., не осилил, но суть вроде уловил, про создание компонент для автоматизации http...

один вопрос по этому поводу, а у тебя есть в дельфи закладки с названиями начинающимися с IW ххх (Intra Web)? и что ты про них думаеш?


 
Пит   (2009-06-30 19:23) [8]


> про создание компонент для автоматизации http...

ну это очень приблизительное описание, ну что-то типа.


> а у тебя есть в дельфи закладки с названиями начинающимися
> с IW ххх (Intra Web)? и что ты про них думаеш?

никогда не работал. Почитал в вики: http://ru.wikipedia.org/wiki/IntraWeb

почитал статейку про IW... Сложилось мнение, что данная технология сильно ограничит возможности.

У нас, во-первых, свой HTTP-сервер (основанный на idHTTP). Свои стили CSS, подсказки, свой дизайн продукта, логика настроек и редактирования. Плюс приложение не использует форм, управляется только через WEB, работает в качестве сервиса... Боюсь, заточка IW под проект будет куда геморойнее, чем реализовать изложенную задачу.

Единственное, чую не встречу человека, который сможет детально понять проблемы ((( Сейчас копаю в сторону того, что сторонний универсальный вспомогательный класс может задавать свойства Delphi объектов через RTTI, ошибки генерировать через исключения в Set"ерах.

Но как конкретно это будет выглядеть. Как организовать редактирование, создание нового объекта... Как связать с сохранением в БД, не писать же в коде каждого set"ера сохранение этого свойства в БД отдельно...

Блин, просто голова пухнет. Писать все варианты и смотреть времени нету, изначально раставить по полочкам и выбрать оптимальный вариант не получается, не хватает опыта, памяти и мозгов ))


 
DVM ©   (2009-06-30 20:40) [9]

Мне тоже было бы интересно услышать кто как подходил к решению данной задачи, описанной Пит-ом.


 
test ©   (2009-06-30 21:46) [10]

Пит   (30.06.09 18:32) [6]
DAO DB это просто требования к классам(программе) как оно должно фунциклировать, реализовать можно хоть на Бейсике.


 
Пит   (2009-06-30 21:49) [11]


> DAO DB это просто требования к классам(программе) как оно
> должно фунциклировать, реализовать можно хоть на Бейсике.
>

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


 
test ©   (2009-06-30 21:55) [12]

Пит   (30.06.09 21:49) [11]
У тебя есть класс основной который занимается соединением и тд, есть соглашения как должен работать класс который таблицу перекрывает. Ты создаешь класс таблицы получаешь запись, меняеш его, сохраняеш состояние, сумбурно мал мало, посмотри в инете там толково расписано, как многие технологии Java они представляет собой описание реализацию делает каждый по своему. Сама технология описывает основные правила и требования к группе классов.


 
Пит   (2009-06-30 22:26) [13]

Попытаюсь кратко подвести размышления, на которых я остановился.
У нас есть три аспекта:

- база данных, которая хранит настройки конфигурации
- некий функциональный код, реализующий нужное нам поведение на основе параметров объектов (свойства которого и хранятся в БД)
- WEB-интерфейс по управления и настройке свойств объектов

Все эти три аспекта должны быть реализованы. Сразу вопрос - где? Сам функционал объекта должен уметь работать с БД, с WEB-параметрами или это отдельный вспомогательный класс, как он будет интегрирован с конкретным объектом?

Грубо говоря у объекта есть:

property Number: integer write xxx read yyy;

Где и кто должен сохранять / загружать это свойство из БД и управлять этим свойством через WEB?

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

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

Можно сделать внешний класс, который при инициализации сделает общий SELECT и по циклу инициализирует все объекты, одна запись в БД = один объект.

Опять же, проверка в сетерах на допустимость значений - это прекрасно. Но допустим нужно проверить не только разрешенный диапазон, но и проверить при загрузке / создания объекта со свойством CodeName равным CodeValue не существует ли уже другого такого объекта с таким же значением CodeName. Сетер класса должен знать о всех других экземплярах данного класса значит. или должен быть вышестоящий управляющий объект со списком всеъ экземпляров, тогда логично в него перенести функционал по работе с БД и WEB...

Блииин, короче я просто не в состоянии продумать адекватную логику. И так, и эдак всплывают подводные камни.

Лучшее, что я сейчас реализовал - это "Пример 2" из поста [2]

Некий универсальный класс, который первоначально нужно настроить на свойства объекта аля:

Config.PKName = "ID";

Config.AddProperty("Name", "Название магазина", tpTextNotEmpty, "", 50, 20);
AddProperty("Priority", "Приоритет", tpInt, "", 3, 3);


Где Name название свойства в БД и в WEB-запросах. Далее идет описание свойства (для текстового описания ошибок), потом тип этого поля (в данном случае текстовое поле, которое не может быть пустым, потом его значение по-умолчанию для нового объекта, размер и максимальная длина в WEB-форме.

В результате этот класс на основании настроек умеет:

- по данным WEB / POST / GET запроса вычленять параметры и сохранять их в БД (редактирование объекта)
- ... создавать в БД новый объект
- ... удалять объект из БД по primary key
- выдавать настройки объекта в виде HTML таблицы
- выдавать HTML таблицу с настройками по-умолчанию для создания нового объекта

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

Поэтому плюс нужно уметь загружать настройки из БД.

И алгоритм немного порочный получается.

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

Минусы очевидны... Но что дальше делать - не знаю. ((


 
antonn ©   (2009-06-30 23:46) [14]

странно что в теме еще не прозвучало слово "xml" :)


 
sniknik ©   (2009-07-01 01:42) [15]

> странно что в теме еще не прозвучало слово "xml" :)
а это что, панацея от всего? или для всего, как бы это правильно выразить.

перечитал, и наконец то все. стало непонятно почему такой упор на дельфи и класс/компонент в дельфи.
"плясать" то тут, имхо, надо от клиента, т.е. html странички, и проверки все в ней яваскриптом делать, и введенное из нее посылать... (а там кстати xml формировать посложнее чем тот же json), на сервере же (в программе) только принять готовые данные и в базу(или ini, без разницы) положить. ну и послать сам html естественно, готовый, просто в нужные места дефоултные значения/старые настройки из базы подставлять.
зачем тут "пляски" с классами, не пойму.


 
antonn ©   (2009-07-01 02:03) [16]


> а это что, панацея от всего? или для всего, как бы это правильно
> выразить.

а это хорошо бы вписалось в протокол обмена через html, и при должном следовании стандарту был бы неплохой независимый интерфейс обмена под разные клиенты, оформленный отдельным "звеном". А пока я почитал автора и какая то каша, точно не понять что не получается, что хочется.
И со стороны расширяемости все таки получше, в данном случае гораздо лучше ini-структуры, удобней описывать св-ва и значения.
Чтоб не делать всякие проверки в коде типа:
if ParamList["action"] = "add" then


 
test ©   (2009-07-01 05:25) [17]

Пит   (30.06.09 22:26) [13]
Поищи в интернете требования/описания/пояснения к Data Acess Objects там готовый вариант алгоритма на описанное тобой лежит, в том числе и с подводными камнями.


 
test ©   (2009-07-01 09:33) [18]

antonn ©   (01.07.09 02:03) [16]
И Ajax и DataMinig и SAX и ....
Не плоди сущности без надобности, бритва Аккамы.


 
makvell   (2009-07-01 10:32) [19]

Послушай test, он дело говорит ;)

Почитать можно, например тут: http://javagu.ru/portal/dt?last=false&provider=javaguru&ArticleId=GURU_ARTICLE_81158&SecID=GURU_SECTION_ 80703
это жава, но проблем с пониманием сути быть не должно :)


 
makvell   (2009-07-01 10:36) [20]

И кстати, по поводу XML, знаю что тут есть его большие "не любители" :) но суть не в этом, как раз тут оно может быть уместно в случае, когда веб морда должна/может меняться, при этом не хочется править код, который ее генерирует. Это, конечно, добавление еще одного звена но... допустим сервер генерит не html, а xml, после чего это xml при помощи xslt трансформируется в нужный нам html. Захотели что-то поменять, поправили трансформацию, ничего не компилим, в код не лезем. Но это просто так, вдруг тоже пригодится :)


 
Пит   (2009-07-01 12:08) [21]


>  стало непонятно почему такой упор на дельфи

потому что программа на дельфи разрабатывается?!


> и класс/компонент
> в дельфи

о компоненте речи не шло. Что касается оформления в виде набора функций / классом - ну так вопрос не принципиальный. Но у нас же все таки ООП, так что наверное лучше оперировать объектами.


> "плясать" то тут, имхо, надо от клиента, т.е. html странички,
>  и проверки все в ней яваскриптом делать

нуууу, братец... Ты сейчас сказанул.

Элементарно отключен JS в браузере и все. Браузер тебе пошлет какие угодно данные (это мы не рассматриваем примеры, когда насильно будут посылать неверные данные). Например, в качестве системного номера тебе прийдет строка:

SysNum=Hi man

И что ты будешь делать? Сделаешь аля:

INSERT INTO ... SysNum = :param1

Query.SetParamByName("param1").AsInteger := StrToInt(PostData["sysnum"]) ;

А там строка - получишь исключение. Клиенту максимум выведется на английском языке стандарный текст исключения об ошибке преобразования. А если параметра нету?

А если тебе нужно гарантировать, что данный SysNum уникальный, что ты там проверишь с помощью JS?

Ты все таки не въехал в проблему. Проблема лежит на НИЗКОМ уровне. Ты просто представь тот объем однотипного кода лишь по извлечению параметров из HTTP-запроса у разных классов (ну или частей кода в общем случае), проверка параметров, запись в БД.

Блин, ну я в общем подозревал, что это бесполезно. Кто реально не пытался такое писать и не понял всего гемора - так не поймет (((


 
Пит   (2009-07-01 12:12) [22]

ну а про DAO почитал - это связь реляционной БД с ООП моделью. Ну это вообще о другом.


 
test ©   (2009-07-01 12:13) [23]

Пит   (01.07.09 12:08) [21]
>>Блин, ну я в общем подозревал, что это бесполезно. Кто реально не пытался
такое писать и не понял всего гемора - так не поймет (((

makvell   (01.07.09 10:32) [19]
Почитать можно, например тут: http://javagu.ru/portal/dt?last=false&provider=javaguru&ArticleId=GURU_ARTICLE_81158&SecID=GURU_SECTION_  80703
это жава, но проблем с пониманием сути быть не должно :)

Какая разница на каком языке дока, главное что Тьюринговые языки, ты почитай ознакомься.


 
Пит   (2009-07-01 12:25) [24]


> ты почитай ознакомься

см [22]


 
Sergey Masloff   (2009-07-01 13:11) [25]

Зачем весь этот геморрой с классами? Классы ради классов?
Вся эта задача решается элементарно процедурно на встроенном процедурном языке СУБД (если таковой имеется - я бы все остальные варианты просто не рассматривал).
 На стороне клиента функции - трубы "записать параметр", "зачитать параметр", "зачитать все параметры определенного объекта"
 Как все это работает можно посмотреть на сайте Ингоса если есть хоть один наш полис - зарегистрироваться и посмотреть свои настройки в личном кабинете ;-) Все работает именно так как я написал. Весь код несколько строчек на PL/SQL который может поддерживать человек слыхом не слыхавший про дельфи, джава и це с решеткой а прочитавший тонкую брошюрку по процедурному программированию ;-)


 
test ©   (2009-07-01 13:16) [26]

Пит   (01.07.09 12:25) [24]

(*псевдокод похожий на Дельфи*)
TAbstractTable= class
(*тут DML и Select*)
.....
end;

TTable = class(TAbstractTable)
private
  fNumber:integer;
  procedure SetNumber(i:integer);
...
published
  property Number: read fNumber write SetNumber;
...
end;

procedure TTable.SetNumber(i:integer);
begin
....
if i > 10000 then
 RaiseException("Выход за диапазон");
....

end;

Ошибку обрабатывает твой личный обработчик но ему не надо возиться с открытием соединений с БД и запросами, логика на TTable, запросы на TAbstractTable.


 
test ©   (2009-07-01 13:18) [27]

Sergey Masloff   (01.07.09 13:11) [25]
Каждому свое.


 
Пит   (2009-07-01 13:18) [28]

Эх, попытка номер 5 )))

У нас фактически три сущности: WEB, БД, функционал

- WEB это совокупность действий, алгоритмов по приему и ответу на WEB / HTTP / POST /GET запросы и взаимодействие с функционалом
- БД это совокупность действий, связывающих функционал и базу данных
- сам функционал это то, что обеспечивает работу объекта )))

Возьмем функциональный класс, допустим который хранит информацию о ВСЕХ клиентах

TClients = class
 function AddClient(Name, Family, ...): boolean;
 function GetClientByName(Name: string): TClientInfo;
 function DeleteClientByID(ID: int64): boolean;
...
end;


Первые вопросы - где и кто будет реализовывать функционал по работе с WEB и БД?

Работа с WEB

Это может быть или частью функционала TClients:
>function TClients.WEBRequest(WebParams: TStrings): string;
Или реализовано во внешнем коде.

В первом случае мы сталкиваемся с записью аля из первого примера в посте [1]. Вручную обработка каждого параметра, выдача ошибок - ужасно. И каждый раз этот функционал нужно повторять в каждом классе: в TOperators, в TPlaces... и т.д.

Во втором случае (вынесено во внешний код) возможно написание некоего универсального класса. по обработке POST-запросов. Но без работы с БД от него мало толку.
Этот универсальный класс не может настраивать конкретные классы аля TClients, TOperators по понятным причинам (ну вот только если грамотно как-то приплести RTTI, но как...). Этот универсальный класс можно настраивать типа того:

>Config.AddProperty("Name", "Название магазина", tpTextNotEmpty, "", 50, 20);
>Config.AddProperty("Priority", "Приоритет", tpInt, "", 3, 3);

И вот он уже готов обрабатывать сущности, имеющие свойства Name и Priority. В смысле работы с WEB он можнт принимать набор параметров (не редактирование, удаление, добавление), вычленять их (по настройкам), проверять правильность. Как-то так:

>Error := Config.CheckParam(WebParams);

На основе заданного описания (AddProperty) он проверяет правильность HTTP параметров, выдает ошибки. Упрощает немного дело, но лишь очень частично.
Можно его завязать еще и на БД. Тогда помимо проверки он еще будет писать / извлекать данные из БД. Что-то вроде:

Config.AddRecord(WebParams) - после проверки добавляет новую запись на основании описания
Config.DeleteRecord(WebParams) - удаляет некую сущность из БД

Опять же на основании заданного описания может генерировать в HTML виде описания сущости из БД :
Config.GetHTMLView(PKValue: int64): string;

Это уже сильно упрощает дело. Но при этом разрывается связь между функционалом (классами TClients, TOperators) и базой данных. Фактически, такой вспомогательный класс TConfig становится провайдером по редактированию БД, без привязки к функциональным классам. У меня пока это обходится где-то так:

{ поступил WEB-запрос }
Config.AddRecord/EditRecord (WebRequest);
Clients.Clear;
Client.LoadAllFromDB;

То есть, фактически, например при добавлении нового экземпляра сущности через WEB - оно через настроенный элементарным образом TConfig пишется в БД с контролем ошибок, а далее идет приказ функциональному классу перезагрузить все из БД.

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

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


 
sniknik ©   (2009-07-01 13:24) [29]

> Браузер тебе пошлет какие угодно данные
ничего он не пошлет, если "посылалка" будет на том же яваскрипте (а много данных посылать придется именно так). и кроме того раз он отключен то лучше выдать страницу с отказом работать без него чем бесполезную форму ввода параметров.

> (это мы не рассматриваем примеры, когда насильно будут посылать неверные данные).
кто? разве не ты пишешь обе стороны, и клиент и сервер?

> И что ты будешь делать? Сделаешь аля:
если там должно быть число, то так и буду работать с ним как с числом.

> А там строка - получишь исключение.
ну и что? нормальное поведение, по нему буду знать что сам где то в передаче напортачил, а исключение обработаю как обычно, сохраню в лог, и выдам его в ответ вместо данных (и вместо таблички например у меня на странице появится ошибка от базы, типа "неверное значение параметра" или "ошибка преобразования").
ничего страшного в этом нет.
ты не путай проверку всего и вся, всякой мелочи типа, входит ли число в диапазон, с нормальными исключениями.  

> А если тебе нужно гарантировать, что данный SysNum уникальный, что ты там проверишь с помощью JS?
а почему нет? если нужно его генерить на клиенте то использую гуид. на крайний случай будет исключение. не проблема.

> Ты все таки не въехал в проблему.
я ее не вижу, в моем представлении как это реализовать.  

> тот объем однотипного кода лишь по извлечению параметров из HTTP-запроса
вот весь однотипный объем -
JSONObject.Text:= ARequestInfo.Document;
для получения готового распаренного объекта со структурой как xml-документа (работал с xml?). это если передавать json-ом, как советовал, и использовать их компонент для дельфей. (в обратную сторону и этого не надо, стандартная функция eval делает стандартный "родной" обьект в яваскрипте (и да там можно сказать что ее использование небезопасно, но это решаемо, а для варианта когда и то и то свое попросту не нужно))

> Кто реально не пытался такое писать и не понял всего гемора - так не поймет (((
вообще то у меня есть что то подобное, не страница параметров, но похожее (формирует страничку, посылает туда сюда данные, работает с базой).
хотя ты прав я не пытался писать, а просто взял и написал, наверное поэтому и не понимаю проблем...


 
Пит   (2009-07-01 13:30) [30]


> Sergey Masloff   (01.07.09 13:11) [25]

Сергей, не очень понятно. Можно на примере привести путь прохождения данных?

Допустим, со стороны клиента от заполненной формы мы получаем следующие WEB параметры типа:

action=edit
id=45
Name=Sergey
Number=4574


Логически это означает отредактировать клиента с ID равным 45 и присвоить ему (поля в БД) имя сергей и номер 4574. Можешь описать всю цепочку прохождения и обработки данных?


> procedure TTable.SetNumber(i:integer);
> begin
> ....
> if i > 10000 then
>  RaiseException("Выход за диапазон");
> ....
>
> end;

test, пример абсолютно понятный, но ЧТО идет в случае else? ))
Если больше 10000 - исключение, ок. А если параметр верный, какой код в else который по идее должен сохранить параметр в БД?

И еще раз, я тебе уже говорил - это ты говоришь о связи реляционной БД с ООП моделью. Но у меня задача иная, там еще сильно впрягается управление по WEB.


 
test ©   (2009-07-01 13:31) [31]

(*Псевдо код похожий на Дельфи*)

TAbstractWeb=class
// Стандартная обработка
end;

TDEfaultPage=class(TAbstractWeb)
// Обработка Default Page
end;

TMailPage=class(TAbstractWeb)
// Обработка почты
end;

ИМХО Вот как то так


 
Polevi ©   (2009-07-01 13:47) [32]

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


 
Polevi ©   (2009-07-01 13:49) [33]

Да, и генерируемый объект также имеет ф-ию Render, которая возвращает html представление


 
makvell   (2009-07-01 13:57) [34]


> test ©   (01.07.09 12:13) [23]
>
> makvell   (01.07.09 10:32) [19]
> Почитать можно, например тут...
>
> Какая разница на каком языке дока, главное что Тьюринговые
> языки, ты почитай ознакомься.


Не совсем понял, к чему наезд на меня :) я сказал, что ты прав, и что близко к использованию ДАО, дал пример (описание) как оно в яве. Не думаю что мне стоит с чем-то еще знакомиться, уже знаком и вполне успешно использую ;) и вообще я не вижу проблемы у топик стартера, такое ощущение, что это обсуждение ради обсуждения, типа "вы все не правы, мне нужно что-то другое, а что я и сам не знаю".


 
Пит   (2009-07-01 13:59) [35]


> ничего он не пошлет, если "посылалка" будет на том же яваскрипте

нуу... Это значит система станет ненастраиваемой в браузерах с отключенным JS. Такой вариант неприемлим.

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


> а почему нет? если нужно его генерить на клиенте то использую
> гуид. на крайний случай будет исключение. не проблема

ты не понял. Допустим, есть список устройств. У каждого устройства есть номер, не ID из БД, а конкретно задаваемый номер, идентифицирующий устройство в транспортной сети. У каждого устройства допустим свой адрес, но при этом адреса не могут повторяться. Где ты будешь делать проверку, в JS? Тебе же нужен доступ к данным всех устройств, чтобы понять, что новый заданный номер не катит по причине уже наличия данного номера у другого устройства.

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


> JSONObject.Text:= ARequestInfo.Document;
> для получения готового распаренного объекта со структурой
> как xml-документа

а что там парсить в HTTP-параметрах? ребенок справится.
Вопрос не в том, чтобы распарсить (у меня точно такие же распарсенные параметры в TStringList хранятся), а в том, чтобы присвоить эти значения функциональному коду.


 
Sergey Masloff   (2009-07-01 14:05) [36]

Пит   (01.07.09 13:30) [30]
Конечно. Только нужно на стороне сервера еще как-то отличить что это за команда (или писать по паре процедура сервера приложений -процедура в субд. Предлагаю вариант с одной процедурой на стороне веб-сервера. Назовем ее ApplyCommand

допустим с такой сигнатурой (абстрактно)

ApplyComand(inBuf, outBuf : string) : boolean;

Тогда примерно так
Клиент передает данные как строку через get или post
 |
Сервер перехватывает строку и (возможно) приводит ее в нужный вид. После преобразования параметров вызывается функция ApplyCommand в которую как входной буфер отдаются параметры приехавшие с клиента. Этот код написан и отлажен 1 (один) раз и не меняется никогда
 |
Процедурный код СУБД
Пусть процедура называется
 ApplyCommandImp() она
    - вызывает другую процедуру которая по буферу понимает что это за команда допустим GetCommandCode(inBuf : string) : integer;

  тогда ApplyCommand() выглядит так

 begin
    case GetCommandCode(inBuf : string) of
    0 : return SaveClientParams(inBuf, outBuf);
    1 : return ReadClientParams(inBuf, outBuf);
    2 : return SomeOtherUsefulInfo(inBuf, outBuf);
    ....
    else
       return StdErrorMsg(inBuf, outBuf);
 end


а например SaveClientParams(inBuf, outBuf); выглядит так

 begin
   if AnalyzeInputParams(inBuf) then begin
      update Client set Name=GetParam(inBuf,"name"), Number=(inBuf,"number") where id = GetParam(inBuf,"id")
      if (ничего не проапдейтилось)
      insert into Client(Name, Number, id) values (Params......
      outBuf = (текст, HTML, XML о том что все в порядке)
      return true;
   else return ReportInvalidParams(outBuf) // в буфер запишем что там плохого - можно сразу как HTML (XML)
 end;

 
Ну что-то в этом роде. На практике все несложно получается и каждая процедура примитивна - даже документировать не нужно
   
 

<>


 
test ©   (2009-07-01 14:06) [37]

makvell   (01.07.09 13:57) [34]
Опечатка, хотел Питу отправить тебя целеком переписывать было лень скопировал. Немного криво получилось ))


 
Пит   (2009-07-01 14:12) [38]


> Для каждого объекта создается набор хранимых процедур для
> создания, сохранения, удаления и выборке по ID
> Пишется генератор, который используя информацию о метаданных
> базы через INFORMATION_SCHEMA генерирует классы-обертки,
>  которые умеют эти процедуры вызывать.
> Реализация ф-ии WebRequest сводится к поиску нужного типа,
>  инстанцированию и вызова метода.

это прекрасно, но я это уже сделал.

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

Я писал в постах [2] и [28] как это реализовано в моем случае. Тоже самое, что ты предложил, только прототип объекта (сущности) берется не из метаданных БД, а настраивается вручную аля:

Config.AddProperty("Name", "Название магазина", tpTextNotEmpty, "", 50, 20);

Это и задает его отображение в WEB (функция Render), и задает способы записи в БД.
Вызов описанных тобой хранимок заменен у меня опять же на основании заданного прототипа сущности на исполнение запросов INSERT, UPDATE и DELETE. В используемой БД нету хранимок, да и не принципиально это. Такой функционал уже есть, он реализован.

Но он не связан с функциональным кодом! Грубо говоря, для твоей реализации представь ситуацию.

В WEB интерфейсе клиент УДАЛЯЕТ некий экземпляр сущности. Провайдер TConfig понимает это и удаляет из БД соответствующую запись. Но как это изменение скажется в программе? Грубо говоря класс TSomebodyCollection, который хранит информацию о всех сущностях - как узнает об изменениях?


 
Polevi ©   (2009-07-01 14:24) [39]

>класс TSomebodyCollection как узнает об изменениях?
а зачем он хранит эту информацию ? web приложение stateless по умолчанию
запросит броузер этот список - выдай ему свежие данные
а вся валидация на уровне базы - констрэйнтов и хранимых процедур


 
Polevi ©   (2009-07-01 14:28) [40]

если ты хочешь отобразить данные на объектную модель и в дальнейшем работать со списками и экземплярами связаных сущностей - тебе нужен ORM.. чтото вроде Hibernate


 
sniknik ©   (2009-07-01 14:28) [41]

> Допустим, есть список устройств. .... Где ты будешь делать проверку, в JS?
да
> Тебе же нужен доступ к данным всех устройств, чтобы понять
да, и он там будет, ведь при таком списке тебе его придется "гнать" на клиента для организации выбора из уже существующих. и их номера там будут. раз говоришь будет их редактирование.
а можно сделать так, что при введении нового не посылать его номер, оставить это серверу (ну как автоинкремент в базах делается, только тут твой сервер будет его генерить и возвращать в ответ на запрос добавления, на случай его редактирования прямо после ввода)

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

> Вопрос не в том, чтобы распарсить (у меня точно такие же распарсенные параметры в TStringList хранятся),
> а в том, чтобы присвоить эти значения функциональному коду.
т.е. вот в этом?
Params.ParamByName(Name).Value  := JSONObject[Name];
Params.ParamByName(Number).Value:= JSONObject[Number];
???
и том как в зависимости от типа операции разные запросы выполнять
типа
 case JSONObject[action] of
   0: .....;
   1: .....;
   и т.д.
???


 
Пит   (2009-07-01 14:43) [42]

>Sergey Masloff   (01.07.09 14:05) [36]

концепцию понял. Но не понял удобства.

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

sniknik предлагает проверять параметры на клиенте (в браузере через JS-скрипт) - что мне кажется самым неправильным. Я проверяю в приложении на delphi. Ты предлагаешь проверять на стороне БД на его встроенном языке. Принципиально поставленные вопросы эти разные подходы не решают. Осуществляется контроль входящих парамметров, просто на разных этапах.

Я для этого уже класс написал. Его настройки я приводил, аля:

>Config.AddProperty("Name", "Название магазина", tpTextNotEmpty, "", 50, 20);

Если есть 7 настроек у сущности - значит 7 строчек настраивающих. И все, проверка автоматом, контроль автоматом, мне так даже больше нравится. Это пост номер [2] в этой ветке, решение описано.

Вопрос в связи с функциональными классами в программе.


> а зачем он хранит эту информацию ? web приложение stateless
> по умолчанию

я нигде не говорил, что у меня WEB-приложение! Если говорил - извиняюсь, это опечатка. У меня приложение, которое УПРАВЛЯЕТСЯ по WEB. А так в большинстве случаев запускается в виде сервиса и постоянно работает.


> если ты хочешь отобразить данные на объектную модель и в
> дальнейшем работать со списками и экземплярами связаных
> сущностей - тебе нужен ORM.. чтото вроде Hibernate

по ходу я погряз (((

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

Связь БД с WEB я реализовал, тут почти претензий нет. А вот как ты говоришь отобразить это на ООП модель - я запнулся. Есть мысли через RTTI присваивать значения свойствах объекта... Но как это все реально сделать... нет опыта, не хватает знаний.


 
Пит   (2009-07-01 14:57) [43]


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

элементарный пример. Сущностей (допустим, клиентов) много, выводятся они группами по 30 человек на странице, всего у нас 600 клиентов, значит это 20 страниц.
Ты предлагаешь в любом случае гнать в браузер информацию о всех 600 клиентах, но выводить на страницу только о 30?

А если для клиента в приложении построено некое дерево исходов, анализа. И по неким критериям оно не должно повторять дерево, построенное для другого клиента... Тоже JS?

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


> т.е. вот в этом?
> Params.ParamByName(Name).Value  := JSONObject[Name];
> Params.ParamByName(Number).Value:= JSONObject[Number];
> ???
> и том как в зависимости от типа операции разные запросы
> выполнять
> типа
>  case JSONObject[action] of
>    0: .....;
>    1: .....;
>    и т.д.
> ???

не понял что ты хочешь сказать.

Переданные параметры доступны в виде TStringList"а, в формате "ParamName = ParamValue"

В посте номер [1] это четко показано:

if ParamList["action"] = "add" then

ну если очень хочется числами, то можно так:

if not TryStrToInt(ParamList["action"], iAction) then iAction := -1;
case iAction of
 0:
 1:
 2:
...
end;


но в вебе лучше не делать так, гораздо нагляднее в URL-ах параметры "говорящие" наподобие "edit_client", "view_publication" и т.д.


 
Пит   (2009-07-01 15:07) [44]

почитал про ORM, про Hibernate. Ага, мне нужно такое, связь ООП и БД.

Но во-первых, разве такая реализация есть для Delphi?
Во-вторых, мне еще нужно связать это с WEB ((

Что сделать просто - связать WEB с БД, это мой класс TConfig, действие которого описано еще в посте [1]

Связывание ООП с БД оказывается называется ORM.
Связывание ООП с WEB не знаю как называется.

А мне нужно все эти три вещи связать...


 
Пит   (2009-07-01 15:09) [45]


> Связывание ООП с WEB не знаю как называется

например, для PHP в этих целях используют часть функционала Zend Framework.

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


 
Sergey Masloff   (2009-07-01 15:10) [46]

Пит   (01.07.09 14:43) [42]

>Во-первых, фактически при таком способе ручной контроль параметров >перенесен из приложения на БД, правильно? Ну а что от этого меняется. >Проверять параметры в приложении или проверять в БД, объем кода от >этого не уменьшится и процесс разработки не сократится.
Уверяю что сократится. За последние 10 лет я "прошел" штук 10 технологий создания расширений веб-сервера каждая из которых объявляла предыдущую полным отстоем (и реально давала некоторые преимущества).
Кроме того за это же время я поменял 4 ОС на которых хостится веб-сервис, из четырех только на одной мог выполняться дельфийский код.
 Вобщем с некоторых пор все что можно написать на стороне субд я пишу там.

 Кстати из практики - код например на оракл связаный с обработкой данных получается статистически (счет строк порядка 10^6) минимум в 2 раза компактней по сравнению с дельфийским. При этом абсолютно портируемый - с солярки на аикс без единого чиха (даже с java проблемы были)


 
Пит   (2009-07-01 15:12) [47]

По ходу все таки мне никто не поможет... (( Технологий таких просто не существует. Только шанс встретить человека, который непосредстевенно решал поставленную задачу связи треугольника: WEB-функционал-БД и возможно имеет какие-то мысли.


 
Пит   (2009-07-01 15:20) [48]


> Уверяю что сократится. За последние 10 лет я "прошел" штук
> 10 технологий создания расширений веб-сервера каждая из
> которых объявляла предыдущую полным отстоем (и реально давала
> некоторые преимущества).
> Кроме того за это же время я поменял 4 ОС на которых хостится
> веб-сервис, из четырех только на одной мог выполняться дельфийский
> код.
>  Вобщем с некоторых пор все что можно написать на стороне
> субд я пишу там.


ты все правильно пишешь. Сокращение кода идет думаю в частности из-за сильно упрощенного способа записи SQL выражений. То есть, то что в дельфи:

TQuery.Create
Query.SQL :=  UPDATE bla bla
Query.Exec;

то на внутреннем языке это будет одна строчка: UPDATE bla bla

Насчет хостингов - согласен с тобой.
Но еще раз, что я писал в [42] - у меня не WEB-приложении, я не говорил про WEB-приложение. У меня обычное приложение, которое просто управляется по WEB! Из-за преимуществ:

1) возможно удаленное управление
2) прозрачное управление в случае работы сервисом
3) не нужна клиентская программа (браузер сейчас везде)


 
b z   (2009-07-01 16:23) [49]

А в чем вопрос? :)
Как синхронизировать данные, т.е. сказать простой программе, что в конфигах произошли изменения и она должна как-то среагировать на это?
Ваше не веб-приложение и та простая программа, типа сервиса, это одна и таже программа/приложение или разные?


 
Polevi ©   (2009-07-01 16:24) [50]

>Пит   (01.07.09 15:12) [47]
Такие технологии существуют, но делфи тут не причем
Например связка Hibernate + Spring. (ORM и Dependency Injection frameworks)
Изначально созданы под Java, есть аналог для .Net (NHibernate и Spring.Net)
Делфи курит в стороне.
Но справедливости ради стоит заметить что время, необходимое на изучение подобных фрейморков часто бывает равно созданию собственных аналогов :)


 
Пит   (2009-07-01 16:25) [51]


> Ваше не веб-приложение и та простая программа, типа сервиса,
>  это одна и таже программа/приложение или разные?

одна и таже. И приложение вовсе не простое ))


 
Пит   (2009-07-01 16:29) [52]


> Делфи курит в стороне

ну а что мне то делать? (((
Нет никаких идей по облегчению интеграции WEB-запросов и настройки функционального кода?


 
b z   (2009-07-01 16:47) [53]


> И приложение вовсе не простое ))
ошибся, "обычное" ...

На сколько я понимаю, вся задача все-таки в том как при изменении свойст конфига(ов), произошла адекватная реакция основного (обычного) процесса, я прав? а то вы как-то не среагировали на 2 мой вопрос.
Если прав, то ваши классы, ормы и т.п. фраймворки особо тут не помогут, хватит обычных датасетов, ну или если угодно вами типизированных, что особо ничего не меняет. И даже не понял при чем тут веб-нивеб, по моему нет разницы, каким образом идет управление. Мухи отдельно, котлеты отдельно. Похоже, что MVC тут может оказаться к месту. Это если я все-таки правильно понял. :)


 
sniknik ©   (2009-07-01 16:59) [54]

> элементарный пример. Сущностей (допустим, клиентов) много ...
блин, ну нельзя же так резко в сторону "вилять", говорили про устройства, которых не так много скорее всего, а ты это все перекинул на клиентов которых больше.
хотя, во первых не страшно, у меня клиентов 5тыс (вернее ~4800), и в некоторых случаях передаются все. и ничего довольно быстро (около секунды) страничка со всем этим передается/отображается (это если они туда сразу в html вставляются, в случае получения подобного по ajax получается несколько дольше).
во вторых логика без загрузки всего тоже возможна, предлагал же ->
> а можно сделать так, что при введении нового не посылать его номер, оставить это серверу
> (ну как автоинкремент в базах делается, только тут твой сервер будет его генерить и возвращать
> в ответ на запрос добавления, на случай его редактирования прямо после ввода)
для клиентов это подойдет.
только вопрос - а ввод дублей человеком из-за того, что не видит большинства клиентов. не страшен?
или группы по какому то признаку так что ввод в эту группу не пересечется с остальными? т.е. дублей не будет.
тогда почему этот признак не вынести за пределы генерируемого номера? т.е. например группа 5 + 1-30 записей в ней, дали просмотрев номер 31 он гарантированно тогда будет уникальным, не пересечется с 31 из первой или другой группы.


 
Пит   (2009-07-01 17:13) [55]

sniknik, да вообще разговор лишний. Я не понимаю тебя, чем проверка на JS проще, чем проверка в коде дельфи.

Ну да это не принципиально. Принципиален вопрос связывания WEB с функционалом программы (пусть будет ООП) и с БД.

Polevi на мой взгляд хорошо понял задачу...


 
Пит   (2009-07-01 17:39) [56]

sniknik, я имею в виду, что ты решаешь проблему, которая не стоит. При этом решаешь на мой взгляд неверно.

Но поскольку речь идет не о том - это не принципиально.

WEB с БД я связал легко, в очередной раз повторюсь, что это прекрасно делает класс, описанный еще в [1]


 
sniknik ©   (2009-07-01 17:39) [57]

> Я не понимаю тебя, чем проверка на JS проще, чем проверка в коде дельфи.
> (пусть будет ООП)
пусть будет
когда ты пишешь на дельфи класс/форму ты разрываешь логику этой формы, того что в ней делается на 2 места? устанавливаешь поведение/значения ее компонентам из кода другой (основной) формы, или стараешься этого избежать и сделать класс "целостным"? потдерживаешь так сказать принципы ООП, инкапсуляцию данных (данные класса должны обрабатываться методами класса. по возможности) или нет?

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

как ответишь надеюсь поймешь.

> Polevi на мой взгляд хорошо понял задачу...
сказал больше умных, непонятных тебе слов, в процентах от общего сказанного количества? :о)


 
Пит   (2009-07-01 18:49) [58]


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

ну если не касаться вопросов безопасности (а вообще-то сложно их не касаться, когда идет удаленное управление), то я может с тобой соглашусь.

Но опять же проблема в сабже не в этом.


 
sniknik ©   (2009-07-01 19:17) [59]

> Но опять же проблема в сабже не в этом.
а в чем же тогда?
мы уже похоже по всем  пунктам цепочки прошлись, отсылка, прием, парсинг, сохранение в базу, и везде по отдельности говоришь проблем нет, и проблема в другом.
да, еще в самом начале предлагал компоненты для формирования html, которые могут прямо с веб через твой сервер в базу данные класть. тоже не подошли...

объяснил бы уж тогда, доступным языком, без использования сложных слов.


 
Пит   (2009-07-01 19:32) [60]

если честно - я просто не знаю как еще сказать.

Ты понимаешь, что проблемы исключительно связки WEB <-> БД нету, решение описано еще в посте [1]

Проблема в связке еще с функционалом кода. Я наверное повторяю эту фразу раз в 15-ый.

Прочти, пожалуйста, внимательно хотя бы мой пост [38], особенно в конце.


 
sniknik ©   (2009-07-01 19:53) [61]

> если честно - я просто не знаю как еще сказать.
как? конкретно. на чем то реальном избегая общих фраз.

> Прочти, пожалуйста, внимательно хотя бы мой пост [38], особенно в конце.
вот это?
> В WEB интерфейсе клиент УДАЛЯЕТ некий экземпляр сущности. Провайдер TConfig понимает это и удаляет из БД соответствующую запись.
> Но как это изменение скажется в программе? Грубо говоря класс TSomebodyCollection, который хранит информацию о всех сущностях
> - как узнает об изменениях?
смотрим [41]
> типа
>  case JSONObject[action] of
>    0: .....;
>    1: .....;
>    и т.д.
> ???
допустим номер 3 у нас удаление. делаем ->
 3: begin
       Command.ParamByName(ID).Value  := JSONObject[ID];
       Command.Execute;

       PostMessage(SelfProgramma, COMM_FROM_WEB, JSONObject[action], JSONObject[ID]);
    end;

все, программа "знает". по этому знанию может сделать чтото адекватное.

все просто, и опять без всяких классов.


 
Piter ©   (2009-07-01 22:14) [62]

sniknik ©   (01.07.09 19:53) [61]

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

хм... ну в принципе надо подумать, наверное ты прав...

Я просто говорил о том, что идет не просто уведомление, что что-то произошло с записью ID, а о том что передаются непосредственные данные что произошло.


 
sniknik ©   (2009-07-01 22:55) [63]

> предлагаешь коду класса после получения такого обновления перечитать БД?
это самое простое хотя и не единственно возможное. можно например по команде удаления вообще не удалять запись в базе, и не посылать уведомлений... а удалять непосредственно в том датасете который ее содержит и открыт, а в базе уж он сам...
или когда открыт делать одно, закрыт другое.

> а о том что передаются непосредственные данные что произошло.
не проблема, если нужно передавай непосредственно данные. собственно для удаления, ID записи собственно и будет полностью этими самыми данными.

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


 
Piter ©   (2009-07-02 00:50) [64]

sniknik ©   (01.07.09 22:55) [63]
не проблема, если нужно передавай непосредственно данные


как раз таки в этом и проблема, связывание запросов в WEB с изменениями в переменных программы. Вручную это делать геморно. Все данные приходят в текстовом виде, надо каждое обработать и присвоить свойствам функционального класса (например). Я и думаю о некой универсальности, которая по заданному прототипу будет вычислять данные из WEB запроса и присваивать значения нужным свойствам, через RTTI. Но как это сделать - проблемс... не придумал красивого решения.

sniknik ©   (01.07.09 22:55) [63]
и при таком упрощении скрипач (класс) не нужен.


да вполне удобный класс, но он связывает WEB-запрос с БД. Связывает очень прозрачно, быстр и легок в настройке.

Поэтому Polevi и предлагает связку двух технологий ORM и Spring, например. Одна связывает WEB с БД, другая связывает БД с ООП объектами в программе непосредственно. Или их интеграция может непосредственно связать WEB запрос и ООП.

Но это существует для java, но не для delphi.


 
sniknik ©   (2009-07-02 01:58) [65]

> Все данные приходят в текстовом виде
сколько раз говорил, передавай в json-e, на стороне веба это практически родной обьект/массив/рекордсет, как составиш, на стороне дельфи через парсер тот же xml-документ (рекордсет, если ты конечно не навернешь туда древовидности)

> да вполне удобный класс, но он связывает WEB-запрос с БД. Связывает очень прозрачно, быстр и легок в настройке.
оно и видно, вопросов у тебя больше чем понимания, наверное изза удобст и легкости в настройке...

у меня же ушло 2 месяца от полного незнания hml и javascript до написания нормального сервлета примерно по такому же принципу работы что ты тут описываешь.
пользовался бы "удобными и легкими" но не на своем месте компонентами возился бы наверное до сих пор... а это уже год, и не закончил бы, к гадалке не ходи.

> предлагает связку двух технологий ORM и Spring, например. Одна связывает WEB с БД, другая связывает БД с ООП
что одно, что другое сомнительное удовольствие... ИМХО.
пытался сделать хоть что-то одно, например разработать объекты для работы с базой? попробуй. упаришься. и ничего кроме ограничений для работы с базой, ухудшения алгоритмов и увеличения ресурсоемкости не добьешься.
вот сделаешь ты например объекты для работы с учебной базой. предметы там. ученики и т.д. будешь долго дописывать/отлаживать добавляя сущности вылезшие по ходу работы, добавишь туда добавление, удаление и т.д. а после окажется нужен будет отчет, и никак его кроме как запросом хитрым с какими нибудь джойнами не сделать (а это уже не объект, это уже объединение черт знает чего. в концепцию не "ложится"), а вот запросом запросто, т.е. либо в обход твоих классов, либо добавлять туда "хитрозатесанные" составные обьекты которые на самом деле не объекты. ти т.д. и т.п.
ну ладно все добавил все решил, отладил, после смотриш на это дело со стороны и с ужасом понимаешь все это получилось УЗКО специализированным, только для учебной базы, а вот использовать для накладных или бугалтерии/любого другого это не получится, даже больше того, поменяй учебную базу на от другого факультета, и это уже тоже не подойдет. надо чуть ли не с нуля переписывать...
а ведь это будет даже не основной код, это будет надстройка по работе с базой, избыточная работа единственное оправдание которой в том что "потом это пригодится, счаз помучаюсь, напишу, потом не придется.". и вот фиг тебе ЕЩЕ КАК придется.

а потом, после того как попробуешь реализовать одно, вот тогда пробуй объединить 2 технологии... но тогда думаю откажешься. поумнеешь и скажешь "а нафига это вообще надо?" (вот тогда и вспомни что тебе это же самое изначально говорили)

> Но это существует для java, но не для delphi.
какая разница? это же не компоненты, это технология, там наверняка тоже надо "классы-объекты в базе" описывать. ну разве, что там уже есть такие предопределенные предки с вшитым коннектом к базе, который автоматически подсоединяется если есть обращение к описанному объекту потомку. в общем не думаю, что там задача сильно облегчена по сравнению с дельфей.


 
Пит   (2009-07-02 11:06) [66]

нда, мы свалились в замкнутый круг. Ты по всему очевидно считаешь, что разбираешься в данном вопросе намного лучше меня, поэтому мои слова просто не воспринимаешь. Смысла так разговаривать нету.


 
Anatoly Podgoretsky ©   (2009-07-02 11:11) [67]

> Пит  (02.07.2009 11:06:06)  [66]

Странно, что еще не побили.


 
sniknik ©   (2009-07-02 12:47) [68]

> Ты по всему очевидно считаешь, что разбираешься в данном вопросе намного лучше меня
ну... у меня есть одно завершенное приложение (сервлет) сделанное по такому принципу, а сколько у тебя?
если скажешь, что 2 или хотя бы 1 с половиной, тогда я радостью возьму на заметку гуру к которому можно обратиться в случае чего...

и кстати у меня не было никаких заморочек при написании, все четко ложилось на предварительно выработанные принципы. хотя пришлось изучать новый язык практически (яваскрипт) и html.
и в общем то все что я пытался донести так это принципы, т.к. у меня по ним все прошло "без сучка и задоринки", а у тебя вижу одни проблемы (желание чего то такого что "пером не описать, и не в сказке сказать"). но если не хочешь, ну действительно не о чем разговаривать. парься со своими классами дальше.


 
Пит   (2009-07-02 13:44) [69]

ну пиписьками я тем более меряться не хочу.

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

В общем, что обсуждать. Я на тебя не обижаюсь, тебе на меня так вроде тоже незачто. Пользу я извлек, больше сам для себя, более логично разложив по полочкам в мозгу задачу и решения...


 
DVM ©   (2009-07-02 14:02) [70]


> sniknik ©

Мне все таки кажется, что полность полагаться исключительно на проверки введенных данных JavaScript-ом несколько ненадежно. Лучше всего дублировать проверки и на клиенте (для удобства) и на стороне сервера.


 
Пит   (2009-07-02 14:05) [71]


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


 
sniknik ©   (2009-07-02 14:33) [72]

> что полность полагаться исключительно на проверки введенных данных JavaScript-ом несколько ненадежно.
полагаться исключительно только на... и не предлагалось, предлагалось проверять там, на сервере считать присланные данные верными, но эксепты все таки не забывать.
большой разницы в том сам ты возбудишь этот ексепт по дублированной (ака лишней)  проверки на сервере, или это придет от базы при записи нет.

или имеются ввиду проверки диапазонов чисел и подобное, но это уже логика разнесенная на 2 места, только дополнительные неудобства. сейчас у тебя один диапазон, завтра другой, и исправлять надо не в одном месте, а по всей цепочке. а если где забыл там будет "непонятка"(глюк).



Страницы: 1 2 вся ветка

Форум: "Прочее";
Текущий архив: 2009.08.30;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.79 MB
Время: 0.006 c
15-1246288695
Kerk
2009-06-29 19:18
2009.08.30
Работа в Питере


10-1158414306
AAAA
2006-09-16 17:45
2009.08.30
TDCOMConnection. Создал


15-1246451106
@!!ex
2009-07-01 16:25
2009.08.30
ЗИЛ в Германии 45 года????


1-1213031306
San1712
2008-06-09 21:08
2009.08.30
Как с помощью кода изменить высоту формы ?


2-1246427745
lewka
2009-07-01 09:55
2009.08.30
Отправка электроной почты





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский