Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2012.02.05;
Скачать: CL | DM;

Вниз

помогите определиться с форматом функции   Найти похожие ветки 

 
dev888   (2011-10-26 15:15) [0]

нужно написать функции (API), которые были бы максимально удобными для перемещения по товарам магазина (GoToFirstProduct, GoToNextProduct, GoToPreviousProduct, GoToLastProduct). Нужно предусмотреть возврат идентификатора товара, а также возможность перемещения к товару. Как это лучше сделать, чтобы не писать еще и функции EOF, BOF? Пока что думаю так:


function GoToFirstProduct(out ProductId: Integer): Boolean;
function GoToLastProduct(out ProductId: Integer): Boolean;


- Если товары в магазине отсутствую, функция будет возвращать False


function GoToNextProduct(out ProductId: Integer): Boolean;
function GoToPreviousProduct(out ProductId: Integer): Boolean;


- если товары в магазине отсутствую, либо текущий товар был последним (GoToNextProduct) / первым (GoToPreviousProduct) функция будет возвращать False.

но:

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


AdapterStore.GoToFirstProduct(ProductId);
// действие на товаром
while AdapterStore.GoToNextProduct(ProductId) do
begin
 // дейсвие над товаров
end;


 
Медвежонок Пятачок ©   (2011-10-26 15:21) [1]

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

type
TEnumCallbackFunc = function(AProduct : integer; var bMore : boolean; ACustomData : Pointer) : boolean;

function enum_products(ACallBackFunc : TEnumCallbackFunc; ACustomData : Pointer) : integer;
var bMore : boolean;
begin
Result := 0; bMore := True;
while product_exists do
 begin
  if ACallBackFunc(ProductID,bMore,ACustomData) then inc(Result);
  if not bMore then break;
 end;
end;


 
Ega23 ©   (2011-10-26 15:41) [2]

First;
Next;
Eof;


Этого достаточно.
И будет тогда что-то вроде

with AdapterStore do
begin
 First;
 while not Eof do
   try
     .... Работаем с ID, также выносим его в public
   finally
     Next;
   end;
end;


 
Омлет ©   (2011-10-26 15:42) [3]

> Нужно предусмотреть возврат идентификатора товара, а также возможность перемещения к товару.

А, может, сразу ссылку на объект возвращать?


 
Медвежонок Пятачок ©   (2011-10-26 15:44) [4]

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


 
Ega23 ©   (2011-10-26 15:46) [5]


> каждый раз будет вынужден писать цикл перебора.


Без индексирования или упорядочивания у тебя и так и так будет цикл перебора.


 
Медвежонок Пятачок ©   (2011-10-26 15:50) [6]

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

а пользователю апи требуется всего лишь реализовать различные варианты
TEnumCallbackFunc

b затем вызвать enum_products c нужным колбаком.


 
Труп Васи Доброго ©   (2011-10-26 15:55) [7]


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

Чувак, ты не поверишь, но я слышал, есть такая маза крутая - базы данных. Говорят вставляет не по детски!!!


 
dev888   (2011-10-26 16:07) [8]


> чувак, ты не поверишь, но я слышал, есть такая маза крутая
> - базы данных. Говорят вставляет не по детски!!!


так мне по сути и надо сделать обертку над компонентом-таблицей товаров базы данных, чтобы человек мог из 1C загружать / выгружать товары / выполнять над ними различные действия.


> First;
> Next;
> Eof;
>
>
> Этого достаточно.


у меня одно из требований в тз это присутствие в имени функций слова "product". как тогда обозвать функцию-обертку над  "eof"


 
sniknik ©   (2011-10-26 16:07) [9]

редко кто хочет учиться... зато "велосипедотворцов" пруд пруди...


 
sniknik ©   (2011-10-26 16:08) [10]

> это присутствие в имени функций слова "product"
ну так...
productFirst;
productNext;
productEof;

Этого достаточно.


 
sniknik ©   (2011-10-26 16:10) [11]

> по сути и надо сделать обертку над компонентом-таблицей товаров базы данных
а чем она должна/будет лучше чем прямые методы работы с таблицей?


 
Медвежонок Пятачок ©   (2011-10-26 16:11) [12]

type
TEnumCallbackFunc = function(ADataSet : TDataSet; var bMore : boolean; ACustomData : Pointer) : boolean;

function enum_dataset(ADataSet : TDataSet; ACallBack : TEnumCallBack; ACustomData : boolean; AFromTheVeryBegining : boolean = false) : integer;
var bMore : boolean;
begin
Result := 0; bMore := True;
if AFromTheVeryBegining then ADataSet.First;
while not ADataSet.Eof do
 begin
  if ACallBack(ADataSet,bMore,ACustomData) then Inc(result);
  if not bMore then Break;
  ADataSet.Next;
 end;
end;


 
Медвежонок Пятачок ©   (2011-10-26 16:15) [13]

а чем она должна/будет лучше чем прямые методы работы с таблицей?

А прикинь, если у тебя есть вот такой грид:

nCount := MyGrid.BatchProcess(MyDeleteCallBack,ACustomData);
nCount := MyGrid.BatchProcess(MyUpdateCallBack,ACustomData);
.....
nCount := MyGrid.BatchProcess(MyExportCallBack,ACustomData);

причем BatchProcess обрабатывает либо текущую, либо всё, либо только мультиселект если он есть.


 
sniknik ©   (2011-10-26 16:17) [14]

> причем BatchProcess обрабатывает либо текущую, либо всё, либо только мультиселект если он есть.
т.е. пишется замена SQL, так?


 
Ega23 ©   (2011-10-26 16:18) [15]


> у меня одно из требований в тз это присутствие в имени функций
> слова "product"


Я бы порекомендовал засунуть такое тз заказчику в ухо. И поджечь.


 
sniknik ©   (2011-10-26 16:19) [16]

> т.е. пишется замена SQL, так?
тогда + вопрос
а чем она должна/будет лучше чем прямые методы работы с таблицей?


 
Медвежонок Пятачок ©   (2011-10-26 16:21) [17]

т.е. пишется замена SQL, так?

нет не так.
пишется избавление от рутины по созданию циклов в групповых операциях.
внутри функций обратного вызова необязательно идет непосредственная обработка датасета.
в них может собираться инфа для (например) формирования sql скрипта который выполняется после BatchProcess если тот вернул > 0
Но не только это.
Это вообще некая групповая обработка записей. Любая.


 
sniknik ©   (2011-10-26 16:38) [18]

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

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

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


 
Медвежонок Пятачок ©   (2011-10-26 16:46) [19]

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

Все.

Вот типичный пример:
Форма с гридом и три кнопки: add,edit,delete
С первыми двумя все ясно, а под третьей как раз место вызова BatchProcess

Ибо юзер может хотеть удалить не одну строку, а все. Или все отобранные мультиселектом.


 
Труп Васи Доброго ©   (2011-10-26 16:50) [20]


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

Я вот не пойму, нафига ты задаёшь вопросы под неизвестными никами, а потом сам же начинаешь критиковать ответы? Тебе от себя спросить стыдно? Послушай умного человека sniknik правильно говорит, не надо велосипед делать, есть SQL, есть СУБД, учи и пользуйся.


 
Медвежонок Пятачок ©   (2011-10-26 16:54) [21]

Я вот не пойму, нафига ты задаёшь вопросы под неизвестными никами

Гражданин, не надо гнать херню.


 
sniknik ©   (2011-10-26 17:01) [22]

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

т.е. в одном случае есть, в другом нет, но нужно универсально... значит возможность должна быть "урезана" ибо в одном варианте перестает работать а в другом просто добавляет тормоза.


 
sniknik ©   (2011-10-26 17:05) [23]

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


 
Медвежонок Пятачок ©   (2011-10-26 17:09) [24]

>Послушай умного человека sniknik

Ты лучше меня послушай, так как sniknik хоть и умный человек, но совершенно не оценил всю красоту и изящество метода.

Речь же идет об элементарных принпах разработчика: разделение кода

Представь, что ты в команде. К вам "снаружи" пришла некая регулярная структура данных.
Одному в команде надо сделать по ней инсерты, другому надо сделать отчет, третьему надо сформировать html по пришедшим данным.

Мой метод:
Я раскуриваю структуру и пишу функцию енумерации структуры и публикую ее для команды.
А вся команда не вникая в сложности структуры пишет свои пользовательские функции обратного вызова и сосредотачивается на непосредственно своей задаче.
Всем сухо и комфортно.

Другой метод:

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

не работает при отключенных. некуда ссылаться, даталинка нет.

Ты поверь, что у меня работает. Уже лет пять.
Просто и мультиселект у меня не такой как у всех.
/* Расширенный и дополненный EhLib"ский. Который SQL-ориентированный */


 
Медвежонок Пятачок ©   (2011-10-26 17:11) [25]

например "обрабатываешь" связанные таблицы

Я таким механизмом обрабатываю все что имеет регулярную структуру.
датасеты, ixmldomnodelist"ы, файлы, списки и прочую дребедень.


 
sniknik ©   (2011-10-26 17:19) [26]

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


 
sniknik ©   (2011-10-26 17:21) [27]

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


 
Медвежонок Пятачок ©   (2011-10-26 17:26) [28]

Вот стандартный мультиселект. Все отключено, но все работает.

DBGrid1.DataSource.DataSet.DisableControls;
for i := 0 to Pred(DBGrid1.SelectedRows.Count) do
 begin
  if DBGrid1.DataSource.DataSet.BookmarkValid(Pointer(DBGrid1.SelectedRows.Items[i]))  then
   begin
    DBGrid1.DataSource.DataSet.GotoBookmark(Pointer(DBGrid1.SelectedRows.Items[i]));
    ShowMessage(Table1.Fields[0].Value);
   end;
 end;

а вот дал ты свой метод "наружу"из своей среды обитания, и кто-то не пользующийся Eh-ом

Сначала я дал "наружу" расширенный EhDBGrid.
Команда им пользуется.
Затем я дал им новый метод этого грида.
Это же метод грида. Просто частный случай применения.
Только потому, что у конечного пользователя приложения есть механизм отбора записей, а у программиста нет удобного механизма обработки.
Никакая универсальность не пострадала.
Так как метод делает ровно то, что делает каждый, когда ему надо перебрать записи.


 
sniknik ©   (2011-10-26 17:49) [29]

> что делает каждый
ну давай посмотрим на реальном коде. сам скажи, что тут "оптимизируемо" твоим методом.

procedure TPaymForm.FillTemplate;
var
 i: integer;
 fID, fCode, fName, fValue: TField;
 Template: TTemplate;
begin
 sPhone:= "";
 
 for i:= 0 to comBoxTemplate.Items.Count - 1 do
   if comBoxTemplate.Items.Objects[i] <> nil then begin
     comBoxTemplate.Items.Objects[i].Free;
     comBoxTemplate.Items.Objects[i]:= nil;
   end;
 comBoxTemplate.Items.Clear;

 if DMod.DSTemplate.Active then
   with DMod.DSTemplate do begin
     fID   := FieldByName("Usr");
     fCode := FieldByName("Code");
     fName := FieldByName("Name");
     fValue:= FieldByName("Value");

     Sort    := "Name";
     Filter  := "Code=" + IntToStr(Code);
     Filtered:= true;

     First;
     while not Eof do begin
       if fCode.AsInteger = Code then begin
         Template:= TTemplate.Create;
         Template.ID   := fID.AsInteger;
         Template.Code := fCode.AsInteger;
         Template.Name := fName.AsString;
         Template.Value:= fValue.AsString;

         comBoxTemplate.Items.AddObject(fName.AsString, Template);
       end;
       Next;
     end;
   end;

 if comBoxTemplate.Items.Count > 0 then begin
   comBoxTemplate.Enabled:= true;
   comBoxTemplate.Color  := clWindow;
 end else begin
   comBoxTemplate.Enabled    := false;
   comBoxTemplate.ParentColor:= true;
 end;
end;


 
Медвежонок Пятачок ©   (2011-10-26 18:04) [30]

если по принципу "можно ли вообще", то можно.
заменить два цикла.

enum_list(comBoxTemplate.Items,DeleteCallback,nil);
enum_dataset(DMod.DSTemplate,Template,nil);

может и не нужно, но зато можно


 
sniknik ©   (2011-10-26 20:17) [31]

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

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

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


 
Медвежонок Пятачок ©   (2011-10-26 20:53) [32]

да нет никаких жестких рамок.

есть банальное желание повторного использования кода и оно реализовано.

я стопицот раз писал вот так, до того как решил покончить с этим:

iList := xdoc.selectNodes("//..........");
for i := 0 to Pred(iLst.length) do
begin
 <что-то_там_в_носу>;
end;

теперь я больше так не делаю. ну жалко мне времени.

nCount := enum_xml_nodes(xdoc,"//.....", MyCallback, ACustomData);

И все! И никаких ограничений, никаких рутинных циклов. Все усилия только на саму задачу обработки, а тупой перебор элементов делает пять лет назад написанная функция в библиотечном модуле.


 
sniknik ©   (2011-10-26 21:34) [33]

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

а как у тебя метод справляется, без рекурсий, ограничений, и только "рутинным циклом"?


 
Медвежонок Пятачок ©   (2011-10-26 21:51) [34]

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

например с рекурсией:

emun_nodes(xdoc,xpath_str_1,firstcallback);

firstcallback(anode : ixmldomnode,......) : boolean;
begin
...
enum_nodes(anode,"./somechild_nodes/....",secondcallback,....)
...
end;

и так далее ...


 
Медвежонок Пятачок ©   (2011-10-26 21:53) [35]

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


 
sniknik ©   (2011-10-26 22:38) [36]

> и он на меня работает.
со стороны мне кажется, что это ТЫ на него работаешь...  копеечная экономия -
вместо 3х строчек цикла
while ... do begin
 Next;
end;
писать 1 строчку вызова процедуры. но с "довеском" в виде написания обработчика в виде другой процедуры, тратя гораздо больше строк.
теряешь в понятности (код не по месту, а куда то вынесен), но тешишь гордость используя везде (ну как же. такое оригинальное, "красивое", решение. бессмысленное но ведь сам придумал! (хотя на самом деле это не оригинальная идея, а такое же в каких то виндовых сетевых функциях видел, использовал... не помню где. главное в винде это есть, и было давным давно (а это было в Симпсонах! ха-ха ;)...)).


 
Медвежонок Пятачок ©   (2011-10-26 22:42) [37]

в понятности как раз теряешь ты.
к тебя в одной процедуре и перебор-итерация чего-то там и одновременно обработка/формирование чего то здесь.

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


 
sniknik ©   (2011-10-26 23:01) [38]

> в понятности как раз теряешь ты.
вот моя часть кода, из приведенного, что может быть "оптимизирована"
    First;
    while not Eof do begin
      if fCode.AsInteger = Code then begin
        Template:= TTemplate.Create;
        Template.ID   := fID.AsInteger;
        Template.Code := fCode.AsInteger;
        Template.Name := fName.AsString;
        Template.Value:= fValue.AsString;

        comBoxTemplate.Items.AddObject(fName.AsString, Template);
      end;
      Next;
    end;


обработка там же где подготовительные/связанные действия

вот что будет у тебя
подготовка, связанное тоже самое а вместо этого "рабочего цикла" -

enum_dataset(DMod.DSTemplate,Template,nil);

сам цикл в отдельном модуле, а обработчик в 3м месте, гда там будет описана процедура Template... ну, если тебе так понятно. ну что тут сказать... а кому нибудь другому ты свой код читать давал? чтобы совсем со стороны.


 
Медвежонок Пятачок ©   (2011-10-26 23:08) [39]

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

представил?
правильно, это будет копипаст.

а уменя колбэк и я его могу вызвать откуда мне вздумается и сколько раз мне вздумается.


 
sniknik ©   (2011-10-27 08:04) [40]

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

> там где одна строка датасета
никаких изменений, цикл по одной строке работает также как по списку...

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

> правильно, это будет копипаст.
ага, копипаст организации цикла - while not Eof do begin Next; end; всегда копипаст. все остальное "по месту" другое.
кстати не задумывался что ВЕСЬ дельфи сплошной копипаст, все слова повторяются... вот например begin end; их же пишем постоянно... ужасть. не думал заменить на свое? избежать "копипаста"? хотя... по большому счету ведь и твоя функция в использовании в другом месте будет с тем же именем... непорядок. копипаст. :)


 
sniknik ©   (2011-10-27 08:10) [41]

p.s. вообще, есть такая фраза, не помню кто сказал - не плодите сущностей...
вот. по моему это вам.


 
Медвежонок Пятачок ©   (2011-10-27 10:26) [42]

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


 
sniknik ©   (2011-10-27 10:59) [43]

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


 
sniknik ©   (2011-10-27 11:07) [44]

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


 
Медвежонок Пятачок ©   (2011-10-27 13:01) [45]

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



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

Текущий архив: 2012.02.05;
Скачать: CL | DM;

Наверх




Память: 0.63 MB
Время: 0.012 c
15-1318859876
lextasy
2011-10-17 17:57
2012.02.05
Посоветуйте учебник по Delphi для школьника


2-1319714974
Очень Злой
2011-10-27 15:29
2012.02.05
Можно ли описать запись неизвестного заранее размера


2-1319647986
Крококо
2011-10-26 20:53
2012.02.05
как получить адрес днс-сервера НА КОМПЬЮТЕРЕ?


2-1319547859
TKN
2011-10-25 17:04
2012.02.05
Многострочные заголовки DBGrid


2-1319447555
Laguna
2011-10-24 13:12
2012.02.05
Ввод в TЕdit руками или сканером штрихкода.