|
![]() |
#1 |
Участник
|
В чем смысл подобной конструкции?
Я щас глупость спрошу. Но весь мозг сломал в размышлениях "зачем?"
AX2012 R3. Класс RetailCDXChannelSpecificData, метод trackChannelDBAssignment() вот очищенный от лишнего код: X++: public void trackChannelDBAssignment() { container channelDB; int i; RefRecId channelDBRecId; while select RefRecId from ref1 where // условия { channelDB += ref1.RefRecID; } for (i = 1; i <= conLen(channelDB); ++i) { channelDBRecId = conPeek(channelDB, i); // некие действия } } нафига разработчики Майкрософт сначала собирают контейнер, а затем делают цикл по контейнеру? контейнер - внутренняя переменная, никуда не возвращается, никаких побочных эффектов он не дает. никаких действий со счетчиком не выполняется. счетчик не возвращается. break'ов из циклов тоже не бывает. ЗАЧЕМ? Почему не сразу один цикл? X++: public void trackChannelDBAssignment() { RefRecId channelDBRecId; while select RefRecId from ref1 where // условия { channelDBRecId = ref1.RefRecID; // некие действия } } |
|
![]() |
#2 |
Участник
|
Может для того чтобы меньше блокировать таблицу ref1. Побыстрее "отпустить". Если операции вставка/удаление/изменение записей в этой таблице происходят часто, а "некие действия" достаточно продолжительны, то вполне возможно - это такая оптимизация.
Последний раз редактировалось S.Kuskov; 29.07.2014 в 12:22. |
|
![]() |
#3 |
Участник
|
Цитата:
никаких особо длинных операций не выполняется. вот полный код: X++: /// <summary> /// Tracks channel database assignment. /// </summary> public void trackChannelDBAssignment() { container channelDB; int i; RefRecId channelDBRecId; RefRecId channelRecId; RetailCDXDataStoreChannel dataStoreChannel; while select RefRecId from ref1 where ref1.NodeID == 0 && ref1.RefTableID == tableNum(RetailCDXDataStoreChannel) && ref1.SYS_CHANGE_OPERATION == 'I' { channelDB += ref1.RefRecID; } for (i = 1; i <= conLen(channelDB); ++i) { channelDBRecId = conPeek(channelDB, i); select Channel from dataStoreChannel where dataStoreChannel.RecId == channelDBRecId; channelRecId = dataStoreChannel.Channel; select firstOnly RecId from ref1 where ref1.NodeID == 0 && ref1.RefTableID == tableNum(RetailChannelTable) && ref1.SYS_CHANGE_OPERATION == 'I' && ref1.RefRecID == channelRecId; if (!ref1) { ref1.initValue(); ref1.NodeID = 0; ref1.RefTableID = tableNum(RetailChannelTable); ref1.RefRecID = channelRecId; ref1.SYS_CHANGE_OPERATION = 'I'; ref1.insert(); } } } но даже предположить не могу ЗАЧЕМ? |
|
![]() |
#4 |
Участник
|
Ну так они же во втором цикле вносят изменения в данные влияющие на выборку в первом.
UPD.: Хотя нет, показалось. Там RefTableID другой. Ну может быть им так же как и мне показалось Последний раз редактировалось S.Kuskov; 29.07.2014 в 12:34. |
|
![]() |
#5 |
Участник
|
Цитата:
![]() не совсем так, в условии выборки присуствует tablenum одной таблицы, а вставляют они tablenum другой таблицы. поэтому выборку они не меняют. если бы это был программист на каком-нибудь проекте, я бы подумал, что он не умеет объявлять еще одну локальную табличную переменную вместо повторного использования ref1... подумал бы... и уволил программиста нафиг. но здесь вроде майкрософтовский код... и может быть, я чего не знаю? |
|
![]() |
#6 |
Moderator
|
Цитата:
Сообщение от mazzy
![]() ![]() не совсем так, в условии выборки присуствует tablenum одной таблицы, а вставляют они tablenum другой таблицы. поэтому выборку они не меняют. если бы это был программист на каком-нибудь проекте, я бы подумал, что он не умеет объявлять еще одну локальную табличную переменную вместо повторного использования ref1... подумал бы... и уволил программиста нафиг. но здесь вроде майкрософтовский код... и может быть, я чего не знаю? Конечно там insert_recordset напрашивается... |
|
![]() |
#7 |
Участник
|
Цитата:
это код из R3. это код, который наваяли уже в Майкрософте весной этого года. унаследованный был в r2 раньше. в унаследованном порядка и логичности было больше. Хотя и там были места для рефакторинга. Но хоть какое-то логичное объяснение тогдашнему коду было. |
|
![]() |
#8 |
Moderator
|
А что ты поповоду использования контейнера думаешь ? Он же immutable - каждый раз память захватывается и освобождается. По моему - правильнее было бы set использовать. (Даже если есть какой-то смысл в подходе в целом). Ну то есть - на мой взгляд - вероятность просто кривого программирования намного выше, чем вероятность хитрого подхода...
|
|
|
За это сообщение автора поблагодарили: mazzy (2), S.Kuskov (1). |
![]() |
#9 |
Участник
|
покопал на предмет использования побочных эффектов с ref1.
ref1 определен как переменная класса. но не, ref1 после вызова не используется. побочных эффектов нет. ЗАЧЕМ? |
|
![]() |
#10 |
Участник
|
А метод ref1.insert() не перекрыт? Там ничего существенного не происходит?
|
|
![]() |
#11 |
Участник
|
Цитата:
эта таблица временная. спасибо за направление. сюда несомненно стоит подумать. но ведь ничто не мешает объявить локальную переменную и направить ее на тот же набор временных записей, что и переменная класса ref1. или таки нет? |
|
![]() |
#12 |
Участник
|
Таки да, очень похоже на то что они не знали о такой возможности SetTmpData. Других объяснений у меня больше нет
Последний раз редактировалось S.Kuskov; 29.07.2014 в 12:53. |
|
![]() |
#13 |
Участник
|
Такую конструкцию не только заморские программисты пишут, часто встречал при кодревью, но на вопрос "зачем?" так никто и не ответил, просто переделывали под второй вариант. видимо зашито где-то в подсознании
![]() |
|
![]() |
#14 |
Участник
|
Делал такое иногда в оракле для длительных процедур.
Например делаем перебор номенклатурного справочника, а для каждой номенклатуры выполняется какая-о длительная операция. Если перебор номенлктаур делать в цикле как предлагал Маззи, то может вылезти ошибка "Snapshot is too old" или что-то в этом духе. В общем сегмент повтора пришлось бы увеличить чтобы этого не было. Для обхода такой особенности, обычно быстро начитывали перечень интересующих номенклатур в set, освобождали курсор и спокойно работали дальше начитывая номенклатуры из Set-а (контейнер - это кривизна !) Возможно для SQL сервера тоже бывают аналогичные проблемы. Версионность забесплатно не дается. На неё БД все равно тратит ресурсы. |
|
![]() |
#15 |
Участник
|
грустно, девушки...
![]() ключевое слово - "длительных". для длительных я согласен, наверное. хотя все равно лучше объявить вторую переменную по методу из книжки Еременко. но в данном то случае никаких "длительных" нет. и не предполагается. вся байда в пределах одного метода. ================== смотрю я на код retail'а в R3, хочется шипя материться. такого накала идиотии давно не видел. все таки остается надежда, что я чего то не понимаю. |
|