-Поиск по дневнику

Поиск сообщений в rss_rss_hh_new

 -Подписка по e-mail

 

 -Статистика

Статистика LiveInternet.ru: показано количество хитов и посетителей
Создан: 17.03.2011
Записей:
Комментариев:
Написано: 51

Habrahabr/New








Добавить любой RSS - источник (включая журнал LiveJournal) в свою ленту друзей вы можете на странице синдикации.

Исходная информация - http://habrahabr.ru/rss/new/.
Данный дневник сформирован из открытого RSS-источника по адресу http://feeds.feedburner.com/xtmb/hh-new-full, и дополняется в соответствии с дополнением данного источника. Он может не соответствовать содержимому оригинальной страницы. Трансляция создана автоматически по запросу читателей этой RSS ленты.
По всем вопросам о работе данного сервиса обращаться со страницы контактной информации.

[Обновить трансляцию]

[Из песочницы] Поиск пакетов Go на PowerShell

Среда, 02 Августа 2017 г. 14:52 + в цитатник
PowerShell

Всем привет! Одним из моих любимых языков является Go, в результате чего я задумался о написании чего-то вроде Package Manager… Ну или хотя бы поисковика пакетов. Есть идея, пора бы сесть за разработку. Конечно же в первую очередь я подумал о Go как о инструменте для решения проблемы. Но, немного поразмыслив, решил дать шанс манящему меня PowerShell, за изучение которого я садился уже раза 3, но что-то меня постоянно останавливало (скорее всего лень и отсутствие проектов, которые можно было бы на нем реализовать). Что же, сказано – сделано. Данная статья рассчитана на людей, не знакомых с PowerShell, но имеющих опыт в программировании. Если вам стало интересно, то добро пожаловать под кат.

Для начала было бы неплохо узнать, что такое PS. Википедия говорит следующее:

Wikipedia
Windows PowerShell — расширяемое средство автоматизации от Microsoft с открытым исходным кодом, состоящее из оболочки с интерфейсом командной строки и сопутствующего языка сценариев.

Теперь можно приступать к делу. Первая проблема, с которой столкнутся новички – это запрет на исполнение сторонних скриптов. Ребята из Microsoft пекутся о нашей с Вами безопасности, но мы же понимаем, что делаем ;). Так давайте исправим эту досадную заботу. Откройте окно PowerShell, которое выглядит примерно так:

PowerShell

И выполните следующую команду:

Set-ExecutionPolicy RemoteSigned

Система спросит у вас, осознаете ли Вы то, что делаете, отвечаем утвердительное Y.
Вообще основой PowerShell являются командлеты. Они имеют следующий синтаксис:

<Глагол>-<Существительное>

Это довольно удобно, так как вводит понимание того, что должно произойти. Помимо командлетов имеются так же Alias’ы для большинства стандартных команд, причет не только CMD, но и Bash. Например, Вы хотите очистить экран. Стандартный командлет для этого Clear-Host, но также можно воспользоваться алиасами для него: cls и clear. Со списком алиасов можно ознакомиться командой Get-Alias.

И так, мы произвели базовую настройку PowerShell и пришло время для написания скриптов. Расширением скриптов PowerShell является “*.ps1”. Создадим файл для разработки наших командлетов командой:

New-Item -Path 'C:\work\goPS.ps1' -Type File -Force

Если с параметром -Path все понятно, то с остальными придется разобраться. -Type указывает тип создаваемого файла, так как нам нужен файл, мы явно указываем это. -Force же создает пути, если они не существуют.

Вопросом: откуда брать список модулей для Go? Ответ: нам в этом поможет ресурс Go-Search, который предоставляет очень удобное, а главное бесплатное API. Спасибо им за это.

Можно переходить в любимый редактор кода, но лично я могу посоветовать Вам использовать PowerShell ISE, любезно предустановленный в систему. Нужно создать каркас нашего модуля:

function Find-GoPackage {
    
}

Это наш будущий командлет. PS вещь не простая, в отличии от Bash и CMD оперирует объектами, а не строками, что очень удобно при работе с конвейером. Каркас есть, теперь займемся параметрами. Переменные в PS задаются аналогично PHP с помощью $my_var. При этом они могут быть как нетипизированные, так и типизированные.

# Нетипизированная
$no_type
# Типизированная, строка
[string]$have_type

Объявим блок аргументов:

[CmdletBinding()]
Param (
    [string]$Name = ""
)

Как видно, задать аргументы проще простого, да и еще значение по умолчанию есть.

Сама логика работы следующая. В первую очередь нам необходимо произвести запрос на сервер. Сделать это можно несколькими способами, но, как по мне, самый простой это использовать Invoke-WebRequest, который вернет нам объект с содержимым ответа.

Введем переменную:

$uri = "http://go-search.org/api?action=search&q=" + $Name

PowerShell поддерживает работу с конвейером. Ответ от сервера приходит в виде json, но спасибо добрым людям, которые уже подумали о нас. В PS есть стандартные сериализаторы и десериализаторы объектов. ConvertFrom-Json принимает в себя строку Json и возвращает “сырой” объект с полями нашего json. Хватит слов, больше кода, а кода будет мало.

$hits = $($(Invoke-WebRequest -Uri $uri).Content | ConvertFrom-Json).hits

Мы передаем нашу ссылку в инвокер, берем из него содержимое ответа из поля .Content и передаем по конвейеру (конвейер это “|”) в ConvertFrom-JSON. Нас же, в свою очередь, интересует поле .hits, которое содержит список найденных модулей. Всего одна строчка выполнила всю работу за нас!

Осталось только вернуть наш список, ну это уже совсем просто:

return $hits

Привожу полный листинг:

function Find-GoPackage {
    [CmdletBinding()]
    Param (
        [string]$Name = ""
    )

    $uri = "http://go-search.org/api?action=search&q=" + $Name
    $hits = $($(Invoke-WebRequest -Uri $uri).Content | ConvertFrom-Json).hits
    return $hits
}

Теперь снова перейдем в PowerShell и импортируем наш модуль в сеанс:

PS C:\ >. “C:\work\goPS.ps1”

PowerShell проанализировал наш скрипт и готов к работе.

Выполните, например, команду “Find-GoPackage -Name json” и получите список найденных модулей для работы с json, ну а для красоты можно еще и форматирование добавить:

Find-GoPackage json | Format-Table -Wrap -AutoSize

Имеем на выходе аккуратную табличку.

Правда импортировать каждый раз модуль не удобно, поэтому можно сделать одну интересную вещь: в PS есть система профилей. Профиль – это файл, который исполняется каждый раз, когда вы открываете терминал.

Введите в PS следующее:

Test-Path $PROFILE

$PROFILE это переменная среды, содержащая путь до вашего файла профиля. Если команда выше вернула $false, значит ваш профиль не настроен. В таком случае выполните следующую команду:

New-Item -Path $PROFILE -Type File -Force

Откройте этот файл:

notepad $PROFILE

И скопируйте наш вышенаписанный код в файл, сохраните, перезапустите PowerShell и проверьте, что все работает.

На этом все, спасибо за внимание!
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/334720/


Метки:  

[Перевод] Создание оффлайнового распознавания лиц с точностью 99,38% на Python и Node.js

Среда, 02 Августа 2017 г. 14:14 + в цитатник
image

Это мой рассказ о том, как я создавал бесплатное, оффлайновое, работающее в реальном времени open source-приложение, предназначенное для помощи организаторам любых мероприятий в допуске/авторизации только приглашённых людей с помощью технологии распознавания лиц или QR-кода.

Если не терпится перейти сразу к коду, то вот мой репозиторий.

Так что да, распознавание лиц — лишь часть приложения, причём самая трудная часть. Так что налейте себе кофе и наслаждайтесь моим рассказом (я старался).

Часто встречаются посвящённые глубокому обучению проекты на Python, но не на Node.js. Причина в том, что под Python гораздо больше библиотек для эффективных вычислений, например, Numpy, Pandas, tensorflow и так далее. И разрыв достаточно велик. Я знаю Node.js, ну, немного знаю, и хотел использовать его в проекте, чтобы освоить получше, пока вожусь с машинным обучением.

Всё началось во время онлайн-соревнования, на котором был вопрос по работе с API AzureML (определение выражения лица). Я увидел, что там есть ещё и API для распознавания лиц, но с некоторыми ограничениями. К тому же сначала нужно загрузить изображение на сервис, затем он вычисляет результат и присылает его мне. По мне слишком медленно. Я хотел с ним поиграться, но в то время сервис был недоступен в моей стране. Так что хочу поблагодарить разработчиков, которые натолкнули меня на идею сделать что-то своё. До той поры я лишь изучал то, что уже сделали другие. У меня были определённые сомнения с точки зрения безопасности, нужна была функция бэкапа. К тому же я прочитал статью моего шефа об изучении нового языка. И подумал, что настала прекрасная возможность применить свои знания в совершенно новом проекте.

Хорошо, и что дальше? Я подключил к своему Macbook шнур питания, потому что понимал, что это будет долгая работа, и взял с собой своего приятеля Google на разгульные поиски лакомых ресурсов, с которых можно начать проект. Оказалось, что люди уже спрашивали в сети, можно ли реализовать то, что я задумал, но толковых ответов не было. В то время я был один на один с этой задачей. Потом наткнулся на отличную серию публикаций Адама Гайтгея. Раньше я читал его блог, но потом как-то увлёкся другими вещами. И тут наткнулся на замечательную статью Адама и узнал, что он создал на Python пакет face_recognition. Я скачал его и протестировал. Ну, работал он не так гладко, как хотелось бы.
image
Так я себя ощущал, когда устанавливал dlib. Не знаю, почему, но возникла проблема с установкой на самом последнем этапе. Я потратил много часов, пытаясь выяснить причину, даже не пошёл в тот день в спортзал.

image

Я был на грани того, чтобы забросить проект. Но потом выяснил, что причина была в конфликте из-за пути Python-пакета anaconda, или что-то типа того. Я всё ещё изучал экосистему, поэтому пришлось решать, оставить ли anaconda и забросить проект, или избавиться от «змеи». В конце концов я совсем убрал anaconda, и потратил день на завершение полного удаления разных версий Python, скачанных разными пакетами, оставив только системную версию. Затем с помощью Homebrew корректно скачал Python3, установил dlib, и к концу дня смог её запустить.

Тут возникла новая проблема: как интегрировать библиотеку в Node.js? Снова я встал перед дилеммой: изучать Python-фреймворк вроде Django, Flask и так далее, чтобы продолжать работу над проектом, или ввязаться в потенциально бесконечную задачу, которая может оказаться вообще нерешаемой. Когда-то я прочитал эту фразу и она всплыла у меня в голове:

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

Фраза вдохновила меня наравне со статьёй шефа, так что я решил продолжать с Node.js, который немного знал по некоторым веб-проектам.

Поэтому я снова занялся поиском способов интегрирования Python и Node.js. Узнал о дочерних процессах (child process) в Node.js. Но моя ситуация выглядела так:

image

Читал документацию со скудными примерами. Читал блоги, и везде был одно и то же. Но на этот раз я намеревался завершить проект любой ценой (читай, с помощью стажировки). Поскольку уже близилось начало сезона стажировки, мне нужно было как можно скорее закончить приготовления. К тому же мне необходимо было достаточно времени для создания следующим летом другого такого проекта, но опять самостоятельно, с помощью одного лишь Google. Если вы немного знакомы с машинным обучением, то вам будет это близко:

Если скорость обучения слишком низкая, то достижение оптимума займёт немало времени, или вы застрянете на локальном минимуме. Если скорость слишком высокая, то вы можете промахнуться. Но если скорость правильная, или регулируется в зависимости от условий, то алгоритм достаточно быстро найдёт оптимальную точку.

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

image

Так что я усердно трудился, иногда работал до 5.45 утра. Это было удивительное время, я совершил немало дурацких ошибок. Не обновлял вкладку, когда менял код на сервере. Несколько раз менял код на клиенте, но не обновлял окно. Не знаю, почему, может быть, слишком хотелось спать, при комфортной температуре в 22 градуса Цельсия в моей уютной постели. Были удивительные моменты, вроде поиска на Stackoverflow ненужной логической ошибки, которую я позднее пофиксил, просто обновив вкладку.

Наконец я смог подружить Python и Node.js.

image

После того случая с AzureML я испытывал благоговение при создании полностью оффлайнового веб-приложения, способного делать всё задуманное безо всякого интернета. Мне пришлось находить альтернативные API или делать их самому. Как вы, наверное, знаете, в информатике это в порядке вещей: время обратно пропорционально пространству. Так что я старался минимизировать время, затрачиваемое на обеспечение работы тех или иных вещей. Отправка фото/видео в облачный сервис занимает время и канал, а значит приходилось увеличивать занимаемое пространство. Хотя облачные сервисы гораздо удобнее, но мне нравится писать много кода, если я делаю то, что мне интересно. Вы можете принять это, прочитав инструкции по установке для моего репозитория.

Я нашёл много пакетов, пробовал один за другим, брал в работу, иногда отбрасывал и снова искал. Например, нужно было интегрировать распознавание QR-кодов в качестве запасного варианта на случай сбоя распознавания лица. Существует много пакетов для генерирования кодов, но не для их сканирования. В конце концов я нашёл пакет Instascan. Натерпелся с ним бед. Дело в том, что я использовал OpenCV3 для распознавания лица в Python, и той же камерой (в ноутбуке она единственная) сканировал QR-коды. Для сканирования мне нужен был маленький видеокадр, но при этом изменялся и размер видео для распознавания лица. Ну, это не казалось какой-то проблемой. Я могу остановить процесс распознавания, выполнить сканирование QR-кода и снова запустить. Довольно просто, да? Но если вы читали внимательно, то заметили два момента:
  • Если это выглядит простым, значит вы делаете неправильно.
  • Я пытаюсь минимизировать время (главная причина, чтобы не ждать, когда станет доступен API).


Так что для решения этой проблемы мне пришлось изучить код пакетов и выполняемые ими процессы.

Парсинг библиотек


Да, я приступал к этой задаче три раза — анализировал библиотеки, чтобы разобраться со всякими сложностями. По крайней мере, сложностями для меня.
  1. Изучал работу пакета face_recognition, чтобы адаптировать его для своих целей. В то же время помог другим.
  2. Изучал маленький Instascan чтобы понять, как он работает с камерой, и как вообще работать с камерой веб-приложению. Есть много случаев, которые нужно обрабатывать: что если пользователь каким-то образом остановит работу камеры, например, кликнув мимо модального окна или вообще закрыв его. Я изменял код, много раз запускал его, каждый раз находя несколько багов. Однажды у меня на Mac практически кончилась память, и я подвис на несколько секунд. После многократных попыток я наконец-то добился успеха, но опять нашёл очередной баг.
  3. На этот раз баг был в модальном окне фреймворка Materialize. Коллбэк не работает. Погуглил, покопался на Github и Stackoverflow — решения не нашёл. Вычислил отвечающий за баг код, попытался в нём разобраться, несколько раз прогнал его с выражениями console.log(), стараясь понять, что происходит, всё ближе подбираясь к багу, по частям изолируя код (почувствовал себя хакером, обходящим пароль). Слышал, что формы в этом фреймворке тоже не слишком хороши, так что поиграюсь с ними в другом веб-приложении.


Event++


Это удивительный баг, возникший из-за jQuery. Количество событий увеличивается с каждым кликом: 1, 2, 3, 4, 5, 6, 7, 8… Мои уведомления в реальном времени полностью забили весь правый столбец, в который они выводились. Выяснилось, что в jQuery я использую on() вместо click(), а также использую события socket.on() вне обработчика.
Наконец, после долгой борьбы, серверная часть начала неплохо работать с клиентской.

image

Я подумал, что всё готово. Но тут меня посетила идея: что если добавить поддержку базы данных, чтобы пользователь мог выполнять CRUD-операции. Я хотел оставить на усмотрение пользователей, что им использовать: SQL или NoSQL. Думал, что добавлю поддержку и, кто знает, смогу делать на этом деньги (можно слишком рано начать витать в облаках, добившись небольшого успеха). Ещё чуть чуть, и у меня будет полноценная функциональность для автоматического учёта приходящих/уходящих посетителей (распознавание лица, сканирование QR-кода, отсутствие ограничений по API, трёхшаговая аутентификация). Но:
  1. Я всё узнал от open-source сообщества.
  2. Не думаю, что могу продавать свой продукт, стучась в разные компании. Для этого я слишком ленив. Я бы предпочёл разработать ещё несколько подобных продуктов.
  3. Представил сцену из фильма «Социальная сеть» в которой Марк написал приложение и выложил в свободный доступ, даже хотя у него были хорошие предложения о приобретении (думаю, от Microsoft), а тут я такой красивый, с маленьким веб-приложением, которые даже не написал с нуля.

Я попробовал интегрировать MongoDB, потому что был с ней немного знаком, и к тому же я ещё не изучал SQL в колледже. Это будет только в следующем семестре. Так что реализацию этой фичи я оставил для другого проекта, возможно, форка или портирования этого.
В общем, я разработал, интегрировал, потратил несколько дней на изучение, применение, отладку и так далее.

Наконец, я увидел это:

image

Фронтенд, бэкенд и база данных работают в унисон. Конечно, в центре — серверная часть (объединившая в себе силу Python и Node.js). Вы можете решать и другие задачи, например, обучать модель, потому что я смог интегрировать OpenCV3 (это требует установки бинарников), face_recognition, numpy, pandas с датасетом, и сохраняю результат в .csv-формате в моём Python-процессе. Так что если у вас есть подходящее железо, то можете сделать на основе моего проекта что-то совершенно другое.

Оставляю на ваше усмотрение, кто на гифке фронтенд, а кто база данных.

Signing.Off();

* * *
Ссылка на проект.

Почему я написал этот текст, хотя моя кодовая база не так велика? Что тут такого? Ну, для многих из вас это лишь несколько сотен строк кода, но для меня интегрирование всех частей, планомерное изучение, обновление имеющихся знаний, самостоятельное исправление одного база за другим в этом бессрочном проекте (для меня) — всё это задача, которую никто ещё не решал (машинное обучение на Python и Node.js). Ну, может я и плохо искал. В общем, для меня это большой проект. Надеюсь, кому-нибудь он будет полезен. Кроме того, этот пост я написал, чтобы оживить в памяти моменты разочарования и временного счастья, когда что-то ломалось или работало. Такова жизнь.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/334716/


Метки:  

Разработка под Sailfish OS глазами iOS-разработчика

Среда, 02 Августа 2017 г. 14:11 + в цитатник
Привет, Хабр!

На днях в офис e-Legion попал очаровательный смартфон, цвета #F9403E. По опознавательным знакам удалось установить его модель — Jolla C и операционку — Sailfish OS. Сайт производителя снабдил нас данными о характеристиках устройства и предоставил информацию о том, с чего начинать разработку.



Под катом вы узнаете о том, как происходил процесс создания, отладки и установки мобильного приложения для Sailfish ОС.

Характеристики для смартфона 2016 не выдающиеся, но ведь дело не только в железе, но и в том, как реализован софт.



Для ОС заявлена поддержка Android-приложений, но зачем заниматься портированием, если можно написать «шедевр», используя нативные средства для разработки.

Spin-Off: кому и зачем это нужно


В Индии и Китае крупные корпорации сотрудничают с Jolla, разработчиком Sailfish OS, для создания альтернативной ОС, которая позволит избежать проблем безопасности и лицензирования, имеющихся у Android. Также внимание акцентируется на новом UX/UI как возможности для привлечения покупателей, которые используют другие платформы. В России решили взяться за разработку под Sailfish с акцентом на государственный сектор и правительственные нужды. С этой информацией вы можете ознакомиться в других статьях на Хабре или на официальном сайте.

Среда разработки


Когда я начинал разработку для iOS, пришлось столкнуться с некоторыми сложностями. Наличие устройства под управлением Mac OS X — обязательное условие для XCode. У меня его не было. Варианта было два: хакинтош или виртуальная машина.
Теперь же macOS является моей основной операционной системой, поэтому наличие на сайте Jolla SDK, протестированного под Mac OS X, меня приятно удивило. А флешка с установщиком Windows так и осталась пылиться в столе.

Также заявлена поддержка и других платформ:
  • Ubuntu 14.04 32/64 bit
  • Windows 8 32/64 bit
  • OS X 10.9.2


И снова линк на официальный сайт:
  1. Устанавливаем VirtualBox (понадобится для запуска симулятора)
  2. Скачиваем дистрибутив Sailfish SDK
  3. Выбираем компоненты для установки
  4. Соглашаемся с лицензионными соглашениями
  5. ...
  6. PROFIT!!!


Процесс очень простой, каких-либо «танцев с бубном» не понадобилось. Установщик самостоятельно настраивает связь с виртуальной машиной и активирует необходимые компоненты для отладки приложения.

В качестве среды разработки используется Qt Creator.



IDE не такая функциональная, как XCode из коробки, зато крашится реже и подсветка синтаксиса не отваливается :)



Код и язык


Для разработки используется QML — Qt Meta Language. Можно задействовать C++ или Python, если у вас больше опыта работы с этими языками.
Я выбрал QML, так как для реализации простого приложения его возможностей вполне достаточно. QML — декларативный язык программирования, с помощью которого описываются визуальные элементы и их взаимодействие. Синтаксис похож на JSON, код читать и воспринимать очень легко.

Для реализации базовых типов и элементов используется Qt Quick. Вы получаете:
  • набор визуальных компонентов для ввода/вывода информации и возможности для анимирования этих компонентов
  • инструменты для работы с сетью и локальными хранилищами данных
  • средства для биндинга и обработки сигналов

По аналогии с iOS и Android, данную информацию я искал на сайте производителя. Как оказалось, для этих целей лучше подходит сайт Qt. doc.qt.io Он содержит больше документации и примеры кода там интереснее.
Jolla предлагает разработчикам использовать собственный QML-модуль “Sailfish Selica”. Модуль предназначен для создания элементов со стилистикой Sailfish. С этими компонентами можно ознакомиться из предустановленного приложения Components.



Также он служит для оформления приложения в цветах, соответствующих основной выбранной для смартфона теме.

Label {
        text: "Hello habrahabr!"
        color: Theme.highlightColor
        x: Theme.horizontalPageMargin
        width: parent.width - x*2
        font.pixelSize: Theme.fontSizeSmall
        wrapMode: Text.Wrap
    }


Концепция чем-то напоминает использование UIAppearance из iOS, только настройки не ограничены рамками приложения.

Создавать интерфейс из стандартных элементов иногда даже проще, чем в iOS. Создаем кнопку, указываем положение и смещение относительно других элементов. Готово. Пожалуй, с той же легкостью мне удалось работать с интерфейсом только начиная с iOS 9, когда был добавлен класс NSLayoutAnchor.

К сожалению, не всё так хорошо с кастомизацией — в большинстве случаев придётся создавать элемент самостоятельно. Стабильность некоторых компонентов тоже не на высоте. SilicaWebView так и не удалось добавить в приложение, оно постоянно падало. Вместо этого я использовал стандартный WebView, входящий в состав QtWebKit.



При работе с web возникли и другие проблемы. Я запустил приложение на следующий день после начала разработки и вместо списка новостей увидел пустой экран. Несколько часов ушло на поиски решения проблемы. Как оказалось, приложение и встроенный в ОС браузер перестали загружать данные по HTTPS. Пару минуты меня мучила совесть, после чего HTTPS превратился в HTTP.

function requestUrl(source) {
    var url = "http://newsapi.org/v1/articles?"
    url += "source=" + source
    url += "&apiKey=" + apiKey
    return url
}

if (status === XMLHttpRequest.DONE) {
    var objectArray = JSON.parse(req.responseText);
    if (objectArray.errors !== undefined) {
        console.log("Error fetching tweets: " + objectArray.errors[0].message)
    } else {
        for (var key in objectArray.statuses) {
            var jsonObject = objectArray.statuses[key];
            news.append(jsonObject);
        }
    }
    if (wasLoading == true) {
        newsObject.isLoaded()
    }
}


Что касается остальных модулей приложения, их реализация не вызвала особых сложностей. Берём зарекомендовавший себя паттерн MVC, добавляем немного биндинга, щепотку делегирования, обильно посыпаем анимацией, перемешиваем… Получаем на выходе новостное приложение, написанное за пару ночей в попытках попробовать себя в разработке под новую платформу.

Симулятор (emulator) и реальный смартфон


Как я писал ранее, процесс запуска приложения практически не вызвал проблем. Перед установкой SDK размещаем на компьютере поддерживаемую версию VirtualBox, а установщик позаботится обо всём остальном.
Далее выбираем платформу для запуска, жмём кнопку Start и запускаем приложение.



Работа симулятора не вызывает нареканий: всё происходит стабильно и быстро. В своё время мне выпал шанс поработать с одной из первых версий симуляторов Android, 5-минутный запуск которого вызывал боль и приступы паники. Да, сейчас дела у него обстоят гораздо лучше, но осадок остался.
Небольшие проблемы, правда, возникли при многократном запуске приложения. Старые инстансы приложения не завершаются, в результате чего у вас оказывается 5-9 одновременно запущенных экземпляров программы. После достижения некоторого максимального числа новая версия не стартует, приходится завершать старые экземпляры вручную.



Запуск отладки на устройстве занял чуть больше времени. Соответствующую документацию обнаружить не удалось, а подключение смартфона к компьютеру не приводило волшебным образом к появлению соответствующего таргета в настройках. Впрочем, опыт сисадмина-эникейщика не прошёл зря. Побродив по настройкам и понажимав все подходящие, кнопки, я обнаружил возможность запуска приложения на устройстве с указанным IP-адресом. Подключил телефон к WiFi-сети, ввёл адрес и снова нажал на Start. Две минуты ожидания, и моя программа запустилась на Jolla C. Apple услышала наши молитвы и связка Xcode 9 + High Sierra + iOS 11 позволит нам творить такие же чудеса.

Впечатления


Не буду рассказывать о перспективах данной платформы в России, на эту тему и так хватает статей, да и начинать очередной холивар не хочется.

Как пользователю мне понравилась отзывчивость устройства, возможность взаимодействовать с приложением прямо с главного экрана, изменение оформления всех приложений после изменения главной темы и интуитивно понятный интерфейс.



С точки зрения разработчика также осталось множество положительных впечатлений.
Порог входа достаточно низкий, за пару дней удалось создать простое, но функциональное приложение. При этом есть возможность использования C++ для более ресурсоёмких и сложных задач, удручает лишь скупая документация на сайте производителя.
Интерфейс и UI-элементы легко реализуются, вот только не хватает указаний и видения со стороны Jolla. Вместо гайдлайна на сайте я обнаружил 1 страницу, посвященную UX, основная идея которой выражается тремя словами: “Simply Beatiful, Logical, Magical”. Зато какое раздолье для дизайнеров! Можно воплощать в жизнь самые смелые идеи.

Буду рад знакомству с Sailfish-разработчиками и вашим отзывам об этой статье!
Приятного дня и хорошего кода!
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/334702/


Модульное тестирование Pega-приложений: меняем жизнь к лучшему с Ninja

Среда, 02 Августа 2017 г. 13:37 + в цитатник
Несмотря на парадигму ‘no coding’, модульное тестирование на сложных проектах Pega так же важно, как и на других проектах по разработке ПО. В этом я убедился лично, работая в проектах по сквозной автоматизации бизнес-процессов на базе решений Pegasystems.

На Хабре я нашел всего одну статью, посвященную платформе Pega. А между тем Pega ежегодно получает высокие оценки в самых авторитетных рейтингах BPM-решений и CRM-приложений.

Развивая тему работы на Pega, предлагаю вам перевод своей статьи о Ninja – инструменте для тестирования приложений Pega. По ходу комментирую терминологию, которую использовал в этом материале.




В 2015 году я участвовал в автоматизации процесса кредитования корпоративного блока на платформе Pega в одном из крупнейших финансовых институтов России и Восточной Европы.

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

Однажды что-то пошло не так


Чтобы вы могли представить масштаб системы, скажу, что к февралю этого года она достигла размера более 32 тысяч рулов (rule – единица построения приложения на платформе Pega, в Java это может соответствовать методу/классу, но аналогия грубая). Сейчас ее развивают три независимые команды, которые производят более четырех тысяч чекинов в день.

В 2015 году мы вместе с коллегами из «ЛАНИТ – Би Пи Эм» завершали очередной этап проекта и готовили релиз, содержащий множество сложных интеграционных взаимодействий с back-end системами заказчика.

Проблемы начались неожиданно. Системное тестирование выявило ряд ошибок в интеграционных сценариях.

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

Итак, до завершения системного тестирования оставалось две недели, и за это время команды всех взаимодействующих систем должны были исправить свои приложения. Пусть в этом контексте «системы» и «приложения» будут синонимами.

Список ближайших задач напоминал обычную проектную рутину. Нужно было:
  • выделить проблемные интеграционные сценарии;
  • выявить конфликты в интеграционных спецификациях со стороны разных систем, ставшие причиной неработающих интеграционных сценариев;
  • в каждом отдельно взятом случае договориться, на чьей стороне исправлять спецификации и реализацию;
  • исправить и выпустить обновления по всем приложениям.


Список сценариев, которые требовали исправлений на стороне нашей системы, не был коротким, но и не казался пугающим. Исправление интеграционного слоя нашего приложения заняло неделю работы всей команды.

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


Источник

Анализ проблемы


Мы проанализировали этот болезненный провал и выделили следующие основные причины.
  • Из-за высокой сложности приложения невозможно было проверить, что изменения, внесенные в одном месте, не ломают что-нибудь в совершенно другом (абсолютно неожиданном) месте. Это стало причиной большого количества регрессионных дефектов.
  • Описание компонентов приложения, которые мы вели на wiki проекта, не были привязаны к коду и часто были неактуальны – не описывали специфичное поведение рулов при определённых условиях. Таким образом, разработчики при использовании существующих компонентов не обладали достаточной информацией о том, как обрабатывать все возможные исключения или специфичные возвращаемые значения.
  • Разработчики фокусировались на обработке основных сценариев, оставляя не реализованными альтернативные ветки, обработку ошибок или поведение при отсутствии данных.


С учетом нашего опыта в Java мы прекрасно понимали, что подобные проблемы в Java-проектах обычно решаются с помощью известных практик: модульного тестирования, test-driven development и continuous integration. Нам показалось логичным применить данные практики в нашем Pega-проекте.

Проектирование модульных тестов


Мы решили начать с покрытия модульными тестами интеграционного слоя приложения, т.к. он был самой сложной частью нашего приложения и порождал до 80% всех дефектов.

Типовой интеграционный компонент нашего приложения состоял из 6 основных элементов.
  • Connect activity – основной элемент, который объединял все остальные элементы и служил точкой входа для вызова интеграции из различных частей приложения.
  • Request mapping data transform заполнял запрос на основе бизнес-данных.
  • Stream XML преобразовывал запрос из интеграционной модели в XML.
  • Connector rule взаимодействовал с внешней системой по требуемому протоколу.
  • Parse XML разбирал XML ответа и преобразовывал его в интеграционную модель данных.
  • Response mapping data transform преобразовывал ответ из интеграционной модели в бизнес-сущности.


Stream и Parse XML рулы обычно создавались автоматически с использованием Connector and Metadata Wizard вместе и интеграционной моделью данных. Connector рул специально оставлялся «тонким» за счёт перемещения всей логики в Connect activity. Наибольшее количество дефектов порождалось Connect activity и Request/Response mapping data transform, т.к. они содержали основную логику интеграционного компонента.

С учетом описанной выше архитектуры интеграционного слоя мы намеревались создать следующий пакет тестов для каждой точки интеграции.


  • Тест Connect activity в изоляции для проверки её логики, включая нестандартные ситуации.
  • Тест Request mapping data transform в изоляции.
  • Тест Response mapping data transform в изоляции.
  • Тест на весь интеграционный компонент с целью проверки, что исходящий XML формируется, а входящий XML обрабатывается корректно (в соответствии со спецификацией).


Элементы на диаграмме раскрашены в соответствии с «забагованностью» и желаемой степенью покрытия тестами:

  • красный – элементы, в значительной степени подверженные ошибкам, должны тестироваться в изоляции для достижения большего покрытия (модульные тесты);
  • зеленый – элементы, менее подверженные ошибкам, при тестировании их достаточно проверить в связке с другими элементами (речь об inner-com тестах, то есть тестах внутреннего компонента в изоляции от внешних систем);
  • серый – компоненты, которые вряд ли могут содержать ошибки и могут оставаться не покрытыми пакетом тестов.


Модульное тестирование средствами платформы Pega


Первое, что мы попробовали, были Pega Test Cases – автоматизированные тесты, созданные соответствующим инструментом платформы. Хотя они полезны для простых приложений, оказалось, что в проектах корпоративного масштаба их использование существенно ограничено: они не позволяют управлять уровнем изоляции зависимых рулов в тестах.

В нашем случае это означало, что мы не сможем выполнять тестирование в изоляции не только для Connect activity, но также и для Data transform, т.к. они могут использовать (и часто используют) Data Pages, которые, в свою очередь, используют другие рулы в качестве источника данных (Activity, Report Definitions, другие Data Transform и т.д.).

Таким образом, модульное тестирование от Pega подходило для реализации только одного из четырех типов тестов – inner-com тестов. Более того, это было возможно только благодаря механизму Integration Simulation, который, в свою очередь, создавал проблемы части гибкости и сопровождения тестов.

Описанное выше ограничение было не единственным, что нас беспокоило в модульных тестах от Pega.

  • До выхода Pega 7.2 (в тот момент мы использовали Pega 7.1.8) не было удобного способа управления подготовкой данных для теста и проверкой результатов. Побочным эффектом данного ограничения была необходимость пересоздания всех тестов после существенных изменений рулов.
  • Низкая степень повторного использования кода тестов: даже с учетом существенных улучшений в Pega 7.2, нет возможности разбить комплексные проверки результатов теста на отдельные блоки и использовать их в нескольких сценариях.
  • Нет возможности писать комплексные тестовые сценарии, включающие вызов нескольких рулов и проверку общего результата их работы.
  • Pega предоставляет поддержку модульного тестирования для ограниченного набора рулов (Data Pages, Activity, Decision Table, Decision Tree, Flow, Service SOAP).


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

Research & Development


Мы начали с подбора сильной команды ветеранов из Java и Pega проектов. Через мозговые штурмы и отзывы от проектных команд мы добились кристально чистого понимания того, какие функции нам нужны. Это:
  • управление изоляцией рулов;
  • Mock и Stub для рулов (аналогично Mock и Stub для классов в Java);
  • декомпозиция сложных тестов на маленькие, повторно используемые блоки;
  • запуск модульных тестов на любом современном build-сервере.


После нескольких месяцев прототипирования и реализации выпуcтили альфа-версию и начали её пилотировать на небольшой части кода приложения. Пилотирование показало успешность нашей задумки – тесты стали приносить пользу: помогли обнаружить несколько существенных дефектов при написании тестов, а также позволили своевременно выявлять регрессионные дефекты.

Приблизительно в течение года мы внедрили новый подход к тестированию на большинстве наших Pega-проектов. Созданному инструменту требовалось название, и оно появилось само собой – Ninja.


Источник

Модульное тестирование с Ninja


Ninja предоставляет Java библиотеку, позволяющую писать JUnit тесты для рулов. Таким образом, модульное тестирование приложения на платформе Pega становится таким же простым, как в Java.

Давайте немного подробнее остановимся на том, что делает Ninja таким удобным.

Во-первых, Ninja шифрует и безопасно хранит ваши учетные данные для подключения к среде разработки Pega (представляет собой web-приложение, известное как Pega Designer Studio) и выполнения тестов от вашего имени. Это позволяет тестировать приватную версию рула, находящуюся в checkout. Здесь на всякий случай поясню: платформа Pega позволяет брать рулы в checkout и вносить в них изменения, «видимые» только автору. После того как автор проверил внесенные изменения, он выполняет check-in. Затем изменения становятся «видны» всем.

Во-вторых, Ninja использует одну и ту же сессию для последовательных запусков теста. Это позволяет определить Requestor (сессию работы с системой), используемый Ninja, и подключиться к нему с помощью Tracer – инструмента для отладки в платформе Pega, который позволяет просматривать детальную информацию о выполняемых шагах и состоянии объектов в памяти. В данном случае Tracer необходим для анализа происходящего при выполнении тестируемого рула.

Таким образом, Ninja позволяет готовить тестовое окружение легко и точно.

final String myClass = "MyOrg-MyApp-Work-MyCase";
// prepare a Top-level page
preparePage("MyTopLevelPage").create(myClass)
        .prop("pyLabel", "This is my top level page for a case")
    	.prop("MyProp", "My value");
// prepare parameter
prepareParameter("myParam").value("My param value");


Вы можете определять заглушки для рулов, прямо или косвенно вызываемых тестируемым рулом. Это позволяет тестировать рулы в управляемой изоляции.

// mock nested activity invocation
expect().activity().className("MyOrg-MyApp-Work-MyCase").name("NestedActivity").andMock(new MockBehaviour() {
	@Override
	public void process(MockActivityContext context) throws Exception {
    	       // assert parameters
    	      context.assertParameter("myParam").value("My value");
               // assert Primary page
    	       context.assertPrimaryPage().prop("MyProp", "My value");
               // assert Top-level page
    	       context.assertPage("TopLevelPage").exists().prop("pyLabel", "This is my TLP");
               // set properties in Primary
    	       context.preparePrimaryPage().prop("pyNote", "My note for this page");
    	       // set parameters on Top-level page
    	       context.preparePage("TopLevelPage").prop("pyLabel", "This is MODIFIED TLP");
    	       // set parameters
    	       context.prepareParameter("myResult").value("Success");
	}
});


//mock Obj-Browse method invocation
final String opClass = "Data-Admin-Operator-ID";
expect().objBrowse().page("OperatorList").className(opClass).andMock(new MockBehaviour() {
	@Override
	public void process(MockObjBrowseContext context) throws Exception {
    	      // prepare result set
    	      final PreparePageList pxResults = context.preparePage("OperatorList").prop("pxResultCount", "2").pageList("pxResults");
    	      pxResults.append(opClass).prop("pyUserIdentifier", "info@pegadevops.com").prop("pyLabel", "Operator ID record");
    	      pxResults.append(opClass).prop("pyUserIdentifier", "alexander.lutay@pegadevops.com").prop("pyLabel", "Operator ID record");
	}
});


В тестовом сценарии вы можете вызвать практически любой рул, обладающий поведением в Pega. Модульное тестирование не применимо для долго живущих процессов и GUI, поэтому Ninja не поддерживает Flow, Flow Action, Section и другие связанные с GUI рулы.

// what about covering a Function with a unit test?
invoke().function().ruleSet("MyRuleset").library("MyLibrary").name("Func").args().string("My string").longO(123).date(new Date());
 // would you like to unit test a When rule?
invoke().when().primaryPage("pyWorkPage").name("ToBeOrNotToBe");


Вы можете всесторонне проверять результаты выполнения теста.

// assert activity status
assertActivityStatus().good();
// assert Clipboard state
assertPage("MyTestPage").exists().propAbsent("ErrorCode")
	.prop("ResultCode", "0").propPresent("ResultDescription");
// assert Params
assertParameter("MyParam").value("Some value");


Еще больше примеров можно найти в Ninja Cookbook на GitHub.
С помощью Ninja мы покрыли основные интеграционные сценарии модульными тестами.

  • Мы тестируем Connect activity в изоляции за счет имитации (mocking) других рулов. Это помогло нам сфокусироваться в этих тестах на интеграционной логике и проверить все ветки, и в том числе исключительные ситуации.
  • Трансформации данных были исчерпывающе проверены в изоляции от всех других рулов (Function, различные Decision рулы, источники данных для Data Pages), вызываемых прямо или косвенно из Data Transform рулов.
  • Мы делали заглушки на Connector рулы, чтобы избежать вызова внешних систем из inner-com тестов, а также для проверки XML, формируемого компонентом.


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

Уверенность в качестве приложения


По состоянию на февраль 2017 года, кредитный процесс имеет несколько параллельных веток разработки: исправление дефектов, возникающих в рамках опытной эксплуатации (Prod-ветка), и несколько веток под разработку функционала будущих релизов.

Каждая ветка покрыта собственными модульными тестами, которые развиваются вместе с приложением. Тесты хранятся в системе контроля версий и также разделены на ветки. Prod-ветка по состоянию на февраль 2017 года имела 350 тестов. Позволю себе уточнить, что на момент перевода статьи, в июле 2017 года, ветка последнего релиза содержала уже порядка 1650 тестов, время выполнения которых не превышает 15 минут.

Модульные тесты запускаются build-сервером отдельно для каждой ветки каждые 30 минут. Это означает, что команда получает «отчёт о здоровье» системы каждые 30 минут и может своевременно реагировать на появляющиеся дефекты.

Ninja позволила нам быстрее выпускать продукт более высокого качества благодаря меньшему количеству циклов Dev-QA, т.к. большинство дефектов теперь обнаруживаются на Dev-среде и сразу устраняются.

Стало меньше дефектов в опытной эксплуатации – благодаря более всестороннему тестированию командой QA, которой теперь не приходится сталкиваться с тривиальными дефектами, блокирующими прохождения тестовых сценариев.

Продолжение следует


Наш опыт подсказал нам, что модульные тесты – не единственная «слабая» область платформы Pega: если сравнивать с Java или другими «традиционными» платформами разработки ПО, инструменты Pega, которыми могут воспользоваться разработчики, обладают существенными ограничениями.

С учетом фидбека от проектных команд и по результатам многочисленных мозговых штурмов мы определили функции, которые следующими появятся в Ninja:

  • Rule Refactoring – рефакторинг рулов;
  • Code analysis – расширенный статический анализ кода;
  • Code review – аудит кода;
  • Release automation – автоматизация сборок и поставок;
  • Continuous delivery pipeline – конвейер continuous delivery.


Отмечу, что сейчас большая часть этих функций уже доступна в Ninja. Уверен, что подобные функции позволят Ninja стать всеобъемлющим инструментарием для внедрения DevOps на проектах Pega.

Нашим решением заинтересовались зарубежные коллеги, и я рад, что этот кейс может служить примером для других команд разработчиков: в России можно хорошо делать нишевые решения для крутых ИТ-продуктов и успешно их экспортировать.

Более подробную информацию о Ninja ищите здесь.

Если вы хотите присоединиться к нашей команде


В заключение предлагаю вам небольшой опрос:
На какой технологии вы разрабатываете корпоративные приложения?

Проголосовало 4 человека. Воздержался 1 человек.

Практикуете ли вы модульное тестирование?

Проголосовало 4 человека. Воздержался 1 человек.

Насколько хорошо вы знаете Pega?

Проголосовало 5 человек. Воздержавшихся нет.

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/334648/


Метки:  

Red Team: командное взаимодействие при проведении тестирования на проникновение

Среда, 02 Августа 2017 г. 13:37 + в цитатник

Метки:  

[recovery mode] Тестирование прототипов при разработке программного продукта

Среда, 02 Августа 2017 г. 12:53 + в цитатник
Дмитрий Мелентьев, глава отдела проектирования компании Paneglif, специально для блога Нетологии рассказал о своем опыте тестирования прототипов при разработке программного продукта.

В процессе разработки мы часто сталкиваемся с такой дилеммой: как сделать продукт хорошо и быстро, но при этом интересным и понятным и пользователям, и заказчикам. Никому не хочется, чтобы сыпались миллионы одинаковых вопросов о том, как это вообще работает.



Рецепт есть: тестировать продукт перед выходом на рынок.

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

Поэтому нужно тестировать не в конце разработки продукта, а намного раньше, может даже в начале.

Тестирование прототипа поможет обмануть время и устранить глобальные проблемы в самом начале разработки.

Нам всегда хочется избежать тестирования прототипов, прикинувшись овощем. Зачем тестировать, если и так «всё понятно»? Это ведь займёт время разработки продукта и ещё добавит организационных проблем — тот же подбор людей на тестирование чего стоит. И помещение нужно где-то взять тихое, и еще быть добрым со всеми респондентами, даже когда они, мягко говоря, несколько не ориентируются в происходящем. Кажется, что можно вычеркнуть этот небольшой «эпизод», сберечь ресурсы, и никто не заметит даже. И всё будет хорошо!

Но так не работает.

В реальности лучше потратить 30 минут на тестирование прототипа на пользователях, чем сделать дизайн, сверстать, запрограммировать, а потом обнаружить, что нужно все [censored] переделывать!

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

Есть несколько проверенных временем и опытом способов тестировать продукт: начиная с этапа, когда он существует только в виде набросков, и заканчивая тестированием прототипа на пользователях, которые будут думать, что это уже готовый сайт в работе, и никакой не прототип. Иногда оно так и есть, правда.

Бумажный прототип


На бумаге идеально тестировать концепты, когда есть доступ к целевой аудитории и несколько человек для проведения исследования. Лучше всего тестировать сложные сценарии с множеством экранов, миллионом кнопок — в общем, что-то такое, что можно аналогично протестировать только на готовом продукте.

Да, прототип будет очень далек до реального результата, но зато у респондентов не будет возникать вопросов: «почему фотка не моя», «почему я нажал на картинку кроссовок, а появился ремень», «почему нет красивой анимации у этого окошка», «почему скролл не двигается», «почему тут кнопки кривые» и т. д.

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

Из опыта


Однажды делали проект единого дизайна сайта муниципальных округов. Сначала провели исследования, чтобы понять, что можно размещать на сайте, что нельзя. Затем определили, что будет важно посетителям, а что нет, но по закону обязательно должно быть на сайте.

Сделали прототипы на бумаге: все экраны и окна. И провели тестирование на бумаге, с тремя участниками тестирования с нашей стороны:
  • один «робот»,
  • один модератор,
  • один наблюдатель.

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

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

Но внезапно всё пошло хорошо. Пользователи кликали прототипные кнопки, скроллили страницу, переходили по вкладкам и искали информацию в поиске. То есть действительно «работали» с бумажным прототипом. Да, немного непривычный, но вполне рабочий процесс.

Первый плюс в том, что нарисовать бумажный прототип можно за 3 часа, а вот спроектировать прототип в программе — это минимум день. А то и два. Потом понадобится вставлять контент, выравнивать всё, готовить под тестирование.

Второй плюс: если во время тестирования что-то не так «работает», на бумаге это быстро исправляется карандашом и ластиком — и можно тестировать дальше. И интернет для этого не нужен.

Кроме того, у людей не возникало отторжения, непонимания или негатива на такое тестирование. Всё было чётко и по делу. У нас получилось выявить немало косяков в навигации и взаимодействии пользователя с сайтом.

Интерактивные прототипы в мелкой детализации


С помощью интерактивных прототипов хорошо тестировать логику, особенно простую, а также ожидания пользователей. Конечно, можно взяться и за сложную навигацию, но придется потрудиться с количеством и качеством экранов. Респондент зачастую не воспринимает интерактивный прототип как прототип, поэтому ему приходится постоянно об этом напоминать.

Для чего плохо подходят такие прототипы:
  • для тестирования сложной логики с серьезными скриптами и анимацией;
  • для оценки визуального дизайна, о котором не выскажется разве что самый ленивый респондент.

Контент в таких прототипах должен быть максимально приближен к реальному.

В интерактивных прототипах не должно быть Lorem Ipsum, стандартных картинок с горами Axure и перечеркнутых прямоугольников.

Такое наполнение плохо воспринимается респондентом, который часто забывает, что это просто прототип для тестирования логики, и зацикливается на наполнении и визуальном оформлении.

Так делать не стоит. Да и зачем, если очень просто найти «рыбу» по теме:
  • взять текст на fishtext.ru;
  • скачать картинки с Яндекс.Картинки;
  • поставить стандартные иконки Bootstrap;
  • разместить фотографии пользователей из поиска по людям ВКонтакте;
  • написать максимально реальные заголовки, чтобы потом не оказалось, что они не входят в ширину экрана.

Есть мнение, что такие прототипы стоит делать черно-белыми. И да, и нет. Да, не стоит делать в интерактивном прототипе цветовые акценты на нужных вам элементах, так как это неверно с точки зрения реальности, когда таких акцентов уже не будет. И всё же не всегда можно обойтись черно-белым прототипом. Если, например, предполагается картинная галерея и акцент на картинах, то лучше сразу делать прототип похожим на реальность, а изображения взять из поиска. Так сразу будет понятно, что это за прототип и зачем он нужен.

Интерактивные прототипы идеально тестировать на целевой аудитории. Можно по скайпу, многие прототипы беспроблемно расшариваются. Пользователь включит трансляцию экрана, а вы сможете наблюдать за его действиями.

Если невозможно найти людей из ЦА, и при этом не требуется проверять слишком сложный прототип, сделайте «коридорное тестирование». Возьмите простых сотрудников компании, которые похожи на ЦА. Главное в такой ситуации — не брать тех, кто идеально знает весь продукт или непосредственно участвует в разработке.

Не все специалисты согласны с «коридорным» подходом, аргументируя это тем, что выборка не представляет целевую аудиторию. Но я зуб даю, что лучше так, чем вообще без тестирования: часто всплывают глупые интерфейсные ошибки, которые сам ни за что не увидишь. Ни за что!

Тестирование цветного прототипа в программах типа Axure


Тут всё достаточно просто. Дизайнер делает красивый интерфейс, в котором вы размечаете области, при взаимодействии с которыми должно что-то происходить. Обычно это просто «on click» или «on move». Можно, конечно, поколдовать с резаком и вырезать различные элементы, но это слишком долго. Хотя есть и такие перфекционисты.

Вся эта красота делается интерактивной и тестируется на пользователях: насколько быстро расставленные вами цветовые акценты позволяют пользователю найти нужные элементы. Респондент может проговаривать действия вслух, а вам нужно просто дождаться, пока он сделает нужное действие. Или не дождаться и уйти плакать — если вы дизайнер. А если вы не дизайнер, то ваша задача — отправить замечания дизайнеру.

Тестируем на целевой аудитории, можно по скайпу. Есть небольшой нюанс: надо постоянно напоминать, что это прототип. Постоянно! Потому что такой прототип уж слишком похож на реальность. Кстати, в нем уже не место бессмысленной «рыбе»: нужны нормальные тексты, картинки, иконки. Можно взять их из интернета, только помните про правообладателей.

Если респонденты допускают невообразимые логические ошибки, значит, либо дизайнер сделал реально плохое решение, либо вы очень плохо протестировали прототип на предыдущем этапе.

Такое тестирование помогает оценить:
  • насколько конкретный элемент, который ранее был, например, большой кнопкой, а сейчас стал красивеньким тонким баром, понятен пользователю;
  • акценты и видимость всех важных элементов дизайна.

Если пользователь не замечает нужные элемент или кликает почём зря — значит, нужно править.

Учтите, что во время тестирования UI- или графический дизайнер, который это всё делал, должен молчать, а лучше вообще быть далеко от респондентов. Если рядом, то только с выражением «poker face». Ему будет сложно, он периодически будет хвататься то за топор, то за верёвку с мылом, так что лучше всего его держать чуть в стороне от самого процесса тестирования дизайна на пользователе.

Тестирование со скриптами, или MVP-тестирование на alfa-версии продукта


Всё работает как нужно, но пока вместо 1 млрд пользователей у вас 5 человек — друзей проекта, вместо базы в 5 млн SKU у вас пока 1 база на 100 товаров, а вместо выделенных серверов на Амазоне, виртуальный хостинг на 1gb.ru. Но всё работает как нужно.

Всё работает как нужно. Это главное условие!

Теперь берёте пользователя из целевой аудитории (не нужно брать программистов из соседнего помещения), даёте ему цель, и пусть он её выполняет. Всё должно пройти идеально. Мелкие баги, которые мешают реальному пользователю прийти к цели быстро и эффективно, записываем, а потом правим.

Ещё раз для тех, кто хитрый. Тестировать надо на ЦА! Не тестируйте свой продукт на работниках столовой у вас в офисе, если ЦА — это девушки с «Барвиха Лухари Вилаж».

Если очень нужно проверить сложную дорогую функциональность, которую разрабатывать минимум год, то сделайте быстрое решение и проверяйте его.

Главное, чтобы всё работало так же, как и в вашем будущем суперкалькуляторе плотности пыли 1 грамма песка Сахары. Можно также заменить готовыми решениями, которые есть на рынке.

Со стороны это всё похоже на ненужный дорогостоящий ад. Но! Вы хотите сделать мобильное приложение со сложной функциональностью. Это минимум 5000 $ на создание, а для некоторых нетривиальных решений это число может быть умножено на 100.

Решение:
  • делаете за 500 $ мобильную версию сайта с той же функциональностью;
  • проверяете, чтобы работало так, как нужно;
  • тестируете на ЦА;
  • выкладываете в дорогую разработку. Или не выкладываете — зависит от результата.

Тестирование на Big Data


Это путь Яндекса и больших компаний: придумать быстрое решение, выпустить бета-версию, сделать пререлиз, пустить миллионный суточный трафик и смотреть, как всё работает.

Здесь я не буду останавливаться, потому как это вариант вам вряд ли подойдёт. Разве только вы из компании с большим трафиком и командой из: UI-дизайнера + быстро-верстальщика + быстро-программиста + быстро-BigData-спеца + быстро-продюсера + быстро-сис. админа + быстро-арт-дира.

Если из такой компании, то собирайте команду, быстро пилите беты, заливайте на продакшен, пускайте трафик через линки и проверяйте гипотезы. Если всё ок — делайте полноценные версии на основе этих бет.

Тестирование имеющегося продукта


Тестирование схожего продукта, что уже у вас есть, или есть у ваших конкурентов отлично подходит тем, кто хочет сделать «идеально, как у конкурента».

Такой подход мало кто использует, но это реально классная штука, особенно перед любым процессом изменения дизайна продукта, если он у вас уже есть. Или у вас нет, но у вашего главного врага по рынку — есть.

Для этого требуется:
  • сайт или приложение,
  • целевая аудитория;
  • юзабилити-исследователь;
  • личное присутствие в месте обитания ЦА или Skype.

Берём, что есть, приглашаем ЦА на тестирование (или на Skype-сессию), смотрим на экране, что делает респондент. Он в этом время проговаривает действия и мысли, мы записываем косяки, составляем статистику по ошибкам.

Метод особенно рекомендуется тем, кто думает что у них плохо работает функциональность, потому что так думает сын директора (который уже через 20 лет станет великим дизайнером). Тестируем то, что есть, и видим косяки. Реальные косяки. Всем, например, безразлично, что у вас сайт бирюзовый, и что кнопочки на нем не в Material Design, а с градиентом 90-х годов. А вот баги всем заметны. Кстати, это очень хороший способ отсеивать визуальных перфекционистов, которым не нравится цвет менюшки, а также компании, которые проводят «usability-аудиты» силами аккаунт-менеджера, который вышел на работу неделю назад.

Есть еще один метод...


Называется «Прототип из разной дешевой фигни», но подходит больше для промышленного дизайна. Используется, например, IDEO. Но в рамках этой дискуссии не буду об этом говорить, так как не про дизайн-мышление мы тут.

Вывод


В работе я постоянно использую интерактивные прототипы, в том числе в цвете. Бумажные прототипы делал несколько раз на реальных проектах и ещё раза четыре на различных интенсивах и курсах. Скорее проектирую на бумаге сложные элементы, но не тестирую на ней, так как это не особо часто требуется. Однако если времени впритык, то лучше бумаги ничего нет. Тестирование со скриптами делал разок, но это долгая история создания такого MVP — нужно отрисовывать каждый экранчик и состояние кнопок, все разворачивающие списки и выполнение тех или иных сценариев. Часто это тратит очень много времени.

Вывод для себя сделайте сами: стоит ли вам использовать тестирование прототипов или нет. В любом случае это ваше решение. Вы рискуете не только собственным временем, но и деньгами компании.

Однако если вы не предложите протестировать продукт на прототипах, вряд ли руководство об этом узнает. Вряд ли вообще кто-то знает, что можно пойти путем такого тестирования: проверить на пользователях ранние решения и исправить основные косяки, которые будут совершать 9 из 10 пользователей. Или 7 из 10. Или всего лишь 1 из 10 — всего-то каких-то 10% рынка.

Именно вы принимаете это важное решение: снизить риски выпустить на рынок полное «неюзабельное» нечто. Понимаете, о чём я? Если вам страшно и лень, да и это не ваши деньги — можете не делать. Можете смело не делать. Потому что у вас просто нет трех дней на тестирование, зато есть полгода на переписывание того безобразия, которое вышло без тестирования. А три дня тестирования при участии трех человек — это ведь то же самое, что и полгода работы команды программистов, правда?

Так что всё зависит от вас.

Нетология проводит набор на курсы:


Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/334694/


[Перевод] Flash мертв: кто следующий?

Среда, 02 Августа 2017 г. 12:46 + в цитатник
На прошлой неделе компания Adobe заявила, что к 2020 году прекратит поддержку Flash. В каком-то смысле это даже неожиданно: мне до сих пор иногда попадаются страницы, на которых он требуется, да и среди разработчиков ПО у него еще остаются сторонники. Но если посмотреть с другой стороны, все к тому шло. Нередко уход технологии можно предсказать заранее, если отслеживать статистику по ее использованию в IT-сообществе. Один из самых известных источников подобной информации — наш инструмент Stack Overflow Trends, и он показывает, что частота появления вопросов о Flash пошла на спад еще в 2010 году:



Такой неожиданный перелом в судьбе Flash позволяет заключить: расхожее мнение, что Apple погубил Flash, когда в 2010 году принял решение не поддерживать его на iPad, возможно, в чем-то соответствует действительности.

Раз у нас была возможность предугадать кризис Flash, давайте привлечем больше данных со Stack Overflow, чтобы понять, какие еще технологии сейчас на спаде.

Кто же следующий на вылет?


В последние десять лет у Flash хватало защитников (вот небольшая историческая справка), хотя то, что его все меньше и меньше используют в разработке, бросалось в глаза уже в 2011 году. Может, есть и какие-нибудь другие технологии, которые на первый взгляд еще живы-здоровы, но в последнее время начали сдавать позиции?



Чтобы ответить на этот вопрос, мы проанализировали вопросы, которые задавали на Stack Overflow в соответствующий временной промежуток — данные брались из все того же Stack Overflow Trends. Мы отслеживали тенденции за последние пять лет (чтобы включить в исследование и те тэги, которые были на подъеме, дошли до пика и пошли на спад) и делали замеры скорости падения популярности для каждой из отобранных технологий. Вся использованная информация находится в открытом доступе (вы можете скачать ее при помощи этого запроса), так что с интересом послушаю, к какими выводам придут другие разработчики.

Мы считали, что интерес к технологии угасает, если количество вопросов, связанных с ней, сокращалось в среднем на 10% в год. Если принять этот критерий, какие технологии быстрее всего теряют пользователей?

Начиная с 2010 в этом отношении лидируют тэги Flex (фреймворк для веб-приложений на базе Flash) и Silverlight от Microsoft. Тот и другой теряют позиции куда быстрее, чем Flash; Flex в особенности стал очень резко сдавать после того, как достиг пика популярности в 2010 году. Число упоминаний обеих технологий на сайте сократилось на два порядка.



Одна из них уже отходит в прошлое: в 2015 году компания Microsoft сообщила о своем намерении прекратить поддержку Silverlight к 2021 году. Flex, строго говоря, поддерживается до сих пор (только начиная с 2011 им занимается уже Apache Foundation, а не Adobe), но учитывая, что Flash списали со счетов и что Flex все реже фигурирует в вопросах разработчиков, сложно назвать его технологией, у которой есть будущее.



Среди других популярных технологией (то есть таких, которые собрали не меньше 100 000 вопросов за период с 2010 года по сегодняшний день) есть и другие претенденты, популярность которых заметно уменьшилась. Частота появления вопросов о ASP.NET, веб-фреймворке от Miscrosoft, стабильно падала с момента основания ресурса. Здесь стоит учитывать то обстоятельство, что на ранних этапах существования сайта в его аудитории преобладали разработчики на C#, однако причина может крыться также и в том, что Microsoft играет все менее значимую роль в веб-разработке.

Регулярность публикации вопросов о Ruby on Rails набирала обороты вплоть до 2011 года, а затем понемногу стала сокращаться. Objective-C тоже на спаде, так как на смену ему как любимому языку разработчиков на iOS пришел Swift. Аналогичным образом тэги «iphone» и «ipad» вытеснил общий тэг «ios» для вопросов о мобильной платформе Apple (мы подробнее разбираем эти тренды в посте о разработке мобильных приложений).



На этом список технологий, которые быстро сдают позиции, не заканчивается. Perl уже давно страдает от недостатка внимания (хотя, справедливости ради, если смотреть по месяцам, он все-таки собирает больше вопросов, чем совсем уже мертвые тэги вроде Flash или Flex). Максимум вопросов о платформе для разработчиков от Facebook пришелся на 2012, с тех пор их стабильно становится меньше. Количество постов о среде разработки Eclipse стало падать начиная с 2014 года. JQuery Mobile когда-то была популярной библиотекой для реактивной веб-разработки, но судя по тому, насколько активно люди задают вопросы, в последнее время сообщество к ней охладело.

Подтверждает ли все эти выводы количество просмотров?


Конечно, число вопросов, которое задают о той или иной технологии, не всегда отражает ее распространенность. Зачастую разработчики сначала проверяют, не предлагал ли кто-нибудь решения проблемы в уже существующих постах, и только потом уже сами задают вопрос. Возможно, когда накапливается обширная база вопросов, пользователи просто обращаются к старым постам и не испытывают необходимости создавать новые. Тогда, может быть, в каких-то из этих тэгов растет количество просмотров старых вопросов?

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

Наблюдается ли там аналогичный спад?



В случае с теми тэгами, которые мы определили в этом посте как угасающие, можно заметить, что в целом и общем трафик говорит о том же, что и количество заданных вопросов. Число просмотров постов о Flash, Flex и Silverlight с 2012 года упало почти до нуля. Тэги ASP.NET и Ruby on Rails, хоть и привлекают по-прежнему значительную долю трафика, также со временем начали терять пользователей. Eclipse до 2014 года был стабилен, но дальше пошел на спад.

Кроме того, статистика по большинству рассмотренных тэгов свидетельствует о том, что трафик как показатель популярности проблемы немного запаздывает по сравнению с количеством вопросов. Если количество вопросов о какой-то технологии начинает сокращаться, значит в скором времени начнет падать и трафик у существующих постов. Подчеркнем, что это нельзя объяснять лишь тем, что новые вопросы получают много просмотров от людей, которые пытаются на них ответить: 98% трафика Stack Overflow приходится на вопросы, которые были заданы не в тот день, когда собирается статистика. Это скорее указывает на перемену в отношении к технологии: когда у разработчиков отпадает необходимость задавать вопросы, готовые ответы им тоже становятся ни к чему.

Вывод: можно ли судить о жизнеспособности технологии по количеству вопросов?


Как однажды сказал Бьёрн Страуструп, автор языка C++, существует два типа языков программирования — те, на которые все жалуются, и те, которыми никто не пользуется. Я бы сказал, что тот же принцип работает и для вопросов.

Команда Stack Overflow часто делает замеры по количеству вопросов, чтобы понять, насколько жизнеспособна та или иная технология. Мне часто возражают, что это не показатель, ведь статистика по вопросам и трафику на самом деле отражает только то, сколько людей не понимает, как пользоваться той или иной технологией, а продвинутые пользователи, возможно, просто не нуждаются в помощи. Действительно, в работе с любой метрикой необходимо учитывать недочеты и искажения данных, и то, насколько свободно пользователи владеют технологией — это фактор, который может влиять на результаты и который следует принимать во внимание.

Тем не менее, я считаю, что данные, которые предоставляет Trends, полезны и информативны. Во-первых, мне кажется, что так же, как нельзя написать все возможные книги, нельзя и задать все возможные вопросы. Тэг Javascript за время своего существования собрал 1.4 миллиона вопросов, и несмотря на это, частота публикаций стабильно возрастает. Если темы для обсуждения, связанные с Javascript, можно бы было исчерпать, мы бы уже определенно это сделали.

Во-вторых, если все, кто работает с технологией, знают ее от и до, значит сообщество не развивается. Жизнеспособная среда всегда предполагает приток новичков, которые осваивают основы, и наличие экспертов, которые проверяют, где проходят границы возможностей. И у тех, и у других в ходе рабочего процесса постоянно возникают вопросы. В 2011 году разработчик, использующий Flash, мог бы возразить: «Да, в последнее время Flash обсуждают не так активно, но это только потому, что документация очень толковая и мы уже разобрались с основами работы». Но время ставит все на свои места.

В будущем я планирую написать пост о тех технологиях, у которых доля вопросов в общем числе стремительно растет, и порассуждать о том, какое значение это будет иметь для всей экосистемы.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/334688/


Метки:  

[Из песочницы] Машинное обучение в горнолыжном спорте

Среда, 02 Августа 2017 г. 12:13 + в цитатник


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

Изначально гипотеза об указанных возможностях свелась к следующему набору требований:

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

Для начальной проверки этой гипотезы мы решили обучить искусственную нейронную сеть (далее ИНС) для распознавания простейших фаз траектории движения спортсмена-горнолыжника.

Этапы работ определили так:

1. Сбор данных.
2. Подготовка данных для обучения.
3. Тренировка сети по распознаванию целых поворотов.
4. Тренировка сети по распознаванию фаз поворотов.
5. Разработка сервиса для пользователей по работе с получившейся системой.

Сбор данных. Motion Capture


Какие данные собирать? Как их получить?

Показателей, которые характеризуют активность спортсмена во время спуска и которые можно измерить, достаточно много, начиная от профиля давления стопы на горнолыжный ботинок (именно с этих незаметных движений и начинается всё управление движением), и заканчивая направлением взгляда (чем на более далекие от спортсмена ворота он смотрит, тем выше шанс построения оптимальной траектории). Для начала, мы решили остановиться исключительно на захвате движений (Motion Capture – MoCap), то есть получить скелетную модель движения сегментов тела, так как данный подход наиболее широко описывает физику процесса.

Захват движений производили с помощью решения (MVN Biomech ) компании Xsens,
которое представляет из себя нейлоновый комбинезон с устанавливаемыми инерционными датчиками (IMU). По своим характеристикам костюм отдаленно напоминает стандартную спортивную экипировку — «спусковой костюм», что позволяет спортсмену, с некоторыми ограничениями, просто одеть его под обычную экипировку.

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

Подготовка данных


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

Система MoCap записывает движение фреймами, проще говоря кадрами, в каждом из которых мы имеем описание положения тела по 23 сегментам, каждый из которых, в свою очередь, определен своим кватернионом (объект линейной алгебры, с помощью которого описываются твердотельные вращения; является аналогом углов Эйлера, но проще с точки зрения операций). Каждый кватернион описывает вращение сегмента тела относительно исходного положения в глобальном пространстве. Фреймы пишутся с частотой 240Hz, что позволяет ловить достаточно быстрые движения, например, отбивку кисти в момент укола палкой.

Теперь, непосредственно, что касается подготовки.

Для начала берем и оставляем только сами проезды, выкидывая всё, что происходит между (подъемы на бугеле, ожидание и т.д.). Как итог — из десяти тренировок, пригодных для работы (было много брака из-за установки датчиков и их последующего смещения), оказались пять. В среднем на каждой тренировке записывалось двадцать проездов, полезное время каждого из которых составляет тридцать секунд. Итого получаем 5 тренировок * 20 проездов * 30 секунд * 240 Hz = 720 000 фреймов; ну или если идти дальше 720 000 фреймов * 23 сегмента * 4 вещественных числа в кватернионе = около 66 миллионов вещественных чисел. Звучит, как будто этого достаточно.

Далее, необходимо вручную разметить данные для обучения — объяснить нейросети что конкретно она должна узнавать. А целью было научить её узнавать сначала полные повороты, а затем их фазы. Для этого просматривалась визуализация движений и показатели ключевых сегментов (в нашем случае стопы, голень) и на временной шкале ставились метки начала и окончания соответствующих элементов. Таким образом, по совокупности всех записей мы получили порядка 3 500 поворотов, или 10 500 фаз.

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

Качество данных


Анализ качества первичных данных проводился с помощью пакетов Python: Jupyter, NumPy, MatPlotLib и TensorFlow.

Тут стоит остановиться на двух существенных моментах.

Первый — данные от некоторых сегментов были «шумом» — менялись либо случайным образом, либо вообще никак. Также встретились сегменты, которые давали адекватные данные, но были существенно подобными на всём спектре движений, что практически означало их линейную зависимость. Например, у двух соседних сегментов позвоночника могло быть одинаковое поведение, так что использовать оба не было смысла.

1. Графики изменений кватернионов углов соединений сегментов при выполнении правого поворот

На иллюстрации хорошо видно, что не все значения сегментов достаточно наглядно демонстрируют характер действия и полезны для обучения. Они могут пригодиться для анализа качества действия и его характеристик, но не для автоматической разметки действий.

Второй существенный момент — знаковая неустойчивости компонент кватерниона. Что это такое? Один и тот же поворот на их языке может быть описан двумя разными наборами из четырех чисел. Например, один и тот же поворот вокруг оси X на 180 и вокруг оси Y на 90 может быть одинаково точно представлен следующими кватернионами: (0,0.7,0,0.7) и (0,-0.7,0,-0.7).


2. Различное представление вращение кватернионами

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


3. Пример знаковой неустойчивости входных данных

Для одного из заездов на этом рисунке графики изменения кватерниона таза спортсмена в правом повороте выделены желтым, для другого — белым. Значения эквивалентны и отображают одинаковые углы, но в силу свойств кватернионов могут иметь противоположные знаки компонент. То, как удалось справиться с этой особенностью, расскажем чуть ниже.

Тренировка сети на определение целых поворотов


Немного матчасти по горнолыжной дисциплине:записывались данные слаломных поворотов (слалом — наименее скоростная из горнолыжных дисциплин, для которой характерны повороты малого радиуса, близко расставленные ворота и, как следствие, большая частота поворотов), средняя продолжительность которых составляла от 0.9 до +- 0.1 секунды. Для начала очень кстати пришелся тот факт, что самый медленный и самый быстрый повороты в наших данных по продолжительности отличались менее чем в два раза.

Для создания прототипа системы распознавания целых поворотов мы, используя пакет TensorFlow, создали и обучили сеть MLP (многослойный персептрон) с двумя скрытыми слоями в 256 нейронов (граф сети — на рисунке 3). Выборка данных для обучения и распознавания поворота выполнялась методом скользящего окна с размером, превышающим наибольшую известную продолжительность целого поворота. Сеть обучалась узнавать попадание целого поворота в окно данных. Скольжение окна обеспечивало распознавание начала и конца поворота.


4. Граф обученной сети MLPс двумя скрытыми слоями в 256 нейронов.

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

Подход сработал, но в дальнейшем пришлось вернуться к этой задаче уже более аккуратно. Без специальных действий сеть видит разницу между компонентами кватерниона и воспринимает их как разные объект, не обобщая. Чтобы она научилась замечать сходства в кватернионах с разными знаками компонент, пришлось обучать ее особым образом — но уже на следующем этапе, о котором ниже.

Как видно на рисунке 5, сеть показала хорошую обучаемость.


5. Обучаемость сети.

В результате на этом этапе мы подтвердили возможность определения целых поворотов, также уточнили критерии подготовки данных.

Тренируем сеть на фазы поворотов


Теперь настало время перейти к фазам поворотов. И опять немного матчасти.

В простейшем случае можно выделить три фазы:

1. Вход в поворот (характеризуется быстрым ростом угла закантовки лыж и в целом высокими первыми и вторыми производными практически по всем относительным положениям сегментов. Проще говоря, лыжник очень быстро из относительно прямого положения переходит в состояние «заложился в поворот»: колени согнуты, таз сильно вынесен в сторону поворота, ярко выражена разножка). Средняя протяженность — 0,25 секунды.

2. Удержание в повороте (фаза в которой лыжник удерживает сформированное в первой фазе положение тела, естественно с некоторыми флуктуациями. То есть сперва мы изготовились, а теперь совершаем основную дугу. Это соответствует промежутку между флагами. На языке биомеханических показателей это выглядит как колебания около нулевых отметок относительных ускорений и скоростей). Средняя протяженность — 0,4 секунды.

3. Выход из поворота (Эта фаза зеркала первой, в ней происходит стремительный возврат из “глубоко заложенного” в прямое состояние, так же, как и первой фазе мы видим взрывной рост относительных скоростей и ускорений, естественно с противоположными данными). Средняя протяженность — 0,25 секунды.

Важно уточнить что, всё описанное выше разделение на фазы высоко-контекстно и сильно зависит от расстановки флагов, покрытия и так далее. Иногда в фазе удержания может происходить нетипичная активность. Еще более сложно дела обстоят с переходом из одной фазы в другую, так как в реальности нет резкой остановки какого-то показателя, а имеется некий пороговый уровень затухания на целой группе сегментов, по которому можно сделать вывод о смене фаз. И всему это предстояло научить нашу сеть.


6. Оценка разброса длины фаз.

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

Соответственно, было решено перейти от MLP-сети к сети типа RNN/LSTM.


7. Граф «натренированной» RNN/LSTM-сети

Но это пол беды. Еще более “интересно” дела обстояли с знаковой неустойчивостью. Если в случае целых поворотов было возможно просто выкидывать инвертированные сегменты, то тут решили поступать хитрее. А именно стохастическим методом.

При загрузке оригинальных наборов данных создавались искусственные наборы, повторяющие данные оригинальных, но имеющие знаковую инверсию параметров кватернионов в случайно выбранном сегменте, которые и «скармливались» сети, доучивая ее искусственными аномалиями. Объем данных вырос, и ИНС научилась понимать, что данные могут иногда врать, но при этом говорят о том же самом. В итоге она научилась распознавать фазы движений независимо от знака компонент кватерниона.

А дальше — дело техники, и в результате была получена качественно натренированная сеть, то есть дающая на новых данных хорошую точность распознавания. Ниже приведен ее граф и результаты распознавания фаз.



8. Результат распознавания фаз в заезде №6. Ступеньками показаны известные типы фаз: вход, максимальная загрузка и выход из поворота. Насыщенными цветами обозначена контрольная разметка, бледными — результаты распознавания. Зеленым выделены левые повороты, синим — правые. Результат распознавания не подвергался дополнительной фильтрации или постобработке.

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

Интерфейс для пользователя


Для того, чтобы придать решению пользовательский вид решили создать сервис, который позволит делать следующее:

1. Отправить на сервис биомеханическую запись слаломного проезда, в том числе в виде потока данных реального времени
2. Получить в ответ разметку (аннотированную запись)
3. Просмотреть проезд в рендере горнолыжника с визуализацией разметки фазами

Ниже приведена схема сервиса:

9. Сервисы системы для потоковой разметки фаз

Его главные компоненты — сеть RNN/LSTM, сетевой сервис потоковой разметки, сервер воспроизведения и рабочее место анализа фаз, выполненное в виде веб-приложения.

В данной форме этот сервис скорее является демонстрацией возможностей, нежели инструментом, решающим прикладные задачи, однако он является необходимой подводкой к нашей большой задаче. Забегая вперед можно сказать, что разметка необходима для последующего анализа сопоставимых технический фрагментов.

Что дальше?


Цель текущего года — система способная классифицировать и оценивать, начиная с поведения отдельного сегмента тела в контексте фазы (возможно более детального чем в описании выше), и далее с повышением степени обобщения: поворот, связка, трасса, уровень катания в целом. Главное же, мы планирует построить на всех указанных элементах метрики качества.

Заключение


Отдельно хочется сказать о том, что была найдена область существенного дефицита сырых данных, а именно описывающих локомоцию человека, или проще данных о том, как мы двигаемся. Наличие таковых позволило бы радикально расширить область применения машинного обучения, как в свое время произошло с визуальными образами.

В связи с этим, хотим пригласить специалистов, да и просто людей, интересующихся данной областью, к сотрудничеству. Формат этого сотрудничества оставляем открытым.

Ждём ваших отзывов!
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/334696/


Метки:  

Контейнеры быстрого развёртывания

Среда, 02 Августа 2017 г. 11:34 + в цитатник
Тот самый момент, когда даже Флэш может позавидовать разработчикам. Ровно неделю назад у нас вышел крутой анонс о новой службе экземпляров контейнеров Azure (Azure Container Instances, ACI), которая максимально упрощает развёртывание контейнеров. Это первая в мире облачная служба такого рода. Ниже я хочу рассказать вам подробнее, что она из себя представляет и как с ней можно работать.



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

Экземпляр контейнера в Azure представляет собой отдельный контейнер с посекундной тарификацией, который запускается практически мгновенно. В ACI имеются гибкие средства контроля за выделяемыми контейнерам ресурсами (память и виртуальные процессоры), с помощью которых вы сможете создать оптимальную инфраструктуру для своего приложения. Теперь вы действительно платите только за фактически используемые ресурсы, учитывается каждая секунда и каждый гигабайт. Контейнеры в ACI — масксимально интегрированы в платформу Azure. Это позволяет использовать контроль доступа на основе ролей (Role-Based Access Control, RBAC) и теги выставления счетов, чтобы учитывать потребляемые ресурсы на уровне отдельных контейнеров. Служба предоставляет доступ к контейнерам напрямую, поэтому не придется задумываться об управлении ВМ или изучать концепции оркестрации кластеров верхнего уровня. Все просто: ваш код запускается в контейнере, развернутом в облаке.

Если вы только начинаете знакомиться с облачными контейнерами, Azure Container Instances может стать для вас удобным инструментом. Чтобы создать и развернуть новый контейнер, достаточно настроить несколько параметров. Например, с помощью следующей команды CLI можно развертывать контейнеры в службе ACI через оболочку Azure Cloud Shell. Подробные инструкции см. в руководстве быстрый старт с ACI.

az container create -g aci_grp --name nginx --image library/nginx --ip-address public

А если вам нужно точно указать объем памяти (ГБ) и количество процессоров, то команда будет выглядеть так:

az container create -g aci_grp --name nginx --image library/nginx --ip-address public –cpu 2 --memory 5



В данный момент доступна предварительная версия с поддержкой контейнеров Linux. В ближайшие недели будет реализована поддержка контейнеров Windows. Для развертывания используется интерфейс командной строки Azure CLI или шаблон. Кроме того, быстро и без лишних усилий развернуть контейнер можно с помощью общедоступного репозитория Docker Hub или вашего частного репозитория, воспользовавшись реестром контейнеров Azure. Каждый развернутый контейнер полностью изолирован от ресурсов других клиентов.

Как вы уже убедились, работать с ACI очень просто. Служба Azure Container Instances не выступает в качестве оркестратора, скорее, это один из компонентов инфраструктуры контейнеров, который следует использовать в сочетании с оркестраторами и другими службами.

Сегодня мы также объявляем о доступности соединителя с открытым исходным кодом ACI Connector для Kubernetes. Он предназначен для развертывания в Azure Container Instances контейнеров для кластера Kubernetes. Такой подход позволяет практически мгновенно выделять кластеру необходимые ресурсы, избавляя администратора от необходимости управлять инфраструктурой ВМ, продолжая использовать универсальное Kubernetes API. В одном кластере K8s вы сможете использовать и виртуальные машины, и экземпляры контейнеров. Служба Azure Container Instances поможет эффективно справляться со скачкообразным ростом нагрузки, а виртуальные машины разрешат более предсказуемо выполнять масштабирование. Более того, рабочие нагрузки можно будет беспрепятственно переносить между этими базовыми инфраструктурными на основе разных моделей. Такой подход обеспечивает высокую гибкость в развертывании Kubernetes. Службы можно запускать за считаные секунды, не создавая предварительно виртуальные машины. Для учета потребляемых ресурсов и масштабирования применяется посекундная тарификация.

Демонстрация соединителя ACI Connector в действии:



Мы постоянно увеличиваем инвестиции и активнее вовлекаем сообщество в работу над поддержкой контейнеров и Kubernetes, включая Helm, Draft, а также k8s ACI коннектор, о выходе которого я рассказал выше. Поддержка сообщества подчеркивает важность открытой экосистемы с точки зрения развития набирающей обороты технологии контейнеров. Этот опыт действительно воодушевляет.

Поэтому я с радостью сообщаю о том, что корпорация Microsoft вошла в состав организации Cloud Native Computing (CNC) в статусе платинового участника. CNCF — коллаборационный проект Linux Foundation (Microsoft присоединилась к этой организации в прошлом году), участники которого курируют проекты Kubernetes, Prometheus, OpenTracing, Fluentd, Linkerd, containerd, Helm, gRPC и многие другие. Мы очень воодушевлены возможностью тесного сотрудничества с сообществом CNCF. Гейб Монрой (Gabe Monroy), ведущий руководитель проектов в Microsoft Azure, который занимается контейнерами, вошел в состав совета CNCF.

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

На основе недавнего анонса от Кори Сандерса.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/334682/


Внедряем безопасность в процесс разработки крупного проекта

Среда, 02 Августа 2017 г. 11:04 + в цитатник



В данной статье нам хотелось бы поделиться своим опытом внедрения нашей команды пентестеров в цикл разработки большого проекта «Мой Офис». Найти материал подобной тематики с реальными кейсами на русском языке практически невозможно. Всем, кого интересует модные направления пентестов, теория, практика, методики, тулзы и реально найденные уязвимости в контексте безопасной разработки, — добро пожаловать под кат. Статья изобилует полезными ссылками на теоретические и практические материалы. Но давайте по порядку.


Дисклеймер:
Статья состоит из двух частей. Первая часть — организационная, которая определяет проблему, рассказывает в целом о подходах к тестам на проникновение и о наших путях решения поставленных задач (наверняка содержит информацию, которая многим известна). Вторая — более техническая, с описанием используемых тулзов и найденных уязвимостей.
Если ты, %username%, любишь технические детали, можешь переходить ко второй части.
И, конечно же, не забудь свой чай с печеньками.


Собираем и распределяем


Некоторое представление подходов к пентестам


Начать стоит с небольшого вступления, описывающего подходы к пентестам и их особенности. Основываясь на нашем опыте, охватывающем различные компании разнообразного профиля, оптимальным видится следующее деление.


Разовый тест на проникновение


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


Виды работ:


  • Аудит безопасности внешнего периметра
  • Аудит безопасности внутреннего периметра
  • Физическая безопасность
  • Мобильные приложения
  • Анализ кода
  • Социальная инженерия
  • И вообще все, что вы сможете придумать (но увлекаться сильно не стоит)

В безопасности, как и в любом сложном процессе, нет “серебряной пули” — никакое средство само по себе не даст полной уверенности в защищенности системы, будь то антивирусное ПО, системы обнаружения вторжений и т.п. То же можно сказать и о тестах на проникновение, в которых нет универсальных подходов, поскольку у каждого из них есть свои минусы и плюсы.


Разовый тест на проникновение эффективен для оценки общего состояния безопасности — пентестеры проводят моделирование ситуации, в которой злоумышленник с ограниченными финансами и в сжатые сроки пытается проникнуть в систему, и какой ущерб он может нанести компании заказчика.


Тест на проникновение с повторением N раз в год


Подход повторяет “единоразовый пентест”, либо его отдельные части. В данном случае аудит защищенности производиться несколько раз в год. Виды работ такие же, как и в первом подходе.


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


Данный вариант позволяет проводить более тщательное изучение периметра компании аудиторами за счет их повышенной осведомленности о сервисах по результатам прошлых тестов на проникновение.


Багбаунти на аутсорсе


Суть данного подхода — в создании своей багбаунти-программы на открытой/закрытой основе, ведение которой осуществляется силами сторонней организации. Такая команда привлекает к своей работе пентестеров на постоянных условиях и производит выплаты за каждую уязвимость в отдельности. Это хорошая возможность дополнительного дохода для исследователей. Примером использования такого подхода является американская компания SYNACK.


Возникает резонный вопрос: “Чем это отличается от HackerOne?” Основное отличие — в количестве исследователей и их скиллах. Для попадания в программу нужно пройти собеседование и тестовое задание, как при устройстве на работу в оффенсив-компанию. Следовательно, получается меньше участников, но выше общий уровень скиллов (и отсутствие всем известных нам персонажей, которые любят кидать отчеты сканеров).


Виды работ (в рамках данного подхода):


  • Аудит безопасности внешнего периметра
  • Мобильные приложения
  • Бинарные исследования

Подход предполагает постоянное штудирование своих сервисов десятками человеческих "сканеров", мотивированных вознаграждениями за уязвимости. Он позволяет обеспечить большее покрытие при проведении работ.


Несмотря вышеозначенные преимущества, у подхода есть и свои недостатки:


  • Ограниченный спектр работ в сравнении с классическим подходом к пентесту. Этот недостаток является следствием удаленной работы всех исследователей и популярности направлений в безопасности.
  • Зависимость результатов работы от выплат. Большое количество исследователей не гарантирует вовлеченность абсолютно каждого, размер вознаграждений оказывает сильное влияние на популярность программы.
  • Сложность в планировании бюджета — типичная проблема для любой багбаунти-программы.

Работы по анализу защищенности на постоянной основе


Именно этот подход рассматривается подробно в нашей статье. Суть его — в постоянном исследовании разрабатываемых продуктов от релиза к релизу.


Список видов работ в данном случае несколько шире по сравнению с описанными выше подходами. Он включает в себя:


  • Аудит безопасности внешнего периметра
  • Аудит безопасности внутреннего периметра
  • Мобильные приложения
  • Десктопные приложения
  • Hardering (безопасная конфигурации серверов)
  • Обучение разработчиков

Что касается таких пунктов, как Десктопные приложения и Hardering, то задача не в поиске бинарных уязвимостей (если говорить о десктопах) и не в тотальном закручивании гаек (в случае с Hardering). Главное — это взгляд на систему с пентестерской стороны.


Особенность подхода состоит в том, что он максимально близок к работе безопасников на местах в компаниях, которые создают защиту изнутри, а именно:


  • Высокая осведомленность о работе (за счет доступа к документации и собственного эмпирического опыта при исследовании конкретного продукта) и разработке внутренних сервисов (возможность влиять на процесс разработки и непосредственно наблюдать за сроками).
  • Доступ к исходным кодам разрабатываемых продуктов.
  • Возможность участвовать в построении архитектуры. Это позволяет находить уязвимости до написания кода. Например, CSRF-токены. Иногда бывает, что люди просто забывают о такой важной и простой вещи, как токены. Если данная проблема вскроется после выката релиза, её исправление может стать дорогостоящим и трудоемким делом (хотя все, конечно же, зависит от размера системы).
  • Высокая актуальность исследуемых продуктов. При выпуске нового релиза или изменений парочки важных строк кода, влияющих на безопасность напрямую, мы сразу можем получить внесенные изменения и начинаем во всю их тестировать.

В итоге получается, что работы проводятся уже не черным, а всеми нами любимом белым ящиком.




Важно отметить, что данный подход помогает решать и такую проблему, как нехватка собственных ресурсов (секьюрити-специалистов) компании для анализа безопасности приложений. Многие исследователи предпочитают оффенсив-компании для работы из-за наличия постоянного опыта в разных направлениях ИБ, привлечение их на аутсорсе позволяет компенсировать нехватку ресурсов.


Немного про SDLC и его друга SecureSDLC


SDLC


Начнем с определений. SDLC — это основа разработки, которая определяет процесс, используемый организациями для создания приложения с момента зарождения идеи до выхода в эксплуатацию.


На данный момент существует большое количество моделей SDLC, самые известные из них — Waterfall, Iterative, Agile (подробнее о них можно почитать тут). Все они имеют свои достоинства и недостатки, каждая из них весьма вариативна в использовании; все зависит от размера проекта, бюджета, объема человеческих ресурсов и других особенностей. Их всех объединяет наличие шести ключевых этапов:


  • Планирование — один из основных шагов, на котором происходит определение решаемой проблемы, подсчет ресурсов и издержек, поиск альтернативных путей решения и т.д.
  • Анализ — разработка требований, осуществление технико-экономического обоснования и прочего, что мы так не любим.
  • Дизайн. На данном этапе происходит построение архитектуры, выделение компонентов, модулей, интерфейсов и т.п.
  • Разработка и внедрение — самый большой и важный этап, именно здесь происходит написание кода, конфигурация и настройка железной части проекта, если таковая существует.
  • Тестирование и интеграция — здесь мы проводим проверку того, насколько результаты соответствуют поставленным задачам.
  • Поддержка системы. Проведение контроля актуальности разработанной системы. Сюда входит как замена оборудования, так и обновление различных программных компонентов.



SecureSDLC


SecureSDLC — тот же SDLC, но с приставкой Secure. Просто добавляешь приставку, и все становится безопасным (нет). Суть всего этого весьма проста: как видно на прекрасной картинке из Интернета, к каждому из этапов разработки добавляются действия, связанные с безопасностью (расчеты рисков, статический\динамический анализ кода, фаззинг, обучение и т.п.).


image


В классической реализаций SDLC проверка безопасности ограничивалась стадией тестирования, если вообще проводились.


Расширенная реализация нацелена на:


  • Постоянный мониторинг исправления существующих/обнаруженных уязвимостей.
  • Уменьшение стоимости исправления уязвимостей благодаря нахождению их на более ранних этапах разработки.
  • Повышение качества разработки за счет глубокого анализа приложений; работы в части обучения в области безопасности самих разработчиков.

На чем же всё базируется?


В настоящее время имеется большое количество компаний, практикующих безопасную разработку. Например, такие крупные и известные, как Microsoft, Cisco, Dell. Сегодня любой уважающий себя вендор следит за безопасностью своих решений (но не всегда это получается). Абсолютно у каждого производителя есть свой подход, который формируется, исходя из внутренних особенностей разработки.


В качестве скелета при построении своей безопасной разработки многие используют общепринятые в мире практики:


  • Open Security Assurance Maturity Model (OpenSAMM) от OWASP
  • Microsoft Security Development Lifecycle (SDL). Process Guidance.

На очередной картинке из Интернета можно увидеть соответствие бизнес-функций и практик безопасности.




Условия задачи


В настоящее время мы ведем большой проект (подробности и особенности — далее), работая по двум большим направлениям: “пентест” разрабатываемых продуктов и бинарные исследования. В данной статье мы сосредоточимся на пентестерской части.


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


Что же не устроило нас в классических подходах? У разового пентеста есть некоторые недостатки:


  • Большое количество отчетности по факту проведения работ. Если вы видели хоть раз пентестерский отчет, то знаете, что он огромен, и занимает в среднем сотню страниц. Его создание требует привлечения человеческих и временных ресурсов. Вместо поиска уязвимости исследователь занимается подготовкой отчетности.
  • Недостаточно слаженное взаимодействие с разработчиками. Последние могут начать реагировать на найденные проблемы только после окончания пентеста. При этом у них часто есть понимание критичности найденных уязвимостей и путей их исправления, которое может отличаться от пентестерского.
  • Низкая осведомленность пентестеров о внутренних особенностях исследуемых систем. Поскольку исследователь не является сотрудником компании, безопасность которой он анализирует, он не может знать всех особенностей процесса разработки, у него банально отсутствует доступ к документации и к исходникам.
  • Ротация аудиторов. Из-за наличия других разовых или постоянных проектов может сложиться такая ситуация, что проектом занимается не тот пентестер, который исследовал его в прошлый раз. Из-за этого падает общая осведомленность о сервисах, которые уже были изучены в рамках прошлого теста на проникновение.

По причине низкой осведомленности аудиторов о внутренних особенностях разрабатываемых продуктов и отсутствия какого-либо разделения по компонентам (для пентестера продукты имеют вид определенного скоупа адресов, пакетов мобильных приложений или бинарей десктопных приложений), список продуктов выглядит как книжная полка с большим количеством книг, на корешках которых отсутствуют названия — глаза разбегаются от обилия сервисов.




Из-за этого появляется проблема выделения времени — оно выделяется на весь проект в целом, и какому-то компоненту может быть уделено меньше внимания. Ресурсы распределяются неэффективно, и это не подходит для глубокого изучения продуктов. Поэтому было принято решение разделять продукты на условные компоненты.


Собираем список продуктов


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




Перед началом работ над таким обширным продуктом, как «МойОфис», необходимо выделить основные его модули и части (даже с виду неделимые), чтобы не получилось той самой книжной полки. Это необходимо и для лучшего понимания внутренних процессов приложений и распределения ресурсов команды.


У нас это получилось таким образом:


  • Web — это настоящее SPA приложение, только js/css/html файлы. Сервисы, которые входят в этот компонент: Почта, Календарь, Контакты, Диск, Редактор документов, Панель управления администратора, Logos (мессенджер).
  • Мобильные приложения — по три приложения (Редактор Документов, Почтовый Клиент, Logos — мессенджер) под каждую из платформ — iOS, Android, Tizen (да-да, не удивляйтесь).
  • Десктопные приложения (Документы, Почта, Мессенджер) под три платформы — Linux, OS X, Windows.
  • Серверное API, доступное публично.
  • Внутренние сервисы, которые общаются друг с другом (Redis, Swift и другие).

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


Планирование спринтов


Чтобы “бесшовно” встроиться в процесс разработки такого продукта, нам необходимо адаптироваться к его глобальным циклам планирования, в нашем случае — релизным циклам. Релиз новых версий «МойОфис» происходит каждые три месяца. Поэтому мы живем спринтами как раз по три месяца. Что же такое спринт в нашем понимании?


Спринт для нас — это ячейка времени, в рамках которой мы стараемся максимально распланировать наши работы. Внутри большого спринта у нас есть более мелкая единица измерения — слот, который равен одной неделе. Мы берем продукты, доступные нам, смотрим циклы и сроки изменений в них, и в необходимой последовательности ставим аудиты этих продуктов в график нашего спринта, разбивая по слотам.


Естественно, мы понимаем, что планирование сроков в разработке, мягко говоря, получается очень плохо, потому ожидаем законного вопроса: “А если сроки едут, что делаете?”




Тут на помощь приходит старая игра детства — “пятнашки”. Помните, там была пустая ячейка, через которую можно было двигать другие фишки, и тем самым менять порядок, не выходя за рамки коробки? В нашем случае, коробка — это и есть такой “спринт”.


Количество пустых слотов решено было увеличить, поскольку есть разные “внеплановые” работы, ресерчи сторонних решений, используемых в разрабатываемых продуктах, а также иные работы, которые могут относиться к проекту. Тем самым, мы мобильны в планировании, а пустые слоты заполнить всегда можно.


Пример одного из спринтов (первое число — номер недели спринта):


  1. Веб-приложения компонентов (Почта, Контакты, Календарь)
  2. Веб-приложения компонентов (Почта, Контакты, Календарь)
  3. Нативные мобильные приложения для Android, iOS, Tizen
  4. Нативные мобильные приложения для Android, iOS, Tizen
  5. Сервер аутентификации; Бекенд веб-приложений
  6. Бекенд файлового сервера, Веб-панель и API администратора
  7. Веб-панель редактора документов, Бекенд редакторов
  8. Десктопный клиент для файлового сервера
  9. Десктопный клиента для почты, календаря, контактов, документов
  10. Мессенджеры для Web, MacOS, Win, Linux и их API
  11. Misc
  12. Misc
  13. Misc

Misc — это как раз те свободные слоты, их наличие очень важно. Как можно заметить, на некоторые, довольно большие части (как Веб, где проверяется и API-часть), мы закладываем больше времени (10 рабочих дней). Также в Misc попадают дополнительные исследования и совместная проработка security-ориентированной архитектуры совместно со специалистами заказчика.


Команда аудиторов


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


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


Стенды


В своих тестах мы используем полную копию того, что поставляется клиентам, со всеми свежайшими обновлениями. Забегая вперед, скажем, что мы посчитали довольно важным развернуть полностью весь «Мой Офис» с нуля и понять каждый шаг, где, что и как деплоится и настраивается, попутно пытаясь сравнить это с документацией. Учитывая, что наша специализация — далеко не системное администрирование, это была сложная задача для “падавана юного”.


Отчетность


Поскольку мы — большие любители багбаунти и такие же не любители писать отчеты и генерировать официальные тексты, было решено отойти от отчетности, присущей классическим тестам на проникновение, и перенять опыт у багбаунти-программ.


В своем подходе мы используем JIRA для создания тикетов (разработчики и тестировщики пользуются этим, почему бы нам тоже не начать это делать), где есть абсолютно стандартные поля, как на HackerOne:


  • Название
  • Тип тикета
  • Критичность уязвимости
  • В каких компонентах проявляется
  • Описание уязвимости — действия для повторения



При таком донесении информации абсолютно любой человек поймет, насколько эта уязвимость критична, даже без какой-либо квалификации в безопасности или вообще в IT.


Анализ защищенности. Немножко практики


Дисклеймер: мы стараемся делать статьи так, чтобы из статьи каждый смог вынести для себя что-то новое и интересное. Так, из первой части менеджер или тимлид команды может наверняка почерпнуть тактику ведения проектов, тогда как из второй кое-что может пригодится исследователям ИБ и разработчикам.


Выглядит так, что вводная часть раскрыта. Давайте перейдем непосредственно к самому анализу защищенности (ура-ура, технические подробности).


Одна из интересных составляющих работы для опытного пентестера — это использование модных и современных технологий. Давайте посмотрим на них. Прежде чем начать, мы, конечно же, посмотрели Веб, попутно регистрируясь с именами ‘“>{{7*7}}, позаливали файлы, поотправляли почту, поставили мобильные приложения и в целом осмотрелись вокруг, как все работает.

После мы пошли к тимлидам разработки и вместе засели над схемой серверной архитектуры на большом листе А1, который с трудом умещается на стене кабинета. Сюда мы ее не вставим, но в целом все довольно стандартно и круто:

  • Пользователю доступны два порта (80 и 443). Все, что за ними, считается кластером и доверенной зоной.
  • Кластер — это может быть неограниченное количество серверных машин (в нашей инсталляции — 2), на которых работает целый пучок микросервисов (java, go, c++ — ядерная часть редактора, базы данных, SWIFT и другие).
  • Часть сервисов ставится из RPM-пакетов, часть — docker-контейнеры (что дает дополнительную изоляцию, это особенно важно при работе с конвертацией документов).

Web


Клиентская часть — это AngularJS и полноценное SPA (Single Page Application) без явных костылей со стороны серверного API (таких как “а вот тут отдадим формочку с бекенда!”).


Серверная часть — по-разному, в качестве фронта используется nginx, за ним множество java/golang сервисов, которые обрабатывают клиентские запросы.


Анализировать SPA-приложения очень круто и довольно удобно, с точки зрения запросов-ответов все логично и складно. Поиск уязвимостей в самом SPA, конечно же, довольно сложная задача.


Burp Suite


Да, тут нет секрета, мы, как и многие, используем Burp (никакого Larry Lau, только лицензия) и его модули для поиска разного рода уязвимостей (инъекции, IDOR, SSTI и другие). Без этого инструмента вообще никак.


Также его могут применять разработчики, чтобы проверить результат после исправления уязвимости, вместо того, чтобы просить нас и растягивать весь этот процесс. Для этого будет достаточно бесплатной версии и двух вкладок Proxy и Repeater.




Также мы используем пучок кастомных скриптов, рассмотрим один из них.


Как вы уже знаете, среди продуктов, исследуемых нами, есть почта. Одной из мощнейших атак здесь может быть XSS в письмах. Причем все еще осложняется тем, что в письмах можно использовать HTML для создания красивых писем в фирменных стилях, а не просто plaintext. Перед разработчиком стоит задача сделать возможность использования HTML так, чтобы отправитель не мог внедрить свой JavaScript.


В security-мире есть исследователь Mario Heiderich @0x6D6172696F (.mario), который много времени посвятил поиску XSS в разных крупных сервисах вроде Google, участвовал в создании библиотеки DOMPurify для безопасной подстановки unsafe html сразу в DOM (подробнее о ней будет рассказано ниже). А главное — он опубликовал для нее автотесты, которые используют различные хитрости и тонкости работы браузеров и HTML5. Идеальное решение для тестирования почтового сервиса на возможность внедрения JS.


Ссылка на демо и тесты.
И не забудьте о специальных векторах для HTML5.


Что мы сделали? Мы взяли эти тесты (+ дописали некоторые свои из секретных закромов) и отослали на IMAP-сервер своим скриптом на Python в десять строчек, ибо обычно HTML нельзя отправлять из Веб-клиента, а только напрямую на почтовый сервер, попутно открывая письма в браузере. Исполнился JS? Заводим тикет.


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


Ограничение схем для некоторых тегов, например, почему нельзя использовать file:/// для тех же "img src" (подробно по ссылке от ValdikSS), были сразу учтены при разработке.


Следующая проблема — это вложения. Обязательно нужно тестировать вложения разных форматов с XSS-нагрузкой, их можно взять тут. Этим мы проверим, как сервер хранит и отдает вложенные файлы в письмах.


Мобильные приложения


Все приложения под каждую из платформ являются классическими нативными приложениями.


Для исследования iOS и Android используются оба подхода: автоматизированный и ручной. Для Tizen — только ручной. Про автоматизированный — в снятии “низко висящих фруктов” здесь очень помогает MobSF.




Он позволяет автоматически собрать типичные проблемы, сделать ревью ресиверов, сервисов и т.п. вещей в Android и даже осуществляет некоторое подобие анализа исходного кода (после декомпиляции). Также проверяет флаги (Stack smashing protection, PIE ...) при компиляции.


Ручной анализ — Android (+root), iOS + jailbreak (на данный момент мы используем последний доступный джейл для iOS 9.3.3).


А вот с Tizen не все так просто. Сам он очень странный и непривычный. Система является одним большим браузером с поддержкой HTML5, давно находится в разработке и тоже представляет интерес для исследователей безопасности, как что-то новое и неизученное.


Для начала вопрос — сколько вы вообще держали телефонов c TizenOS? Вот столько же статей и security-тулз для этой платформы. Мы пошли по developer way — скачали Tizen SDK, подключились к телефону и дебажили приложение. В этом режиме можно просмотреть файловую систему, получить debug console и делать другие вещи, позволяющие найти проблемы в безопасности. К сожалению, функционал достаточно ограничен, и нет прямого консольного доступа к OS.


Инструмент находится на официальном сайте Tizen. Можно использовать эмулятор, если есть желание познакомиться с этой операционной системой.




Сама платформа Tizen на данный момент имеет большое количество недостатков со стороны безопасности. Можно вспомнить недавнюю новость о сорока зеродеях в платформе и вот эту публикацию . Также о некоторых уязвимостях в SmartTV, где был затронут и TizenOS, рассказывал BeLoveпрезентация.


Desktop


Про десктопные приложения «Мой Офис» будет отдельная статья, посвященная бинарному фаззингу. В рамках же данных работ (именно в пентестах) смотрятся такие области, как взаимодействие с файловой системой (временные папки, права на них и т.п.), DLL hijacking, работа с сетью (передача данных по защищенным каналам — TLS), хранение токенов и подобное.


Многие десктопные приложения написаны на основе Electron, на котором созданы решения GitHub, Slack, Discord и многие другие. Сам Electron является открытым проектом и представляет собой webview, то есть небольшой браузер, который визуально не отличить от нативного приложения.


Исследование сторонних продуктов. DOM Purify и причем тут Safari


Зачастую при исследовании безопасности какого-либо продукта возникает проблема, связанная с тем, что не всегда прозрачно и понятно, где же в итоге была найдена уязвимость: в кастомном написанном коде заказчика или в стороннем продукте, библиотеках, фреймворках, которые используются при разработке. У нас также был такой случай.


При исследовании одного из компонентов нами была найдена довольно критичная уязвимость клиентской части — внедрение JS-кода, ну или просто XSS. Изначально было непонятно, почему так произошло, ведь данный компонент использовал ту самую JS библиотеку DOM Purify для защиты от XSS.


DOM Purify — это средство только для DOM-а, сверхбыстрое, убер-толерантное XSS-дезинфицирующее решение для HTML, MathML и SVG (немножко описания с Гита). MathML — это язык разметки на основе XML для представления математических символов и формул. Все это, конечно, работает и в контексте HTML5 фишек. То есть в этом продукте собрано все самое новое и современное.


Он написан на JavaScript и работает во всех популярных браузерах:


  • Safari
  • Opera (15+)
  • Internet Explorer (10+)
  • Firefox
  • Chrome
  • Все, что использует Blink or WebKit

Разрабатывает инструмент компания Cure53, в частности, Mario Heiderich @0x6D6172696F (.mario), а контрибьютят туда такие известные ребята, как @filedescriptor, @shafigullin и другие. Выходит, такая сборная самых крутых исследователей веб-безопасности трудится над открытым программным средством для защиты от уязвимостей клиентской стороны.


Ссылочка на Гит.


Немного пораскинув мозгами, мы пришли к выводу, что уязвимость действительно не в разработанном приложении, а в подключенной JS-библиотеке.


Далее, мы проверили уязвимость на последней версии DOM Purify и были весьма удивлены, что такой простой пейлоад без всяких хитростей сработал, но только под Safari.


Payload: 



Ребята быстро исправили уязвимость, а компания FastMail, которая взяла DOM Purify под крыло своей багбаунти-программы, выплатила нам немножко денег “на пиво”.


Но на этом все не закончилось, поскольку дыра работала только для Safari, мы немного копнули в его сторону и получилось, что функция DOMParser работает некорректно, и при парсинге html страницы исполняет JS, что никакой браузер из популярных не делает (да-да, даже IE), о чем мы сообщили в Apple.


Payload: new DOMParser().parseFromString('', 'text/html');



И буквально на днях Apple выдало CVE-2017-7038 — что-то очень похожее на UXSS-уязвимость, но без обхода SOP. Подробнее обо всех возможных уязвимых функциях, возможно, мы когда-нибудь опишем в отдельной статье.


В итоге, получилась такая нетривиальная схема: XSS в приложении «Мой Офис» была возможна из-за подключения DOM Purify-библиотеки, которая не обрабатывала SVG теги (хотя должна была), а отдавала напрямую стандартной браузерной функции DOMParser, которая была реализована с ошибкой.


Вот таким длинным путем мы исправили уязвимость не только у нашего клиента, но и сделали мир немного безопаснее.


Реальные уязвимости


Невозможно написать что-то большое и не допустить ни одной баги, нет такой методологии. Поэтому разберем парочку реальных уязвимостей с высоким уровнем критичности.


Внедрение внешних сущностей XML


Поскольку у нас есть хранение и редактирование документов, мы каким-то образом должны отрисовывать пользователю документ и вносить изменения в них, если это нужно. Как вы можете знать, современные офисные документы — это набор XML-файлов, упакованных в архив. А какое редактирование документов без парсера XML?


Каждый Веб-ресерчер сразу же подумает про XXE. Как же посмотреть эту уязвимость в действии в данном случае?


  • Загружаем документ
  • Сервер распаковывает архив
  • Пытается преобразовать XML во внутренний формат
  • Сохраняет в нужном себе формате на сервере

Вот как раз шаг номер три является опасным, осуществляется он с помощью опенсорсной библиотеки, в которой можно было подключать внешние сущности. Что мы сделали:


  • Создали валидный .docx документ
  • Распаковали
  • В один из xml файлов добавили


   ]>
…
&xxe;

  • Запаковали обратно, переименовали в .docx
  • Загрузили на сервер

И после обработки увидели содержимое /etc/passwd. Но с помощью этой уязвимости можно не только читать файлы на сервере.




Так или иначе, нам не удалось ничего важного прочитать, поскольку весь парсинг происходит в изолированном контейнере (docker). Уязвимость была оперативно закрыта.


Кстати, для генерации подобных файлов и проверки XXE можно использовать тулзу. С её помощью некоторые исследователи находили XXE и в багбаунти-программах тоже.


Remote Command Execution via EL Injection


Расскажем и про честное RCE — удаленное выполнение команд OS на сервере. Некоторая часть микросервисов написана на Java, в том числе, с применением Spring. Уязвимости такого рода для Spring (и не только) очень хорошо поддаются фаззингу, если вы отправите на сервер {{7*7}}, то в ответе на странице получите выполнение математической функции равное 49.


Далее, можно уже пробовать выполнять функции языка и даже запустить команду с помощью:


${T(java.lang.Runtime).getRuntime().exec("ls")}

Подробнее про похожую уязвимость в Spring Boot Oauth модуле можно прочитать тут. А тут тикет на гите, описывающий проблему, которая повлекла выполнение кода в нашем случае.


Но в нашей конкретной ситуации такая простая отправка пейлоада не работала, поскольку при отправке запроса на Веб-сервер наши кавычки проходили URL-encode и не воспринимались Spring-ом как спецсимволы. Что же делать в такой ситуации? Все достаточно просто: можно, используя стандартные средства языка, провести кодировку из числовых значений в символы с помощью функции java.lang.Character.toString() и конкатенировать все символы. Про данный трюк можно прочитать тут.


В итоге, у нас получился большой и страшный пейлоад (чтение /etc/passwd/):


${T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(99).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(112)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(100))).getInputStream())}

Стоит отметить, что RCE было также внутри docker-контейнера, и хоть он создан не для защиты, но все же дает некую изоляцию.


Заключение


Уф, вот и подошла к концу статья. Давайте теперь суммируем, чем отличается наш подход от классических тестов на проникновение:


  • Аудиторы больше знают о процессе разработки и работе продукта. Осведомленность достигается за счет доступа к документации и возможности следить за темпами разработки.
  • Возможность участвовать в построении архитектуры, что позволяет находить проблемы и уязвимости на стадии планирования.
  • Доступ к исходным кодам.
  • Смещение работ от черного ящика к белому ящику. Классические тесты обычно сильно ограничены в этом плане.
  • Ликвидация проблемы генерации больших отчетов.
  • Грамотное распределение ресурсов аудиторов. Все расписано по неделям, время используется эффективно, и всегда в проекте участвуют люди, осведомленные о внутренних особенностях компонентов.
  • Повышение уровня экспертизы за счет исследования большого количества разнообразных сервисов.
  • Наличие возможности искать уязвимости в сторонних продуктах, которые используются в разработке, и делать мир “чище и приятней” .
  • Более подробное изучение системы. За счет перехода от поверхностного сбора “низко висящих фруктов” к исследованию каждого компонента в отдельности, следовательно, возможно осуществлять поиск более сложных уязвимостей.

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


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


Надеемся, что вы смогли вынести для себя что-то новое и приобрели понимание того, как происходит работа по поиску уязвимостей в крупных проектах.


Полезные ссылки



P.S. Выражаю благодарность за помощь в подготовке материала BeLove.

Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/334692/


Галерный хакатон

Среда, 02 Августа 2017 г. 11:03 + в цитатник
Вдохновителем статьи послужила история habrahabr.ru/post/334490 и идея наблюдателя habrahabr.ru/post/334490/#comment_10338270.

Все знают, как труден путь по прибрежным городам, где не всегда ветер попутный, поэтому нам помогает дружная команда галерщиков. Эти скромные труженики моря тихо скрипят на своих клавиатурах, в полуоткрытых кубиклах с одним-двумя Windows и мощными профессиональными вёслами в интерфейсе. Их вклад в наши проекты неоценим, и всё же, мы всегда думаем о том, как сделать его ещё весомее.

Ведь вот что получается, свободные лодочники на выходных, бывает, успевают смотаться на ливийский берег, пощёлкать там львов, привезти к следующему базару шкуры и имеют за них очень хорошие инвестиции. Вот и у наших хорошо бы раздуть огонь энтузиазма.

Наша команда галерщиков очень дружна. Разлучить их может только увольнение. Именно про таких песни поют: связанные одной целью, скованные одной… И вот помочь бы им так же за два дня напрямик махнуть через море, а там бы наши воины постреляли бы львов. Обычно окольный путь по побережью занимает две недели, но ведь умеют же лодочники выкладываться и гнать напрямик. Казалось бы, нашим в чём разница?

image



В выходные мы решили, что не будем заставлять их работать — просто по-человечески жалко, когда в понедельник лучшие работники временами отдают концы вёсел новичкам, когда по плану надо промотнуться по соседним городам, продать оливки и купить мануфактуру, а сами тихо увольняются, откидывая сандалии. Ещё они у нас не очень разговорчивы, поэтому вёсельные циклы у них выполняются, а чтобы сюда в чат отзыв написать — не дозовёшься. На самом деле, статуса у них нет. Когда наши славные менеджеры держат совет на мостике, галерщики работают.

Поэтому не смотрите, что мы всё о себе да о себе — работа у нас такая — говорить про себя и вдохновлять группу, делать из них команду. В которой мы будем ведущими.

Как всегда, за ударную работу полагается приз — отдых на пустынном берегу, с возможностью укрыться у скал и посидеть у колодца, восполнить запасы потраченной воды, чтоб после с новыми силами заработать себе на похлёбку. Если такие вылазки часто не делать, раз в месяц они радостно подчиняются призыву идти в новый поход.

image

(копия; художник: А. Байкин)

Почему это работает?

1. Потому что мы кормим своих галерщиков. Очень многие команды не доходили до берега, потому что среди дня забывали свою рабочую силу покормить. У нас же обед — по расписанию.

2. Потому что мы тащим слабых. И с помощью других постепенно добиваемся, чтобы были на равных выкинуты за борт.

3. Потому что мы не забываем славить нашего босса, который построил этот корабль и нанял нас ездить туда-сюда и приумножать его богатства.

4. Потому что мы не гоним работников беспрерывно, а даём им отдохнуть каждые 5 минут через полчаса.

5. Да и на берегу они могут отдыхать, а не носить, скажем, шатёр и опахала за нами.

Почему нас в будущем ждёт успех?

Разумеется, не все смогут работать у нас. Не все показали себя такими выносливыми. Но стараемся подобрать такую команду, которая в штормах нас не подведёт и работаетм над своим будущим каждый день. Будьте наблюдательными на своём мостике, и успех вас будет преследовать в каждом порту, куда бы вы ни попали. Не теряйте холодности духа, глядя через бортик кубикла — не забывайте, что вы — здесь, а не там, и поэтому выстроенная вами система работает и каждый профессионал трудится на своём месте. И… в общем, на рынках труда не попадайтесь нам на глаза — ведь вы можете не пройти отбора.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/334690/


Метки:  

Juniper Node Slicing и Universal Chassis

Среда, 02 Августа 2017 г. 10:47 + в цитатник
Разглядеть то что находится на верху лестницы находясь где-то в ее середине настолько же сложно как понять какие тенденции индустрии телекоммуникаций прочно укрепятся и станут фундаментом будущих разработок, а какие исчезнут без следа. Не так давно, в рамках дизайна Cloud-Grade Networking, Juniper Networks анонсировал появление нового механизма виртуализации своих продуктов, а также представил концепцию универсального шасси для routing и switching применений. Новости важны в плане практического применения и интересны как повод погадать о будущем.

Сначала маркетологи, а потом и инженеры стали называть современные маршрутизаторы мультисервисными. Ведь прекрасно когда одно шасси может решать задачи маршрутизации на пиринговых стыках, терминировать абонентов ШПД, передавать транзитный MPLS трафик, вытягивать пакеты из оверлея ЦОД и даже делать трансляцию адресов и протоколов. Многофункциональность и снижение единиц оборудования кажется обоснованной и людям, в костюмах, которые хорошо умеют считать Capex/Opex, и людям, которые рассчитывают место в стойке и требуемую мощность ИБП, по ночам смотрят на алерты мониторинга, занимаются инвентаризацией, настраивают или обслуживают это оборудование, потому-что с одной сущностью управляться легче чем с десятью. Все бы хорошо, но по мере увеличения количества функций, между ними появляются внутренние противоречия. Представьте себе мульти-прибор, который стирает, готовит обед и хранит зимние шины, из-за неидеального ПО обед может получится не вкусный, потому-что в ингредиенты случайно попало немного стирального порошка, а шины могут деформироваться из-за близкого расположения духовки. В своей практике я работал с клиентами, маршрутизаторы, которых на протяжении жизненного цикла превратились в монолит. Разобрать его уже не получается, потому-что «это наше все», а эксплуатировать становится все сложнее, потому-что одна функция, опять таки из-за неидеальности ПО, мешает выполнению другой.

Наши коллеги по IT давно решили для себя похожие проблемы — администраторы серверов все плотнее используют виртуализацию и контейнеры, а разработчики активно декомпозируют сущности и пишут микро-сервисы. Сетевые инженеры до недавнего времени могли позволить себе только виртуализацию, как сказал один мой друг из Одессы — виртуализацию для нищих, в виде отдельных таблиц маршрутизации, контекстов управления или логических маршрутизаторов. Это добавляет стабильности и удобства так как разделяет задачи хотя бы на уровне процессов сетевой операционной системы, но не решает проблему монолитности глобально. И вот наконец Donyel Jones-Williams Director of Service Provider Product Marketing Management из Juniper Networks заявил следующее — We are doing the same thing for routers that hypervisors did for servers. На мой взгляд, получилось даже интереснее, потому-что Junos Node Slicing, так называется система виртуализации от Juniper Networks, подразумевает запуск экземпляров операционной системы не на RE, а на отдельных серверах, вот как это выглядит.

image

Как видно из иллюстрации, GNF (guest network function) — экземпляр Junos, запускается в виде отдельной виртуальной машины и монопольно получает в распоряжение набор ресурсов помещенных в слоты FPC. Каждый GNF вместе с набором FPC видится снаружи и функционирует как совершено отдельный маршрутизатор, при этом трафик между GNF можно передавать по фабрике. Такой подход исключает внутренние противоречия между функциям маршрутизатора, повышает стабильность системы в целом, а кроме этого обладает «природной» способностью разделить административные домены управления между подразделениями организации. Позвольте еще одну иллюстрацию, уж очень красиво стали их рисовать.

image

Скорое появление универсального шасси, где могут быть использованы интерфейсные карты от PTX10008, PTX10016, QFX10008, QFX10016 и MX, а именно об этом сообщается в пресс-релизе Juniper Networks, вызывает только один вопрос — А что, так можно было? У Juniper уже есть некоторые наработки в области унификации, так например некоторые концентраторы линейных карт от MX240-MX960 уже давно можно использовать на топовых MX2010 и MX2020. Нынешняя задача выглядит более серьезной, так как в одном шасси нужно объединить карты, спроектированные с учетом особенностей работы во всех сегментах сети — ЦОД, ядро, граница. Как это сделано, пока не сообщается, но по словам Donyel Jones-Williams новая платформа уже находится в тестовой эксплуатации в сетях крупных заказчиков.

Так какое же будущее пытается приблизить Juniper Networks? Производитель концентрируется не только на аппаратуре, а смешает акценты в сторону управления и гибкости эксплуатации. По разным оценкам, стоимость конечного продукта только на 40% определяется аппаратной начинкой, примерно столько же стоит разработка программного обеспечения, средств интеграции и автоматизации. Посмотрим что из этого получится и, по-возможности, поучаствуем в развитии индустрии, ведь никто не знает куда выведет лестница, как сказал Док Браун — будущее еще не написано.

Пресс-релиз и документацию на Junos Node Slicing можно посмотреть тут:
Juniper Networks Unveils Cloud Grade Networking to Accelerate Agility and Innovation in the Cloud Era
Junos Node Slicing Feature Guide
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/334684/


Метки:  

Обзор возможностей библиотеки Apache Curator для Apache Zookeeper

Среда, 02 Августа 2017 г. 09:30 + в цитатник


По долгу работы мне приходится сталкиваться с проектированием и разработкой распределенных приложений. Такие приложения часто используют различные средства межпроцессного взаимодействия для организации взаимодействия компонентов. Особые сложности возникают в процессе реализации алгоритмов, обрабатывающих связанные данные распределенно. Для поддержки таких задач используются специализированные системы распределенной координации. Самым популярным и широко используемым продуктом является Apache Zookeeper.


Zookeeper — продукт сложный. Несмотря на солидный возраст, периодически в нем обнаруживаются те или иные ошибки. Однако, это лишь следствие его возможностей, которые помогают сделать жизнь легче многим разработчикам распределенных систем. Далее, я рассмотрю некоторые особенности Zookeeper, которые помогут понять лучше его возможности, а затем перейдем к библиотеке Apache Curator (Netflix), которая делает жизнь разработчиков распределенного ПО приятной и предлагает множество готовых рецептов для реализации распределенных объектов координации.


Apache Zookeeper


Как уже ранее было отмечено, Zookeeper — жизненно важный компонент распределенных систем. Базу данных Zookeeper проще всего представить в виде дерева, похожего на файловую систему, при этом каждый элемент дерева идентифицируется путем (/a/path/to/node) и хранит в себе произвольные данные. Таким образом, с помощью Zookeper вполне можно организовать иерархическое распределенное хранилище данных, а также другие интересные конструкции. Полезность и широкая распространенность Zookeeper-а обеспечивается рядом важнейших свойств, которые перечислены далее.


Распределенный консенсус


Консенсус обеспечивается с помощью алгоритма ZAB, данный алгоритм обеспечивает свойства C(consistency) и P(partition tolerance) CAP-теоремы, что означает целостность и устойчивость к разделению, жертвуя доступностью. На практике это приводит к следующим эффектам:


  1. Все клиенты видят одно и то же состояние, неважно на каком сервере они запрашивают это состояние.
  2. Изменение состояния происходит упорядоченно, "гонка" невозможна (для операций set, операции get-set не атомарные).
  3. Кластер Zookeepr может "развалиться" и стать полностью недоступным, но при этом он станет недоступным для всех.

Консенсус — способность распределенной системы каким-то образом прийти к соглашению о ее текущем состоянии. Zookeeper использует алгоритм ZAB, часто применяются и другие алгоритмы — Raft,
Raft.

Эфемерные узлы


Клиент, устанавливая соединение с кластером Zookeeper, создает сессию. В рамках сессии существует возможность создавать узлы, которые будут видны другим клиентам, но, время существования которых равно времени жизни сессии. При завершении сессии данные узлы будут удалены. Такие узлы имеют ограничения — они могут быть только терминальными и не могут иметь потомков, то есть, нельзя иметь эфемерные поддеревья. Эфемерные узлы часто применяются с целью
реализации систем обнаружения сервисов.


Представим, что у нас есть несколько экземпляров сервиса, между которыми производится балансировка нагрузки. Если какой-то из экземпляров появляется, то для него создается эфемерный узел, в котором находится адрес сервиса, а при аварии сервиса этот узел удаляется и более не может использоваться для балансировки. Эфемерные узлы применяются очень часто.


Подписка на события узла


Клиент может подписаться (watch) на события узлов и получать обновления при возникновении каких-либо событий, связанных с данными узлами. Однако, тут тоже есть ограничение — после возникновения события на узле, подписка снимается и ее необходимо восстанавливать заново, при этом, очевидно, существует возможность пропуска других событий, которые возникают на данном узле. В связи с данным фактом, возможность использования данной функции достаточно ограничена.


Например, в рамках сервисов обнаружения ее применять можно, для реакции на изменение конфигурации, но необходимо помнить, что после установки подписки необходимо выполнить операцию "вручную", чтобы убедиться, что пропуска изменения состояния не произошло.


Последовательные узлы


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


Версии узлов


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


ACL на узлы


Существует возможность задавать для узлов ограничения доступа, определяемые ACL, что предназначено для защиты данных от недоверенных приложений. Стоит отметить, что, конечно, ACL не защищают от перегрузок, которые может создать вредоносный клиент, предоставляя только механизм ограничения доступа к содержимому.


TTL на узлы


Zookeeper позволяет устанавливать узлам TTL, по истечении которого (если нет обновлений) узел будет удален. Данная функциональность появилась сравнительно недавно.


Серверы-наблюдатели


Существует возможность подключения к кластеру серверов в режиме наблюдатель (observer), которые могут использоваться для выполнения операций чтения, что очень полезно в тех случаях, когда нагрузка на кластер, генерируемая операциями записи является высокой. С использованием серверов-наблюдателей проблема может быть решена. Может возникнуть вопрос, почему бы просто в кластер не добавлять обычные узлы? Ответ кроется в алгоритме консенсуса — чем больше узлов, позволяющих писать данные, тем дольше будет тратиться времени на достижение консенсуса и тем меньше будет производительность
кластера на запись. Серверы-наблюдатели не участвуют в консенсусе, а поэтому не влияют на производительность операций записи.


Синхронизация времени на узлах


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


Конечно, в бочке меда должен быть деготь и он действительно есть — Zookeeper имеет свойств, которые могут ограничивать его применение. Есть даже выражение, которое достаточно иронично описывает сложности работы с Zookeeper — Single Cluster of Failure © Pinterest, что саркастически демонстрирует тот факт, что, стремясь избавиться от единой точки отказа с помощью распределенной системы, используя Zookeeper, можно столкнуться с ситуацией, когда он станет той самой точкой отказа.


База данных Zookeeper должна помещаться в RAM


Zookeeper загружает базу в память и держит ее там. Если база данных не помещается в RAM, то она будет помещена в Swap, что приведет к существенной деградации производительности. Если БД большая, требуется сервер с достаточно большим объемом RAM (что, впрочем, не является проблемой в настоящее время, когда 1TB RAM на сервере — далеко не предел).


Время таймаута сессии


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


Деградация производительности от количества узлов в кластере


Обычно, в кластере используют 3 узла, которые участвуют в достижении консенсуса, желание добавить дополнительные узлы существенно снизит производительность операций записи. Количество узлов должно быть нечетным (требование алгоритма ZAB), соответственно, расширение кластера до 5, 7, 9 узлов будет негативно влиять на производительность. Если проблема именно в операциях чтения — используйте узлы-наблюдатели.


Максимальный размер данных в узле


Максимальный размер данных в узле ограничен 1MB. В случае, если требуется хранить большие объемы данных, Zookeeper не подойдет.


Максимальное количество узлов в листинге потомков


Zookepeer не накладывает на то, сколько у узла может быть потомков, однако, максимальный размер пакета данных, который сервер может отправить клиенту составляет 4МБ (jute.maxbuffer). Если у узла такое количество потомков, что их перечень не помещается в один пакет, то, к сожалению, не существует способа получить сведения о них. Данное ограничение обходится с помощью организации иерархических "псевдоплоских" списков таким же образом, каким строятся кэши в файловой системе, имена или дайджесты объектов разбиваются на части и организуются в иерархическую структуру.


Несмотря на недостатки, достоинства их перевешивают, что делает Zookeeper важнейшим компонентом многих распределенных экосистем, например, Cloudera CDH5, или DC/OS, Apache Kafka и других.


Zookeeper для разработчика


Поскольку Zookeeper реализован с использованием языка Java, то в средах JVM его использование является органичным, к примеру, достаточно легко запустить сервер или даже кластер серверов из Java и использовать его для реализации интеграционных или smoke-тестов приложения без необходимости развертывания стороннего сервера. Однако, API клиента Zookeeper достаточно низкоуровневый, что, хотя и позволяет выполнять операции, но напоминает заплыв против течения реки. Кроме того, требуется глубокое понимание основ Zookeeper, чтобы правильно реализовать обработку исключительных ситуаций. К примеру, когда я использовал для работы с Zookeeper базовый интерфейс, отладка и поиск ошибок в коде распределенной координации и обнаружения доставляли достаточно большие проблемы и требовали существенное время.


Однако, решение существует и оно было подарено сообществу разработчиком Netflix Джорданом Циммерманом. Знакомьтесь, Apache Curator.


Apache Curator


На главной странице проекта расположена цитата:



Это утверждение на 100% отражает суть Curator. Начав использовать данную библиотеку, я обнаружил, что код работы с Zookeeper стал простым и понятным, а количество ошибок и время на их устранение снизилось кратно. Если, как ранее было сказано — стандартный клиент напоминает заплыв против течения, то с куратором ситуация меняется на 180 градусов. Кроме того, в рамках Curator-а реализовано большое количество готовых рецептов, которые я обзорно рассмотрю далее.


Базовый API


API выполнен в форме исключительно удобного текучего интерфейса, что позволяет просто и лаконично определять требуемые действия. К примеру (далее, примеры приводятся на языке Scala):


client
    .create()
    .orSetData()
    .forPath("/object/path", byteArray)

что может быть переведено как "создай узел или, если существует, просто установи данные для пути "/object/path" и запиши в него byteArray".


Или, к примеру:


client
    .create()
    .withMode(CreateMode.EPHEMERAL_SEQUENTIAL)
    .forPath("/head/child", byteArray)

"создай узел типа последовательный и эфемерный для пути "/head/child000000XXXX" и запиши в него byteArray". Еще несколько примеров могут быть найдены на этой странице руководства.


Асинхронные операции


Curator поддерживает как синхронный, так и асинхронный режим выполнения операций. В случае асинхронного использования клиент имеет тип AsyncCuratorFramework, в отличие от синхронного CuratorFramework. А каждая цепочка вызовов принимает метод thenAccept, в котором указывается Callback, который вызывается при завершении операции. Более подробно об асинхронном интерфейсе можно узнать на посвященной ему странице руководства.


val async = AsyncCuratorFramework.wrap(client);
async.checkExists().forPath(somePath).thenAccept(stat -> mySuccessOperation(stat))

При использовании Scala использование асинхронного интерфейса не кажется оправданным, поскольку функциональность может быть легко реализована с использованием Scala Future, что позволяет коду сохранить особенности scala-way разработки. Однако, в случае Java и других JVM языков, данный интерфейс может быть полезным.

Поддержка схем данных


Zookeeper не поддерживает семантику хранимых данных. Это означает, что разработчики самостоятельно несут ответственность за то, в каких форматах хранятся данные и по каким путям они расположены. Это может стать неудобным во многих случаях, например, когда в проект приходят новые разработчики. Для решения данных проблем Curator поддерживает схемы данных, которые позволяют задавать ограничения на пути и типы узлов, в рамках данных путей. Схема, создаваемая из конфигурации, может быть представлена в формате Json:


[
    {
        "name": "test",
        "path": "/a/b/c",
        "ephemeral": "must",
        "sequential": "cannot",
        "metadata": {
            "origin": "outside",
            "type": "large"
        }
    }
]

Поддержка миграций


Миграции Curator чем-то напоминают Liquibase, только для Zookeeper. С их помощью возможно отражать эволюцию базы данных в новых версиях продукта. Миграция состоит из набора последовательно выполняемых операций. Каждая операция представлена некоторыми преобразованиями над БД Zookeeper. Curator самостоятельно отслеживает примененность миграций с помощью Zookeeper. Данная функция может быть использована в процессе развертывания новой версии приложения. Подробно миграции описаны на
соответствующей странице руководства.


Тестовый сервер и тестовый кластер


Для упрощения тестирования, Curator позволяет встроить сервер или даже кластер серверов Zookeeper в приложение. Данную задачу можно достаточно просто решить и без использования Curator, только с Zookeeper, но Curator предоставляет более лаконичный интерфейс. К примеру, в случае Zookeeper без Curator:


class ZookeeperTestServer(zookeperPort: Int, tmp: String) {

  val properties = new Properties()
  properties.setProperty("tickTime", "2000")
  properties.setProperty("initLimit", "10")
  properties.setProperty("syncLimit", "5")
  properties.setProperty("dataDir", s"$tmp")
  properties.setProperty("clientPort", s"$zookeperPort")

  val zooKeeperServer = new ZooKeeperServerMain
  val quorumConfiguration = new QuorumPeerConfig()
  quorumConfiguration.parseProperties(properties)

  val configuration = new ServerConfig()

  configuration.readFrom(quorumConfiguration)

  private val thread = new Thread() {
    override def run() = {
      zooKeeperServer.runFromConfig(configuration)
    }
  }

  def start = {
    thread.start()
  }

  def stop = {
    thread.interrupt()
  }
}

...

val s = new ZookeeperTestServer(port, tmp)

s.start
...
s.stop

В случае Curator:


val s = new TestingServer(port)
s.start()
...
s.stop()

Рецепты Curator


Рецепты Curator — основной мотив использования данной библиотеки для реализации распределенных механизмов взаимодействия процессов. Далее, перечислим основные рецепты, которые поддерживаются Curator и как они могут применяться. Некоторые рецепты я не применял на практике, поэтому для них дан максимально приближенный к руководству перевод.


Выбор лидера


Данные рецепты предназначены для реализации отказоустойчивой модели выполнения процессов, в рамках которой существует текущий лидер и несколько процессов находится в горячем резерве. Как только лидер перестает выполнять свои функции, другой процесс становится лидером. Существует два подходящих рецепта:


  1. Leader Latch, который представляет собой аналог CountDownLatch, который заблокирован до тех пор, пока процесс не стал лидером;
  2. Leader Election, которые реализует выбор лидера через вызов метода. В момент, когда процесс становится лидером, вызывается метод, выход из которого свидетельствует об утрате лидерства.

Блокировки


Блокировки — один из важнейших механизмов распределенной межпроцессной синхронизации. Curator предоставляет широкий набор объектов блокировок:


  1. Shared Reentrant Lock — распределенная блокировка, в которую может повторно входить клиент, который имеет к ней доступ;
  2. Shared Lock — распределенная блокировка;
  3. Shared Reentrant Read Write Lock — объект, который позволяет осуществлять раздельную блокировку на чтение и на запись, при этом заблокировать объект на чтение могут несколько клиентов одновременно, блокировка на запись является эксклюзивной;
  4. Shared Semaphore — считающий семафор, с помощью которого легко осуществить работу с ограниченным количеством ресурсов, которое задается 32-битным целым числом;
  5. Multi Shared Lock — высокоуровневый объект, который позволяет выполнять операции над несколькими распределенными блокировками атомарно.

Барьеры


  1. Barrier — объект, который позволяет некоторому клиенту заблокировать доступ к участку кода для остальных участников до выполнения определенных условий, а при их наступлении — разблокировать доступ, что приводит к тому, что все участники могут продолжить свое исполнение;
  2. Double Barrier — объект позволяет синхронизовать вход некоторого количества клиентов в сегмент кода и их выход из него.

Счетчики


  1. Shared Counter — обычный целочисленный счетчик (32 bit) с защитой от гонки;
  2. Distributed Atomic Long — счетчик типа Long (64 bit).

Кэши


  1. Path Cache — объект, который наблюдает за узлом и обновляет локальный кэш о его дочерних узлах и опционально об их данных при его изменении;
  2. Node Cache — объект, который наблюдает за узлом и обновляет локальный кэш о нем и его данных;
  3. Tree Cache — объект, который наблюдает за всем деревом потомков узла и обновляет локальный кэш при изменении в дереве;

Узлы


  1. Persistent Node — данный рецепт позволяет создать узел с данными, для которого Curator будет стремиться обеспечить его присутствие и неизменность, даже при внешних воздействиях;
  2. Persistent TTL Node — рецепт для создания узла, время жизни которого определяется TTL, который поддерживает те же свойства, что и Persistent Node;
  3. Group Member — позволяет организовать группу участников.

Очереди


Хочу заметить, что Zookeeper — не лучший кандидат для организации интенсивных распределенных очередей, если требуется обеспечить пропуск большого количества сообщений, то рекомендую воспользоваться специально предназначенным решением, например, Apache Kafka, RabbitMQ или другими. Тем не менее, Curator предоставляет набор рецептов для поддержки очередей:

  1. Distributed Queue — обычная распределенная очередь, позволяет класть и извлекать сообщения в порядке очередности;
  2. Distributed Id Queue — распределенная очередь, которая с каждым сообщением сохраняет идентификатор и позволяет извлечь сообщение из очереди по идентификатору с его немедленным удалением;
  3. Distributed Priority Queue — очередь с приоритетами;
  4. Distributed Delay Queue — очередь позволяет задать для каждого добавляемого элемента время, в формате Unixtime, когда он станет доступен для чтения из очереди;
  5. Simple Distributed Queue — аналог очереди, которая предоставляется стандартным API Zookeeper.

Заключение


Apache Curator безусловно стоит того, чтобы рассмотреть ее к применению, библиотека является выдающимся образцом инженерного труда и позволяет значительно упростить взаимодействие с Apache Zookeeper. К недостаткам библиотеки можно отнести малый объем документации, что повышает входной барьер для начинающих разработчиков. В своей практике мне не раз требовалось изучать исходные коды библиотеки, чтобы понять как именно работает тот или иной рецепт. Однако, это дает и положительный эффект — глубокое понимание реализации позволяет совершать меньше логических ошибок, основанных на предположениях.


Необходимо отметить, что разработчики Curator рекомендуют изучить документацию Zookeeper до того, как начать использовать библиотеку. Это очень разумный совет, поскольку Zookeeper является продуктом, для эффективного использования которого необходимо понимать как именно он функционирует, а не только знать его API. Эти затраты безусловно окупятся, а в руках опытного инженера возможности Zookeeper позволяет создавать надежные и производительные распределенные системы.

Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/334680/


Разбор задач викторины Postgres Pro на PGDay'17

Среда, 02 Августа 2017 г. 08:30 + в цитатник

Хорошей традицией на постгресовых конференциях стало устраивать викторины с розыгрышем билетов на следующие конференции. Наша компания Postgres Professional на недавнем PgDay’17 разыгрывала билеты на PgConf.Russia 2018, которая пройдет в феврале 2018 года в Москве. В этой статье представлен обещанный разбор вопросов викторины.



Участникам конференции были предложены следующие вопросы:


1. При выполнении на базе read-only запросов была обнаружена запись на диск. Кто (что) виноват?


Варианты ответа: WAL, Hint bits, Vacuum, Russian Hackers, Еноты.


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


Правильный ответ — Hint bits, в русской документации это “вспомогательные биты”. К сожалению, в документации мало о них говорится, но это восполнено в Wiki. Эти биты находятся в заголовке кортежа, и предназначены для ускорения вычисления его видимости. Они содержат информацию о том:

  • создан ли кортеж транзакцией, которая уже зафиксирована,
  • создан ли кортеж транзакцией, которая была прервана,
  • удален ли кортеж транзакцией, которая уже зафиксирована,
  • удален ли кортеж транзакцией, которая была прервана.

Значения этих битов могут быть проставлены и при операции чтения, если при определении видимости было определено значение какого-либо из них.


2. Сколько записей будет добавлено в pg_class командой:


CREATE TABLE t (id serial primary key, code text unique);

Поиск правильного ответа начнем с того факта, что в системной таблице pg_class хранятся не только таблицы, но и индексы, последовательности, представления и некоторые другие объекты.


Поскольку мы создаем таблицу, то одна запись в pg_class точно добавится. Итак, одна запись в pg_class есть.


Следующий факт, который нам понадобится, заключается в том, что для реализации ограничений PRIMARY KEY и UNIQUE в PostgreSQL используются уникальные индексы.


В создаваемой таблице есть и первичный ключ (id), и уникальный (code). Значит на каждое из этих ограничений будет создано по индексу. Промежуточный итог — 3 записи.


Теперь посмотрим на тип данных serial, который используется для столбца id. В действительности, такого типа данных нет, столбец id будет создан с типом integer, а указание serial означает, что нужно создать последовательность и указать её в качестве значения по умолчанию для id. Таким образом, будет создана последовательность, а количество записей в pg_class увеличивается до 4.


Столбец code объявлен с типом text, а этот тип может содержать очень большие значения, значительно превышающие размер страницы (обычно 8KB). Как их хранить? В PostgreSQL используется специальная технология для хранения значений большого размера — TOAST. Суть её в том, что если строка таблицы не помещается на страницу, то создается еще одна специальная toast-таблица, в которую будут записываться значения «длинных» столбцов. Для пользователя вся эта внутренняя кухня не видна, мы работаем с основной таблицей и можем даже не догадываться как там всё внутри устроено. А PostgreSQL для того чтобы быстро «склеивать» строки из двух таблиц создает еще и индекс на toast-таблицу. В итоге, наличие столбца code с типом text приводит к тому, что в pg_class создаются еще две записи: для toast-таблицы и для индекса на неё.


Общий итог и правильный ответ: 6 записей (сама таблица, два уникальных индекса, последовательность, toast-таблица и индекс на неё).


3. Есть две таблицы:


CREATE TABLE t1(x int, y int);
CREATE TABLE t2(x int not null, y int not null);

В обе добавили 1 млн записей. Какая таблица займет больше места на диске и почему?
Варианты ответа были такими: Первая, вторая, займут поровну, первая займет меньше или столько же, сколько вторая, зависит от версии PostgreSQL.


Если в первую таблицу добавили значения, не являющиеся NULL, то она будет занимать столько же места, сколько и вторая. Если же в нее добавили NULL’ы, она будет занимать меньше места.


Это так вследствие особенностей хранения NULL-ов (вернее, не-хранения: они не хранятся, вместо них в заголовке записи проставляются специальные биты, указывающие на то, что значение соответствующего поля — NULL). Подробнее об этом можно узнать из из документации и доклада Николая Шаплова Что у него внутри.


Кстати, если в таблице t1 только одно из двух полей будет NULL, t1 займет столько же места, сколько и t2. Хотя NULL не занимает места, действует выравнивание, и поэтому в целом на занимаемый записями объем это не влияет. Выравнивание еще встретится нам в задаче №4.


Дотошный читатель возразит: «ну хорошо, сами NULL’ы не хранятся, но где-то же должна храниться та самая битовая строка t_bits, где по биту отводится на каждое поле, способное принимать значение NULL! Она не нужна для таблицы t2, но нужна для t1. Поэтому t1 может занять и больше места, чем t2».


Но дотошный читатель забыл про выравнивание. Заголовок записи без t_bits занимает ровно 23 байта. А под t_bits будет в t1 выделен один байт заголовка записи; а в случае t2 он будет съеден выравниванием.


Если у Вас установлено расширение pageinspect, можно заглянуть в заголовок записи, и, справляясь с документацией, увидеть разницу:


SELECT * FROM heap_page_items(get_raw_page('t1', 0)) limit 1;
SELECT * FROM heap_page_items(get_raw_page('t2', 0)) limit 1;

4. Есть таблица:


CREATE TABLE test(i1 int, b1 bigint, i2 int);

Можно ли переписать определение так, чтобы ее записи занимали меньше места на диске и если да, то как? Предложите Ваш вариант.


Тут все просто, дело в выравнивании. Если у вас 64-разрядная архитектура, то поля в записи, имеющие длину 8 байт и более, будут выровнены по 8 байт. Так процессор умеет быстрее читать их из памяти. Поэтому 4-байтные int нужно складывать рядом, тогда они будут занимать вместе 8 байт.


На 32-разрядной архитектуре разницы нет. О внутреннем устройстве записей можно узнать из документации и уже упоминавшегося доклада Николая Шаплова Что у него внутри.



5. Какой тип занимает больше места на диске: timetz или timestamptz?


Результат неожиданный: timetz занимает больше места (12 байт), чем timestamptz (8 байт),
почему же так? Это историческое наследие. И никто не собирается от него избавиться? См. ответ Тома Лэйна. Кстати, если кому нибудь действительно понадобилось timetz (time with time zone) на практике, напишите нам об этом.



6. Как можно проверить консистентность БД для того, чтобы убедиться, что часть данных в БД не потеряна?


Ответ простой: в PostgreSQL пока такого средства нет. Чексуммы есть во многих местах, но защищают не всё. Поэтому ответы типа “задампить и сравнить” мы вынуждены были считать правильными. В Postgres Pro ведется работа над улучшением самоконтроля целостности.



7. Какое из условий ниже истинно и почему?


(10,20)>(20,10)
array[20,20]>array[20,10]

Сравнение строк производится слева направо, поэтому первое выражение ложно.
Сравнение массивов производится также, поэтому второе — истино.



8. Действие каких подсистем выключает настройка track_counts = off?


Варианты ответа: Statistics Collector, Checkpointer, WAL archiving, Autovacuum, Bgwriter, Ни одна из перечисленных


В документации сказано, что track_counts включает сбор статистики доступа к таблицам и индексам, которая нужна, в том числе, для автовакуума. С помощью этой статистики автоваккум решает, за какие таблицы ему браться. Подробности можно почитать в комментариях к исходникам автовакуума.


Конечно, архивирование WAL, Bgwriter и checkpointer с этим параметром не связаны.


9. Каков будет результат запроса


select NULL IS NULL IS NULL ?

Это, наверное, самый простой вопрос. Ответ False, т.к. NULL — это NULL, и всё это истина.


10. С какими типами индексов не работает команда


CLUSTER [VERBOSE] table_name [ USING index_name ] 
и почему?

Команда CLUSTER упорядочивает таблицу в соответствие с некоторым индексом. Некоторые индексы могут задавать порядок, а некоторые — нет.


Ответ можно узнать с помощью команды

select amname from pg_am where amclusterable ;

Эта команда выдаст два ответа — ожидаемый btree и не очень ожидаемый GiST. Казалось бы, какой порядок задает GIST-индекс? Раскроем страшную тайну — CLUSTER просто перестраивает таблицу, обходя ее в порядке обхода индекса. Для GiST порядок не столь определен, как для B-Tree, и зависит от порядка, в котором записи помещались в таблицу. Тем не менее, этот порядок есть, и есть сообщения, что кластеризация по GIST в отдельных случаях помогает.


При использовании пространственных индексов, например, она означает, что геометрически близкие объекты будут находится, скорее всего, ближе друг другу и в таблице.


11. Пусть настроена синхронная репликация и на мастере synchronous_commit = on.


При каком значении этой же опции на реплике задержка при выполнении COMMIT на мастере будет меньше, и почему?


synchronous_commit = on на мастере означает, что мастер будет считать COMMIT завершенным только после получения сообщения от реплики об успешной записи соответствующей части WAL’a на диск (ну, или о её застревании в буфере ОС, если у вас стоит fsync = off, но так делать не стоит, если данные представляют хоть какую-то ценность). Хитрость же в том, что момент, когда WAL сбрасывается на диск, определяется локальным значением synchronous_commit, то есть его значением на реплике.


Если на реплике synchronous_commit = off, запись произойдет не сразу, а когда WAL writer процесс сочтёт нужным ее выполнить; если точнее, он занимается этим раз в wal_writer_delay миллисекунд, но при большой нагрузке на систему сбрасываются только целиком сформированные страницы, так что в итоге максимальный промежуток времени между формированием WAL записи и ее записью на диск при асинхронном коммите получается 3 * wal_writer_delay. Все это время мастер будет терпеливо ждать, он не может объявить транзакцию завершенной до окончания записи.


Если же на реплике synchronous_commit имеет более высокое значение (хотя бы local), она сразу попытается записать WAL на диск, и поэтому задержка всего COMMIT потенциально будет меньше. Впрочем, и запись синхронного коммита можно отложить с помощью commit_delay, но это уже совсем другая история. Из этого всего следует неочевидный сходу вывод: выключенный synchronous_commit, который, казалось бы, должен уменьшать задержку COMMIT, в описанной схеме с репликацией ее увеличивает.


Подробнее об этом можно почитать в архиве списков рассылки и в документации:
Надёжность и журнал упреждающей записи, synchronous_commit.


12. Что даст запрос:


select #array[1,2,3] - #array[2,3]

Чтобы ответить на этот вопрос, надо знать, как PostgreSQL работает с массивами. Унарный оператор “#”, определенный в расширении intarray
вычисляет длину массива. При этом напрашивается ответ: в первом массиве три элемента, во втором — два. Казалось бы — ответом будет число 1! Но нет, если выполнить этот запрос, ответом будет ДВА. Откуда?


Важно учитывать также приоритет операторов (он намертво пришит к синтаксису и для пользовательских операторов это ведет часто к неочевидной семантике). У унарного # приоритет ниже, чем у оператора вычитания. Поэтому правильно запрос читается так:

select #( array[1,2,3] - #(array[2,3]))

Это означает, что из массива [1,2,3] “вычитается” число 2, остается массив [1,3], и в конце вычисляется длина этого массива. ДВА. Почти всем.

Ближе к концу викторины надо активизировать чувство юмора.


13. Сколько записей будет добавлено в pg_class командой:


CREATE TABLE t (id serial primary key, code text unique);

Этот вопрос “случайно” повторяет вопрос №2. См. также следующий вопрос.
Надо заметить, что ответ на 13-й вопрос, тем не менее, не должен повторять ответа на 2-й вопрос :) Это заметил всего лишь один из участников. Ведь таблица t уже создана в вопросе №2. Повторная команда не создаст ни одной записи в БД. (см также Задачи, расположенные по цепочке, Квант №10, 1987 )


14. Что использовалось при составлении данного теста: UNION или UNION ALL?


История этого вопроса такова. Случайно, в процессе подготовки викторины, в ней два раза был напечатан один и тот же вопрос. Увидев это, Иван Фролков пошутил “надо было использовать UNION, а не UNION ALL”. Шутка понравилась “товарищу полковнику” ( www.anekdot.ru/id/-10077921 ), и викторина была пополнена 14-м вопросом.



Благодарности


В составлении викторины участвовали:
Алексей Шишкин, Алексей Игнатов, Арсений Шер, Анастасия Лубенникова, Александр Алексеев, Иван Панченко, Иван Фролков.


За 12-й вопрос мы благодарны Николаю Шуляковскому из mail.ru.



Победители викторины получили промокоды, которые они могут ввести вместо оплаты участия в PgConf.Russia 2018

.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/334386/


Метки:  

Олег Ненашев, Кирилл Толкачёв и Александр Тарасов про Groovy DSL и Pipeline в Jenkins на jug.msk.ru

Среда, 02 Августа 2017 г. 00:46 + в цитатник
27 июля 2017 года прошла совместная встреча сообществ jug.msk.ru и Jenkins MSK. На встрече с докладами о Jenkins выступили Олег Ненашев («Groovy DSL в Jenkins и Pipeline. Как оно работает?») и Кирилл Толкачёв с Александром Тарасовым («DSL много не бывает. Мигрируем со Scripted Pipeline на Declarative (Live)»).



О докладчиках


Олег работает в компании CloudBees, разрабатывающей коммерческие решения на основе Jenkins. Является контрибьютором ядра и плагинов продукта. Занимается организацией и активно участвует в Jenkins-митапах. Твиттер, GitHub, Speaker Deck.

Доклады Олега:

  • «Who is Mr. Jenkins? Текущее состояние, проблемы и основные тренды развития» (SPb Jenkins Meetup #0 2015: презентация, видео)
  • «Q&A про разработку плагинов» (SPb Jenkins Meetup #0 2015: видео)
  • «Обзор Jenkins Pipeline» (Moscow Jenkins Meetup #1 2016: видео)
  • «Jenkins 2 и планы на будущее» (Moscow Jenkins Meetup #1 2016: видео)
  • «Вводный доклад. Сообщество Jenkins» (Belarus Jenkins Meetup #0 2016: видео)
  • «Tool chains» (SPb Jenkins Meetup #3 2016: видео)
  • «Jenkins 2. Как сделать мажорный релиз и не развалить сообщество?» (SECR 2016: презентация, видео)
  • «Jenkins по требованию. Управляем инстансами в облаке» (SPb Jenkins Meetup #5 2017: видео)
  • «Тёмная сторона Jenkins. Как стабилизировать Remoting?» (SPb Jenkins Meetup #6 2017: видео)
  • «Реализация тестирования плагинов Jenkins в ci.jenkins.io» (SPb Jenkins Meetup #7 2017: видео)

Кирилл и Александр — постоянные спикеры конференций и митапов, к значительной части которых имеет отношение JUG.ru. Ранее на jug.msk.ru они выступали с совместным докладом в 2015 году. В 2016 году Кирилл также выступал, но уже с Барухом Садогурским.

Доклады Кирилла за время, прошедшее с его прошлых выступлений:

Доклады Александра:
  • «Александр Тарасов о DevOps» (JUG.ru-2016: видео)
  • «Тонкости реализации шаблона Service Discovery на примере SpringCloud» (Joker 2016: презентация)
  • «Everything as a Code» (DevOpsBy 2017, RootConf 2017: презентация)
  • «Service Discovery: More Than Seems» (JavaDay Minsk 2017: презентация)

Совместные их доклады:

Нельзя не упомянуть об уже пятой статье Саши, опубликованной на DZone (с чем мы его поздравляем).

О докладах


Кирилл перед докладом. Традиционное начало встречи: рукопожатие Андрея Когуня с докладчиками.



Олег начал с вступления о региональных сообществах Jenkins и ближайших мероприятиях. Основная часть была посвящена Groovy DSL, присутствующем в различных частях продукта. Далее значительное внимание было уделено Jenkins Pipeline.



Кирилл и Александр продолжили тему Pipeline, легко и непринуждённо предприняв попытку преобразования императивного описания в декларативное. Увенчалась ли попытка успехом, можно узнать, посмотрев видео.

Спойлер

script {
Главное - результат!)
}

— Tarasov Aleksandr (@aatarasoff) July 27, 2017




В перерыве и после выступлений можно было пообщаться в неформальной обстановке, задав вопросы и обсудив животрепещущие темы.



Доклад Олега:

Доклад Кирилла и Александра:

Фотографии со встречи. Видео скоро ожидается на YouTube (с анонсом в VK и G+). Подписка на рассылку следующих встреч jug.msk.ru.

2 августа 2017 года в Санкт-Петербурге состоится встреча JUG.ru с Александром Тарасовым (тема — Service Discovery), зарегистрироваться.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/334374/


Метки:  

JetBrains MPS для интересующихся #3

Среда, 02 Августа 2017 г. 00:35 + в цитатник

Бинго-бонго и Джимбо-джамбо, дорогие друзья!


У меня на дачке не было света 2 дня, я практически иссох и впал в спячку, но я снова здесь!
В этом посте мы начнем писать предсказания погоды и немного напишем кода, а не потыкаем мышкой! Ура! Наконец-то!


Какие прогнозы мы хотим делать


Очень простые! Пока прогнозировать будем только следующий день, а правила придумаем сами; а точнее, правил не будет. Мы просто будем выводить температуру на следующий день, абсолютно такую же, как и сегодня.
Сделаем один прикольчик, демонстрирующий возможности projectional editor.


Концепты


В данном случае мы прибегнем к крутой фиче — мы создадим концепт, который будет содержать только ссылку на исходные данные, а данные мы будем выводить как график на своем Swing компоненте. О как умеем, хотя swing я жуть как не люблю.
image


Создаем концепт PredictionResult, добавляем в него reference "input", которая является ссылкой на реализацию концепта в текущем scope AST! Но поскольку нам не нужны области видимости, или scope, то для нас сойдет поиск всех элементов данного типа.(Кстати, Scopes это не самая легкая тема в MPS + по ней довольно сложная документация, местами непонятная, так что я накатаю статейку про Scope тоже. Когда нибудь.) Но теперь нужно добавить идентификацию для WeatherData, изменим немного структуру и Editor аспект.
image
Я добавил INamedConcept после implements, и теперь у нашего концепта WeatherData есть имя, но мы его никак не присваеваем, поэтому изменим Editor.
image
Здесь мы просто добавили 1 строчку, которая будет содержать имя. Пересоберем язык и посмотрим, че получилось.
image
Ура, теперь называем эту WeatherData именем "today" и возвращаемся к концепту PredictionResult и меняем его Editor аспект.
image
Пока так. У нас будет отображаться Prediction for tommorow, data %name_of_weather_data%
Добавим концепт в PredictionList — наш рутовый концепт, где пока находятся только входные данные.
image


image


Если собрать, то получится
image
… как раз то, чего мы и хотели. Мы можем выбирать из списка WeatherData(ничего страшного, что у нас только 1 WeatherData, зато расширяемо).
Здорово, теперь нужно как-то круто выводить наши прогнозы. Я уже написал, что выводить мы их будем на swing компоненте, если кто не знает — javax.swing. — пакет для разработки нативных графических интерфейсов на Java. На нем построена IntelliJ. Swing компоненты можно юзать в editor. Уря.
Перед тем, как рисовать все это дело, распишем по пунктам, как мы будем действовать.


  1. Берем ширину графика в пикселях и делим ее на 60 * 24 — количество минут в дне. Это нужно для того, чтобы правильно отображать точки по оси абсцисс.
  2. Переводим все температуры в одну единицу измерения, например, цельсии (потом мы настроим так, чтобы можно было самим выбирать, в цельсиях показывать или в фаренгейтах) и находим наибольшую температуру и наименьшую. Вычитаем из наибольшей наименьшую и получаем полную "высоту" в градусах. Суть в том, что если мы поделим высоту графика на эту величину, то получим сколько "пикселей в одном градусе". Это потребуется для того, чтобы проецировать температуры на график.
  3. Сортируем массив входных данных по времени(чем ближе к 00:00 — тем меньше, естественно) и проходимся по нему. Вычисляем x по формуле

    $$display$$время_в_минутах * коэффициент_из_пункта_1$$display$$

    а y

    $$display$$температура * коэффициент__из__пункта 2$$display$$

    P.S. формулы это ужас


    Рисуем!
    Чтобы Вас не мучать поэтапным написанием строчек, скину весь и пройдусь по более-менее сложным местам.


    { 
    final int chartWidth = 400; 
    final int chartHeight = 200; 
    final JPanel panel = new JPanel() { 
    
    @Override 
    protected void paintComponent(final Graphics graphics) { 
      super.paintComponent(graphics); 
      editorContext.getRepository().getModelAccess().runReadAction(new Runnable() { 
        public void run() { 
          string unit = node.unit; 
          final list labels = node.input.items.where({~it => !it.temperature.concept.isAbstract(); }).select({~it => 
            message debug "Woaw!" + it.temperature.concept.isAbstract(), , ; 
            double x = it.time.hours * 60 + it.time.minutes; 
            double y = it.temperature.getValueFromUnit(unit.toString()); 
            new Point2D.Double(x, y); 
          }).sortBy({~it => it.x; }, asc).toList; 
          final double minTemp = labels.sortBy({~it => it.y; }, asc).first.y; 
          final double maxTemp = labels.sortBy({~it => it.y; }, asc).last.y; 
    
          final double yKoef = chartHeight / (maxTemp - minTemp); 
          final double xKoef = chartWidth / (60.0 * 24.0); 
          int prevY = chartHeight; 
          int prevX = -1; 
    
          Graphics2D g2 = ((Graphics2D) graphics); 
          labels.forEach({~it => 
            message debug unit + "/" + it.y, , ; 
            int xTranslated = (int) (it.x * xKoef); 
            int yTranslated = chartHeight - (int) ((it.y - minTemp) * yKoef); 
            g2.setStroke(new BasicStroke(1)); 
            if (prevX > 0) { 
              // It is first element, no need to draw trailing line 
              g2.drawLine(prevX, prevY, xTranslated, yTranslated); 
            } 
            g2.drawString(String.format("%.2f", it.y) + unit, xTranslated + 3, chartHeight - Math.abs(chartHeight - (yTranslated + 20))); 
            g2.setStroke(new BasicStroke(5)); 
            g2.drawLine(xTranslated, yTranslated, xTranslated, yTranslated); 
    
            prevX = xTranslated; 
            prevY = yTranslated; 
          }); 
    
        } 
      }); 
    
    } 
    }; 
    panel.setPreferredSize(new Dimension(chartWidth, chartHeight)); 
    
    return panel; 
    }

    Первое, что бросается в глаза — editorContext.getRepository().getModelAccess().runReadAction...
    Это такая фишка редактора MPS: чтобы получить доступ к модели/узлу откуда угодно, нам нужно запросить выполнение этого кода. Это похоже на runOnUIThread в андроиде, смысл примерно тот же. Короче, если нужно получить что-то из главного потока, то нужно делать это именно так. Еще есть runWriteAction, он нужен для внесения изменений и он нам еще потребуется.
    Что происходит внутри:
    1) Мы определяем единицы измерения
    1) Определяем ширину и высоту графика
    2) Трансформируем массив типа WeatherTimedData в список типа java.awt.geom.Point2D.Double, где


    $x = hours * 60 + minutes$


    а y = температура в выбранном измерении, например, в цельсиях.
    Мы используем синтаксис baseLanguage, который облегчает работу с коллекциями и позволяет нормально использовать различные паттерны, например map, filter, flatMap. Естественно,
    вместо привычных названий используются select, where, selectMany соотвественно.
    Внимание! Кусок кода, отвечающий за фильтрацию WeatherTimedData, а именно where({~it => !it.temperature.concept.isAbstract(); }) — когда мы инициализируем новый WeatherTimedData, то у нас не иницилизирована температура. То есть у нас нет дефолта в цельсиях или фаренгейтах, поэтому у нас абстрактная температура, и если бы мы не добавили этой фильтрации, то у нас зависал бы редактор. Вот он, опыт!
    3) Получаем верхнюю и нижнюю границы температур, затем получаем те самые "коэффициенты" для проекций на оси
    4) Рисование на компоненте — очень простая часть. Если рисуем первую точку — рисуем только точку и подпись о температуре, если рисуем НЕ первую — рисуем линию между предыдущей и текущей точками. Ну и плюс всякие визуальные прикольчики, аля отступы от краев, чтобы видно было текст.
    image
    Вау! Это что такое — реально график? Прямо в редакторе кода? Который реактивно обновляется если поменять температуру или время? Вау!
    Тем не менее, сейчас у нас захардкожены ширина и высота графика, а так же мы не можем выбрать единицы измерения.
    Самое время сейчас заменить везде наши захардкоженные "°C", "°F" на enumeration datatype. Думаю, объяснять суть enumeration не стоит, только в контексте MPS.
    enumeration datatype — это простой enum class, который может быть использован в property.
    Если раньше мы использовали только string, integer и _FPNumber_String, то теперь мы можем создать enum для единиц измерения температур, в котором будет 2 элемента: цельсий и фаренгейт.
    ПКМ на WeatherPrediction.structure -> New -> Enum Data Type -> TemperatureUnit.
    image
    Выбираем тип, в данном случае string
    Нам нужно дефолтное значение, так что оставляем false в no default
    default = first member(celsius)
    member identifier — отвечает за определение элемента по входным данным. Чтобы изменить значение TemperatureUnit, нужно подать на вход строку, которая сравнивается с каждым внутренним или внешним значением, смотря какое выбрать.
    Поясняю: то, что слева и синенькое — внутренее значением элемента enum. Оно скрыто. Справа — внешнее, оно используется для отображения в редакторе.
    То есть если мы в member identifier выберем derive from internal value, то задавать значение нам придется либо celsius, либо fahrenheit. А если мы выберем derive from presentation, то задавать значение придется строками °C или °F. Еще можно добавить кастомную идентификацию, например, чтобы можно было задавать значение по внутреннему и внешнему значению, но это уже сами, нам не нужно.
    Выбираем derive from presentation и добавляем 2 элемента.
    Четко!
    Добавляем свойство unit в PredictionResult.
    image
    Теперь нужно добавить выпадающий список, в котором мы будем выбирать единицу измерения.


    string[] units = enum/TemperatureUnit/.members.select({~it => it.externalValue; }).toArray; 
    final ModelAccess modelAccess = editorContext.getRepository().getModelAccess(); 
    final JComboBox box = new JComboBox(units); 
    box.addActionListener(new ActionListener() { 
    public void actionPerformed(ActionEvent p0) { 
    modelAccess.executeCommand(new EditorCommand(editorContext) { 
      protected void doExecute() { 
        Object selectedItem = box.getSelectedItem(); 
        node.unit = selectedItem.toString(); 
      } 
    }); 
    } 
    }); 
    box.setSelectedIndex(0); 
    box;



    Это код для другого $swing component$ в коде редактора PredictionResult. Мы получаем список возможных единиц измерения температуры, создаем выпадающий список, вешаем обработчик события. Здесь тоже используется "прикол MPS", вместо readAction или writeAction можно просто executeCommand. Видимо, 2 предыдущих существуют для читаемости.
    При изменении выбранного элемента из JComboBox меняется node.unit, который задается строковым значением, как я объяснял выше.
    Собираем язык, смотрим.
    image
    Можете мне поверить, там действитетельно выпадает еще и фаренгейт. Осталось только связать JComboBox и график, и на этом можно будет закончить, а сделать это будет легко.
    Привожу оригинальный код отрисовки графика.


    Захардкоженные единицы измерения
    { 
      public void run() { 
        string unit = "°C"; 
        final list labels = node.input.items.select({~it => 
          double x = it.time.hours * 60 + it.time.minutes; 
          double y = it.temperature.getValueFromUnit(unit.toString()); 
          new Point2D.Double(x, y); 
        }).sortBy({~it => it.x; }, asc).toList; 
        final double minTemp = labels.sortBy({~it => it.y; }, asc).first.y; 
        final double maxTemp = labels.sortBy({~it => it.y; }, asc).last.y; 
    
        final double yKoef = chartHeight / (maxTemp - minTemp); 
        final double xKoef = chartWidth / (60.0 * 24.0); 
        int prevY = chartHeight; 
        int prevX = -1; 
    
        Graphics2D g2 = ((Graphics2D) graphics); 
        labels.forEach({~it => 
          message debug unit + "/" + it.y, , ; 
          int xTranslated = (int) (it.x * xKoef); 
          int yTranslated = chartHeight - (int) ((it.y - minTemp) * yKoef); 
          g2.setStroke(new BasicStroke(1)); 
          if (prevX > 0) { 
            // It is first element, no need to draw trailing line 
            g2.drawLine(prevX, prevY, xTranslated, yTranslated); 
          } 
          g2.drawString(String.format("%.2f", it.y) + unit, xTranslated + 3, chartHeight - Math.abs(chartHeight - (yTranslated + 20))); 
          g2.setStroke(new BasicStroke(5)); 
          g2.drawLine(xTranslated, yTranslated, xTranslated, yTranslated); 
    
          prevX = xTranslated; 
          prevY = yTranslated; 
        }); 
    
      } 
    }

    Да, смекаете? Нам нужно только заменить string unit = "°C"; на string unit = node.unit; и мы гучи!
    А теперь итог: график в цельсиях и фаренгейтах, уаа!
    image
    image


    P.S.
    Я думаю именно в этой статье очень много опечаток, расхождений, потому что я много отвлекался, как минимум на то, чтобы реализовать то, что хотел поведать в этой статье. Что ни день, то открытие, поэтому, пожалуйста, пишите в комментах все моменты, которые вам кажутся странными, скорее всего это я выпал из контекста повествования и написал какую-то ересь.
    В следующей статье мы рассмотрим такой аспект, как TextGen. Будем генерировать прогноз погоды в текстовую форму!

Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/334672/


Метки:  

Математический пакет для Android — «Микро-Математика» — теперь с открытым исходным кодом

Среда, 02 Августа 2017 г. 00:16 + в цитатник

Некоторое время назад я писал здесь о «Микро-Математике» — математическом пакете для Android, который я разработал в качестве хобби-поделки. Этим летом исполняется три года с тех пор, как «Микро-Математика» была выложена в Google Play на всеобщее обозрение. С тех пор программа развивалась дальше, и вот настал момент, когда доход от Google Play окупил разработку. В связи с этим я не вижу смысла дальше утаивать исходный код от общественности и перевожу проект в разряд Open Source. Тех, кому интересно познакомиться с репозиторием «Микро-Математики» на github, и, быть может, поучаствовать в дальнейшем развитии проекта, прошу под кат.


Я не буду повторять здесь содержание предыдущей статьи — идеология, ядро и базовый функционал приложения с тех пор не изменились. Естественно, за три года добавилось много новых возможностей. Выделю наиболее важные, на мой взгляд:


  • Реализован функциональный файловый менеджер, который поддерживает не только SD-карту, но и доступ к ресурсам приложения. За основу взято ядро достаточно известного файлового менеджера «Ghost Commander»
    Окно файлового менеджера


  • В ресурсах приложения теперь содержится большая библиотека примеров.
    Если у тех, кто пользуется этим приложением, есть интересные примеры вычислений, и вы не против поделиться ими с общественностью, высылайте их мне по почте, я с удовольствием включу их в эту библиотеку.
    Окно выбора примера


  • Теперь приложение может работать с комплексными числами:
    Пример расчёта с комплексными чмслами


  • Кроме этого, добавлена поддержка массивов, использование которых позволяет значительно ускорить расчёт
    Пример расчёта с использованием массивов


  • Появился экспорт документа в формате HTML, после чего его можно открыть в браузере, например, на ПК:
    Экспортированный документ на ПК


  • Добавлена возможность автоматического тестирования математического ядра. Модуль-тестировщик встроен в приложение, он позволяет прогонять скрипты, имеющие специальный синтаксис и контролировать результаты вычислений. На сегодня разработаны 30 скриптов, которые содержат более 250 тестов, покрывающих все вычислительные алгоритмы.

Github репозиторий находится тут. Лицензия — GNU General Public License v3.0.


Так уж исторически сложилось, что вся разработка у меня происходит под Linux, и, стыдно сказать, до сих пор в Eclipse. Но я открыт к альтернативным рабочим окружениям, так что если кто-то захочет запуллить конвертацию служебных скриптов под Windows, или проектные файлы для Android Studio — буду только рад.


На текущий момент в репозитории содержится как весь исходный код и SVG-исходники всех иконок приложения, так и некоторые вспомогательные вещи:


  • src: папка с исходниками. Там можно найти: сами исходники, шаблон форматирования для Eclipse, а также в папке src/assets документацию, библиотеку примеров и скрипты автоматического тестирования
  • images: SVG-исходники иконок и шелл-скрипты для их конвертации в PNG-ресурсы. Для работы скриптов необходим установленный Inkscape.
  • thirdParty: архивы всех использованных библиотек.
  • release: собранный, но не подписанный APK. Там же находится архив с результатами автоматического тестирования
  • autotest: служебные скрипты для генерации тестовых виртуальных машин и для прогона на них тестов.

За последнее время я получил много пожеланий по дальнейшему развитию приложения. Среди них могу выделить такие, как:


  • Экспорт в PDF
  • Матричные вычисления
  • Циклы, как, например, это реализовано в Matcad
  • Улучшение редактирования: перетаскивание формул пальцем, более удобный доступ к палитре мат. символов.
  • Внедрение пакетной системы для группировки мат. функционала: например, опциональные пакеты по обработке сигналов, статистике, специальные функции.
  • Я уже использую библиотеку «The Apache Commons Mathematics Library», где есть модуль символьных вычислений. Неплохо было бы его задействовать.

Для одного человека работы многовато, поэтому приглашаю к сотрудничеству всех энтузиастов, кто интересуется математикой, алгоритмами, численными методами и т.д. Спасибо за внимание!

Как часто Вы присоединяетесь к чужим Open Source проектам?

Проголосовало 14 человек. Воздержалось 7 человек.

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/334670/


Метки:  

Как сделать простое «главное меню» для игры в Unreal Engine 4

Вторник, 01 Августа 2017 г. 23:26 + в цитатник

Метки:  

Работа с сервлетами для чайников. GET / POST

Вторник, 01 Августа 2017 г. 23:20 + в цитатник


В прошлой статье Создание сервлетов для чайников. Пошаговое руководство я описал, как создать сервлеты и попытался объяснить, как это работает. В этой статье мы научим наши сервлеты работать с UI через HTTP-запросы GET и POST.

На самом деле, этих запросов намного больше, но для чистоты эксперимента мы разберём только два основных.

  • GET — обрабатывает адресную строку, которая получается при вызове сервлета. Например, site.com/example?action=test&id=10&admin=true
  • POST — обрабатывает загруженный контент (картинку, файл, строки, объектные данные


В Java-сервлете запросы POST и GET обрабатывают соответствующие методы doPost(); и doGet().

Для чистоты объяснения принципов обработки запросов мы создадим:

  • простой объект класса Bot, который будет иметь имя, серийник и id
  • страницу, на которую мы будем выводить данные объекта
  • страницу, на которой мы будем менять данные объекта
  • сервлет, который будет обрабатывать соответствующие запросы

Создаём класс Bot с тремя полями, а также, геттерами, сеттерами и перегруженным toString():

package ru.javawebinar.topjava.model;

/**
 * Класс Bot.
 * 
 * Created by promoscow on 26.07.17.
 */
public class Bot {
    private Integer id;
    private String name;
    private String serial;

    public Bot(String name, String serial, Integer id) {
        this.name = name;
        this.serial = serial;
        this.id = id;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSerial() {
        return serial;
    }

    public void setSerial(String serial) {
        this.serial = serial;
    }

    @Override
    public String toString() {
        return "Bot{" +
                "id=" + id +
                ", name='" + name + ''' +
                ", serial=" + serial +
                '}';
    }
}


Пометим сервлет в xml-документе web.xml:


        botServlet
        web.BotServlet
        0
    
    
        botServlet
        /bot
    


Пишем вот такую страницу bot.jsp (пока просто копируем, потом разберём):






    


Bot info

ID: ${bot.id} | Name: ${bot.name} | Serial number: ${bot.serial} Update


Эта страница выводит нам данные бота.
Строчка
обрабатывает аргумент «bot», при чём мы даём понять, что это объект класса Bot. ${bot.name} и прочие подобные — это переменные, которые мы берём из полученного в аргументе объекта (это будет в сервлете).
Отметим, что ссылка Update переводит на адрес bot?action=update содержит данные для GET-запроса.

Также, у нас будет страница, которая отправляет изменённые данные бота (update.jsp):





    


ID:
Name:
Serial number:


Мы также получаем данные бота и вставляем их в поля, меняем их и отправляем изменённые данные в POST-запросе. Отметим, что POST-запрос инициируется через отправку формы
, где method=«post» означает, что данные формы попадут в POST, а action=«bot?action=submit» означает, что после отправки формы произойдёт переход по адресу bot?action=submit

Разберём для наглядности одно поле формы:

По нажатию кнопки Save все введённые данные будут отправлены в метод doPost() нашего сервлета. В данной строчке, мы задаём новый id.

Имя атрибута формы: «id» (name=«id»), значение, которое мы передадим — поле id объекта bot (${bot.id}), также, мы вносим в поле имеющееся значение, полученное в атрибуте «bot» (placeholder="${bot.id}).

Поскольку задачей этой статьи является описание работы POST- и GET-запросов, я объясняю смысл кода строк вскользь. Более подробно атрибуты страниц можно изучить в Справочнике по HTML.

Ну и давайте добавим самую примитивную страницу index.html, содержащую единственную ссылку на страницу bot:



    
    






Мы закончили с jsp / html и можем перейти, наконец, к моему любимому Java-коду.

BotServlet.java:

import model.Bot;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Bot Servlet class.
 *
 * Created by promoscow on 26.07.17.
 */
public class BotServlet extends HttpServlet {

    Bot bot;

    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init();

        bot = new Bot("Amigo", "228274635", 1);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("Enter doGet");

        String action = request.getParameter("action");
        request.setAttribute("bot", bot);
        switch (action == null ? "info" : action) {
            case "update":
                request.getRequestDispatcher("/update.jsp").forward(request, response);
                break;
            case "info":
            default:
                request.getRequestDispatcher("/bot.jsp").forward(request, response);
                break;
        }
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("Enter doPost");

        request.setCharacterEncoding("UTF-8");
        String action = request.getParameter("action");

        if ("submit".equals(action)) {
            bot.setId(Integer.parseInt(request.getParameter("id")));
            bot.setName(request.getParameter("name"));
            bot.setSerial(request.getParameter("serial"));
        }

        request.setAttribute("bot", bot);
        request.getRequestDispatcher("/bot.jsp").forward(request, response);
    }
}


Сервлет содержит 3 метода: init(), doGet() и doPost().

init() — вызывается при первой инициализации сервлета и единожды исполняет написанный в нём код. В нашем случае, создаётся экземпляр класса Bot.

doGet() — обрабатывает запрос GET.

doPost() — обрабатывает запрос POST.

Теперь мы по цепочке пройдём логику выполнения приложения и разберём, что как работает.

Итак, загружаем проект в Tomcat. Перед нами — одинокая ссылка «Bot». Нажимаем её.

Мы переходим в сервлет BotServlet. Метод doGet() исполняется всегда (ведь адресная строка есть всегда), метод doPost() исполняется только по запросу (у нас он есть —


@Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //просто выводим в консоль, что мы заходили в метод doGet
        System.out.println("Enter doGet");

        //здесь мы уже начинаем работать с адресной строкой. в ссылке "bot?action=update" (bot.jsp, 20 строчка) после вопросительного знака идут пары ключ-значение, разделённые знаком &. у нас есть пара action=update. Вызываем значение (параметр) по ключу action, у нас это update и заносим результат в String.
        String action = request.getParameter("action");

        //загодя вносим в запрос атрибут, при исполнении сервлета он будет отправлен в целевую строку. атрибут вносится вместе с ключом. в нашем случае, мы вносим объект bot со всеми его полями как атрибут и задаём ключ "bot", по которому мы потом вызовем данные объекта в jsp-странице
        request.setAttribute("bot", bot);

        switch (action == null ? "info" : action) {
            //если параметр имеет значение update (action=update), мы отправляемся на строку /update.jsp, где будем изменять данные бота (и отправляем туда атрибут bot)
            case "update":
                request.getRequestDispatcher("/update.jsp").forward(request, response);
                break;
            //если параметр пустой (action == null ? "info"), отправляемся на страницу bot.jsp, где мы увидим данные бота (и по дефолту тоже)
            case "info":
            default:
                request.getRequestDispatcher("/bot.jsp").forward(request, response);
                break;
        }
    }


Как видите, метод doGet() работает с адресной строкой, извлекает из неё атрибуты и обрабатывает их. Инструментарий метода doGet() велик, например, в строке может содержаться ?action=update&id=23847&admin=true (к примеру), мы можем извлечь id, отправить на доработку робота с полем id, равным 23847 и сделать его админом.

Поскольку в index.html атрибут адресной строки по ссылке имеет значение update, мы исполняем эту часть кода doGet():

request.setAttribute("bot", bot);
request.getRequestDispatcher("/update.jsp").forward(request, response);


— добавляем атрибут с объектом bot и ключом «bot» и отправляем всё это на страницу /update.jsp

В странице update.jsp мы вносим новые значения в формы, соответствующие полям класса Bot и отправляем всё по адресу «bot?action=submit». Повторю — в этой статье не ставится задача разбирать тэги jsp/html, для этого есть Справочник по HTML.

Итак, мы нажимаем кнопку «Save». Поскольку форма содержит method=«post» action=«bot?action=submit», мы обрабатываем данные, полученные в форме, в методе doPost(). В этом методе можно как обрабатывать входящие данные, так и извлекать атрибуты адресной строки.

@Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("Enter doPost");

        //правилом хорошего кода будет задать кодировку UTF-8 — в метод могут приходить параметры, скажем, на кириллице (опять же, мы можем дать нашему боту кириллическое имя)
        request.setCharacterEncoding("UTF-8");

        //извлекаем значение параметра action и сохраняем в Stiring, как мы это делали в методе doGet()
        String action = request.getParameter("action");

        //если action=submit, назначаем нашему боту новые значения, которые мы получили в метод. это делается также, извлекая параметры. у каждого параметра из формы есть своё имя, по этому имени мы извлекаем значение (например, в разбираемой выше строчке формы update.jsp name="id" value=${bot.id} мы задаём нашему боту новый id, извлекая его в строчке bot.setId(Integer.parseInt(request.getParameter("id")));
        if ("submit".equals(action)) {
            bot.setId(Integer.parseInt(request.getParameter("id")));
            bot.setName(request.getParameter("name"));
            bot.setSerial(request.getParameter("serial"));
        }

        //опять запихиваем объект bot в атрибут и возвращаемся на страницу /bot.jsp, где наблюдаем изменения
        request.setAttribute("bot", bot);
        request.getRequestDispatcher("/bot.jsp").forward(request, response);
    }


Вот и вся статья. Мы отработали в сервлете запросы POST и GET через соответствующие методы doPost() и doGet().

Целью статьи является создание понимания у начинающих разработчиков JavaEE, как работают запросы в сервлетах и по какой логике выстраивается работа с этими запросами в Java-коде.

Это вторая моя статья на тему сервлетов, запуск первого сервлета мы разбирали в статье Создание сервлетов для чайников. Пошаговое руководство
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/334138/


Метки:  

Тематическое моделирование средствами BigARTM

Вторник, 01 Августа 2017 г. 21:45 + в цитатник

Введение


Обратил внимание на перевод публикации под названием «Тематическое моделирование репозиториев на GitHub» [1]. В публикации много теоретических данных и очень хорошо описаны темы, понятия, использование естественных языков и многие другие приложения модели BigARTM.

Однако, обычному пользователю без знаний в области тематического моделирования для практического использования достаточно знаний интерфейса и чёткой последовательности действий при подготовке текстовых исходных данных.Разработке прогамного обеспечения для подготовки текстовых данных и выбору среды разработки и посвящена данная публикация.

Установка BigARTM в Windows и подготовка исходных данных


Установка BigARTM хорошо изложена в видео презентации [2], поэтому я на ней останавливаться не буду, отмечу только что приведенные в документации программы рассчитаны на определённую версию и на скаченной версии могут не работать. В статье используется версия_v 0.8.1.

Программа BigARTM работает только на Python 2.7. Поэтому для создания единого программного комплекса все вспомогательные программы и примеры написаны на Python 2.7, что привело к некоторому усложнению кода.

Текстовые данные для тематического моделирования должны пройти обработку в соответствии со следующими этапами [4].

  1. Лемматизация или стемминг;
  2. Удаление стоп-слов и слишком редких слов;
  3. Выделение терминов и словосочетаний.


Рассмотрим как можно реализовать на Python указанные требования.

Что лучше применять: лемматизацию или стемминг?


Ответ на этот вопрос мы получим из следующего листинга, в котором в качестве примера использован первый абзац текста из статьи [5]. Здесь и дальше части листинга и результат их работы буду представлять как они выводятся в формате среды jupyter notebook.

Листинг лемматизации с lemmatize
# In[1]:
#!/usr/bin/env python
# coding: utf-8
# In[2]:
text=u' На практике очень часто возникают задачи для решения\
которых используются методы оптимизации в обычной жизни при \
множественном выборе  например подарков к новому году мы интуитивно \
решаем задачу минимальных затрат при заданном качестве покупок '
# In[3]:
import time
start = time.time()
import pymystem3
mystem = pymystem3 . Mystem ( )
z=text.split()
lem=""
for i in range(0,len(z)):
         lem =lem + " "+ mystem. lemmatize (z[i])[0]
stop = time.time()
print u"Время, затраченное lemmatize- %f на обработку %i слов "%(stop - start,len(z))


Результат роботы листинга по лемматизации.

на практика очень часто возникать задача для решение который использоваться метод оптимизация в обычный жизнь при множественный выбор например подарок к новый год мы интуитивно решать задача минимальный затрата при задавать качество покупка
Время, затраченное lemmatize — 56.763000 на обработку 33 слов

Листинг стемминга с stemmer NLTK
#In [4]:
start = time.time()
import nltk
from nltk.stem import  SnowballStemmer
stemmer = SnowballStemmer('russian')
stem=[stemmer.stem(w) for w in text.split()]
stem= ' '.join(stem)
stop = time.time()
print u"Время, затраченное stemmer NLTK- %f на обработку %i слов "%(stop - start,len(z))



Результат роботы листинга.

на практик очен част возника задачи, для решен котор использ метод оптимизац в обычн жизн при множествен выборе, например, подарк к нов год мы интуитивн реша задач минимальн затрат при зада качеств покупок
Время, затраченное stemmer NLTK- 0.627000 на обработку 33 слов

Листинг стемминга с модулем Stemmer
#In [5]:
start = time.time()
from Stemmer import Stemmer
stemmer = Stemmer('russian')
text = ' '.join( stemmer.stemWords( text.split() ) )
stop = time.time()
print u"Время, затраченное Stemmer- %f на обработку %i слов"%(stop - start,len(z))



Результат роботы листинга

на практик очен част возника задачи, для решен котор использ метод оптимизац в обычн жизн при множествен выборе, например, подарк к нов год мы интуитивн реша задач минимальн затрат при зада качеств покупок
Время, затраченное Stemmer- 0.093000 на обработку 33 слов

Вывод

Когда время на подготовку данных для тематического моделирования не критично, следует применять лемматизацию при помощи модулей pymystem3 и mystem, в противном случаи следует применить стемминг при помощи модуля Stemmer.

Где взять список стоп-слов для их последующего удаления?


Стоп-слова по определению слова не несущих смысловой нагрузки. Список таких слов нужно составлять с учётом специфики текста, однако должна быть основа. Основу можно получить при помощи корпуса brown.

Листинг получения stop-words
#In [6]:
import nltk
from nltk.corpus import brown
stop_words= nltk.corpus.stopwords.words('russian')
stop_word=" "
for i in stop_words:
        stop_word=  stop_word+" "+i
print stop_word



Результат роботы листинга.

и в во не что он на я с со как а то все она так его но да ты к у же вы за бы по только ее мне было вот от меня еще нет о из ему теперь когда даже ну вдруг ли если уже или ни быть был него до вас нибудь опять уж вам ведь там потом себя ничего ей может они тут где есть надо ней для мы тебя их чем была сам чтоб без будто чего раз тоже себе под будет ж тогда кто этот того потому этого какой совсем ним здесь этом один почти мой тем чтобы нее сейчас были куда зачем всех никогда можно при наконец два об другой хоть после над больше тот через эти нас про всего них какая много разве три эту моя впрочем хорошо свою этой перед иногда лучше чуть том нельзя такой им более всегда конечно всю между

Получить список стоп-слов можно и в сетевом сервисе [6] по заданному тексту.

Вывод

Рационально сначала использовать основу стоп-слов, например, из корпуса brown и уже после анализа результатов обработки изменять или дополнять список стоп-слов.

Как выделить из текста термины и ngram?


В публикации [7] для тематического моделирования с применением программы BigARTM рекомендуют «После лемматизации по коллекции можно собирать n-граммы. Биграммы можно добавлять в основной словарь, разделив слова специальным символом, отсутствующим в Ваших данных:
  • русский_общение;
  • украинский_родной;
  • засылать_казачок;
  • русский_больница
»

Приводим листинг для выделения из текста bigrams, trigrams, fourgrams, fivegrams.
Листинг адаптирован под Python 2.7.10 и настроен на выделение bigrams, trigrams,fourgrams ,fivegrams из текста.В качестве специального символа использован — "_".

Листинг получения bigrams,trigrams, fourgrams , fivegrams
#In [6]:
#!/usr/bin/env python
# -*- coding: utf-8 -*
from __future__ import unicode_literals
import nltk
from nltk import word_tokenize
from nltk.util import ngrams
from collections import Counter
text = "На практике очень часто возникают задачи для решения которых используются методы\ оптимизации в обычной жизни при множественном выборе  например подарков к новому\
году мы интуитивно решаем задачу минимальных затрат при заданном качестве покупок"
#In [7]:
token = nltk.word_tokenize(text)
bigrams = ngrams(token,2)
trigrams = ngrams(token,3)
fourgrams = ngrams(token,4)
fivegrams = ngrams(token,5)
#In [8]:
for k1, k2 in Counter(bigrams):
         print (k1+"_"+k2)
#In [9]:
for k1, k2,k3 in Counter(trigrams):
         print (k1+"_"+k2+"_"+k3)
#In [10]:
for k1, k2,k3,k4 in Counter(fourgrams):
         print (k1+"_"+k2+"_"+k3+"_"+k4)
#In [11]:
for k1, k2,k3,k4,k5 in Counter(fivegrams):
         print (k1+"_"+k2+"_"+k3+"_"+k4+"_"+k5)



Результат роботы листинга.Для сокращения привожу только по одному значению из каждой ngram.

bigrams — новому_году
trigrams — заданном_качестве_покупок
fourgrams — которых_используются_методы_оптимизации
fivegrams- затрат_при_заданном_качестве_покупок

Вывод

Приведенную программу можно использовать для выделения устойчиво повторяющихся в тексте NGram учитывая каждую как одно слово.

Что должна содержать программа для подготовки текстовых данных к тематическому моделированию ?


Чаще копии документов располагают по одному в отдельном текстовом файле. При этом исходными данными для тематического моделирования является так называемый «мешок слов», в котором слова, относящиеся к определённому документу, начинаются с новой строки после тега -|text.

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

Для ускорения моделирования, после каждого слова через двоеточие указывается частота его употребления в данном документе.

Исходными данными для тестирования программы были 10 статей из Википедии. Названия статей следующие.
  1. География
  2. Математика
  3. Биология
  4. Астрономия
  5. Физика
  6. Химия
  7. Ботаника
  8. История
  9. Физиология
  10. Информатика


Листинг получения готового для моделирования текста
#In [12]:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
import codecs
import os
import nltk
import numpy as np
from nltk.corpus import brown
stop_words= nltk.corpus.stopwords.words('russian')
import pymystem3
mystem = pymystem3.Mystem()
path='Texts_habrahabr'
f=open('habrahabr.txt','a')
x=[];y=[]; s=[]
for i in range(1,len(os.listdir(path))+1): #перебор файлов с документами по номерам i
      filename=path+'/'+str(i)+".txt"
      text=" "      
      with codecs.open(filename, encoding = 'UTF-8') as file_object:# сбор текста из файла i-го документа             
            for line in file_object:
                  if len(line)!=0:
                        text=text+" "+line                        
      word=nltk.word_tokenize(text)# токинезация текста i-го документа      
      word_ws=[w.lower()  for w in   word if w.isalpha() ]#исключение слов и символов      
      word_w=[w for w in word_ws if w not in stop_words ]#нижний регистр  
      lem = mystem . lemmatize ((" ").join(word_w))# лемматизация i -го документа
      lema=[w for w in lem if w.isalpha() and len(w)>1]
      freq=nltk.FreqDist(lema)# распределение слов в i -м документе по частоте
      z=[]# обновление списка для нового документа
      z=[(key+":"+str(val)) for key,val in freq.items() if val>1] # частота упоминания через : от слова    
      f.write("|text" +" "+(" ").join(z).encode('utf-8')+'\n')# запись в мешок слов с меткой |text          
      c=[];d=[]
      for key,val in freq.items():#подготовка к сортировке слов по убыванию частоты в i -м документе
            if val>1:
                  c.append(val); d.append(key)
      a=[];b=[]    
      for k in np.arange(0,len(c),1):#сортировка слов по убыванию частоты в i -м документе 
            ind=c.index(max(c));  a.append(c[ind])
            b.append(d[ind]); del c[ind]; del d[ind]
      x.append(i)#список номеров документов
      y.append(len(a))#список количества слов в документах     
      a=a[0:10];b=b[0:10]# TOP-10 для частот a  и слов b в i -м документе    
      y_pos = np.arange(1,len(a)+1,1)#построение TOP-10 диаграмм      
      performance =a
      plt.barh(y_pos, a)
      plt.yticks(y_pos, b)
      plt.xlabel(u'Количество слов')
      plt.title(u'Частоты слов в документе № %i'%i, size=12)
      plt.grid(True)
      plt.show()         
plt.title(u'Количество слов в документах', size=12)
plt.xlabel(u'Номера документов', size=12)
plt.ylabel(u'Количество слов', size=12)
plt.bar(x,y, 1)
plt.grid(True)
plt.show()
f.close()  



Результат роботы листинга по генерации вспомогательных диаграмм.Для сокращения привожу только одну диаграмму для TOP-10 слов из одного документа и одну диаграмму распределение слов по документам.


В результате работы программы мы получили десять диаграмм на которых отобраны по частоте употребления 10 слов.Кроме этого программа строит диаграмму распределения количества слов по документам. Это удобно для предварительного анализа исходных данных.При большом количестве документов частотные диаграммы можно сохранять в отдельной папке.

Результат роботы листинга по генерации «мешка слов».Для сокращения привожу данные из созданного текстового файла habrahabr.txt только по первому документу.

|text земной:3 кругом:2 страна:4 перекипелый: 2 человек:2 традиция:2 строение:2 появление:2 некоторый:2 имя:2 первый:4 создавать:2 находить:2 греческий:3 иметь:4 форма:2 ii:2 обитаемый:4 содержать:3 река:4 восточный:2 море:6 место:2 эратосфен:3 сведение:2 вид:3 геродот:3 смысл:4 картография:2 известный:2 весь:2 воображать:2 немало:2 наука:4 современный:2 достижение:2 период:2 шар:3 определение:2 предположение:2 закладывать:2 представление:7 составлять:3 изображать:2 страбометр:3 термин:2 круглый:7 употребляться:2 берег:2 южный:2 координата:2 земля:16 посвящать:2 доходить:2 карта:7 дисциплина:2 меридиан:2 диск:2 аристотель:4 должный:2 описание:6 отдельный:2 географический:12 оно:2 окружать:3 анаксимандра:2 название:8 тот:2 автор:2 сочинение:3 древний:8 поздний:4 опыт:2 птолемей:2 география:10 время:3 труд:2 также:6 объезд:3 свой:2 подходить:2 круг:2 омывать:3 средиземное:2 греков:2 китай:2 век:6 ее:2 океан:3 северный:2 сторона:2 эпоха:3 внутренний:2 плоский:2 красный:2 аррианин:2 который:8 другой:2 пользоваться:3 этот:5 основа:3 жить:2

Была использована одна текстовая модальность обозначенная в начале каждого документа как |text. После каждого слова через двоеточие введено число его употребления в тексте. Последнее ускоряет как процесс создания batch так и заполнение словаря.

Как можно упростить работу с BigARTM для создания и анализа topic ?



Для этого нужно во первых готовить текстовые документы и проводить их анализ с использованием предложных программных решений, а во вторых использовать среду разработки jupyter notebook.



В директории notebooks размещаются все необходимые для работы программы папки и файлы.
Части программного кода отлаживаются в отдельных файлах и после отладки собираются в общий файл.

Предложенная подготовка текстовых документов позволяет провести тематическое моделирование на упрощённом варианте BigARTM без регуляризаторов и фильтров.

Листинг для создания batch
#In [1]:
#!/usr/bin/env python
# -*- coding: utf-8 -*
import artm
# создание частотной матрицы из batch
batch_vectorizer = artm.BatchVectorizer(data_path='habrahabr.txt',# путь к "мешку слов"
                                        data_format='vowpal_wabbit',# формат данных
                                       target_folder='habrahabr', #папка с частотной матрицей из batch
                                        batch_size=10)# количество документов в одном batch




Из файла habrahabr.txt программа в папке habrahab создаёт один batch из десяти документов, количество которых приведено в переменной batch_size=10. Если данные не изменяются и частотная матрица уже создана, то указанную выше часть программы можно пропустить.

Листинг для заполнения словаря и создания модели
#In [2]:
batch_vectorizer = artm.BatchVectorizer(data_path='habrahabr',data_format='batches')
dictionary = artm.Dictionary(data_path='habrahabr')# загрузка данных в словарь
model = artm.ARTM(num_topics=10,
                  num_document_passes=10,#10 проходов по документу
                  dictionary=dictionary,
                  scores=[artm.TopTokensScore(name='top_tokens_score')])
model.fit_offline(batch_vectorizer=batch_vectorizer, num_collection_passes=10)#10 проходов по коллекции
top_tokens = model.score_tracker['top_tokens_score']



Программа BigARTM после загрузки данных в словарь dictionary генерирует 10 тем (по числу документов), количество которых приведено в переменной num_topics=10.Количество проходов по документу и по коллекции указаны в переменных num_document_passes=10, num_collection_passes=10.

Листинг для создания и анализа topics
#In [3]:
for topic_name in model.topic_names:
    print (topic_name)
    for (token, weight) in zip(top_tokens.last_tokens[topic_name],
                               top_tokens.last_weights[topic_name]):    
         print token, '-', round(weight,3)


Результат роботы программы BigARTM
topic_0
растение — 0.088
ботаника — 0.032
век — 0.022
мир — 0.022
линней — 0.022
год — 0.019
который — 0.019
развитие — 0.019
аристотель — 0.019
природа — 0.019
topic_1
астрономия — 0.064
небесный — 0.051
тело — 0.046
задача — 0.022
движение — 0.018
изучать — 0.016
метод — 0.015
звезда — 0.015
система — 0.015
который — 0.014
topic_2
земля — 0.049
географический — 0.037
география — 0.031
древний — 0.025
который — 0.025
название — 0.025
представление — 0.022
круглый — 0.022
карта — 0.022
также — 0.019
topic_3
физика — 0.037
физический — 0.036
явление — 0.027
теория — 0.022
который — 0.022
закон — 0.022
общий — 0.019
новый — 0.017
основа — 0.017
наука — 0.017
topic_4
изучать — 0.071
общий — 0.068
раздел — 0.065
теоретический — 0.062
вещество — 0.047
видимый — 0.047
физический — 0.044
движение — 0.035
гипотеза — 0.034
закономерность — 0.031
topic_5
физиология — 0.069
щитовидный — 0.037
человек — 0.034
организм — 0.032
латы — 0.03
артерия — 0.025
железа — 0.023
клетка — 0.021
изучать — 0.021
жизнедеятельность — 0.018
topic_6
математика — 0.038
клетка — 0.022
наука — 0.021
организм — 0.02
общий — 0.02
который — 0.018
математический — 0.017
живой — 0.017
объект — 0.016
ген — 0.015
topic_7
история — 0.079
исторический — 0.041
слово — 0.033
событие — 0.03
наука — 0.023
который — 0.023
источник — 0.018
историография — 0.018
исследование — 0.015
философия — 0.015
topic_8
термин — 0.055
информатика — 0.05
научный — 0.031
язык — 0.029
год — 0.029
наука — 0.024
информация — 0.022
вычислительный — 0.017
название — 0.017
science — 0.014
topic_9
век — 0.022
который — 0.022
наука — 0.019
химический — 0.019
вещество — 0.019
химия — 0.019
также — 0.017
развитие — 0.017
время — 0.017
элемент — 0.017
Полученные результаты в целом отвечают темам и результат моделирования можно считать удовлетворительным. При необходимости в программу можно добавить регуляризаторы и фильтры.

Выводы по результатам работы


Мы рассмотрели все этапы подготовки текстовых документов к тематическому моделированию. На конкретных примерах провели простой сравнительный анализ модулей для лемматизации и стемминга. Рассмотрели возможность использования NLTK для получения списка стоп-слов и поиска словосочетаний для русского языка. Рассмотрены листинги, написанные на Python 2.7.10 и адаптированные для русского языка, что позволяет их интегрировать в единый прогамный комплекс. Разобран пример тематического моделирования в среде jupyter-notebook, которая предоставляет дополнительные возможности для работы с BigARTM.

Используемые ссылки

1. Тематическое моделирование репозиториев на GitHub. https://habrahabr.ru/post/312596/
2. Lecture 49 — Установка BigARTM в Windows https://www.coursera.org/learn/unsupervised-
learning/lecture/qmsFm/ustanovka-bigartm-v-windows

3. bigartm/bigartm https://github.com/bigartm/bigartm/releases
4. Основы обработки текстов. http://docplayer.ru/40376022-Osnovy-obrabotki-tekstov.html
5. Решение задач линейного программирования с использованием Python.
https://habrahabr.ru/post/330648/
6. Испытываем новый алгоритм проверки. Вопросы и предложения https://glvrd.ru/
7. Использование библиотеки для тематического моделирования BigARTM.
http://www.machinelearning.ru/wiki/images/f/f5/MelLain_Python_API_slides.pdf
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/334668/


Метки:  

Поиск сообщений в rss_rss_hh_new
Страницы: 1437 ... 1076 1075 [1074] 1073 1072 ..
.. 1 Календарь