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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 14.04.2011, 11:50   #1  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,715 / 1204 (44) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Цитата:
Сообщение от Владимир Максимов Посмотреть сообщение
Как мне кажется, вопрос о способе записи статических данных "вообще" в отрыве от способа использования этих самых статических данных - не имеет смысла.
Цитата:
Сообщение от mazzy Посмотреть сообщение
предложи варианты
Именно это я и делаю. Предлагаю варианты конкретных ситуаций, поскольку по прежнему считаю, что просто нет единого "правильного" способа хранения статических данных. Тот или иной вариант является прямым следствием конкретной задачи. Говорить "вообще" - это говорить "ни о чем"

Исходная постановка задачи после всех уточнений, замечаний, разных "но" и "если" выглядит довольно странно. Примерно так:

Необходимо обеспечить запись некой "матрицы" (таблицы) значений с возможностью их последующей модификации. При этом предполагается, что возможно абсолютно произвольное изменение любой характеристики этой матрицы. Может измениться количество строк, количество столбцов, типы и расположение отдельных элементов и т.д. и т.п.

И что здесь можно ответить? Да любой объект, который может хранить списки подходит для этого! Хоть обычные массивы. Другой вопрос, а подходит ли выбранное решение для конкретной ситуации?

Другими словми, в исходной постановке задача решения не имеет, поскольку сводится к перечню всех возможных инструментов Axapta. Нужно четко обозначить границы задачи. Для каких целей будет использован статический набор?
Старый 14.04.2011, 11:59   #2  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от Владимир Максимов Посмотреть сообщение
Именно это я и делаю. Предлагаю варианты конкретных ситуаций, поскольку по прежнему считаю, что просто нет единого "правильного" способа хранения статических данных.
Ок. Понял.
На ваш взгляд:
1. В Аксапте нет универсального способа хранения статических данных
2. для Query лучше хранить сам query в AOT.

Владимир Максимов, я отключюсь в этой ветке от общения с вами. Извините.

Другие мнения/дополнения будут?
__________________
полезное на axForum, github, vk, coub.
За это сообщение автора поблагодарили: Владимир Максимов (0).
Старый 12.04.2011, 12:57   #3  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,448 / 1792 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Я думаю важнее иметь контроль типов не в смысле контроля атомарных типов данных, а в смысле контроля самой структуры данных. Поясню. Например, если форматом хранения является контейнер сложной структуры (контейнер контейнеров), то очень просто можно запутаться в количестве параметров и порядке их включения во вложенные контейнеры. Здесь контроль типов данных нужен для того чтобы помочь разработчику сопоставить значение соответствующему параметру, а не для того чтобы предотвратить потерю точности при преоброзовании real в int.
За это сообщение автора поблагодарили: mazzy (2).
Старый 13.04.2011, 14:55   #4  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,448 / 1792 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от Владимир Максимов Посмотреть сообщение
Какое отношение это все имеет к контролю типов и значений "параметров"?
post #33

Цитата:
Сообщение от Владимир Максимов Посмотреть сообщение
например, создан вместо контейнера Struct, или MAP, или временная таблицы. И как Вы собираетесь угадывать "что есть что" в этом "чудо-хранилище"? Опираясь на имена?
Ну скажем так, игнорировать имена я уж точно не буду. Если я знаю что мне нужно указать пару "id столбца" - "значение", то Id поля я запишу в поле с именем FieldId а значение в поле с именем Value, а не наоборот. В случае с контейнером это совсем не очевидно.
Старый 13.04.2011, 17:39   #5  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,715 / 1204 (44) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Цитата:
Сообщение от S.Kuskov Посмотреть сообщение
Ну скажем так, игнорировать имена я уж точно не буду. Если я знаю что мне нужно указать пару "id столбца" - "значение", то Id поля я запишу в поле с именем FieldId а значение в поле с именем Value, а не наоборот. В случае с контейнером это совсем не очевидно.
Если речь идет о большом количестве элементов структуры, то, безусловно, имена помогают ориентироваться. Но это всего-лишь подсказки, которые, сами по себе, ничего не гарантируют. Все-равно придется читать документацию или разбирать код, чтобы удостоверится в правильности сделанных предположений.

Получается, что если элементов структуры мало, то ориентироваться в них достаточно просто вне зависимости от того, есть имя или нет. А если элементов структуры много, то ориентироваться в них сложно, опять же, вне зависимости от того, есть имя или нет.
Старый 13.04.2011, 18:43   #6  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,448 / 1792 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от Владимир Максимов Посмотреть сообщение
Получается, что если элементов структуры мало, то ориентироваться в них достаточно просто вне зависимости от того, есть имя или нет.
Хорошо. В отдельно взятой простой структуре ориентироваться просто и без имён. Но мы говорим о системе, количество классов в которой измеряется тысячими. Если разработчик будет вынужден держать в голове мелочи подобные этим, ему сложно будет мыслить глобально. Разработчик в аксапте должен мыслить понятиями бизнесс-процессов, а не порядковыми номерами элементов. Это производители низкоуровневых драйверов могут позволить себе играться с побитывыми операциями , а в аксапте чем нагляднее тем лучше.
Цитата:
Сообщение от Владимир Максимов Посмотреть сообщение
А если элементов структуры много, то ориентироваться в них сложно, опять же, вне зависимости от того, есть имя или нет.
Но при наличии имён на порядок проще. Проще и в плане написания той же самой документации.


P.S.: по-мойму оффтоп получается
Старый 12.04.2011, 20:22   #7  
Ievgenii is offline
Ievgenii
Участник
Аватар для Ievgenii
MCBMSS
Соотечественники
Сотрудники Microsoft Dynamics
 
111 / 113 (4) +++++
Регистрация: 21.09.2008
Адрес: Copenhagen, Denmark
К слову

Цитата:
Сообщение от Владимир Максимов
Как "стандартно" задается пара <таблица, поле> для будущего Range? Очевидно, через функции tablenum(), fieldnum(). И вот КАК здесь можно ошибиться? Приведи пример.


В Ax2012 как MFP уже рассказывал все ID выделяються отдельной инсталяцией. То есть tableNum(InventTable) != tableNum(InventTable) на разных машинах в числовых значениях. Это я к тому что в мета данных вне Ах хранить числовые значений не стоит.
__________________
Thx,
Ievgenii Korovin| Dynamics Ax SCM| Microsoft Corp| http://blogs.msdn.com/DynamicsAxSCM/
Старый 12.04.2011, 21:34   #8  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от Ievgenii Посмотреть сообщение
Это я к тому что в мета данных вне Ах хранить числовые значений не стоит.[/I]
Я так понимаю, что у участников идеи по самой теме кончились, раз пошли боковые ветки.

Ок. Тогда попробую подвести итоги:
1. контейнер значений (в т.ч. контейнер контейнеров)
плюсы:
= очень просто инициализировать значения, легко добавлять/изменять значений
= стандартный функционал работает с контейнерами, поэтому проблем с примером использования не будет
= единственный способ сериализации, приемлемый для передачи параметров между клиентом и сервером (за таблиц, конечно)

минусы:
= контейнер - константа. ВСЕГДА. любая попытка изменить контейнер приводит к пересозданию контейнера. что чревато проблемами производительности для больших наборов
= контейнер - содержит только константы. не содержит ссылки. поэтому хранить ссылку на класс внутри контейнера нельзя
= никакой встроенной проверки типов. нужно писать самому
= никакой встроенной проверки количества данных. нужно писать самому. или надеятся на добросовестность программиста

пример инициализации:
container parm = [['<html>','</html>'],['<body>','</body>']];
container parm = [[myTable1, myField1], [myTable2, myField2]];

пример использования:
= pack/unpack
= класс keySum

2. класс (set, list, map и т.п.)
плюсы:
= контроль типов присутствует (хоть и минимальный)
= класс не пересоздается в памяти при изменении

минусы:
= писать нужно гораздо больше кода чем с контейнерами

примеры использования:
???

2.1. класс (set, list, map и т.п.), хранящий экземпляры специально написанного класса
плюсы:
= полный контроль над значениями

минусы:
= писать надо очень много

пример инициализации:
set mySet = new Set(Types:Class);
mySet.add(new MyParm(myTable1, field1));
mySet.add(new MyParm(myTable2, field2));

пример использования:
???

2.2. класс (set, list, map и т.п.), хранящий struct:
плюсы:
= не надо писать собственного класса

минусы:
= struct не делает контроля обязательности
= очень многословная запись

пример инициализации:
set mySet = new Set(Types:Class);
struct myStruct = new Struct(Types::Integer, "age", Types::String, "name");
myStruct.value("name","Jane Dow");
myStruct.value("age", 34);
mySet.add(myStruct);

myStruct.value("name","Tom Gun");
myStruct.value("age", 45);
mySet.add(myStruct);

пример использования:
???

2.3. класс (set, list, map и т.п.), хранящий контейнеры:
= даже не знаю

минусы:
= бу-э-э-э... способ объединяет минусы всех способов

пример инициализации:
set mySet = new Set(Types:Class)
mySet.add([myTable1, field1]);
mySet.add([myTable2, field2]);

пример использования:
FactureCalcBalances_RU

3. таблицы
плюсы:
= полный контроль
= эффективная передача клиент/сервер
= достаточно очевидно для любого програмиста

минусы:
= нужно писать кода не меньше, чем в случае 2.1 "класс собственных классов"

пример использования:
NumberSeqReference.loadModule()
NumberSeqReference_Ledger.loadModule()

4. xml-файл в ресурсе
плюсы:
= удобно передавать вместе с приложением. особенно большие наборы данных

минусы:
= очень неочевидно для программистов
= работа с xml ресурсоемка

пример использования:
\Data Dictionary\Tables\BITimePeriodsMDX\Methods\importFromAOT

так? вроде ничего не забыл?
__________________
полезное на axForum, github, vk, coub.
Старый 12.04.2011, 22:38   #9  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,342 / 3563 (125) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
По п. 2.1 пример - разноска в ГК: класс LedgerVoucherList - обертка Map, состоящий из объектов LedgerVoucherObject. Здесь формируется список проводок в ГК по ваучеру. (см. класс LedgerVoucher и метод addVoucher)
Другой пример: Объекты List и Map, хранящие в себе список контролек диалога. List хранит упорядоченный список (см Dialog.addCtrlDialogField()), а Map - ссылки на объекты (Dialog.addFieldCon() и Dialog.addDialogClass())

Struct (согласно перекрестным ссылкам) используется для задания свойств объекта. В частности у контрольки в DialogField и в классе WebApplication (тут есть типизация, а не только String)
__________________
Возможно сделать все. Вопрос времени
За это сообщение автора поблагодарили: mazzy (2).
Старый 12.04.2011, 23:27   #10  
CDR is offline
CDR
MCTS
MCBMSS
 
236 / 175 (6) ++++++
Регистрация: 27.11.2003
Если честно, не совсем понимаю смысл создания отдельного динамического хранилища для статичных начальных данных (данных по умолчанию).
Зачем придумывать и создавать коллекцию для этих данных, что бы потом тратить время (и свое и процессорное ) на:
  • заполнение этой коллекции данными
  • на извлечение данных из этой коллекции для их последующей обработки

Поясню на примере.
Что подразумевает использование отдельно-выделенного хранилища данных? Использование как-минимум двух методов.
1. Метод, в котором коллекция заполняется данными.
X++:
void initDataCollection()
{
    ;
    dataCollection = new DataCollection(Type);
    dataCollection.append(data1);
    dataCollection.append(data2);
    dataCollection.append(data3);
    dataCollection.append(data4);
    .....
}
2. Метод, в котором данные извлекаются из коллекции в каком-то цикле для последующей обработки.
X++:
void processDataCollection()
{
    while(dataCollection.more())
    {
        processData(dataCollection.getData());
        dataCollection.next();
    }
}
Т.е. сначала СТАТИЧЕСКИЕ данные запихиваются в ДИНАМИЧЕСКУЮ коллекцию, что бы потом их оттуда обратно извлечь. Какой смысл в этих действиях? Что мешает использовать один метод, в котором сразу и вызывать обработку СТАТИЧЕСКИХ начальных данных (данных по умолчанию)?
3. Метод, в котором сразу обрабатываются статические данные без заморочек со всякими коллекциями-хранилищами.
X++:
void processDefaultData()
{
    ;
    processData(data1);
    processData(data2);
    processData(data3);
    processData(data4);
    ....
}
ИМХО, в подавляющем большинстве Аксаптовых случаев это наиболее простой, быстрый, наглядный, гибкий и т.д. способ обработки статичных начальных данных без всяких коллекций и хранилищ.
__________________
Dynamics AX Experience

Последний раз редактировалось CDR; 12.04.2011 в 23:37.
За это сообщение автора поблагодарили: mazzy (2).
Старый 12.04.2011, 23:48   #11  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от CDR Посмотреть сообщение
X++:
void processDefaultData()
{
    ;
    processData(data1);
    processData(data2);
    processData(data3);
    processData(data4);
    ....
}
ИМХО, в подавляющем большинстве Аксаптовых случаев это наиболее простой, быстрый, наглядный, гибкий и т.д. способ обработки статичных начальных данных без всяких коллекций и хранилищ.
да, спасибо.
во-первых, я забыл записать этот способ. а он обсуждался.
это будет способ 5.

во-вторых,
чтобы так написать нужно чтобы processData был реентерабельным.
в принципе, не такое уж усложняющее требование. но все-таки.

в-третьих, я не зря упомянул в теме про классы.
при таком подходе, класс-потомок сможет только добавлять начальные данные, но не изменять начальные данные родителя.
X++:
class foo
{
    void processDefaultData()
    {
        ;
        processData(data1);
        processData(data2);
        processData(data3);
        processData(data4);
        ....
    }
....
}

class fooBar extends foo
{
    void processDefaultData()
    {
        ;  // как в этом методе изменить/убрать из списка data3?
        super();
        processData(data5);
        ....
    }
}
в-четвертых, инициализация динамического списка может потребоваться чтобы выполнить какую-нибудь пред-обработку. Так, например, LedgerVoucher суммирует движения по... Ой, я же не пишу про учет. Ок, например, Query не позволяет удалять Range. Поэтому, по-уму надо бы сначала провести оптимизацию range'й.

в общем, бывают случаи, когда совсем статический подход не работает.
но согласен - это очень хороший подход в большинстве случаев.
__________________
полезное на axForum, github, vk, coub.
Старый 13.04.2011, 00:25   #12  
CDR is offline
CDR
MCTS
MCBMSS
 
236 / 175 (6) ++++++
Регистрация: 27.11.2003
Цитата:
Сообщение от mazzy Посмотреть сообщение
во-вторых,
чтобы так написать нужно чтобы processData был реентерабельным.
в принципе, не такое уж усложняющее требование. но все-таки.
Если processData будет еще не реентерабельным, то задача обработки однотипных данных для коллекции не решается в принципе. В то же время в 5-ом способе запросто можно написать метод processDataSpecial() и вызвать его для нужных data2 и data4, например.

Цитата:
Сообщение от mazzy Посмотреть сообщение
в-третьих, я не зря упомянул в теме про классы.
при таком подходе, класс-потомок сможет только добавлять начальные данные, но не изменять начальные данные родителя.
Ну да, это ограничение ООП. Насколько я знаю, ни в одном языке нельзя в потомке менять код родительского метода. Его можно либо дополнить, либо полностью переопределить. Ну либо сделать небольшой рефакторинг - разбить родительский метод на несколько отдельных методов и переопределить нужные.

Цитата:
Сообщение от mazzy Посмотреть сообщение
в-четвертых, инициализация динамического списка может потребоваться чтобы выполнить какую-нибудь пред-обработку.
Задача на грани невероятного для статического набора данных.
__________________
Dynamics AX Experience
Старый 14.04.2011, 11:22   #13  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,715 / 1204 (44) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Чем объект AOT отличается от статического набора?
За это сообщение автора поблагодарили: S.Kuskov (0).
Старый 14.04.2011, 11:28   #14  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от Владимир Максимов Посмотреть сообщение
Чем объект AOT отличается от статического набора?
можно и в AOT.
об этом был способ №4 "xml-файл в ресурсе"
и способ №5 "Метод, в котором сразу обрабатываются статические данные без заморочек со всякими коллекциями-хранилищами"

"query в AOT" - частный случай для инициализации с query.
мало того, именно такой способ я и рекомендовал всегда для работы с кверями.
ищите по ключевому слову "querystr"

просто тема не о кверях.
__________________
полезное на axForum, github, vk, coub.
Старый 14.04.2011, 12:10   #15  
mayk is offline
mayk
Участник
Аватар для mayk
 
43 / 65 (3) ++++
Регистрация: 07.03.2008
Вот, кстати, вспомнилось. Не совсем начальные данные, правда, но всё равно показательно.

Пример использования контейнеров в системе когда не надо использовать контейнеры, а надо таблицы: RTax25RegisterTrans.RegsiterValues. там хранится около дюжины самых разнотипных полей.
См. например LedgerJournalCreate_Tax25AmountDiff_RU

Код:
        ledgerJournalTrans.DocumentNum           = conpeek(registerTrans.RegisterValues, #Value3);
        ledgerJournalTrans.DocumentDate          = conpeek(registerTrans.RegisterValues, #Value4);
Ещё вот как хорошо сделано в RAssetAdvancedAssessedTaxDeclaration
Код:
        taxPay += (this.round(conpeek(_trans.RegisterValues, #Value10)) -
                   this.round(conpeek(_trans.RegisterValues, #Value13)));
Очень легко читать и отлаживать /s.

Надеюсь, когда нибудь проверка BP научится бить по рукам за #define.Value13(13) от которого толку - ноль.

Ещё один плюс таблиц перед containerами: фильтры. Помню была доработка по этим RTax25* где надо было выбирать определенные RegisterValues. Так как делать joinы и фильтры на container'ы внутри таблиц нельзя, то приходилось перебирать все RTax25RegisterTrans принадлежащие RTax25RegisterTable'у.

Последний раз редактировалось mayk; 14.04.2011 в 12:13.
За это сообщение автора поблагодарили: mazzy (2).
Теги
как правильно

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Загрузка начальных данных MIVura DAX: Прочие вопросы 1 31.03.2009 14:52
Набор данных на лету HorrR DAX: Программирование 15 26.09.2008 15:21
Прогноз роста базы данных и выбор топологии системы, Как правильно расчитать возможный рост sergeypp DAX: Администрирование 0 05.12.2006 16:55
Введение в Аксапту Роман Кошелев DAX: Прочие вопросы 0 18.12.2001 14:00
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра
Комбинированный вид Комбинированный вид

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

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

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