Форум: "Начинающим";
Текущий архив: 2012.02.05;
Скачать: [xml.tar.bz2];
Внизпомогите определиться с форматом функции Найти похожие ветки
← →
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; их же пишем постоянно... ужасть. не думал заменить на свое? избежать "копипаста"? хотя... по большому счету ведь и твоя функция в использовании в другом месте будет с тем же именем... непорядок. копипаст. :)
Страницы: 1 2 вся ветка
Форум: "Начинающим";
Текущий архив: 2012.02.05;
Скачать: [xml.tar.bz2];
Память: 0.59 MB
Время: 0.005 c