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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 22.01.2018, 08:54   #21  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Цитата:
Сообщение от EVGL Посмотреть сообщение
Верно. Однако, случай, когда один и тот же метод платежа применяется к нескольким банковским счетам достаточно экзотичен и мы можем это исключить правильной конфигурацией.
Я повторю список вариантов, который мне пришел в голову:
  • Попытаться получить то же самое другими способами. Например, если схема с offset account отдельной строкой нужна для удобства ввода, сделать примочку, чтобы генерировать строки или еще как-то обудобнить ввод
  • Зарегистрировать сообщение об ошибке, если UI поддерживает ввод такой конструкции, но платеж не генерируется.
  • Зарегистрировать extensibility request

Цитата:
P.S. Ой, извините, я - EVGL - по ошибке отредактировал ваш текст. Надо отнять у меня права модератора, что-ли?
Наоборот, вы теперь модератор с опытом!

P.S. Может быть вынесем это обсуждение в отдельную тему? Потому, что к данной теме оно относится ОЧЕНЬ косвенно.
Старый 22.01.2018, 17:52   #22  
trud is offline
trud
Участник
Лучший по профессии 2017
 
1,039 / 1630 (57) ++++++++
Регистрация: 07.06.2003
Записей в блоге: 1
Цитата:
Сообщение от EVGL Посмотреть сообщение
Встретился с фирменным стилем belugin в классе CustVendPaymERExport.
Кстати да, не в обиду, но хорошее замечание. т.е. нарушается одно из правил кодеревью что код не должен быть персонализирован(а так в АХ больше никто не пишет)
читать такой код на мой взгляд сложно(непонятно на каком классе вызывается методы), да и отлаживать подозреваю тоже
как вообще такое пропускают
Старый 23.01.2018, 09:04   #23  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
За несколько лет никто не жаловался именно на это. Это не фирменный стиль belugin это FluentInterface - распространенный прием в языках, где нет property и collection initializers (например в java, с которой слизали X++).

Их не надо отлаживать особо - там никакой логики нет, только передача параметров.

BTW у отладчика в VS гораздо больше возможностей, чем то, к чему мы привыкли на предыдущих версиях AX (step into specific, tracepoints, conditional breakpoints, etc) если вдруг кто-то не знает что-то из этого, рекомендую почитать доку.
За это сообщение автора поблагодарили: Link (5).
Старый 23.01.2018, 19:22   #24  
ax_mct is offline
ax_mct
Banned
 
2,548 / 1091 (0) ++++++++
Регистрация: 10.10.2005
Адрес: Westlands
Цитата:
Сообщение от belugin Посмотреть сообщение
За несколько лет никто не жаловался именно на это. Это не фирменный стиль belugin это FluentInterface - распространенный прием в языках, где нет property и collection initializers (например в java, с которой слизали X++).

Их не надо отлаживать особо - там никакой логики нет, только передача параметров.

BTW у отладчика в VS гораздо больше возможностей, чем то, к чему мы привыкли на предыдущих версиях AX (step into specific, tracepoints, conditional breakpoints, etc) если вдруг кто-то не знает что-то из этого, рекомендую почитать доку.
Бить по рукам надо линейкой за FluentInterface
X++:
c1.FirstName("vinod").LastName("srivastav").Sex("male").Address("bangalore").Print();
И категорически запрещать. Каждый раз проклинаю. И ни разу не порадовался.

А по теме, раз отчет то делайте временную таблицу и забудьте о нюансах join, делайте максимально тупо.
Вот на форме, да стоит думать, но для отчета нет смысла. Для отчета нужна гибкость, а это временная таблица.
За это сообщение автора поблагодарили: S.Kuskov (5).
Старый 23.01.2018, 20:56   #25  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Цитата:
Сообщение от ax_mct Посмотреть сообщение
Бить по рукам надо линейкой за FluentInterface
X++:
c1.FirstName("vinod").LastName("srivastav").Sex("male").Address("bangalore").Print();
Почему в одну строчку и не со значимым именем? Слишком читаемо?

Цитата:
И категорически запрещать. Каждый раз проклинаю. И ни разу не порадовался.
Можно включить левое полушарие и вместо эмоций привести аргументы?

Цитата:
А по теме, раз отчет то делайте временную таблицу и забудьте о нюансах join, делайте максимально тупо.
А как данные будут приходить во временную таблицу? За каждой связанной записью ходить на SQL Server? Или тот же join?
Старый 23.01.2018, 22:50   #26  
ax_mct is offline
ax_mct
Banned
 
2,548 / 1091 (0) ++++++++
Регистрация: 10.10.2005
Адрес: Westlands
Цитата:
Сообщение от belugin Посмотреть сообщение
Почему в одну строчку и не со значимым именем? Слишком читаемо?
Можно включить левое полушарие и вместо эмоций привести аргументы?

А как данные будут приходить во временную таблицу? За каждой связанной записью ходить на SQL Server? Или тот же join?
Ни один "системный" программист не может вообразить всех потребностей "прикладного".
Сам каждый раз поражаюсь требованиям и ситуациям.

Возможность дебажить и расширять. Вот что нужно "прикладному" программисту.
Экономия на переменных и строках, для красоты - это говнокод на самом деле. То есть красиво придавленное но г@вно.

Даже инициализацию параметров требуется дебажить и иногда менять. А когда иерархия и все в строку да с запуском в конце то уматываешься проходить по всем параметрам пока до нужного метода доберешься. Часто приходиться переписывать такой код добавляя переменные для удобства дебага.

Те же join это примерно такая же "оптимизация" как и сокращенный код. В топку такую оптимизацию.
Лучше лишний раз сходить на SQL Server. Не нужно ничего оптимизировать заранее и без реальной на то необходимости.
За это сообщение автора поблагодарили: Link (5), Pandasama (1), Stitch_MS (2).
Старый 24.01.2018, 00:34   #27  
Link is offline
Link
Британский учённый
Аватар для Link
Соотечественники
 
568 / 523 (19) +++++++
Регистрация: 25.11.2005
Адрес: UK
Записей в блоге: 9
Цитата:
Сообщение от belugin Посмотреть сообщение
Можно включить левое полушарие и вместо эмоций привести аргументы?
Коллега конечно излишне эмоционален, но я тоже считаю, что такого кода не должно быть в стандарте. Ну и сам X++ Coding Standards:

General Guidelines
  • Only one statement per line.
  • Break up complex expressions that are more than one line - make it visually clear.
  • Use a single blank line to separate entities.
__________________
Людям физического труда для восстановления своих сил нужен 7-8 часовой ночной сон. Людям умственного труда нужно спать часов 9-10. Ну а программистов будить нельзя вообще.
За это сообщение автора поблагодарили: skuull (1), Stitch_MS (2), Vadik (1), AlGol (3).
Старый 24.01.2018, 19:02   #28  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Цитата:
Сообщение от ax_mct Посмотреть сообщение
Возможность дебажить и расширять.
Про возможность дебажить я согласен, что она меньше. На практике жалоб от коллег, что это сильно мешает не слышал (может слышал, но забыл) но это не тот вопрос, которые регулярно всплывает.

У нас не очень много такого кода в production но много такого в тестах.

Учтите, что в AX7 можно просто провалиться по F12 в метод и поставить breakpoint уже там.

К сожалению, в X++ (в отличие от C#) не работает "step into specific" и бряки по имени функции.

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

Про возможность расширять, я не очень понял. EVGL сказал, нашел две проблемы:
1. private методы
2. создание запроса не выделено в отдельный метод

По-моему, это ортогонально стилю заполнения параметров.

Цитата:
Вот что нужно "прикладному" программисту.
Экономия на переменных и строках, для красоты - это говнокод на самом деле. То есть красиво придавленное но г@вно.
Никакой красоты нет. Есть время на чтение и удобство анализа кода. Если есть дублирование, то для анализа надо сканить дубли на предмет различий. Я много раз ловил ошибки типа "скопировали, но забли поменять имя переменной".

Цитата:
Даже инициализацию параметров требуется дебажить и иногда менять. А когда иерархия и все в строку
В каком смысле "иерархия и все строку" обычно разбивается по нескольким строкам?

Цитата:
да с запуском в конце то уматываешься проходить по всем параметрам пока до нужного метода доберешься. Часто приходиться переписывать такой код добавляя переменные для удобства дебага.
Как я уже говорил, можно поставить бряку внутрь метода. Учтите, что VS позволяет смотреть возвращаемое в методе значение.

Цитата:
Те же join это примерно такая же "оптимизация" как и сокращенный код. В топку такую оптимизацию.
Лучше лишний раз сходить на SQL Server. Не нужно ничего оптимизировать заранее и без реальной на то необходимости.
А если 200000 раз?
Старый 24.01.2018, 19:17   #29  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Цитата:
Сообщение от Link Посмотреть сообщение
Коллега конечно излишне эмоционален, но я тоже считаю, что такого кода не должно быть в стандарте.
Моя претензия не к тому что есть эмоции, а к тому, что в исходном сообщении не было ничего кроме них. А так, лично для меня, пусть хоть матом ругается только по делу.

Цитата:
Only one statement per line.
Не очень совместимо с длинными именами (если читать как one and only one - я прочитал как "на каждую строчку должен приходиться только один statement (но он может быть и несколько строчек)") - нельзя разбивать вызов на несколько строчек.

Цитата:
Break up complex expressions that are more than one line - make it visually clear.
Если речь идет про выделение переменных, мне кажется, вложенность описанная отступами более визуальна, чем несколькими присваиваниями на одном уровне.

Цитата:
Use a single blank line to separate entities.
Непонятно, при чем тут это.
Старый 24.01.2018, 23:38   #30  
ax_mct is offline
ax_mct
Banned
 
2,548 / 1091 (0) ++++++++
Регистрация: 10.10.2005
Адрес: Westlands
Цитата:
Сообщение от belugin Посмотреть сообщение

Про возможность расширять, я не очень понял. EVGL сказал, нашел две проблемы:
1. private методы
2. создание запроса не выделено в отдельный метод

По-моему, это ортогонально стилю заполнения параметров.
Цитата:
Сообщение от belugin Посмотреть сообщение
В каком смысле "иерархия и все строку" обычно разбивается по нескольким строкам?
По дебагу.
(class InventAvailabilityByUnit, AX2012R3)
Бодрый Java стиль который не плох сам по себе но неуместен в AX.
Параметр.Параметр.Метод.
КрасивоЖ! Читать легко. Дак то ж его читает то? Дебажат его, а не читают.
X++:
/// <summary>
/// Gets the the quantity available for physical reservation.
/// </summary>
/// <returns>
/// The quantity in the inventory and catch weight units.
/// </returns>
public PmfQtyDataCarrier availPhysical()
{
    PmfQtyDataCarrier result = new PmfQtyDataCarrier();

    result.parmCwQty(this.parmPdsCWInventAvailability().pdsCWAvailPhysical());
    result.parmInventQty(this.parmInventAvailability().availPhysical());

    return result;
}
Но это в принципе не страшно, неудобно но не критично.
Но такая вот инициализация это зуд программиста писать изящно.
И не только private делает больно но и сокращение кода. На тот же level вообще не повлиять никак. Согласен что не в точках дело, но там где программисту хочется в одну строку то отдельный метод для определения level он точно писать не будет. Как бы симптом болезни.
(class WHSInventReserveQtyCalculator, AX2012R3)

X++:
private void initializeCalculations()
{
    InventUpdateOnhand inventUpdateOnhand;

    if (!needsInitializeCalculations)
    {
        return;
    }

    inventUpdateOnhand  = appl.inventUpdateOnhandGlobal().inventUpdateOnhand();
    productDimensions   = EcoResProductDimGroupSetup::newInventTable(inventTable);
    includeDelta        = inventUpdateOnhand.mustAddInventSumDeltaOnhand(inventTable.ItemId);
    ttsId               = inventUpdateOnhand.ttsId();
    level               = WHSReservationHierarchyInventDimUtil::deepestLevelFromInventDimParm(
                                WHSReservationHierarchyProvider::construct()
                                    .getDimListAllFromInventTable(inventTable, WHSReservationHierarchySortOrder::BottomUp),
                                requestedInventDimParm);
    optimizedInventDimParm = this.calculateOptimizedInventDimParm(inventDimCriteria, requestedInventDimParm);

    needsInitializeCalculations = false;
}
Нет в нормально-стандартной AX "fluent interface", все что такое есть привнесли Враги.
In software engineering, a fluent interface (as first coined by Eric Evans and Martin Fowler) is a method for constructing object oriented APIs, where the readability of the source code is close to that of ordinary written prose.
Проза блин

Цитата:
Сообщение от belugin Посмотреть сообщение
Как я уже говорил, можно поставить бряку внутрь метода. Учтите, что VS позволяет смотреть возвращаемое в методе значение.
Пока на AX2012R3 что я очень надеюсь последний MS продукт в моей работе.

Цитата:
Сообщение от belugin Посмотреть сообщение
А если 200000 раз?
Совсем не факт что эти 200000 раз будут дольше чем join.
Вот когда будет 200000 тогда и надо думать о join но не раньше.

Вот пример. И кому такое надо? Оно типа быстрое? Сомнительно, просто читать удобнее, прямо как прозу
(class PdsRebateFindAndCreate.findPdsRebateAgreementAndCreateClaim, AX2012R3)

X++:
//Find all applicable Rebate Agreements.
    while select validTimeState(dateMin, dateMax) pdsRebateAgreement
        where (pdsRebateAgreement.PdsCustRebateCode             == TableGroupAll::All
                || (pdsRebateAgreement.PdsCustRebateCode        == TableGroupAll::GroupId
                    && pdsRebateAgreement.PdsRebateProgramType  == PdsRebateProgramType::Rebate
                    && pdsRebateAgreement.PdsCustRebateRelation == pdsRebateCustInvoiceTrans.SalesTablePdsCustRebateGroupId)
                || (pdsRebateAgreement.PdsCustRebateCode        == TableGroupAll::GroupId
                    && pdsRebateAgreement.PdsRebateProgramType  == PdsRebateProgramType::Freight
                    && pdsRebateAgreement.PdsCustRebateRelation == custTable.PartyCountry)
                || (pdsRebateAgreement.PdsCustRebateCode        == TableGroupAll::GroupId
                    && pdsRebateAgreement.PdsRebateProgramType  == PdsRebateProgramType::TMA
                    && pdsRebateAgreement.PdsCustRebateRelation == pdsRebateCustInvoiceTrans.SalesTablePdsRebateProgramTMAGroup)
                || (pdsRebateAgreement.PdsCustRebateCode        == TableGroupAll::Table
                    && pdsRebateAgreement.PdsCustRebateRelation == custTable.AccountNum))

            && (pdsRebateAgreement.PdsItemRebateCode            == PdsRebateItemCode::All
                || ((pdsRebateAgreement.PdsRebateProgramType    == PdsRebateProgramType::Rebate
                    || pdsRebateAgreement.PdsRebateProgramType  == PdsRebateProgramType::TMA)
                    && pdsRebateAgreement.PdsItemRebateCode     == PdsRebateItemCode::GroupId
                    && pdsRebateAgreement.PdsItemRebateRelation == pdsRebateCustInvoiceTrans.SalesLinePdsItemRebateGroupId)
                || (pdsRebateAgreement.PdsRebateProgramType     == PdsRebateProgramType::Freight
                    && pdsRebateAgreement.PdsItemRebateCode     == PdsRebateItemCode::GroupId
                    && pdsRebateAgreement.PdsItemRebateRelation == inventTable.PdsFreightAllocationGroupId)
                || (pdsRebateAgreement.PdsItemRebateCode        == PdsRebateItemCode::Table
                    && pdsRebateAgreement.PdsItemRebateRelation == custInvoiceTrans.ItemId)
                || pdsRebateAgreement.PdsItemRebateCode         == PdsRebateItemCode::Selection)

            && ((pdsRebateAgreement.RebateCalcDateType == PdsRebateCalcDateType::CreatedDate
                    && (!pdsRebateAgreement.ValidFrom || pdsRebateAgreement.ValidFrom <= pdsRebateCustInvoiceTrans.SalesLineCreatedDate)
                    && (!pdsRebateAgreement.ValidTo   || pdsRebateAgreement.ValidTo >= pdsRebateCustInvoiceTrans.SalesLineCreatedDate))
                || (pdsRebateAgreement.RebateCalcDateType == PdsRebateCalcDateType::RequestedReceiptDate
                    && (!pdsRebateAgreement.ValidFrom || pdsRebateAgreement.ValidFrom <= pdsRebateCustInvoiceTrans.SalesLineReceiptDateRequested)
                    && (!pdsRebateAgreement.ValidTo   || pdsRebateAgreement.ValidTo   >= pdsRebateCustInvoiceTrans.SalesLineReceiptDateRequested))
                || (pdsRebateAgreement.RebateCalcDateType == PdsRebateCalcDateType::RequestedShipDate
                    && (!pdsRebateAgreement.ValidFrom || pdsRebateAgreement.ValidFrom <= pdsRebateCustInvoiceTrans.SalesLineShippingDateRequested)
                    && (!pdsRebateAgreement.ValidTo   || pdsRebateAgreement.ValidTo   >= pdsRebateCustInvoiceTrans.SalesLineShippingDateRequested)))

            && (pdsRebateAgreement.RebateGenericCurrency == NoYes::Yes
                ||  pdsRebateAgreement.RebateCurrency    == custInvoiceTrans.CurrencyCode)

            && (pdsRebateAgreement.RebateUOMOption       == PdsRebateUOMOption::Convert
                || (pdsRebateAgreement.PdsUnitType       == PdsUnitType::InventoryUnit
                    && pdsRebateAgreement.PdsRebateUnit  == custInvoiceTrans.SalesUnit)
                || (pdsRebateAgreement.PdsUnitType       == PdsUnitType::CWUnit
                    && pdsRebateAgreement.PdsRebateUnit  == custInvoiceTrans.pdsCWUnitId()))

            && pdsRebateAgreement.Validated
            && pdsRebateAgreement.Verifier
        #FreightAccruedCondition(custTable.PdsFreightAccrued)
        #CatchWeightCondition(custInvoiceTrans.ItemId)
    #TAMRebateInventDimExistsJoin(pdsRebateAgreement.InventDimId, inventDim, custInvoiceTransInventDim)
    #JoinPdsRebate
    #NotExistRebateTable(pdsRebateAgreement, custInvoiceTrans)
Зы. Задача програмиста в дебаге ответить на вопрос почему не находиться конкретное соглашение. А не читать клиенту с экрана
При этом необходимость join крайне сомнительна.
2 while select или join?
Не говоря уже о об услових выборки в самом SQL.

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

Последний раз редактировалось ax_mct; 24.01.2018 в 23:53. Причина: Зы
Старый 25.01.2018, 09:07   #31  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Цитата:
Сообщение от ax_mct Посмотреть сообщение
КрасивоЖ! Читать легко. Дак то ж его читает то? Дебажат его, а не читают.
Дебажить, понимая что, несколько эффективнее, чем не понимая. Для понимания надо прочитать.

Цитата:
Сообщение от ax_mct Посмотреть сообщение
Нет в нормально-стандартной AX "fluent interface", все что такое есть привнесли Враги.
Тут никакого fluent и не было, кстати в ваших примерах.

Цитата:
Совсем не факт что эти 200000 раз будут дольше чем join.
Вот когда будет 200000 тогда и надо думать о join но не раньше.
Вы ж не знаете сколько у автора темы?
За это сообщение автора поблагодарили: ax_mct (3).
 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
2 while select или join? _scorp_ DAX: Программирование 9 23.01.2009 16:02
AX UK: Join the Virtual Partner Community Blog bot DAX Blogs 0 26.03.2008 04:17
Глюки в Query с разными типами Join (в т.ч. NonExistsJoin) к одной таблице gl00mie DAX: Программирование 10 14.02.2007 13:22
2 и более OUTER JOIN к одному паренту Ronin DAX: Программирование 21 19.12.2005 13:42

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

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

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