AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 18.07.2012, 14:26   #1  
MikeR is offline
MikeR
MCT
Аватар для MikeR
MCBMSS
Лучший по профессии 2015
Лучший по профессии 2014
 
1,628 / 627 (24) +++++++
Регистрация: 28.11.2005
Адрес: просто землянин
Коллеги, что вы думаете о данном коде?
Этот табличный метод
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 is offline
ice
Участник
Аватар для ice
Лучший по профессии 2014
 
1,732 / 406 (17) +++++++
Регистрация: 23.03.2006
а что вас в нем смущает? код пробегает по цепочке "вверх" и что то апдейтит или создает. Оформление конечно страдает

Последний раз редактировалось ice; 18.07.2012 в 15:10.
Старый 18.07.2012, 15:20   #3  
MikeR is offline
MikeR
MCT
Аватар для MikeR
MCBMSS
Лучший по профессии 2015
Лучший по профессии 2014
 
1,628 / 627 (24) +++++++
Регистрация: 28.11.2005
Адрес: просто землянин
Вы тоже так пишите?
Я хочу услышать мнения коллег, насколько так вообще корректно писать.
Или может у меня одного глаз замылился.
__________________
Axapta book for developer

Последний раз редактировалось MikeR; 18.07.2012 в 15:27.
Старый 18.07.2012, 15:44   #4  
ZVV is offline
ZVV
MCITP
MCP
Oracle
MCBMSS
 
1,006 / 246 (11) ++++++
Регистрация: 13.02.2004
Адрес: Минск
->
Цитата:
Сообщение от MikeR Посмотреть сообщение
Вы тоже так пишите?
Я хочу услышать мнения коллег, насколько так вообще корректно писать.
Или может у меня одного глаз замылился.
Рекурсивный метод тут лучше бы смотрелся.
Ну по крайней мере я бы использовал рекурсию...

OFFTOP: не знал, что PL\SQL Formatter можно к Х++ прикрутить...
__________________
Zhirenkov Vitaly

Последний раз редактировалось ZVV; 18.07.2012 в 15:44. Причина: синтаксис
За это сообщение автора поблагодарили: MikeR (2).
Старый 18.07.2012, 15:58   #5  
MikeR is offline
MikeR
MCT
Аватар для MikeR
MCBMSS
Лучший по профессии 2015
Лучший по профессии 2014
 
1,628 / 627 (24) +++++++
Регистрация: 28.11.2005
Адрес: просто землянин
Коллеги, вы не поверите, но суть в том, что цикл вообще не нужен.
X++:
WHILE(TRUE)
это стоит для того, что бы просто "запустить" выполнение.
Я подумал, что это очевидно.....
__________________
Axapta book for developer
Старый 18.07.2012, 16:07   #6  
samolalex is offline
samolalex
Участник
Аватар для samolalex
Самостоятельные клиенты AX
 
259 / 107 (4) +++++
Регистрация: 18.06.2010
Адрес: Москва
Цитата:
Сообщение от MikeR Посмотреть сообщение
Коллеги, вы не поверите, но суть в том, что цикл вообще не нужен.
X++:
WHILE(TRUE)
это стоит для того, что бы просто "запустить" выполнение.
Я подумал, что это очевидно.....
Кстати, да. О чем и говорит firstonly. А теперь и мне стало интересно, зачем так было сделано - "запускать выполнение" таким образом?
__________________
С уважением, Александр.
Старый 18.07.2012, 16:08   #7  
ZVV is offline
ZVV
MCITP
MCP
Oracle
MCBMSS
 
1,006 / 246 (11) ++++++
Регистрация: 13.02.2004
Адрес: Минск
->
Цитата:
Сообщение от MikeR Посмотреть сообщение
Коллеги, вы не поверите, но суть в том, что цикл вообще не нужен.
X++:
WHILE(TRUE)
это стоит для того, что бы просто "запустить" выполнение.
Я подумал, что это очевидно.....
Так ли?
Он нужен для того что бы запускать и следующие итерации тоже, а не только первую.
Цикл будет выполнятся, кока не закончится дерево (не будет парента) и сработает брэйк.
Ну собственно такая эмуляция рекурсии...
__________________
Zhirenkov Vitaly
За это сообщение автора поблагодарили: S.Kuskov (1).
Старый 18.07.2012, 16:20   #8  
oip is offline
oip
Axapta
Лучший по профессии 2014
 
2,564 / 1416 (53) ++++++++
Регистрация: 28.11.2005
Записей в блоге: 1
Цитата:
Сообщение от MikeR Посмотреть сообщение
Коллеги, вы не поверите, но суть в том, что цикл вообще не нужен.
X++:
WHILE(TRUE)
это стоит для того, что бы просто "запустить" выполнение.
Я подумал, что это очевидно.....
Почему? По-моему, это такой обход дерева. И без "while true" работать не будет. При каждой итерации меняется InvGUID и цикл прервется только тогда, когда не найдется parent. И "while true" при таком написании кода очень даже нужен. Понятно, что код можно переписать иначе.
Старый 18.07.2012, 15:57   #9  
samolalex is offline
samolalex
Участник
Аватар для samolalex
Самостоятельные клиенты AX
 
259 / 107 (4) +++++
Регистрация: 18.06.2010
Адрес: Москва
Если не касаться оформления, а именно верхних регистров SQL-операторов (лично для меня это непривычно), то while(true) в сочетании с break'ом - это очень "плохой тон", мягко говоря, в программировании в целом (не говоря уже о табличном методе в Ax), о чем, кстати, упоминал в своей книге "Совершенный код" Стив Макконнелл.
ИМХО, следует все же изучить связи таблиц и перестроить данный запрос на while select в сочетании с join'ом, пусть даже с внутренним select'ом.
Даже вложенный while не так бьет по глазам, как while(true), хотя это тоже не есть хорошо.
__________________
С уважением, Александр.
За это сообщение автора поблагодарили: MikeR (2).
Старый 18.07.2012, 15:59   #10  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5798 (201) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Слов нет, одни эмоции Вспомнились комментарии в ководстве к одному "шедевру":
Цитата:
Буааууеееееееееее! Ааааа! Глаза кровоточат!
Честно минут 15 тупил, пытаясь понять глубокий смысл этого кода и заодно - такой схемы данных. Что тут еще скажешь... "Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живете" (с) Стив Макконнелл
За это сообщение автора поблагодарили: MikeR (2), jeky (2), someOne (8).
Старый 18.07.2012, 16:30   #11  
oip is offline
oip
Axapta
Лучший по профессии 2014
 
2,564 / 1416 (53) ++++++++
Регистрация: 28.11.2005
Записей в блоге: 1
Цитата:
Сообщение от MikeR Посмотреть сообщение
Кстати, а действительно кто-нибудь пишет рекурсию через
X++:
while (true)
в Dynamics Ax?
Да, в АОТе должно быть полно примеров. Например, в классе ReqCalc.
Старый 18.07.2012, 16:39   #12  
MikeR is offline
MikeR
MCT
Аватар для MikeR
MCBMSS
Лучший по профессии 2015
Лучший по профессии 2014
 
1,628 / 627 (24) +++++++
Регистрация: 28.11.2005
Адрес: просто землянин
Цитата:
Сообщение от oip Посмотреть сообщение
Да, в АОТе должно быть полно примеров. Например, в классе ReqCalc.
Олег, там используется перебор коллекции
X++:
while (mi.....more())
Это немного другое дело, здесь очевидно, надо было использовать запросную часть.
__________________
Axapta book for developer
Старый 18.07.2012, 16:52   #13  
oip is offline
oip
Axapta
Лучший по профессии 2014
 
2,564 / 1416 (53) ++++++++
Регистрация: 28.11.2005
Записей в блоге: 1
Цитата:
Сообщение от MikeR Посмотреть сообщение
Олег, там используется перебор коллекции
X++:
while (mi.....more())
Это немного другое дело, здесь очевидно, надо было использовать запросную часть.
Ок. BOMDesignerCtrl\canMoveNode
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  
MikeR is offline
MikeR
MCT
Аватар для MikeR
MCBMSS
Лучший по профессии 2015
Лучший по профессии 2014
 
1,628 / 627 (24) +++++++
Регистрация: 28.11.2005
Адрес: просто землянин
Цитата:
Сообщение от oip Посмотреть сообщение
Ок. BOMDesignerCtrl\canMoveNode
Отыскал таки
По существу - ты бы сам рекомендовал при однозначной связи потомком и родителя делать через while (true), а не через рекурсию?
__________________
Axapta book for developer
Старый 18.07.2012, 17:06   #15  
db is offline
db
Роман Долгополов (RDOL)
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
 
393 / 692 (24) +++++++
Регистрация: 01.04.2004
Адрес: Москва
Спор ни о чем.
Например с помощью топора можно построить дом или проломить кому нибудь голову. Из этого можно сделать однозначное заключение о применимости топора в любых условиях?

Цитата:
Сообщение от MikeR Посмотреть сообщение
Отыскал таки
По существу - ты бы сам рекомендовал при однозначной связи потомком и родителя делать через while (true), а не через рекурсию?
Рекурсия может легко переполнить стек. Но это утверждение опять же ничего не значит в отрыве от конкретной задачи
Старый 18.07.2012, 17:45   #16  
ice is offline
ice
Участник
Аватар для ice
Лучший по профессии 2014
 
1,732 / 406 (17) +++++++
Регистрация: 23.03.2006
ни где не встречал требований, каким образом делать проход по дереву, так что выбранный программистом подход имеет место быть. и отлавливать ошибки в таком подходе гораздо легче, чем при использовании рекурсии. но рекурсия конечно красивей
Старый 18.07.2012, 17:56   #17  
lvan is offline
lvan
Участник
Аватар для lvan
Лучший по профессии 2014
 
858 / 82 (4) ++++
Регистрация: 15.04.2011
Записей в блоге: 1
с рекурсией поосторожнее, в 2012 она не поддерживается в CIL
Старый 18.07.2012, 18:47   #18  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5798 (201) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
С точки зрения сохранения целостности данных обновление всего "дерева", наверно, все же нужно выполнять в одной транзакции, однако, сама по себе схема данных, из-за которой "выросло дерево" и из-за особенностей обновления которого возникают, как я понимаю, блокировки, вызывает какие-то неясные подозрения. Такое ощущение, что реализована попытка решить задачу, обычно решаемую с помощью закрытия склада, т.е. будто бы на каждом обновлении идет проход по графу зависимостей проводок и накручиваются коррекции.
Старый 18.07.2012, 19:26   #19  
MikeR is offline
MikeR
MCT
Аватар для MikeR
MCBMSS
Лучший по профессии 2015
Лучший по профессии 2014
 
1,628 / 627 (24) +++++++
Регистрация: 28.11.2005
Адрес: просто землянин
Большое всем спасибо за высказанные мнения.
Наверное тему все ж таки закрою, так как за меня взялись серьезные тролли.
Приходится объяснять очевидные вещи, а это грозит перейти в обсуждение теории относительности (кто вокруг кого крутится )
Мое мнение таково, что не зря существуют в серьезных системах определенные фреймворки и надо их знать, что бы было легко поддреживать код.
А так согласен, что писать можно лишь бы работало.
В сравнение с ремонтом машин - в сервис БМВ берут слесаря после ремонта Жигулей только после переатестации, так как ремонт отличается, хотя и там и там одни и те же гайки, но подход к ремонту отличен. Да можно вручить "местному спецу" отремонтировать и БМВ, но ездить на машине скорее всего будете не долго.
__________________
Axapta book for developer
Старый 18.07.2012, 19:33   #20  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
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/
__________________
полезное на axForum, github, vk, coub.
За это сообщение автора поблагодарили: MikeR (1), alex55 (1).
 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
.NET business connector не видит изменений в коде Аксапты rkorchagin DAX: Программирование 2 22.01.2010 11:43
Номерная серия длиннее 20 символов - баг в коде Максимка DAX: Функционал 17 29.12.2009 02:11
Нужно сделать выборку из нескольких таблиц (в данном случае из четырех). niktata DAX: Программирование 10 30.09.2008 09:42
Как быстро найти "главную" процедуру обработки в коде X++ ? Gustav DAX: Программирование 12 14.02.2006 12:15
Можно ли в коде управлять свойством Mandatory? kostas DAX: Программирование 5 10.03.2004 11:14

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 02:56.