SSH вполне безопасен, особенно при использовании ключей, что поддерживается.
psexec не так безопасен, но эту проблему можно решить, установив windows SSH сервер и отказавшись от использования psexec.
Можно использовать хуки в Continuous Integration проекте CacheGitHubCI для запуска юнит тестов. Преимуществом проекта является также то, что он полностью написан на COS. После каждого коммита тесты будут запущены автоматически.
>на выходе не только «childrens», но как-нибудь по другомy
Можно с помощью класса %ZEN.proxyObject — подробнее в спойлере.
Генерация json
ClassMethod json()
{
set obj=##class(%ZEN.proxyObject).%New()
set obj.property = "value"
set obj.objproperty = ##class(%ZEN.proxyObject).%New()
set obj.objproperty.simpleproperty="value"
set obj.arrayofdt = ##class(%ListOfDataTypes).%New()
do obj.arrayofdt.Insert(1)
do obj.arrayofdt.Insert("string")
set obj.arrayofobj = ##class(%ListOfObjects).%New()
set obj2=##class(%ZEN.proxyObject).%New()
set obj2.property = "value"
do obj.arrayofobj.Insert(obj2)
do obj.arrayofobj.Insert(obj2)
do obj.%ToJSON() //object root
////////////////////////////////////////////////
set arrayofdt = ##class(%ListOfDataTypes).%New()
do arrayofdt.Insert(1)
do arrayofdt.Insert("string")
do ##class(%ZEN.Auxiliary.jsonProvider).%ObjectToJSON(arrayofdt) //array root, %ListOfObjects is pretty much the same
////////////////////////////////////////////////
set array(1) = $lb("Sam","M",20)
set array(2) = $lb("John","M",25)
set array(3) = $lb("Kate","F",30)
do ##class(%ZEN.Auxiliary.jsonProvider).%ArrayToJSON($lb("name","sex","age"),.array)
}
Метод saveItemData может быть переработан с использованием стандартного механизма десериализации json<->bin.
$$$THROWONERROR(st, ##class(%ZEN.Auxiliary.jsonProvider).%ConvertJSONToObject(ListColumnsJSON ,,.listColumns ,1)) преобразует ListColumnsJSON в экземпляр класса %Library.ListOfObjects.
А есть какой-то флаг включать/отключать логирование?
Отключение логирования возможно — для этого надо закомментировать 1 строку (сохранения записи). Как более постоянный вариант можно сделать получение настройки вкл/выкл из параметра или глобала. Но это, мне кажется, нужно делать при интеграции системы логирования с конкретным приложением — вместе с остальными настройками приложения.
> На самом деле, компилятор классов генерирует INT-код.
Поговорил с разработчиком компилятора классов COS. Класс преобразуется в MAC-подобный набор методов, на основе которого генерируется INT код.
Я являюсь сторонником макросов, так как после однократного выверения макроса с использованием INT кода, CLS код становится понятней, и на INT больше смотреть не надо. Кроме того вызов функций при компиляции может ощутимо уменьшить нагрузку в рантайме. Подробнее об этом я расскажу в следующей статье.
>Не увидел в вашем примере конструкций вида: set result=$$$SomeMacro(...)
Например:
ClassMethod Test8()
{
#define SomeMacro(%name) "Hello "_ ##Continue
%name
set result=$$$SomeMacro("World")
}
>Если уж на то пошло, гораздо труднее представить себе ситуацию, когда многострочные макросы привносят что-то полезное, >недостижимое при использовании обычных вызовов функций (методов класса),
Они упрощают чтение INT кода.
> А ограничений и дополнительных затруднений немало.
Какие, кроме проблем с точками?
>Попробуйте, например, вернуть значение из многострочного макроса (как его может вернуть однострочный макрос-выражение).
Пример 3 оперирует со значением, возвращаемым многострочным макросом.
2*0+1+6 == 7
2+0*1+6 == 8
2+0+1+6 == 9
2*(0+1)*6 == 12
-2+0+16 == 14
-(2^0)+16 == 15
2*0+16 == 16
2^0+16 == 17
2+0+16 == 18
(2*(0+1))^6 == 64
Хотелось бы иметь поддержку InterSystems Caché.
С psexec никак (внутри проекта RCE). C SSH собираем вывод переданной команды. Соответственно его можно использовать.
psexec не так безопасен, но эту проблему можно решить, установив windows SSH сервер и отказавшись от использования psexec.
Можно с помощью класса %ZEN.proxyObject — подробнее в спойлере.
{
set obj=##class(%ZEN.proxyObject).%New()
set obj.property = "value"
set obj.objproperty = ##class(%ZEN.proxyObject).%New()
set obj.objproperty.simpleproperty="value"
set obj.arrayofdt = ##class(%ListOfDataTypes).%New()
do obj.arrayofdt.Insert(1)
do obj.arrayofdt.Insert("string")
set obj.arrayofobj = ##class(%ListOfObjects).%New()
set obj2=##class(%ZEN.proxyObject).%New()
set obj2.property = "value"
do obj.arrayofobj.Insert(obj2)
do obj.arrayofobj.Insert(obj2)
do obj.%ToJSON() //object root
////////////////////////////////////////////////
set arrayofdt = ##class(%ListOfDataTypes).%New()
do arrayofdt.Insert(1)
do arrayofdt.Insert("string")
do ##class(%ZEN.Auxiliary.jsonProvider).%ObjectToJSON(arrayofdt) //array root, %ListOfObjects is pretty much the same
////////////////////////////////////////////////
set array(1) = $lb("Sam","M",20)
set array(2) = $lb("John","M",25)
set array(3) = $lb("Kate","F",30)
do ##class(%ZEN.Auxiliary.jsonProvider).%ArrayToJSON($lb("name","sex","age"),.array)
}
$$$THROWONERROR(st, ##class(%ZEN.Auxiliary.jsonProvider).%ConvertJSONToObject(ListColumnsJSON ,,.listColumns ,1)) преобразует ListColumnsJSON в экземпляр класса %Library.ListOfObjects.
Отключение логирования возможно — для этого надо закомментировать 1 строку (сохранения записи). Как более постоянный вариант можно сделать получение настройки вкл/выкл из параметра или глобала. Но это, мне кажется, нужно делать при интеграции системы логирования с конкретным приложением — вместе с остальными настройками приложения.
Поговорил с разработчиком компилятора классов COS. Класс преобразуется в MAC-подобный набор методов, на основе которого генерируется INT код.
>Не увидел в вашем примере конструкций вида: set result=$$$SomeMacro(...)
Например:
ClassMethod Test8()
{
#define SomeMacro(%name) "Hello "_ ##Continue
%name
set result=$$$SomeMacro("World")
}
Они упрощают чтение INT кода.
> А ограничений и дополнительных затруднений немало.
Какие, кроме проблем с точками?
>Попробуйте, например, вернуть значение из многострочного макроса (как его может вернуть однострочный макрос-выражение).
Пример 3 оперирует со значением, возвращаемым многострочным макросом.
{
#define HW Write "Hello, World!"
#define Five 5
#define WriteLn(%str,%cnt) for ##unique(new)=1:1:%cnt { ##Continue
$$$HW,! ##Continue
Write %str,! ##Continue
}
$$$HW $$$WriteLn("Hello, World!",$$$Five) $$$HW $$$WriteLn("Hello, World!",$$$Five)
}
}
Компилируется в:
zTest6() public {
Write "Hello, World!" for %mmmu1=1:1:5 {
Write "Hello, World!",!
Write "Hello, World!",!
} Write "Hello, World!" for %mmmu2=1:1:5 {
Write "Hello, World!",!
Write "Hello, World!",!
} }
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!