четверг, 27 сентября 2007 г.

X++: исключения, часть 1

[id:49]

Механизм исключений в Аксапте тесно связан с подсистемой Infolog. А синтаксис идентичен C++. Попробуем простейшее: static void BLG49_TryExceptions1() { try { throw Exception::Info; } catch(Exception::Error) { print 'Exception::Error'; } print 'End of Job'; pause; } Какой будет результат? Никакой. Причина: блок "catch(Exception::Error)" не будет ловить исключение типа "Exception::Info". А я то раньше наивно предполагал о наличии какой-то иерархии исключений с базовым классом и прочими вещями, как это сделано в .NET!
Но нет. В данном случае мой код не отлавливает исключение "Exception::Info", и оно попадает в лапы Аксапты. Это значит, что до строки "print ’End of Job’" дело не дойдет.

Кстати, с таким же успехом вместо: throw Exception::Info; вы могли бы написать: throw info('Information exception'); Во втором случае, в Infolog сразу попадет ваше сообщение.
Последний вариант приемлем, если хочется сообщить пользователю об ошибке во всех подробностях (которые известны, зачастую, только в том месте, где она возникла).

Итог:

в Аксапте отсутствует иерархия исключений

воскресенье, 23 сентября 2007 г.

X++: открыть документ Word

[id:48]

В систему встроена библиотека вызова некоторых, но не всех, WinAPI-функций. Они доступны через класс Winapi.

Здесь мы попробуем открыть документ Word. Сделай следующий джоб: static void BLG48_ShellExecuteJob(Args _args) {; WINAPI::shellExecute('C:\\temp\\MyBlog.doc'); } Конечно, файл "MyBlog.doc" должен находиться в папке "C:\temp\".
Заметили двойной обратный слэш в строке пути к файлу? Не изменяй своим привычкам, программист С++!

Итог:
  • метод shellExecute() просит операционную систему Windows открыть файл с помощью программы, ассоциированной с расширением файла;
  • удваивайте обратный слэш в строковых константах.

суббота, 15 сентября 2007 г.

Система: компиляция

[id:26]

X++ — объектно-ориентированный язык программирования. Да вы уже сами догадались об этом. Догадались ли вы о том, что это также интерпретируемый язык? Видимо тоже да. Может удивить вас тем, что результатом компиляции является некий байт-код? А знаете ли вы, что сгенерированный байт-код будет во время исполнения интерпретироваться? И вся эта байткодовая возня ради того, чтобы увеличить скорость ваших решений вы тоже знали?

Сохранение изменений объекта – суть тоже самое, что и компиляция. Скомпилировать объект – это значит, что его также сохранили.

Есть одна неприятная новость, и снова глупенький компилятор. Лучше это прочувствовать самому; поэтому создайте проект с двумя классами в нем: Новый проект Код для классов: class BLG26_BaseClass { public int baseMethod(int _i) { return _i + _i; } } class BLG26_ChildClass extends BLG26_BaseClass { public int baseMethod(int _i) { return super(_i) + super(_i); } static void main(Args args) { BLG26_ChildClass cls = new BLG26_ChildClass(); ; info(strfmt('%1', cls.baseMethod(5))); } } Итак, здесь мы создали два класса — папу и дочку. В дочернем классе перекрыли метод "baseMethod()". И, конечно, создали метод main(), чтобы проверить работу написанного кода. Запустил, увидел цифру 20. Пока все нормально, дальше будет хуже.

Поменяем сигнатуру метода baseMethod() в базовом классе: class BLG26_BaseClass { public real baseMethod(real _i) { return _i + _i; } } Компилируйте базовый класс (в дереве проекта щелкните правой кнопкой мыши на классе "BLG26_BaseClass" и во всплывающем меню выберите пункт «Компилировать»). Все в порядке. Откомпилируйте дочерний класс. И снова: все в порядке! Хотя нужно ожидать ошибки. Ведь перегруженный в дочернем классе метод "baseMethod()" по-прежнему работает с целыми числами и вызывает метод "baseMethod()" своего родителя, вполне законно ожидая, что тот тоже работает с целыми числами. А на самом деле папаша уже переметнулся и манипулирует вещественными переменными. Однако компилятор молчит.
Если вы снова выполните метод "main()" дочернего класса, то снова получите цифру 20.

Выход из сложившегося положения — инкрементная компиляция. Для этого щелкните правой кнопкой на родительском классе — "BLG26_BaseClass" —, пункт «Надстройки», «Инкрементная компиляция»: Спасательный круг - инкрементная компиляция Это действие занимает несколько больше времени, чем просто компиляция, потому что система заново генерирует байт-код для текущего класса и всех его дочек. И, о, чудо! Ошибка найдена! Ошибочка вышла Мне было сказано: «ошибка 85, Перегруженная функция имеет неправильный тип возвращаемого значения».

Итог:
  • Аксапта исполняет предварительно созданый байт-код;
  • инкрементная компиляция поможет в трудную минуту.

пятница, 14 сентября 2007 г.

X++: метод strfmt()

[id:47]

Метод strfmt() — первый на очереди, когда хочется выразить свое недовольство действиями пользователя. Это то же самое, что и функция printf() в языке С++. Это тоже самое, что и метод String.Format() в .NET. Да, правильно, этим методом формируют строки. Места для подстановки значений обозначаются парой «процент-число». Поехали: static void BLG47_Ads(Args _args) { Counter cnt; str AdString(str sex, str horoscope, str behavoiur, str partner, str purpose) { return strfmt('#%6, %1, знак зодиака %2, %3, ищет %4 для %5', sex, horoscope, behavoiur, partner, purpose, cnt); } ; cnt++; info(AdString('мужчина', 'близнец', 'без в/п', 'женщину', 'создания семьи')); cnt ++; info(AdString('женщина', 'скорпион', 'курю/выпиваю', 'состоятельного мужчину с квартирой', 'самых серьезных отношений')); } Там, где стоит пара символов "%1" будет подставлено значение переменной "sex", вместо "%2" будет значение переменной "horoscope". И так далее.

Новость первая — тип "Counter" — это расширенный тип данных на базе целого числа. Откройте AOT, ветка "Data Dictionary", "Extended Data Types" и найдите этот тип. Его предназначение быть счетчиком. Использовать его или просто создавать целочисленные переменные является делом вкуса.

Новость вторая — внутри метода можно создать так называемую встроенную функцию. У нас это функция AdString(). Подобные конструкции видны только внутри текущего метода (внутри джоба BLG47_Ads). Заметьте также: то, что для джоба является локальной переменной, то для встроенной функции будет глобальной переменной. На примере видно, как AdString() имеет прямой доступ к переменной cnt, объявленной в джобе.

И третье — порядок символов подстановки для глобального метода strfmt() произвольный. В данном примере видно, что подстановка "%6" идет первой, хоть и берет значение последней переменной (переменной cnt).

Итог:

знакомится с девушками лучше в реальности. Однако уж лучше через объявления делать попытки, чем завязывать служебный роман. Служебный роман — это очень, очень нехорошо.

X++: логическое И, ИЛИ

[id:35]

Попробуем проверить поведение X++ в ситуациях с логическими условиями. Создайте джоб: static void BLG35_CheckAND() { boolean blnTest = false; if (blnTest && checkFailed('Недостижимый участок кода')) { info('Test passed'); } info('End of job'); }

В условии IF искусственно делаем так, чтобы компилятор споткнулся на первом же условии — переменной blnTest. Следующую часть проверять бессмысленно, так как условие уже не выполнилось. И здесь X++ ведет себя логично: он не будет выполнять метод checkFailed(), и сообщение «Недостижимый участок кода» мы не увидим.

Точно такая же ситуация с логическим ИЛИ: static void BLG35_CheckOR() { boolean blnTest = true; if (blnTest || checkFailed('Недостижимый участок кода')) { info('Test passed'); } info('End of job'); }

Итог:

логические И/ИЛИ работают вполне логично

воскресенье, 9 сентября 2007 г.

Система: как бы закрыть окно

[id:039]

Периодически возникает ситуация, когда я оставляю окно проекта развернутым и закрываю систему. Затем открываю Аксапту снова и получаю: Как закрыть окно проекта?

Я не вижу кнопок «Закрыть», «Восстановить» для окна проекта. Один выход: меню «Окно», пункт «Каскад». Это баг.

В компании Майкрософт ошибки в коде могут называться по-разному: багом или фичей. Соответственно, когда в службу технической поддержки отправляется сообщение об обнаруженной ошибке, вам могут ответить по-разному. В первом случае будет сказано «Спасибо. В следующих версиях системы ошибка обязательно будет исправлена». Во втором случае ответят: «Компания считает это не ошибкой, а фирменной особенностью программного продукта, и исправляться не будет».

воскресенье, 2 сентября 2007 г.

X++: точка с запятой

[id:46]

Вспоминаю свой первый день работы с Аксаптой, первые примеры готового кода, с которыми разбирался. Как тогда мне резала глаза точка с запятой, безжизненно и одиноко висящая без всяких на то причин!

Вот, например, код метода одного из классов системы: public Common parmBuffer(Common _buffer = buffer) {; buffer = _buffer; return buffer; } Точка с запятой после открывающей скобки метода — это вообще что такое???

Начнем с того, что в X++ объявления переменных должны располагаться строго в начале метода, как в старые добрые времена языка Си. Дополнительно, сделайте скидку на то, что анализатор кода Аксапты глуповат, либо прикидывается таковым. Одинокая точка с запятой является наследственной, как у человека копчик; она подсказывает компилятору место, где заканчивается область определения переменных и начинается код метода.

До сих пор не смог понять, когда нужно ставить такую точку с запятой, а когда — нет. Не ставлю из принципа. Но если компилятор ругается, а вины своей я не вижу, вот тогда и ставлю этот «копчик», авось поможет (и помогает в 30% случаев).

Итог:
  • переменные можно объявить только в начале метода;
  • может стоит все-таки ставить точку с запятой после объявления переменных, ведь это же не сделка с совестью?

суббота, 1 сентября 2007 г.

X++: самый первый джоб

[id:45]

"Job", он же «джоб», он же «задание» — это отдельно стоящий кусочек кода; он независим от всех, как африканские племена независимы от системы центрального отопления. Похож на функцию, которая не пренадлежит ни одному классу. Предназначен для решения локальных задач разработчика (попробовать какой-то алгоритм, массово исправить данные, запорченные ошибкой в коде).
Далее я буду использовать термин «джоб».

Откройте дерево проектов и создайте новый проект "Blog45", и группу в нем (смотрите рисунок). У группы свойство "ProjectGroupType" должно быть равно "Jobs". Создание нового джоба Для создания нового джоба нажмите на правую кнопку мышки на узле "Jobs" и выберите пункт «Создать», "Job". Откроется редактор X++ с объявленным джобом. Переименуйте его в BLG45_Job и напишите код на рисунке ниже: Тело джоба BLG45_Job На рисунке выделены две кнопки: левая — сохранение изменений, правая — компиляция кода. Названия различные, суть одна: процессы сохранения и компиляции в Аксапте неотделимы («сохраняя, компилируем», «компилируя, сохраняем»).

В результате увидите белое окно с приветственным сообщением: Результат работы джоба

Итог

Джоб — это для программистов.