|
18.07.2012, 14:26 | #1 |
MCT
|
Коллеги, что вы думаете о данном коде?
Этот табличный метод
X++: static void updateParent(InventoryGuidInvoice inventoryGuidInvoice) { InventoryGuid current, parent; InventoryGuidInvoice parentDistr; InvGuid InvGuid; ; InvGuid = inventoryGuidInvoice.InvGUID; ttsbegin; WHILE(TRUE) { SELECT FIRSTONLY current WHERE current.InvGuid == InvGUID; InvGUID = current.ParentInvGUID; SELECT FIRSTONLY parent WHERE current.ParentInvGUID == parent.InvGUID; if(parent) { //parentDistr.disableCache(); SELECT FIRSTONLY FORUPDATE parentDistr WHERE parentDistr.InvGUID == InvGUID && parentDistr.TransRecId == inventoryGuidInvoice.TransRecId //........... && parentDistr.JuridicalPersonId == inventoryGuidInvoice.JuridicalPersonId; if(parentDistr) { parentDistr.AMOUNTCUR += inventoryGuidInvoice.AmountCur;//слияние к предку //....... parentDistr.Update(); } else { parentDistr.data(InventoryGuidInvoice); parentDistr.InvGUID = parent.InvGUID; parentDistr.insert(); } } else { break; } current.clear(); } ttscommit; }
__________________
Axapta book for developer |
|
18.07.2012, 15:07 | #2 |
Участник
|
а что вас в нем смущает? код пробегает по цепочке "вверх" и что то апдейтит или создает. Оформление конечно страдает
Последний раз редактировалось ice; 18.07.2012 в 15:10. |
|
18.07.2012, 15:20 | #3 |
MCT
|
Вы тоже так пишите?
Я хочу услышать мнения коллег, насколько так вообще корректно писать. Или может у меня одного глаз замылился.
__________________
Axapta book for developer Последний раз редактировалось MikeR; 18.07.2012 в 15:27. |
|
18.07.2012, 15:44 | #4 |
MCITP
|
Цитата:
Ну по крайней мере я бы использовал рекурсию... OFFTOP: не знал, что PL\SQL Formatter можно к Х++ прикрутить...
__________________
Zhirenkov Vitaly Последний раз редактировалось ZVV; 18.07.2012 в 15:44. Причина: синтаксис |
|
|
За это сообщение автора поблагодарили: MikeR (2). |
18.07.2012, 15:58 | #5 |
MCT
|
Коллеги, вы не поверите, но суть в том, что цикл вообще не нужен.
X++: WHILE(TRUE) Я подумал, что это очевидно.....
__________________
Axapta book for developer |
|
18.07.2012, 16:07 | #6 |
Участник
|
Кстати, да. О чем и говорит firstonly. А теперь и мне стало интересно, зачем так было сделано - "запускать выполнение" таким образом?
__________________
С уважением, Александр. |
|
18.07.2012, 16:08 | #7 |
MCITP
|
Цитата:
Он нужен для того что бы запускать и следующие итерации тоже, а не только первую. Цикл будет выполнятся, кока не закончится дерево (не будет парента) и сработает брэйк. Ну собственно такая эмуляция рекурсии...
__________________
Zhirenkov Vitaly |
|
|
За это сообщение автора поблагодарили: S.Kuskov (1). |
18.07.2012, 16:20 | #8 |
Axapta
|
Почему? По-моему, это такой обход дерева. И без "while true" работать не будет. При каждой итерации меняется InvGUID и цикл прервется только тогда, когда не найдется parent. И "while true" при таком написании кода очень даже нужен. Понятно, что код можно переписать иначе.
|
|
18.07.2012, 15:57 | #9 |
Участник
|
Если не касаться оформления, а именно верхних регистров SQL-операторов (лично для меня это непривычно), то while(true) в сочетании с break'ом - это очень "плохой тон", мягко говоря, в программировании в целом (не говоря уже о табличном методе в Ax), о чем, кстати, упоминал в своей книге "Совершенный код" Стив Макконнелл.
ИМХО, следует все же изучить связи таблиц и перестроить данный запрос на while select в сочетании с join'ом, пусть даже с внутренним select'ом. Даже вложенный while не так бьет по глазам, как while(true), хотя это тоже не есть хорошо.
__________________
С уважением, Александр. |
|
|
За это сообщение автора поблагодарили: MikeR (2). |
18.07.2012, 15:59 | #10 |
Участник
|
Слов нет, одни эмоции Вспомнились комментарии в ководстве к одному "шедевру":
Цитата:
Буааууеееееееееее! Ааааа! Глаза кровоточат!
|
|
|
За это сообщение автора поблагодарили: MikeR (2), jeky (2), someOne (8). |
18.07.2012, 16:30 | #11 |
Axapta
|
|
|
18.07.2012, 16:39 | #12 |
MCT
|
Олег, там используется перебор коллекции
X++: while (mi.....more())
__________________
Axapta book for developer |
|
18.07.2012, 16:52 | #13 |
Axapta
|
Цитата:
X++: while (true) { if (bomTableMove.RecId == bomTableDrop.RecId) { dropParent = tree.getParent(curParent); bomTableDropParent = node2BOMTable.lookup(dropParent); return bomTableMoveParent.RecId != bomTableDropParent.RecId || dropParent == rootId; } else { curParent = tree.getParent(curParent); if (curParent == rootId) return true; bomTableDrop = node2BOMTable.lookup(curParent); } } |
|
18.07.2012, 17:00 | #14 |
MCT
|
Отыскал таки
По существу - ты бы сам рекомендовал при однозначной связи потомком и родителя делать через while (true), а не через рекурсию?
__________________
Axapta book for developer |
|
18.07.2012, 17:06 | #15 |
Роман Долгополов (RDOL)
|
Спор ни о чем.
Например с помощью топора можно построить дом или проломить кому нибудь голову. Из этого можно сделать однозначное заключение о применимости топора в любых условиях? Рекурсия может легко переполнить стек. Но это утверждение опять же ничего не значит в отрыве от конкретной задачи |
|
18.07.2012, 17:45 | #16 |
Участник
|
ни где не встречал требований, каким образом делать проход по дереву, так что выбранный программистом подход имеет место быть. и отлавливать ошибки в таком подходе гораздо легче, чем при использовании рекурсии. но рекурсия конечно красивей
|
|
18.07.2012, 17:56 | #17 |
Участник
|
с рекурсией поосторожнее, в 2012 она не поддерживается в CIL
|
|
18.07.2012, 18:47 | #18 |
Участник
|
С точки зрения сохранения целостности данных обновление всего "дерева", наверно, все же нужно выполнять в одной транзакции, однако, сама по себе схема данных, из-за которой "выросло дерево" и из-за особенностей обновления которого возникают, как я понимаю, блокировки, вызывает какие-то неясные подозрения. Такое ощущение, что реализована попытка решить задачу, обычно решаемую с помощью закрытия склада, т.е. будто бы на каждом обновлении идет проход по графу зависимостей проводок и накручиваются коррекции.
|
|
18.07.2012, 19:26 | #19 |
MCT
|
Большое всем спасибо за высказанные мнения.
Наверное тему все ж таки закрою, так как за меня взялись серьезные тролли. Приходится объяснять очевидные вещи, а это грозит перейти в обсуждение теории относительности (кто вокруг кого крутится ) Мое мнение таково, что не зря существуют в серьезных системах определенные фреймворки и надо их знать, что бы было легко поддреживать код. А так согласен, что писать можно лишь бы работало. В сравнение с ремонтом машин - в сервис БМВ берут слесаря после ремонта Жигулей только после переатестации, так как ремонт отличается, хотя и там и там одни и те же гайки, но подход к ремонту отличен. Да можно вручить "местному спецу" отремонтировать и БМВ, но ездить на машине скорее всего будете не долго.
__________________
Axapta book for developer |
|
18.07.2012, 19:33 | #20 |
Участник
|
MikeR, отвечу поскольку ты попросил.
В целом согласен с предыдущими авторами. Прежде всего - насколько я понимаю, вопрос не об оформлении кода, а о сути метода. Метод по сути выполняет обход и обновление дерева. Причем почему-то достраивает дерево на лету. На человеческий язык пользовательской задачи этот метод я не могу перевести. ======================== С деревом в реляционных базах - плохо. Я об этом писал http://axapta.mazzy.ru/lib/tree2/ (там ссылки есть на обсуждения у других) Особенно плохо с универсальным деревом parent/child с произвольной глубиной. Обход универсального дерева в реляционых базах никак не делается в один запрос. Это по запросам. Кроме того, работа с универсальным деревом с произвольной глубиной именно через бесконечный цикл и делается. Или через рекурсию. (Но рекурсия на сложных структурах в java выполняется сложно, поскольку в java все переменные передаются по ссылке) Это по циклу/рекурсии. по поводу ttsbegin/ttscommit - тоже согласен. для сохранения целостности правильно поставлено. Цитата:
Сообщение от MikeR
Этот табличный метод
X++: static void updateParent(InventoryGuidInvoice inventoryGuidInvoice) { InventoryGuid current, parent; InventoryGuidInvoice parentDistr; ... SELECT FIRSTONLY current WHERE current.InvGuid == InvGUID; ... SELECT FIRSTONLY parent WHERE current.ParentInvGUID == parent.InvGUID; ... } но если у таблицы задано кэширование, то два простых запроса по одному ключу каждый будут брать данные из кэша самой Аксапты, что здорово сэкономит на запросах к SQL. Поэтому может быть и правильно, что два запроса. ==================== в общем: если в постановке задачи стояло универсальное дерево, то по-другому написать было сложно другое дело, что деревья в реляционной базе - зло. и их просто не нужно допускать по возможности. А если уж необходимость в дереве есть, то рассмотреть возможность другого хранения ссылок (не parent/child). Почитай по ссылкам со страницы http://axapta.mazzy.ru/lib/tree2/ |
|
|
За это сообщение автора поблагодарили: MikeR (1), alex55 (1). |
|
|