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

Поиск сообщений в 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 ленты.
По всем вопросам о работе данного сервиса обращаться со страницы контактной информации.

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

Let’s Encrypt: раздаем видео по HTTPS в один клик

Понедельник, 17 Июля 2017 г. 15:32 + в цитатник
image
Что такое Let's Encrypt знает, наверное, каждый читатель Хабрахабра, ведь опубликовано уже более 100 статей на эту тему. Большая часть из них, это инструкции по установке и настройке: какой пакет установить, какие строчки конфига поправить, какой скрипт разместить в crontab, как завести это очередном веб-сервере и автоматизировать для docker и прочих модных технологий.

В нашем продукте — Flussonic, мы сделали, пожалуй, самый простой способ настройки Let's Encrypt, не требующий правки конфигов, просто нажатием кнопки «Сделай мне HTTPS».


Справка


Для тех кто первый раз слышит про «Let's Encrypt», небольшая справка:

Let's Encrypt — центр сертификации предоставляющий в автоматическом режиме бесплатные криптографические сертификаты для TLS шифрования (HTTPS) со сроком на 90 дней. Проект создан для того, чтобы HTTPS стал доступнее для интернет-проектов, чтобы максимально упросить процесс получения, настройки и сделать его абсолютно бесплатным, без ущерба безопасности.

Выдача и продление сертификата происходоит в автоматическом режиме по протоколу Automated Certificate Management Environment (ACME). В этом протоколе к веб-серверу, запросившему сертификат, производится серия запросов, для подтверждения факта владения доменом.

image

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

На данный момент, Let's Encrypt выдали уже более 100 миллионов сертификатов. Сервис невероятно популярен и рекомендуется к использованию.

Let's Encrypt и Flussonic



Как-то неприлично аудитории Хабра объяснять зачем нужен HTTPS, когда речь идет о передаче видео, в том числе с камер видеонаблюдения. Пользователи становятся более грамотными, обращают внимание на наличие безопасного соединения, когда речь идет о заполнении форм, и уж тем более, для них важно, чтобы видео с камеры наблюдения доставлялось безопасно. А если речь идет про корпоративное использование, то это просто обязательно.

Мы добавили поддержку Let's Encrypt во Flussonic уже давно, а недавно прокачали его, чтобы сам следил за сроком жизни. А сейчас я покажу вам, как наши клиенты настраивают HTTPS, это невероятно просто.

Предполагается, что клиент уже имеет доменное имя, настроил DNS соответсвующим образом. Открывает веб-интерфейс Flussonic и переходит во вкладку «Config» и указывает порт для HTTPS:

image

После ввода номера порта, в интерфейсе появляется кнопка «Issue by LetsEncrypt», нажав на которую происходит общение по ACME. Вводить имя домена не требуется, Flussonic получает его из адресной строки браузера. Это решение экономит несколько секунд времени, исключает ошибку при наборе, что в целом упрощает жизнь нашим клиентам.

image

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

Итоги



Как я и написал в самом начале: пожалуй, у нас самая простая реализация настройки Let's Encrypt: никакого дополнительного софта и ввода настроек с клавиатуры.

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

https://habrahabr.ru/post/333512/


Настройка среды разработки: кружок рукоделия (Часть 1)

Понедельник, 17 Июля 2017 г. 15:12 + в цитатник
Настройка среды разработки
Привет, дорогой читатель!
Сегодня я хочу поделиться своим опытом настройки персонального окружения для работы с различными PHP-based проектами. В данной статье описывается опыт ручной настройки окружения.

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

Автоматизацию процесса развертывания среды я напишу в одной из следующих статей.

Статья будет очень длинной с уклоном в техническую сторону. Прошу под «кат».


Предыстория


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

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

В конце 2016 года мне пришлось перейти с одного проекта на другой в связи с чередой очень неприятных событий. Перейдя на новый проект с толкнулся с тем, что архитектура проекта была построена так, что нужно одновременно поддерживать минимум 5 сервисов, работающих в связке. Так же мне все еще приходится время от времени поддерживать предыдущие проекты. Да и, не забывать об R&D проектах, Open Source проектах, “халтурке”, семье и детях.

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

Цель: гибкая среда разработки для PHP-based проектов


И так. Мне нужно получить рабочее окружение, позволяющее вести разработку, отладку и исследования во множественных PHP-based проектах с привязкой к инфраструктуре компании.
Примечание: дальнейшее описание относится к двум проектам, которые сейчас находятся в моей зоне ответственности: Warface Hub — то, что от него осталось, и CryEngine Hub — результат молниеносной реализации, “удачной” архитектуры и “правильного” планирования.

Таким образом я получил следующее
  • Windows 10 — Host с VMWare или VitrualBox
  • Ubuntu — Guest c:
    • Samba — для работы с файлами проектов
    • Bind9 — локальный DNS сервер
    • Nginx, PHP FPM, MySQL и все остальное

  • Другие виртуальные машины


Ресурсы


В крупных компаниях очень часто используют решения от компании Microsoft для обеспечения работы внутренней связи между сотрудниками (Outlook, Lync, AD) и еще кучи «самописных» приложений. Так как лень мне не позволяет искать и настраивать клиенты под Linux или использовать Wine, то я успешно начал использовать “гибрид” двух OS и виртуализацию:

  • Windows 10 (Host OS)
  • Ubuntu 16.04 (Guest OS — VM)
  • SSD — максимально быстрый. При данной реализации очень важно иметь быстрый диск.
  • 16Gb ram — Чем больше, тем лучше. Мне приходится выделять до 12Gb для всех гостевых OS, так как приходится решать cross-browser проблемы, которые на эмуляторах не воспроизводятся.


Установка серверов, приложений и компонентов.


На этом этапе устанавливаем все (Guest OS), что может нам понадобится для того чтобы поднять простой стек из Nginx, PHP и MySQL, а также все остальное, что может пригодится в проектах (NPM, Yarn, Composer). Не забываем про нашу среду разработки и добавляем туда Samba и Bind9.

Для меня это выглядит так
$ sudo add-apt-repository ppa:ondrej/php
$ sudo apt-get install php5.6 php7.0 php7.1 php7.1-fpm
$ sudo apt-get install php-bcmath php-curl php-dev php-fpm php-gd php-intl php-json php-mbstring php-mcrypt php-mysql php-readline php-soap php-sqlite3 php-tidy php-xml php-zip php-codecoverage php-codesniffer php-common php-geoip php-igbinary php-imagick php-memcache php-memcached php-redis php-ssh2 php-xdebug php-xhrpof
$ sudo apt-get install php5.6-bcmath php5.6-curl php5.6-dev php5.6-fpm php5.6-gd php5.6-intl php5.6-json php5.6-mbstring php5.6-mcrypt php5.6-mysql php5.6-opcache php5.6-readline php5.6-soap php5.6-sqlite3 php5.6-tidy php5.6-xml php5.6-zip
$ sudo apt-get install php7.0-bcmath php7.0-curl php7.0-dev php7.0-fpm php7.0-gd php7.0-intl php7.0-json php7.0-mbstring php7.0-mcrypt php7.0-mysql php7.0-opcache php7.0-readline php7.0-soap php7.0-sqlite3 php7.0-tidy php7.0-xml php7.0-zip
$ sudo apt-get install php7.1-opcache
 
$ sudo apt-get install memcached redis-server redis-tools nginx mysql-server-5.7 mysql-client-5.7 composer npm curl nodejs nodejs-legacy ruby-full
 
$ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
$ echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
$ sudo apt-get update && sudo apt-get install yarn

$ sudo gem update --system
$ sudo gem install compass
$ composer global require hirak/prestissimo
$ sudo npm install -g grunt-cli

$ sudo apt-get install bind9 samba



Samba-сервер


Samba-сервер Первое, к чему я потянулся — Samba-сервер, который настроил для того, чтобы моя IDE могла работать непосредственно с файловой системой гостевой OS.

Все мои проекты будут находится по пути /var/www/{project-name}.
Так же в процессе настройки гостевой ОС я принудительно настроил DHCP сервер так, чтобы у нее был статический IP и пряталось все за NAT: 172.16.126.130.

$ cat /etc/samba/smb.conf
[global]
workgroup = WORKGROUP
server string = %h server (Samba, Ubuntu)
dns proxy = no

# few changes to speed up smbd
strict allocate = Yes
read raw = Yes
write raw = Yes
strict locking = No
socket options = TCP_NODELAY IPTOS_LOWDELAY SO_RCVBUF=131072 SO_SNDBUF=131072
min receivefile size = 16384
use sendfile = true
aio read size = 16384
aio write size = 16384

max log size = 1000
syslog only = no
syslog = 0
server role = standalone server

usershare allow guests = yes

[www]
    path = /var/www
    available = yes
    valid users = oxcom
    read only = no
    browsable = yes
    public = yes
    writable = yes
    executable = yes



Чтобы IDE могла работать с этим ресурсом я монтирую эту Netbios папку как удаленный локальный диск.
Mount local drive on Windows
@echo off
@title Local UBUNTU Network Drive

net use q: \\172.16.126.130\www {user-password} /USER:oxcom

Unmount local drive
Unmount local drive
@echo off
@title Local UBUNTU Network Drive

net use q: /delete



Почему я стал использовать Samba, а не Shared Folders?
На то время, когда я этим вопросом задался получалось так, что Shared Folders являлись монтируемой директорией, а NGINX не хотел их использовать как root директорию проекта. Второй причиной стало то, что время от времени у меня Shared Folders отваливались без видимой на то причины и без возможности быстро все восстановить. А также нет возможности работать с симлинками, которые необходимы для некоторых пакетов npm и не только.

Есть ли какие-то проблемы с IDE?
Да и разные, но SSD спасает:
  • иногда индексирование проектов происходит долго
  • при быстром изменении большого количества файлов (merge, rebase, смена бранча) не сразу подхватываются изменения. Смотрю в сторону rsync.
  • Если отключить диск раньше, чем закрыть IDE, то, при закрытии проекта, IDE зависнет
  • Если отвалится сеть, то проект скорее всего нужно будет открыть еще раз


DNS-сервер


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

Так как я очень ленивый, то через какое-то время мне надоело добавлять в hosts файл записи вида:
172.16.126.130 project1.lo
172.16.126.130 project2.lo


Было решено, что нужен локальный DNS-сервер, который можно настроить быстрее, чем я смогу выпить бутылку немецкого крепкого пива. После чего был послан запрос в лигу лени. Результат не заставил себя долго ждать: BIND9

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

$ cat /etc/bind/db.lo
;
; BIND data file for local loopback interface
;
$TTL 604800
@ IN SOA lo. root.lo. (
0000119 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
;
@ IN NS lo.
@ IN A 172.16.126.130
@ IN AAAA ::1
* IN CNAME @

$ cat /etc/bind/db.126.16.172
;
; BIND data file for local loopback interface
;
$TTL 604800
;
; BIND reverse data file for local loopback interface
;
$TTL 604800
@ IN SOA ns.lo. root.lo. (
0000112 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
;
@ IN NS lo.

$ cat /etc/bind/named.conf.local
zone "lo" {
type master;
file "/etc/bind/db.lo";
check-names ignore;
allow-query { any; };
allow-transfer { any; };
};

zone "126.16.172.in-addr.arpa" {
type master;
file "/etc/bind/db.126.16.172";
allow-query { any; };
allow-transfer { any; };
};

$ cat /etc/bind/named.conf.options
options {
directory "/var/cache/bind";

forwarders {
8.8.8.8;
8.8.4.4;
};

recursion yes;
listen-on { any; };

auth-nxdomain no; # conform to RFC1035

listen-on-v6 { any; };
};



Сервер настроен. Теперь, для полной радости осталось решить еще несколько задач:
  • заставить Host систему использовать наш DNS-сервер для домена .lo. По-этому меняем на Host машине нужно параметры виртуальной сети так, чтобы первым был наш DNS-сервер, и чистим DNS-кеш.
  • заставить Guest систему тоже использовать наш DNS-сервер. Тут проще: редактируем сетевой интерфейс и прописываем туда наш DNS-сервер


Результат не заставляет себя ждать:
$ dig example.lo
; <<>> DiG 9.10.3-P4-Ubuntu <<>> example.lo
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 32204
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 1, ADDITIONAL: 2

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;example.lo. IN A

;; ANSWER SECTION:
example.lo. 604800 IN CNAME lo.
lo. 604800 IN A 172.16.171.130

;; AUTHORITY SECTION:
lo. 604800 IN NS lo.

;; ADDITIONAL SECTION:
lo. 604800 IN AAAA ::1

;; Query time: 0 msec
;; SERVER: 172.16.171.130#53(172.16.171.130)
;; WHEN: Mon Jul 17 11:09:52 CEST 2017
;; MSG SIZE rcvd: 111

ping example.lo
Pinging lo [172.16.171.130] with 32 bytes of data:
Reply from 172.16.171.130: bytes=32 time<1ms TTL=64
Reply from 172.16.171.130: bytes=32 time<1ms TTL=64


Вот только «nslookup example.lo» не работает. Почему — не знаю, но любой браузер на Host машине будет нормально ходить на соответствующий сервер.

PHP-FPM и Pools


PHP Вроде все работает. Теперь необходимо приступить к настройке PHP для каждого из проектов.
Работая над последними проектами у меня получилось так, что один проект может состоять из различных сервисов или собирать в себе многие другие проекты. По-этому у меня получилась следующая структура:
  • warface.com
  • cryengine.com
  • shop.cryengine.com
  • forum.cryengine.com


В процессе работы приходится использовать API вызовы между проектами и было бы очень хорошо уметь «дебажить» это все с помощью XDebug и любимой IDE. При попытках использовать один PHP Pool я сталкивался со следующими проблемами:
  • при отладке на одном домене с общей сессией PHP-FPM блокирует исполнение остальных запросов с такой же сессий (как смог так и описал :)). Таким образом останавливаясь на где-то на cryengine.com я не смогу работать с forum.cryengine.com, пока не завершится предыдущий запрос.
  • неудобно проводить отладку двух проектов одновременно с разными ключами XDebug. Да-да, я стараюсь максимально избегать изменения настроек среды из PHP


И так. Чтобы это решить, я создал свой PHP Pool по шаблону для каждого проекта под каждую версию PHP. И подключаю их 'include=/etc/php/7.0/fpm/pool.d/*.d/*.conf'
Шаблон
$ cat /etc/php/{php-version}/fpm/pool.d/{project-name}.d/{project-subname}.conf
; Start a new pool
; the variable $pool can we used in any directive and will be replaced by the
; pool name ('www' here)
[{project-name}-{project-subname}]

user = www-data
group = www-data

listen = /run/php/php7.0-$pool-fpm.sock

listen.owner = www-data
listen.group = www-data
 
pm = dynamic
pm.max_children = 20
pm.start_servers = 5
pm.min_spare_servers = 3
pm.max_spare_servers = 7

php_admin_value[xdebug.idekey] = key-$pool


Выглядит это примерно так:
$ ls -la /etc/php/7.0/fpm/pool.d/
cryengine.d/www.conf
cryengine.d/shop.conf
cryengine.d/forum.conf
warface.d/www.conf
www.conf
Список PHP-Sockets
php5.6-cryengine-www-fpm.sock
php5.6-cryengine-shop-fpm.sock
php5.6-cryengine-forum-fpm.sock
php5.6-warface-www-fpm.sock
php5.6-fpm.sock
php7.0-cryengine-www-fpm.sock
php7.0-cryengine-shop-fpm.sock
php7.0-cryengine-forum-fpm.sock
php7.0-warface-www-fpm.sock
php7.0-fpm.sock



Теперь каждый проект имеет свой PHP Pool и проставленным xdebug.idekey, что позволяет проводить непрерывную отладку между несколькими проектами (не забывайте настроить php.ini)

NGINX


NginxНастройка сервера довольно проста. Для каждого проекта создается отдельный файл конфигурации в 'sites-available', который описывает конфигурацию vhost. В конфигурации мы подключаем соответствующие файлы конфигурации для каждого проекта.

Основываясь на указанной выше архитектуре я реализовал вот такую структуру:
$ ls -la /etc/nginx/
cryengine.d/
- www.conf
- forum.conf
- shop.conf
- ssl.conf
warface.d/
- www.conf
- ssl.conf

sites-available/
- www.cryengine.conf
- forum.cryengine.conf
- shop.cryengine.conf
- www.warface.conf

nginx.conf

$ cat /etc/nginx/sites-available/{project-subname}.{project-name}.conf
server {
    listen 443 ssl http2;
    server_name {project-subname}.{project-name}.lo;

    root /var/www/{project-subname}.{project-name}.com/wwwroot;
    index           index.php;

    error_log  /var/www/{project-subname}.{project-name}.com/log/nginx.error.log error;
    access_log /var/www/{project-subname}.{project-name}.com/log/nginx.access.log;

    # configuration related to sub-project
    include {project-name}.d/www.conf;
    # global configuration for projects
    include {project-name}.d/ssl.conf;
}


Таким образом в /etc/nginx/{project-name}.d/ хранятся все конфигурации, которые относятся к проекту, а также сопутствующим под проектам. Каждый проект имеет свой PHP Pool пока каждую версию PHP, что позволяет быстро переключаться между версиями и только для одного проекта.

Итоги


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

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

Минусы:
  • Долгая индексация в IDE
  • При переустановке/переносе виртуальной машины нужно изменять конфигурацию для Bind9 и скрипт подключения диска
  • Это все не автоматизировано


Плюсы:
  • рабочую среду можно переносить с машина на машину
  • разработчик остается в Windows окружении и есть возможность использовать MS сервисы, которые установлены в компании.
  • разработчик работает с Linux окружением, которое может быть легко настроено как LIVE среда.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/333484/


Метки:  

[Из песочницы] Применение преобразования Фурье для создания гитарного тюнера на Android. Часть 1

Понедельник, 17 Июля 2017 г. 14:58 + в цитатник

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

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

ДПФ, БПФ. Библиотека JTransforms.


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

Для вычисления преобразования Фурье на компьютерах ввели понятие дискретное преобразование Фурье (ДПФ), которое требует в качестве входа дискретную функцию.

Рассмотрим принцип работы дискретного преобразования Фурье в среде программирования Java. Для начала, опишем некоторую функцию, которая будет представлять сумму двух гармоник (косинусов) с частотами 100 Гц и 880 Гц соответственно.

private double someFun(int index, int sampleRate) {
    final int amplitudeOfFirstHarmonic = 15;
    final int amplitudeOfSecondHarmonic = 1;
    final int frequencyOfFirstHarmonic = 100;
    final int frequencyOfSecondHarmonic = 880;

    return amplitudeOfFirstHarmonic * Math.cos((frequencyOfFirstHarmonic * 2 * Math.PI  * index ) / sampleRate)
            + amplitudeOfSecondHarmonic *Math.cos((frequencyOfSecondHarmonic * 2 * Math.PI  * index) / sampleRate);
}

В качестве частоты дискретизации возьмём значение 8000 Гц и заполним массив из 8000 элементов данными, вызывая функцию someFunc() в цикле

final int sampleRate = 8000;
final int someFuncSize = 8000;
double[] someFunc = new double[someFuncSize];
for (int i = 0; i < someFunc.length; i++) {
    someFunc[i] = someFun(i, sampleRate);
}

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


Как видно из диаграммы, гармоника с частотой 100 Гц имеет амплитуду 15, значение которой и было указано в константе amplitudeOfFirstHarmonic. Поверх первой гармоники с частотой 100 Гц и амплитудой 15, рисуется вторая гармоника с частотой 880 Гц и амплитудой равной единице.
По такому же принципу создадим две базисные функции косинуса и синуса. Только теперь, мы будем передавать значение частоты в параметры методов наших базисных функций

private double cos(int index, int frequency, int sampleRate) {
    return Math.cos((2 * Math.PI * frequency * index) / sampleRate);
}
private double sin(int index, int frequency, int sampleRate) {
    return Math.sin((2 * Math.PI * frequency * index) / sampleRate);
}

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

private double[] dft(double[] frame, int sampleRate) {
    final int resultSize = sampleRate / 2;
    double[] result = new double[resultSize * 2];
    for (int i = 0; i < result.length / 2; i++) {
        int frequency = i;
        for (int j = 0; j < frame.length; j++) {
            result[2*i] +=frame[j] * cos(j, frequency, sampleRate);
            result[2*i + 1] +=frame[j] * sin(j, frequency, sampleRate);
        }
        result[2*i] =result[2*i] / resultSize;
        result[2*i + 1] = result[2*i + 1] / resultSize;
    }

    return result;
}

После выполнения преобразования Фурье, полученные значения, определяют проекции всех векторов, упорядоченных по частоте, на оси косинусов и синусов. Для того, чтобы найти длину такого вектора, необходимо применить теорему Пифагора $inline$A=\sqrt{a^2+b^2}$inline$.

double[] result;
long start = System.currentTimeMillis();
result = dft(someFunc, sampleRate);
long finish = System.currentTimeMillis();
long timeConsumedMillis = finish - start;
System.out.println("Time's dft: " + timeConsumedMillis);
double[] amplitude = new double[sampleRate/2];
for (int i = 0; i < result.length / 2; i++) {
    amplitude[i] = Math.sqrt(result[2*i]*result[2*i] + result[2*i+1]*result[2*i+1]);
    System.out.println(i + ": " + "Projection on cos: " + result[2*i] + " Projection on sin: " + result[2*i + 1]
            + " amplitude: "+ amplitude[i] + "\n");
}

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

Таким образом, для гармоник с частотами 100 Гц и 880 Гц, значения амплитуд, будут соответствовать тем значениям, которые были указаны в константах amplitudeOfFirstHarmonic и amplitudeOfSecondHarmonic метода someFunc(). А для остальных гармоник, которых остаётся ровно 3998, значения амплитуд будут приближены к нулю, потому что, остальные гармоники не были определены в исходной дискретной функции someFunc(), которая передавалась на дискретное преобразование Фурье.




Выведем значения амплитуд, полученных после преобразования Фурье функции someFunc(), в файл .csv и построим график в программе Excel. В результате преобразования Фурье, мы получили спектр исходного сигнала



Алгоритм дискретного преобразования Фурье на компьютере выполняется за время $inline$O(n^2)$inline$, что является слишком медленным процессом. Для быстрых вычислений дискретного преобразования Фурье, придумали быстрое преобразование Фурье (БПФ). Алгоритм БПФ, производит вычисления, используя рекурсивный подход, благодаря которому, время выполнения алгоритма уменьшается до $inline$O(n*\lg{n})$inline$. Существует готовая реализация алгоритма БПФ в среде программирования Java, которая представлена в виде библиотеки JTransforms.

Запись данных с микрофона. AudioRecord


За получения звуковых данных в формате PCM с мобильного устройства на платформе Android отвечает класс AudioRecord.
Для создания экземпляра класса AudioRecord, в конструкторе класса AudioRecord, необходимо указать такие параметры как:
  • audioSource — источник, откуда ведётся запись.
  • sampleRateInHz — частота дискретизации в Герцах.
  • channelConfig — тип аудио канала.
  • audioFormat — формат кодирования данных.
  • minBufferSize — минимальный размер буфера.

После создания экземпляра класса AudioRecord, необходимо вызвать метод startReading(), который начнёт запись с мобильного устройства. Записанные звуковые данные будут храниться во внутреннем буфере класса AudioRecord в размере порции, указанной в параметре minBufferSize при создании экземпляра класса. Из внутреннего буфера класса AudioRecord, необходимо периодически забирать записанные данные с помощью вызова метода read() класса AudioRecord.
Для примера, запишем звуковые данные с мобильного устройства, а затем выведем, эти данные, в текстовый файл .csv и построим график полученных звуковых данных, используя программу Excel


При создании экземпляра класса AudioRecord, используем частоту дискретизации равной 8000 Гц и размер буфера равный 1024.

Если эта часть статьи была интересна, то во второй части статьи мы займёмся созданием гитарного тюнера на Android.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/333514/


Метки:  

[Перевод] CSS — это не чёрная магия

Понедельник, 17 Июля 2017 г. 14:49 + в цитатник
Всем веб-программистам время от времени приходится писать CSS. Впервые с ним столкнувшись, вы, скорее всего, сочтёте, что понять CSS — это ерунда. И правда — тут добавили границы, там поменяли цвет… JavaScript — вот по-настоящему сложная штука. CSS по сравнению с ним — игрушка.



Однако, по мере того, как вы будете совершенствоваться в деле веб-разработки, легкомысленное отношение к CSS останется в прошлом. Столкнувшись с чем-то неописуемо странным, вы поймёте, что попросту не представляете, как именно CSS работает, что делается в его недрах. Что-то похожее было и у меня. Первые пару лет после учёбы я занималась JavaScript-разработкой полного цикла, эпизодически касаясь CSS. Я всегда считала, что мой хлеб — это JavaScript, ему я отдавала всё своё время.

Например, участвовала в дискуссиях на JavaScript Jabber. В последний год я решила сосредоточиться на фронтенде и только тогда поняла, что не в состоянии, например, отлаживать таблицы стилей так же, как JS-код.

Про CSS часто шутят, но немногие отнеслись к нему достаточно серьёзно и попытались его понять. Кто, столкнувшись с проблемой, осмысленно занимался поиском ошибок, учитывая то, как CSS обрабатывают браузеры? Вместо этого мы хватаем код из первого попавшегося ответа на Stack Overflow, не брезгуем разного рода хаками, или просто игнорируем проблемы.

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

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

DOM и CSSOM


Для начала, важно понимать, что в браузерах, помимо прочих подсистем, имеется JavaScript-движок и движок рендеринга. Нас, в данном случае, интересует последний. Например, мы обсудим детали, которые относятся к WebKit (Safari), Blink (Chrome), Gecko (Firefox), и Trident/EdgeHTML (IE/Edge).

Браузер, в ходе вывода веб-страницы на экран, выполняет определённую последовательность действий, ведущую к построению объектной модели документ (DOM, Document Object Model), и объектной модели таблицы стилей (CSSOM, CSS Object Model). Эту последовательность действий, упрощённо, можно представить в следующем виде:

  • Преобразование: чтение байтов HTML- и CSS-кода с диска или загрузка их из сети.
  • Токенизация: разбивка потока входных данных на фрагменты (например: начальные теги, конечные теги, имена атрибутов, значения атрибутов), удаление ненужных символов, таких, как пробелы и переводы строк.

  • Лексирование: этот шаг похож на токенизацию, но здесь осуществляется определение типа каждого токена (например: этот токен — число, тот — строковой литерал, ещё один — оператор равенства).

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

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

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

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

CSSOM может оказать сильнейшее влияние на дерево рендеринга, но не на дерево DOM.

Рендеринг


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

  • Создание макета страницы. Этот этап включает в себя вычисление размеров элемента и его позиции на экране. Родительские элементы могут воздействовать на дочерние элементы. Иногда и дочерние элементы могут воздействовать на родительские.

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

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

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

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

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

Сведение слоёв с использованием аппаратного ускорения позволяет значительно увеличить скорость рендеринга в сравнении с традиционным подходом, при котором используется лишь процессор. В связи со всем этим нельзя не вспомнить о CSS-свойстве will-change, умелое использование которого позволяет ускорить вывод страниц. Например, при использовании CSS-трансформаций, свойство will-change позволяет подсказать браузеру, что элемент DOM будет трансформирован в ближайшем будущем. Выглядит это как will-change: transform. Это позволяет передать GPU некоторые операции по отрисовке и сведению слоёв, что способно значительно повысить производительность страниц, содержащих много анимированных элементов. Улучшить производительность с помощью will-change можно, воспользовавшись конструкциями will-change: scroll-position, will-change: contents, will-change: opacity, will-change: left, top.

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

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

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

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

Ещё одно различие между DOM и CSSOM заключается в том, что при анализе CSS используется контекстно-независимая грамматика. Другими словами, в движке рендеринга нет кода, который доводил бы CSS до некоего приемлемого вида, как это делается при разборе HTML для создания DOM.

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

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

Браузер выполняет HTTP-запрос, запрашивая у сервера страницу. Веб-сервер отправляет ответ. Браузер конвертирует данные, полученные от сервера, в токены, которые затем преобразуется в узлы деревьев DOM и CSSOM. После того, как эти деревья готовы, строится дерево рендеринга, на основе которого формируется макет страницы, производится послойная отрисовка элементов и сведение слоёв. В результате получается веб-страница, которую мы видим на экране.

Специфичность селекторов


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

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

Расчёт показателей специфичности селекторов сбивает с толку многих JavaScript-разработчиков, поэтому давайте остановимся на этом подробнее. Мы будем использовать следующий пример. Имеется тег div с классом container. В этот тег вложен ещё один div, id которого — main. Внутри main имеется тег p, в котором содержится тег a.

 
   

     Hello!    

 

Сейчас, не подглядывая в ответ, попытайтесь проанализировать нижеприведённый CSS и сказать, какого цвета будет текст ссылки в теге a.

#main a { 
  color: green;
}
p a { 
  color: yellow;
}
.container #main a {
  color: pink;
}
div #main p a { 
  color: orange;
}
a { 
  color: red;
}

Может, красного цвета? Или зелёного? Нет. Ссылка будет розового цвета со значением специфичности 1,1,1. Вот остальные результаты:

  • div #main p a: 1,0,3
  • #main a: 1,0,1
  • p a: 2
  • a: 1

Для нахождения этих чисел нужно произвести следующие вычисления:

  • Первое число: количество селекторов ID.

  • Второе число: количество селекторов класса, селекторов атрибутов (например: [type="text"], [rel="nofollow"]) и псевдоклассов (:hover, :visited).

  • Третье число: количество селекторов типа и псевдоэлементов (::before, ::after)

Например, взглянем на такой селектор:

#header .navbar li a:visited

Значение специфичности для него будет 1,2,2. Тут имеется один ID, один класс, один псевдокласс, и два селектора типа элемента (li и a). Это значение можно прочитать и так, как будто в нём нет запятых, вместо 1,2,2 — 122. Запятые тут имеются только для того, чтобы подчеркнуть, что перед нами не десятичное число из трёх цифр, а три числа. Это особенно важно для теоретически возможных результатов вроде 0,1,13. Если переписать это в виде 0113, неясно будет, как вернуть его в исходное состояние.

Позиционирование элементов


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

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

Часто меня спрашивают о преимуществах и недостатках использования flexbox и float. Конечно, flexbox — это, с точки зрения юзабилити, очень хорошо, будучи применённым к одному и тому же элементу, макет с flexbox рендерится примерно 3.5 мс, в то время как рендеринг макет с float может занять около 14 мс. Таким образом, для учёта мелких, но важных деталей, JS-разработчикам имеет смысл поддерживать свои знания в области CSS в таком же хорошем состоянии, как и знания в области JavaScript.

Свойство z-index


И, наконец, мне хотелось бы поговорить о свойстве z-index. На первый взгляд кажется, что говорить тут особо не о чем. Каждый элемент в HTML-документе может быть либо перед другими, либо позади них. Кроме того, это работает только для позиционированных элементов. Если установить свойство z-index для элемента, позиционирование которого явно не задано, это ничего не изменит.

Ключ к поиску и устранению проблем, связанных с z-index, заключается в понимании идеи контекстов наложения. Поиск неполадок всегда начинается с корневого элемента контекста наложения. Контекст наложения — это концепция расположения HTML-элементов в трёхмерном пространстве, в частности — вдоль оси Z, относительно пользователя, находящегося перед монитором. Другими словами — это группа элементов с общим родителем, которые вместе перемещаются по оси Z либо ближе к пользователю, либо дальше от него.

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

Однако, можно создавать новые контексты наложения с помощью свойств, отличающихся от z-index, и вот тут уже всё становится сложнее. Среди них — свойство opacity, когда это значение меньше единицы, filter, когда значение этого свойства отличается от none, и mix-blend-mode, значение которого не normal. Эти свойства, на самом деле, создают новые контексты наложения. На всякий случай хочется напомнить, что режим наложения (blend mode) позволяет задать то, как пиксели на некоем слое взаимодействуют с видимыми пикселями на слоях, расположенных ниже этого слоя.

Свойство transform тоже вызывает создание нового контекста наложения в тех случаях, когда оно отличается от none. Например, scale(1) и translate3d(0,0,0). Опять же, как напоминание, свойство scale используется для изменения размера элемента, а translate3d позволяет задействовать GPU для CSS-переходов, повышая качество анимации.

Итоги


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

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

https://habrahabr.ru/post/333506/


Метки:  

Машинное обучение и поиск темной материи: соревнование от ЦЕРНа и Яндекса

Понедельник, 17 Июля 2017 г. 14:47 + в цитатник

Метки:  

[Перевод] Как создать виртуальную машину в Google Таблицах

Понедельник, 17 Июля 2017 г. 14:11 + в цитатник
Автор материала рассказывает, как с помощью Google-таблиц создать виртуальную машину, которая генерирует числа Фибоначчи.

Недавно я заметил, что в Google Документах есть достаточно полнофункциональная система скриптов под названием Apps Script. Она позволяет вам писать на JavaScript некоторые довольно полезные вещи:

  • Запускать код в ответ на такие события, как открытие документов или изменение ячеек
  • Создавать пользовательские функции таблиц для формул в Google Таблицах
  • Использовать такие сервисы, как Google Переводчик для перевода текста или Gmail для отправки электронной почты
  • Добавлять новые элементы меню в интерфейс Google Документов с помощью своих пользовательских функций

Естественно, по этой причине мне пришлось создать что-нибудь интересное. Вот, смотрите: виртуальная машина в Google Таблицах, генерирующая числа Фибоначчи!

image

Как она работает


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

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

image

Обратите внимание на следующее:

  • RA, RB, RC и RD — это регистры общего назначения.
  • RI — это указатель на команду. Он указывает на следующую команду, которая должна быть выполнена в области памяти, которая подсвечивается зеленым цветом.
  • RS — это указатель на стек. Он указывает на ячейку памяти в верхней части стека. Она подсвечивается синим цветом.
  • Вывод (Output) отображает вывод программы.
  • Ошибка (Error) отображает любые ошибки, возникающие при анализе или выполнении команды.
  • Память (Memory) — это область из 100 ячеек памяти.

Чтобы запустить команду, Apps Script проверяет значение RI в фоновом режиме, чтобы понять, какая команда должна выполняться следующей. Она считывает команду в ячейке, на которую указывает RI, и анализирует ее.

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

После выполнения команды значение RI увеличивается, чтобы указывать на следующую ячейку в памяти.

Использование


Существует специальное меню под названием «Компьютер» (Computer) с некоторыми функциями, которые используются для управления ВМ:

image

  • Запуск (Run) запускает текущую программу до ее окончания или обнаружения ошибки.
  • Шаг (Step) запускает одну команду, а затем приостанавливается.
  • Сброс (Reset) очищает все регистры и поле вывода, тем самым подготавливая программу к повторному запуску.
  • Загрузка факториальной программы (Load Factorial Program) загружает факториальный пример из другой таблицы.
  • Загрузка программы Фибоначчи (Load Fibonacci Program) загружает пример Фибоначчи с другого листа.

Команды


Существует несколько реализованных команд:

Общие

  • mov dst src копирует значение из src в dst.

Математические

  • add dst src прибавляет dst к src и сохраняет результат в dst.
  • sub dst src вычитает src из dst и сохраняет результат в dst.
  • mul dst src умножает dst на src и сохраняет результат в dst.

Операции со стеком

  • push src загружает src в стек.
  • pop dst извлекает значение из верхушки стека и сохраняет его в dst.

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

  • jmp target переходит к команде в ячейке, на которую ссылается target.
  • jl cmp1 cmp2 target сравнивает cmp1 с cmp2. Если cmp1 меньше, чем cmp2, выполнение переходит к target.

Функции

  • call target — это вызов функции. Он загружает текущий указатель на команду в стек, чтобы он мог быть возвращен позже, а затем переходит к target.
  • ret возвращает функцию. Он извлекает значение из стека и переходит к нему.

Прочее

  • output src записывает src в Вывод (Output): раздел интерфейса.
  • end завершает программу.

Способы адресации


Операнды в приведенных выше командах могут принимать несколько форм:

Immediates — это литеральные значения, встроенные в команду. Примеры: 7 и123. Например, чтобы скопировать значение 7 в регистр ra:

mov ra 7

Registers ссылаются на регистры по имени. Примеры: ra, rb, rc. Чтобы скопировать значение из rc в rb:

mov rb rc

Memory ссылается на значение внутри ячейки области памяти. Примеры: $0, $10, $99. Чтобы скопировать значение из ra в первую ячейку памяти:

mov $0 ra

Чтобы скопировать значение из последней ячейки памяти в rd:

mov rd $99

Indirect ссылается на значение, на которое указывает ячейка памяти. Примеры: @15, @50. Поэтому, если ячейка памяти 10 содержит значение 20, а ячейка памяти 20 содержит значение 30, вы можете скопировать значение 30 в ra следующим образом:

mov ra @10

Он проверяет ячейку памяти 10, чтобы найти значение 20. Затем он обращается к ячейке памяти 20, чтобы найти значение 30, и копирует это значение в ra.

Рекурсия


Вы можете использовать стек и команды call и ret для выполнения рекурсивных вызовов. Вот пример, который использует рекурсию для генерации факториала числа 5:

image

Код, начинающийся с jl ra 2 50, является функцией, которая принимает вводное значение в ra и возвращает результат в rd. Она вызывает себя рекурсивно для вычисления факториала значения в ra.

Как получить копию


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

Вы можете увидеть код Apps Script, выбрав «Инструменты» (Tools), а затем «Редактор скриптов» (Script Editor).

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

https://habrahabr.ru/post/319754/


Метки:  

[recovery mode] Unity на Linux? Да без проблем

Воскресенье, 16 Июля 2017 г. 00:33 + в цитатник
image

Думаю долго мучает эта идея многих из нас: А не перейти ка мне полностью на Linux? Так было и со мной. Много дней раздумий, много за и против.

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

Думал как ставить Unity так, чтобы не через Wine. И о чудо. Unity уже давно ведут ветку Linux пакетов, готовых к установке. Есть у них как и .sh скрипт, так и готовый .deb пакет(ссылки внизу).
Каждая выпускаемая версия Unity собирается и для нашей OC. Есть косяки иногда, но они малозаметны и, в принципе, для комфортной разработки есть всё что нужно и всё хорошо работает.
И так. Unity ставится просто и легко

  1. С помощью готового .deb пакета через менеджер
  2. Или через терминал
    sudo sh /path/to/*.sh


Дальше начинается неразбериха. Думаю вы знаете, что Unity использует свой компилятор. Ему нежен .Net версии 3.5.

Я пробовал для работы Rider от JB(на окнах всё хорошо, в Ubuntu,Mint ругается на отсутствие .Net 3.5), VSCode(тоже самое и ещё чуть чуть) и новый MonoDevelop, который поставляется через flatpack. Но с ним оказалась куча проблем, главной из которых является неполное, а с моей стороны даже некорректное чтение файловой системы. Лезет не в те разделы, не видя при этом то, что надо. В итоге нарушается линковка и вы вряд ли захотите каждый раз мучаться с настройкой библиотек. Поэтому я пришёл к простому решению — поставить Mono из стандартных репозиториев через apt. Приступим.

Советую сделать перед началом всего
sudo apt-get update

Обновились.
Дальше ставится Mono версии 5.9.6\

sudo apt-get install monodevelop


И так. Нам нужна сама программа. Мы её получили. Указываем на неё в Unity.
В Unity идём Edit->Preferences->External Tools->External Script Editor выбираем пункт monodevelop

Запускаем. Всё хорошо. Но линковщик ругается: чувак, а где .Net 3.5? И многие тут стопорятся. У mono есть так называемые mono-reference-assemblies. Нам то оно и нужно

sudo apt-get install mono-reference-assemblies-3.5


В итоге: Unity замечательно дружит с Linux, не создавая проблем при разработке. Так же всё ПО, которое было у меня на Windows, я смог заменить аналогами на Linux Mint.

У меня стоит третья снизу
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/333422/


Метки:  

Дорога к С++20

Суббота, 15 Июля 2017 г. 23:56 + в цитатник
imageСегодня завершилась летняя встреча комитета ISO WG21 C++, проходившая в Торонто с 10 по 15 июля. Вскоре нас наверняка ждёт подробный отчёт от РГ21, а сегодня уважаемой публике предлагается пост-«разогрев» с обсуждением самого интересного.

Итоги встречи следующие: стандарт С++17 завершен и будет опубликован на следующем собрании в ноябре этого года; стандарт С++20 уже обзавелся первыми серьезными фичами — концептами (concepts), явными обобщёнными лямбда-функциями (explicit generic lambdas) — и это только начало.

Возможности нового стандарта С++17 обсуждались уже не раз, про нововведения писали на Хабре, проводили доклады на конференциях, поэтому снова их приводить здесь я не буду. Не секрет, что ключевой особенностью этого выпуска С++ стал перенос самых «вкусных» возможностей в неопределенное будущее. Что ж, теперь можно с уверенностью сказать, что многие долгожданные «фичи» переехали именно в С++20. Взятый курс на расширение stdlib никуда не делся, поэтому от C++20 можно ожидать гораздо большего и богатого набора функций. Как обычно, заранее прошу прощения за любые неточности.


Черновик стандарта С++20


Концепты


Многострадальные Concepts, когда-то не вошедшие в C++11, потом переделанные в виде нового предложения Concepts-Lite, наконец-то становятся частью стандарта.

По поводу краткого синтаксиса для концептов (terse syntax) комитету договориться пока не удалось; однако, обсуждение будет продолжаться в рамках С++20.

_VA_OPT_


#define LOG(msg, ...) printf(msg __VA_OPT__(,) __VA_ARGS__)

LOG("hello world")   // => printf("hello world")
LOG("hello world", ) // => printf("hello world")
LOG("hello %d", n)   // => printf("hello %d", n)


Явные обобщённые лямбда-функции (Explicit generic lambdas) [pdf]


[]  (T t) { /* ... */ }

Лямбда-функции были добавлены в язык в стандарте C++11, требовавшие указания конкретного типа; стандарт C++14 в свою очередь позволил объявлять параметры лямбда-функций со спецификатором типа auto:
[](auto x) { /* ... */ }

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

[](T x) { /* ... */ }
[](T* p) { /* ... */ }
[](T (&a)[N]) { /* ... */ }


shared_ptr для массивов [pdf]


shared_ptr p = make_shared(1024);

Тема поднималась неоднократно — например, здесь1.

Определение порядка байтов


Больше нет нужды прибегать к хитрым приёмам — на самом деле, компилятор и так всегда знал ответ, просто теперь он им сможет поделиться:
enum class endian
{
  little = __ORDER_LITTLE_ENDIAN__,
  big    = __ORDER_BIG_ENDIAN__,
  native = __BYTE_ORDER__
};


Улучшенная дедукция аргумента шаблона


vector v{vector{1, 2}};
 // Выведет vector вместо vector>


TS (Technical Specifications)



Перечисленные ниже TS отныне являются частью С++17 (уже обсуждались в прошлые разы):
  • Filesystem v1 [pdf] — порт boost::filesystem,
  • Parallelism v1 [pdf] — благодаря этому TS, большая часть библиотеки algorithm отныне будет доступна в «параллельной» версии,
  • Library Fundamentals v1 [pdf] — расширение стандартной библиотеки: std::string_view, std::optional, std::any, system_error.


Помимо этого, комитет опубликовал следующие технические спецификации, для которых компиляторы уже могут делать экспериментальные реализации (и они наверняка здесь обсуждались ранее):
  • Coroutines v1 — вокруг сопрограмм было много обсуждений
  • Ranges v1 — проскочили вслед за концептами, и, будем надеяться, попадут в С++20
  • Networking v1 — имеет все шансы попасть в C++20; библиотека для работы с сокетами, в основе которой лежит boost::asio.

Далее рассматриваются TS, работа над которыми все ещё продолжается.
Некоторые из них — но, определенно, не все — войдут в состав С++20.

Модули (Modules) [pdf]


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

Concurrency v1 [pdf]


Опубликован, и уже на следующей встрече будет частично принят в С++20. Содержит улучшения, которые сделают futures неблокирующими (в отличие от std::async), а также latches, барьеры и atomic smart pointers. Не вошел в С++17 по причине того, что был поздно опубликован и не получилось собрать достаточно практического опыта.
Непосредственно имплементация была вдохновлена MS Visual Studio, HPX и just::thread. Перед встречей были опасения, что новые предложения P0676 и P0701 могут отодвинуть принятие TS на неопределенный срок.

Transactional Memory v1 [pdf]


Опубликован, однако по этому TS еще совсем недавно у его же авторов оставались вопросы по части того, насколько быстрыми могут быть атомики и shared_ptr вне транзакций, если они должны с транзакцией взаимодействовать. Остается ждать разъяснений по поводу того, изменилось ли что-либо с прошлого раза.

Library Fundamentals v2


Опубликован. Нечто вспомогательное, потребуется для С++20.

Executors v1 [pdf]


В разработке. Должен войти в С++20, т.к. на него завязаны несколько других TS библиотек, связанных с гетерогенными вычислениями.

Reflection v1 [pdf]


В разработке. Есть все шансы попадания в С++20, ибо ему будет посвящена одна из грядущих встреч.

В основе TS лежат интроспекция кода и (с недавних пор) материализация (reification). По мнению комитета, TS пригодится в метапрограммировании, ставшему популярным благодаря Boost::Hana и аналогичных библиотек — а также для гетерогенных контейнеров.

Concurrency v2


В разработке на ранней стадии. Библиотека concurrent data structures, сoncurrent queues, lock-free алгоритмов и структур данных; включает в себя Hazard pointers (указатели опасности), RCU (безопасное освобождение памяти для lock-free контейнеров), atomic views. Вероятность попадания в С++20 крайне мала, т.к. находится еще на ранней стадии — при этом комитет осознает востребованность этого функционала и он, по словам автора, в самой активной разработке.

Parallelism v2


В разработке. Оказывается, за время разработки Parallelism v1 сделали не только Parallel STL для CPU, но и для GPU. Parallelism v2 —

Library Fundamentals v3


В разработке.

Contracts v1


В разработке. Будет либо TS, либо включение в стандарт С++20. Вкратце: улучшенная версия assert, которая позволяет проводить проверку пре- и пост- условий (т.е. инварианты). По мнению комитета, библиотека поможет С++ стать более безопасным языком, чтобы разработчики ПО для медицины, автомобилей, авиации и кибер-безопасности спали спокойней.

Numerics [pdf]


В разработке на ранней стадии. Кое-что из продвинутой арифметики наверняка войдет в С++20: decimal floating point, bounded types (например, fixed point types), unbounded types, multiprecision arithmetic. Должно пригодиться в работе в работе игровым разработчикам (которые, впрочем, привыкли сами писать то, что им требуется).

2D Graphics v1


На ранней стадии.

По мелочи


Идёт работа над добавлением новых функций к std::string — starts_with, ends_with.

Стоит заметить, что причиной появления сразу нескольких будущих TS стали распределенные и гетерогенные вычисления. Участники комитета понимают, что вот уже долгое время CUDA/OpenMP/OpenCL обгоняет нативный C++. В данный момент, все функции вроде std::invoke, std::async, параллельные алгоритмы и пр. предполагают, что std::thread используется исключительно на CPU; и даже несмотря на то, что черновик Executors TS содержит подвижки на этом фронте в виде включения в него новых фич, этого будет недостаточно, и работы предстоит еще очень много.

Уже продолжительное время эксперты из Google, NVidia, Codeplay и NASDAQ принимают участие в работе над черновиками грядущих TS, чтобы определить направление развития С++, и приоритеты будущего языка вам известны: Concurrency, Parallelism, Transactional Memory, и Networking.

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

Литература


Michael Wong — What's in C++20 and the C++17 final score card
Обсуждение
2017 Toronto ISO C++ Committee Discussion Thread (Concepts in C++20; Coroutines, Ranges and Networking TSes published)
C++17: The Language Features — Nicolai Josuttis
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/333414/


Метки:  

Разработка скриптов-обёрток с помощью инструмента Sparrow

Суббота, 15 Июля 2017 г. 22:45 + в цитатник

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


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


 script 

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


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


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

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


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


Установка Sparrow


Sparrow — это CPAN модуль, поэтому ставим его соответственно:


$ cpanm Sparrow 

Выбор скрипта, для которого будем писать обёртку


Так как это обучающая статья — выберу любой скрипт, в чисто ознакомительных целях, в реальной жизни, это будет скрипт или скрипты, которые вы используете в своей работе. Пусть это будет утилита speedtest-cli, предназначенная для тестирования скорости интернета на вашем локальном узле. Судя по документации, у скрипта достаточное большоеи количество настроек, задаваемых через аргументы командной строки — как раз тот самый случай, когда обёртка может быть уместна. Представим себе что мы хотим запускать данный скрипт по крону и отсылать отчёты что бы анализировать доступность интернета в течение определённого периода времени. Пердположим на интересуют два варианта вызова скрипта:


sppedtest-cli  --no-download # не выполнять тест скачивания 

и


speedtest-cli  --no-upload # не выполнять тест закачивания 

И в обоих случаях мы хотим всегда добавлять опцию


--bytes # выводить информацию в отчёте в байтах, а не в битах 

Также, допустим что в первом случае мы хотим указать тайм-аут ожидания при http запросах:


--timeout 10 # http тайм-аут 

Хорошо, таким образом у нас есть два отдельных запуска скрипта speedtest-cli с различными параметрами.


Написание скрипта-обёртки в виде Sparrow плагина


Создаём скрипт-историю:


$ nano story.bash

   speedtest-cli $(args_cli)

В данном случае всю работу делает предопределённая в Sparrow bash функция args_cli, котороя прозрачно передаст на вход скрипта speedtest-cli все входные параметры.


Определяем загрузчик утилиты speedtest-cli. Sparrow умеет ставить зависимости для скриптов, поддерживая ряд пакетных менеджеров, определённых для различных языков программирования, в том числе для Python. Утилита speedtest-cli ставится как pip модуль, так что просто определим файл зависимостей в стиле установщика pip:


$ nano requirements.txt

   speedtest-cli==1.0.6

Хорошо, идём дальше осталось определить файл с мета данными плагина и собственно загрузить его в репозиторий Sparrow плагинов:


$ nano sparrow.json

  {
     "name" : "speedtest-cli",
     "description" : "Simple wrapper for speedtest-cli from https://github.com/sivel/speedtest-cli",
     "version" : "0.0.1",
     "url" : "https://github.com/melezhik/sparrow-plugins/tree/master/speedtest-cli",
     "category": "utilities",
     "python_version" : 2,
     "sparrow_version": "0.2.45"
   }

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


Теперь у нас все готово, что бы загрузить плагин в репозитарий:


 $ sparrow plg upload # запускаем из дериктории где лежат файлы плагина

Настройка Sparrow задач для запуска скрипта-обёртки


Здесь собственно начинается самое интересное. Это то, как мы будем использовать созданный нами плагин для запуска утилиты speedtest-cli, описанной ранее.


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


$ sparrow plg install speedtest-cli

Если все пройдёт успешно мы получим установленный Sparrow плагин и собственно саму утилиту speedtest-cli вместе со всеми Python зависимостями.


Сделаем простую поверку, что плагин работает:


 $ sparrow plg run speedtest-cli -- --help

Если все хорошо, то мы получим help от утилиты speedtest-cli.


Что бы связать запускаемый плагин с определёнными параметрами создадим задачи. Вспоминаем, что нам требуется запускать speedtest-cli с разными аргументами.


 $ sparrow project create monitoring #  создадим проект - это контейнер для задач

 $ sparrow task add monitoring nettest-download speedtest-cli 
 $ sparrow task add monitoring nettest-upload speedtest-cli 

Последними двумя командами мы создали задачи для разных запусков утилиты speedtest-cli, теперь настроим их:


$ sparrow task ini monitoring/nettest-download

  --- 
  args:
     - timeout: 10
     - 
       - bytes
       - no-upload 

$ sparrow task ini monitoring/nettest-upload


  --- 
  args: 
     - 
       - bytes
       - no-download

Теперь нам просто отсатется запустить наши задачи:


$ sparrow task run monitoring/nettest-upload
$ sparrow task run monitoring/nettest-upload

Наши обёртки готовы и работают как надо.


Заключение


Sparrow позволяет легко и просто писать обёртки для практически любых консольных утилит. Это избавляет от необходимости писать отдельные скрипты для запуска одной и той же утилиты с различными параметрами, для этого есть простой и мощный инструмент Sparrow задач. Sparrow плагины переносимы практически на любой Linux сервер, где установлен Perl. Также настройка скриптов в стиле Sparrow подразумевает генерацию входных данных в форматах YAML и JSON, что сильно упрощает запуск подобных скриптов из любых современных языков программирования и делает их автоматизацию более простой. Для примера можно посмотреть проект Sparrowdo, который позволяет настраивать и запускать Sparrow задачи удалённо по ssh.


Ссылки по теме



С уважением, Алексей Мележик, автор Sparrow

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

https://habrahabr.ru/post/333410/


Метки:  

Метод BFGS или один из самых эффективных методов оптимизации. Пример реализации на Python

Суббота, 15 Июля 2017 г. 20:47 + в цитатник

Метки:  

А был ли взлом «Госуслуг»? Расследование расследования от ИБ Яндекса

Суббота, 15 Июля 2017 г. 16:19 + в цитатник
Вчера в сети появилась информация о том, что на сайте Госуслуг найден потенциально опасный код, и сегодня мы хотим поделиться с вами результатами собственного расследования и в очередной раз напомнить о важности применения Content Security Policy.



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

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



Такие фрагменты попадают в код страницы на стороне клиента, если у него установлено расширение. И здесь напрашивается вопрос: «как же тогда этот код оказался на стороне сервера?» И у нас есть гипотеза.

Мы считаем, что появление данного кода на страницах gosuslugi.ru не связано со взломом, целенаправленной атакой. Более вероятно, что у администратора, который редактировал содержимое этих страниц, было установлено подобное расширение. Оно внедрило посторонний код в документ, когда он загружался на сторону клиента, а на сервере он появился уже после того, как сотрудник сохранил свои изменения. В пользу этой версии говорит еще один факт. Мы внимательно мониторили все найденные фрагменты, и ни один из них так и не начал подгружать какой-либо контент – авторы кода вряд ли предполагали, что получат доступ к пользователям портала государственных услуг. Но это не означает, что угрозы не было — они могли начать делать это в любой момент, как только поняли, на страницах какого сайта оказался их код.

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

К счастью, в случае с Госуслугами пользователи Яндекс.Браузера по большей части уже были защищены: 15 найденных фрагментов из 16 уже были внесены в базу SafeBrowsing еще до ситуации с сайтом в рамках обычного процесса поиска угроз.

И еще кое-что. Иметь щит на стороне клиента хорошо, но и о защите на стороне сервиса тоже не стоит забывать. Мы рекомендуем всем крупным сервисам, работающим с приватными данными пользователей, внедрять поддержку Content Security Policy. Это позволит заблокировать подгрузку стороннего контента и защитить ваших пользователей. Сервисы Яндекса уже давно используют CSP для предотвращения загрузки постороннего кода.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/333404/


[Из песочницы] Рекомендации по безопасности при работе с Docker

Суббота, 15 Июля 2017 г. 16:00 + в цитатник

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


1. Достоверность образа


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


Если вы хоть когда-нибудь пользовались Docker, то вам должно быть известно, что с его помощью вы можете разместить контейнеры практически на любом образе — как на образе из официального списка поддерживаемых репозиториев, таких как NGINX, Redis, Ubuntu, или Alpine Linux, так и на любом другом.


В результате у нас есть огромный выбор.


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


Если вы со мной не согласны, давайте рассмотрим этот вопрос с другой стороны.


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


Я прав?


Ну и с таким же подозрением надо относиться к Docker-контейнерам.


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


Верно, никакой уверенности тут быть не может.


При таких условиях я могу дать три совета.


Используйте приватные или доверенные репозитории (trusted repositories)


Во-первых, можно использовать приватные или проверенные репозитории, вроде доверенных репозиториев Docker Hub.


В официальных репозиториях можно найти следующие образы:


  • Операционные системы (Ubuntu, например)
  • Языки программирования (PHP и Ruby)
  • Сервера (MySQL, PostgreSQL и Redis)

Что выделяет Docker Hub из других репозиториев, помимо прочего, — это то, что образы всегда сканирует и просматривает Docker’s Security Scanning Service.


Если вы не слышали об этом сервисе, то вот цитата из его документации:


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

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


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


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


Используйте Docker Content Trust


Еще один инструмент, которым стоит воспользоваться — Docker Content Trust.


Это новая функция, доступная в Docker Engine 1.8. Она позволяет верифицировать владельца образа.


Цитата из статьи о новом релизе, автор Diogo M'onica, ведущий специалист по безопасности Docker:


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

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


Docker Bench Security


Еще один инструмент, которым я недавно пользовался — это Docker Bench Security. Это большая подборка рекомендаций по развертыванию контейнеров в продакшене.


Инструмент основывается на рекомендациях из the CIS Docker 1.13 Benchmark, и применяется в 6 областях:


  • Конфигурация хоста.
  • Конфигурация демона Docker.
  • Файлы конфигурации демона Docker.
  • Образы контейнеров и build файлы.
  • Runtime контейнера.
  • Операции Docker security.

Чтобы его установить, клонируйте репозиторий при помощи


    git clone git@github.com:docker/docker-bench-security.git

Потом введите cd docker-bench-secutity и запустите такую команду:


    docker run -it --net host --pid host --cap-add audit_control \
    -e DOCKER_CONTENT_TRUST=$DOCKER_CONTENT_TRUST \
    -v /var/lib:/var/lib \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -v /etc:/etc --label docker_bench_security \
    docker/docker-bench-security

Таким образом, вы соберете контейнеры и запустите скрипт, который проверит безопасность хост машины и ее контейнеров.


Ниже пример того, что вы получите на выходе.


Docker Security Benchmark Sample


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


В моем случае необходимы некоторые исправления.


Что мне особенно нравится в этой функции, так это то, что ее можно автоматизировать.


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


2. Лишние полномочия


Теперь следующий момент. Насколько я помню, вопрос лишних полномочий всегда имел место. Что во времена установки дистрибутивов Linux на bare-metal сервера, что сейчас, когда их устанавливают в качестве гостевых операционных систем внутри виртуальных машин.


То, что теперь мы их устанавливаем внутри Docker-контейнера, не значит, что они стали существенно безопаснее.


К тому же с Docker повысился уровень сложности, т.к. теперь граница между гостем и хостом неясна. В отношении Docker я концентрируюсь на двух вещах:


  • Контейнеры, запущенные в привилегированном режиме
  • Лишние полномочия у контейнеров

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


Цитата из документации:


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

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


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


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


Цитата из Armin Braun:


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

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


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


В зависимости от того, где вы хостите ваши Docker-контейнеры, включая таких вендоров как DigitalOcean, sloppy.io, dotCloud и Quay.io, их дефолтные настройки могут отличаться от ваших.


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


Откажитесь от ненужных привилегий и возможностей


Не важно, где вы хоститесь. Как говорится в руководстве Docker по безопасности:


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

Подумайте над этими вопросами:


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

Если нет, то отключите эти возможности.


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


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


Чтобы это сделать, используйте опции --cap-drop and --cap-add.


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


docker run \
--cap-drop SETPCAP \
--cap-drop NET_BIND_SERVICE \
--cap-add SYS_MODULE \
-ti /bin/sh

Более подробные инструкции можно изучить в документации Docker: “Runtime privilege and Linux capabilities


3. Безопасность системы


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


Но насколько безопасен этот образ?


Например, какие права будут у злоумышленников, если они вдруг получат доступ к вашим контейнерам? Другими словами, насколько вы обезопасили свои контейнеры?


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


Docker, безусловно, безопасен по умолчанию, благодаря namespaceам и cgroupам, но не стоит беззаветно уповать на эти функции.


Вы можете пойти дальше и воспользоваться другими инструментами безопасности на Linux, такими как AppArmor, SELinux, grsecurity и Seccomp.


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


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


AppArmor


Это модуль безопасности ядра Linux, который позволяет системному администратору ограничить возможности программы с помощью индивидуальных профилей программ. Профили могут выдавать разрешения на такие действия как read, write и execute для файлов on matching paths. AppArmor предоставляет обязательный контроль доступа (mandatory access control, MAC) и таким образом служит хорошим дополнением к традиционной модели контроля Unix (discretionary access control, DAC). AppArmor включен в основное ядро Linux, начиная с версии 2.6.36.

Источник: Википедия.


SELinux


Security-Enhanced Linux (SELinux) — Linux с улучшенной безопасностью) — реализация системы принудительного контроля доступа, которая может работать параллельно с классической избирательной системой контроля доступа.

Источник — Википедия.


Grsecurity


Это проект для Linux, который включает в себя некоторые улучшения связанные с безопасностью, включая принудительный контроль доступа, рандомизацию ключевых локальных и сетевых информативных данных, ограничения /proc и chroot() jail, контроль сетевых сокетов, контроль возможностей и добавочные функции аудита. Типичной областью применения являются web-серверы и системы, которые принимают удалённые соединения из сомнительных мест, такие как серверы, которые обеспечивают shell-доступ для пользователей.

Источник — Википедия.


Seccomp


Это объект безопасности компьютера в ядре Linux. В версии 2.6.12, опубликованной 8 марта 2005 года, его объединили с основным ядром Linux. Seccomp позволяет перевести процесс в "безопасный" режим, из которого нельзя делать никаких системных вызовов, кроме exit(), sigreturn(), read() и write() уже открытых файловых дескрипторов. Если процесс пытается сделать какие-либо другие системные вызовы, то ядро убивает процесс с SIGKILL. Таким образом, Seccomp не виртуализирует системные ресурсы, а просто изолирует от них процесс.

Источник: Wikipedia.


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


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


4. Ограничьте потребление доступных ресурсов


Что нужно вашему приложению?


Это совершенно легкое приложение, потребляющее не более 50Мb памяти? Тогда зачем давать ему больше? Выполняет ли приложение более интенсивный процессинг, которому требуется 4+ CPU? Тогда дайте ему к ним доступ, но не более того.


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


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


Для этого используйте следующие команды для Docker:


    -m / --memory: # Установить лимит памяти
    --memory-reservation: # Установить мягкий лимит памяти
    --kernel-memory: # Установить лимит памяти ядра
    --cpus: # Ограничьте количество CPU
    --device-read-bps: # Ограничьте пропускную способность чтения для конкретного устройства

Вот пример конфига из официальной документации Docker:


    version: '3'
    services:
        redis:
        image: redis:alpine
    deploy:
        resources:
            limits:
                cpus: '0.001'
                memory: 50M
            reservations:
                memory: 20M

Больше информации можно найти при помощи команды docker help run или же в разделе “Runtime constraints on resources” документации Docker.


5. Большая поверхность атаки


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


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


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


Вы не в курсе статистики развертывания приложений в вашей организации? Тогда задайте себе следующие вопросы:


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

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


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


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


  • Когда пользователь создал свой аккаунт
  • Когда он его активировал
  • Когда пользователь последний раз менял пароль и т.п.

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


Не стоит этот учет излишне усложнять. Следует вести учет таких действий, как:


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

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


Вдобавок стоит внедрить уведомления по почте или любым другим способом (IRC, Slack или HipChat). Этот прием позволит убедиться, что все могут видеть, когда что разворачивается.


Таким образом, если случилось что-то неподобающее, спрятать это не получится.


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


Я не предлагаю вам нырнуть за борт и увязнуть в создании множества новых процессов.


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


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


Заключение


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


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


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


Об авторе


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




Данная статья является переводом Docker Security Best Practices

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

https://habrahabr.ru/post/333402/


Метки:  

Стоимость качества в разработке программного обеспечения

Суббота, 15 Июля 2017 г. 15:52 + в цитатник


  1. Что такое качество в разработке ПО?
  2. Во сколько нам обходится некачественное ПО?
  3. Кто отвечает за качество?

Для меня поводом задаться этими вопросами стала встреча с компанией в которой 3 месяца в году всё подразделение разработки (около сотни человек), занято устранением ошибок и дефектов, а остальные 9 месяцев они пишут ошибки софт для Заказчиков.

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

Что такое качество в разработке ПО?


На вопрос что такое качество в разработке ПО можно ответить с разных точек зрения. Свои ответы буду формулировать с точки зрения Пользователя-Заказчика и Руководителя компании.

С позиции Пользователя высокое качество ПО — это полное отсутствие ошибок и решение им задачи ради которого оно создавалось.

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

Средний уровень качества — всё что выше + отсутствие ошибок, которые существенно влияют на опыт использования ПО (Обязательные к устранению), при этом присутствуют ошибки, которые никак не влияют на решение бизнес-задачи: орфография, разные шрифты там где должен быть один и т.д. (Желательные к устранению).

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

Во сколько обходится нам некачественное ПО?


Часть 1: Подтверждение Дефекта


Когда Пользователь находит дефект он обращается к инженеру службы поддержки. Инженер СП пытается его воспроизвести и подтвердить что это дефект производства. Здесь возникают первые затраты из которых начинается складываться стоимость качества:
  • Затраты времени Пользователя — 1 ед.
  • Затраты времени Инженера СП — 1 ед.

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

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

Отсутствие документации особенно часто встречается когда практикуется быстрая разработка. Все помнят о «Работающий продукт важнее исчерпывающей документации», но забывают про то что ниже написано «То есть, не отрицая важности того, что справа, мы всё-таки больше ценим то, что слева».

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

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

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

Если им повезло найти ответ на свой вопрос, то всё заканчивается следующими затратами:
  • Владельца Продукта — 1 ед.
  • Инженер-Разработчик — 1 ед.
  • Заказчик — 1 ед.
  • Затраты времени Инженера СП — 1 ед.

Если не повезло, то их ожидает торг по поводу того считать ли это дефектом, который будет устраняться за собственный счёт, или новым требованием, которое будет оплачивать Заказчик. Допустим, что сторговаться не удалось, Заказчик продавил, считаем это дефектом и устраняем за собственный счёт.
  • Ухудшение репутации — 1 ед. (за счёт того, что Дефект и что пришлось привлечь Заказчика к расследованию)
  • Пока затраты на устранение дефекта здесь не учитываю, так как они добавятся чуть позже.

 Промежуточный итог:
  1. Затраты времени Пользователя — 1 ед.
  2. Затраты времени Инженера СП — 2 ед.
  3. Затраты времени Владельца Продукта — 1 ед.
  4. Затраты времени Инженера-Разработчика — 1 ед.
  5. Затраты времени Заказчика — 1 ед.
  6. Ухудшение репутации — 1 ед.
Стоимость качества — 7 единиц

Можно оптимизировать затраты в этой части заранее потратившись на подготовку пользовательской документации Тех.Писателем-Аналитиком, тогда это будет выглядеть вот так:
  1. Затраты времени Пользователя — 1 ед.
  2. Затраты времени Инженера СП — 1 ед.
  3. Затраты времени Тех.Писателя-Аналитика — 1 ед.
  4. Ухудшение репутации — 0,5 ед. (Потому что Дефект)
Стоимость качества — 3,5 единицы

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

Часть №2: Устранение Дефектов


Каждая «Блокирующая ошибка» порождает выпуск отдельного устраняющего патча-обновления. Это обновление проходит через стандартные процедуры тестирования, дабы не породить новых ошибок. Передаётся Инженеру СП для распространения среди Клиентов, которые пользуются версией ПО, в которой была найдена эта ошибка, и закрытия «тикета» дефекта. Затраты:
  • Инженер-Разработчик — 1 ед.
  • Инженер-Тестировщик — 1 ед.
  • Инженер СП — 1 ед.

«Обязательная к устранению ошибка» устраняется в следующим плановом релизе (версии), поэтому затраты на устранение ниже, так как затраты на сборку релиза и регрессионное тестирование ложатся на новые функции и не попадают в стоимость устранения ошибки. Дополнительных затрат на работу Инженера СП также нет кроме закрытия «тикета». Затраты:
  • Инженер-Разработчик — 0,5 ед.
  • Инженер-Тестировщик — 0,5 ед.

Затраты в обоих случаях оплачиваются из прибыли компании.
Стоимость качества — 4 единицы.

Часть №3: Недопущение Дефектов (Качество основанное на контроле)


Чтобы Пользователи не находили Дефекты для этого есть собственные Инженеры по тестированию. Для них критерий эффективности 100% ошибок — 0% дефектов.

Информация о найденном дефекте передается Инженеру по тестированию для анализа причин пропуска дефекта при тестировании и внесения изменений в методики и инструменты тестирования. Затраты:
  • Инженера-Тестировщик — 1 ед.

Эффективная работа здесь сводит на нет следующие затраты времени
Части 1:
  1. Пользователя — 1 ед.
  2. Инженера СП — 1 ед.
  3. Ухудшение репутации — 0,5 ед.
Части 2:
  1. Инженер-Разработчика — 1,5 ед.
  2. Инженер-Тестировщика — 1,5 ед.
  3. Инженер СП — 1 ед.
Стоимость — 6,5 ед. Вложения — 1 ед. Экономия — 5,5 единиц.

Часть №4: Устранение Ошибок


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

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

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

Затраты здесь:
  1. Ухудшение репутации — 1 ед.
  2. Инженер-Разработчик — 1 ед.
  3. Инженер-Тестировщик — 1 ед.
  4. Потерянный доход — 2 ед. (п.2 + п.3)
Стоимость качества — 5 единиц.  

Часть №5: Недопущение Ошибок (Качество основанное на развитии производственного процесса)


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

Допущенные ошибки передаются на анализ Руководителю Разработки (Тим-Лиду) для выявления причин, сотрудников, которые их чаще допускают, и чаще «болеющих» продуктов. Эта работа выливается в ряд мероприятий по код-ревью, дополнительному обучению Инженеров-Разработчиков по темам где недостаёт квалификации и т.д.
  • Затраты Руководителя-Разработки — 1 ед.
  • Затраты Инженера-Разработчика — 1 ед.

Эффективная работа здесь сводит на нет следующие затраты Части 4:
  1. Инженер-Разработчик — 1 ед.
  2. Инженер-Тестировщик — 1 ед.
  3. Потерянный доход — 2 ед.
  4. Ухудшение репутации — 1 ед.
Стоимость — 5 ед. Вложения — 2 ед. Экономия — 3 единицы.

Общий расчёт стоимости качества


Обычно ситуация выглядит так: Мы ведем разработку, допускаем ошибки, порой их устранение требует более двух итераций и несмотря на эту работу Пользователи всё равно находят дефекты в ПО, которые нам приходится исправлять путем выпуска дополнительных обновлений.
Вид затрат Часть 1 Часть 2 Часть 4 Итого
Затраты времени Пользователя 1 - - 1
Затраты времени Инженера СП 2 1 - 3
Затраты времени Владельца Продукта 1 - - 1
Затраты времени Инженера-Разработчика 1 1,5 1 3,5
Затраты времени Заказчика 1 - - 1
Затраты времени Инженера-Тестировщика - 1,5 1 2,5
Ухудшение репутации 1 - 1 2
Потерянный доход - - 2 2
Итого 7 4 5 16
Если будем готовить документацию по факту выполненной разработки, вложив 1 единицу ресурса Технического Писателя, то это сэкономит 3,5 единицы и стоимость качества снизится с 16 до 12,5. (Структура затрат: Документирование + Подтверждение Дефекта + Устранение Дефекта + Устранение Ошибок)

Обеспечив недопущение дефектов, вложив в это дополнительные затраты времени Инженера-Тестировщика в размере 1 единицы, стоимость качества снизится с 12,5 до 7 единиц. (Структура затрат: Документирование + Недопущение Дефектов + Устранение Ошибок)

Недопущение ошибок потребует вложения 2 единиц, по одной от Инженера-Разработчика и Руководителя-Разработки, и снизит стоимость качества с 7 до 4 единиц. (Структура затрат: Документирование + Недопущение Дефектов + Недопущение ошибок)

Если вложимся в то, что Технический Писатель — Аналитик начнёт писать пользовательскую документацию про то как система должна решать бизнес-задачу Пользователя ещё до разработки, то, возможно, не придется:
  1. Не только спорить с Заказчиком дефект это или нет, но и вообще общаться с ним по поводу дефектов.
  2. Анализировать причины по которым ошибки в выполнении целевых задач ПО проскочили к Пользователям через этап Тестирования.
  3. Анализировать причины по которым Разработчик сделал так, что программа работает не так как должна и отдал это в Тестирование.
  4. Тратится на дополнительные мероприятия по недопущению ошибок и дефектов, когда проектная документация отсутствует и нужно что-то придумывать чтобы компенсировать её отсутствие.
И на это нужна всего 1 единица затрат. (Качество основанное на развитии процесса проектирования продукта)



Кто отвечает за качество?


В западных компаниях есть такая позиция Quality Assurance Engineer, который отвечает за весь процесс выпуска программного обеспечения и фокусируется на аспекте обеспечения качества.

У нас Software Quality Assurance (Обеспечение качества ПО) утрировано до восприятия как Тестирование, а Quality Assurance Engineer до Инженер-Тестировщик. Но Инженер-Тестировщик максимум что может сделать это найти все ошибки и вернуть их Software Ingineer (Инженеру-Разработчику), но он никак не влияет на их появление.

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

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

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

Есть ещё Product Owner (Владелец Продукта), который как владелец подходит на роль Отвечающего за Качество Продукта. По этой причине их порой делят на две позиции Marketing Product Manager (Менеджер по продукту) и Software Delivery Manager (Менеджер по выпуску ПО). Первый отвечает за развитие продукта с точки зрения рынка (работа с Заказчиками и требованиями), а второй за развитие производственного процесса выпуска продукта.

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

Поделить ответственность по этапам Software Development Life Cycle (Жизненного цикла разработки ПО) не получается. Как только это деление начинается, неэффективная работа по середине сразу делает бессмысленной работу сделанную в начале и нагружает дополнительной работой как тех кто стоит в конце, так и всю производственную цепочку заводя на её вход ошибку для устранения.

Заключение


Это классический подход к работе с качеством из промышленности, который основан на трёх методах:
  1. Качество через проверку готового продукта (тестирование: отлавливание ошибок и дефектов)
  2. Качество через развитие производственного процесса (предотвращение ошибок в ходе производства)
  3. Качество через развитие процесса проектирования продукта (предотвращение ошибок закладываемых в скелет-основу продукта при проектировании)
И основным посылом: необходимо больше внимания уделять работе с причинами, а не работе с последствиями.

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

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

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

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

Что с этим делать? — мне нравятся ответы данные в статье «Будущее гибкой разработки».

Что ещё почитать по теме:


  1. Будущее гибкой разработки
  2. Что такое качество программного обеспечения?
  3. Управление качеством проекта
  4. Карьера в IT: должность QA engineer
  5. Гуру менеджмента качества и их концепции: Э.Деминг, Дж.Джуран, Ф.Кросби, К.Исикава, А.Фейгенбаум, Т.Тагути


Уделите пару минут ответу на три вопроса, так вы поможете провести диагностику средней температуры отношения и внимания к качеству ПО в ИТ-отрасли нашей страны на 1 августа 2017 года. +1 вам в карму за это доброе дело.
Кто отвечает в вашей компании за качество?

Никто ещё не голосовал. Воздержался 1 человек.

Какой стратегии (ям) по обеспечению качества следует ваша компания?

Никто ещё не голосовал. Воздержался 1 человек.

Как много ошибок приходится устранять в новом релизе?

Никто ещё не голосовал. Воздержался 1 человек.

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

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

https://habrahabr.ru/post/332724/


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

Суббота, 15 Июля 2017 г. 15:13 + в цитатник
image

Несмотря на то, что понятие «виртуальная реальность» уже не первый год мелькает перед глазами, оно до сих пор остается загадкой для большинства людей, а цены на аксессуары, связанные с этим развлечением, могут уходить в бесконечность. Но существует бюджетный вариант. Среднестатистический человек, интересующийся новыми технологиями, может позволить себе смартфон с гироскопом, встроенный в Google Cardboard или любой аналог этого нехитрого устройства и простой джойстик с парой кнопок. В наше время такой вариант знакомства с этой технологией наиболее распространенный. Но, как и многие другие технологичные новинки, вроде квадрокоптеров, интересная игрушка быстро превращается в пылящуюся на полке. Практическое применение сильно ограничено. Взрослые люди, купившие очки виртуальной реальности, первые дни играются в игрушки, смотрят различные видео с прекрасными барышнями, радуются, как дети. Это здорово. Новые впечатления всегда полезны. Но быстро приходит понимание, что графика в игрушках находится на уровне конца 90-х, видео наскучивает, а другого практического применения очкам для этих людей нет. Для отдельных разработчиков, дизайнеров и экспериментаторов очки становятся инструментом в работе, но обычный потребитель кладет их на полку и забрасывает. Было бы интересно применить эту технологию в интернете на обычных сайтах. В этой статье мы попробуем с помощью Javascript адаптировать привычную нам верстку под новые условия отображения. Информации по теме пока не много, статья носит характер эксперимента, так что всем заинтересованным людям, а также тем, кто имел подобный практический опыт, заранее предлагается присоединиться к обсуждению и поделиться своими мыслями и опытом в комментариях.



Введение


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

Что-то получаем, но и что-то теряем


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

image

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

Потребление контента. Все-таки плоскости?


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

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

А вот с текстом все интереснее. Первым делом, оказавшись в виртуальном пространстве, возникает мысль об отходе от идеи плоского монитора и расположении текста на кривой поверхности. Шарик? А пользователь в центре. Почему бы и нет. Но лучше все же сохранить вертикальные оси на повержности, а то и вырвать может от такого интерфейса. Раньше мы не задумывались о таком? А теперь придется. На некоторых игрушках делают предупреждения для эпилептиков, а теперь видимо будут для людей с проблемами с вестибулярным аппаратом. Цилиндрическая поверхность кажется хорошим выбором. Одинаковое «расстояние» до текста во всех точках должно снизить нагрузку на глаза (по сравнению с огромным монитором), эффективное использование пространства…

image

Но реальность бьет очень больно. Из-за искажений читать такой текст очень сложно, причем это усугубляется плохим качеством дисплеев у большинства смартфонов — буквы по краям области видимости превращаются в мыльно-пиксельное нечто. А постоянно крутить головой на каждой строчке текста — не вариант. Похоже, что в ближайшем будущем мы будем ограничены плоскостями в 3d. Придется склониться к призме — три вертикальных монитора мы можем встроить в наше пространство и при этом более-менее сохраним читаемость текста. Причем желательно разместить их так, чтобы при повороте головы к «монитору» взгляд попадал ровно в его центр и линия взгляда была перпендикулярна плоскости монитора. Таким образом искажения будут минимальными. Если вы пробовали сидеть под углом к монитору, то поймете о чем я. Почему три? Можно было бы сделать еще пару мониторов за спиной, но если предполагать длительную работу, то нужно будет иметь здоровье космонавта, чтобы вращаться на стуле целый день. Некоторых людей и без очков от пары оборотов хватит весьма неприятный приступ головокружения и помутнение в глазах. Так что имеет смысл ограничить угол обзора. Возможно стоит произвести эксперименты с частью додекаэдра, а не с призмой, но мне пока сложно представить интерфейс, построенный на пятиугольниках.

А что со вводом?


Трехмерный контроллер — вещь интересная. Но… Вы когда-нибудь видели обычного художника, который рисует на мольберте? Формально он не занимается физическим трудом — кисточка весит несколько граммов (ну может пару десятков), но после полного дня рисования рука у него просто отваливается. Да и спина устает, что бы там не говорили. Вот у трехмерных контроллеров та же проблема. Ослабленные от многих лет лежания на столе и печатания на клавиатуре руки не могут весь день находиться в подвешенном состоянии. Так что для игр — здорово, для отдельных этапов 3d-моделирования — может быть, но для постоянной работы такой вид контроллера плохо приспособлен. Остается вариант, когда рука лежит и нажимает несколько кнопок. Но и это уже хорошо. На контроллерах кнопок обычно больше, чем на стандартной мышке (для пользователей топовых моделей от Razer напомню, что их там две + колесико).

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

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

Попробуем что-нибудь сделать.


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

....
....
....


Вариантов использовать обычную разметку HTML + CSS в трехмерном пространстве не так уж и много. Но существуют пара рендереров для Three.js, которые сразу привлекают к себе внимание. Один из них, который называется CSS3DRenderer, позволяет взять нашу разметку и отрендерить ее на плоскости. Это вполне подходит под нашу задачу. Второй, CSS3DStereoRenderer, который мы и будем использовать, делает то же самое, но делит экран на две части, создает как бы два изображения, по одному для каждого глаза.

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

var scene    = null,
    camera   = null,
    renderer = null,
    controls = null;

init();
render();
animate();

function init() {
    initScene();
    initRenderer();
    initCamera();
    initControls();
    initAreas();
    initCursor();
    initEvents();
}

function initScene() {
    scene = new THREE.Scene();
}

function initRenderer() {
    renderer = new THREE.CSS3DStereoRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.domElement.style.position = 'absolute';
    renderer.domElement.style.top = 0;
    renderer.domElement.style.background = '#343335';
    document.body.appendChild(renderer.domElement);
}

function initCamera() {
    camera = new THREE.PerspectiveCamera(45,
            window.innerWidth/window.innerHeight, 1, 1000);
    camera.position.z = 1000;
    scene.add(camera);
}


Второй компонент, который мы сразу добавим, — это DeviceOrientationController, который позволит использовать поворот устройства для ориентации в 3d-пространстве. Технология определения положения устройства является экспериментальной, и, мягко говоря, на сегодняшний день работает так себе. Все три устройства, на которых она проверялась, вели себя по-разному. Это еще усугубляется тем, что помимо гироскопа (а, возможно, и вместо него) браузером используется компас, который в окружении различного железа и проводов ведет себя сильно неадекватно. Мы будем использовать именно этот контроллер еще и для того, чтобы сохранить возможность использования обычной мышки при оценке результатов эксперимента.

function initControls() {
    controls = new DeviceOrientationController(camera, renderer.domElement);
    controls.connect();

    controls.addEventListener('userinteractionstart', function () {
        renderer.domElement.style.cursor = 'move';
    });

    controls.addEventListener('userinteractionend', function () {
        renderer.domElement.style.cursor = 'default';
    });
}


CSS3DRenderer, как мы уже сказали, дает возможность использовать обычную разметку в нашем 3d примере. Создание CSS объектов при этом похоже на создание обычных плоскостей.

function initAreas() {
    var width = window.innerWidth / 2;

    initArea('.vr-area.-left',   [-width/2 -width/5.64,0,width/5.64], [0,Math.PI/4,0]);
    initArea('.vr-area.-center', [0,0,0], [0,0,0]);
    initArea('.vr-area.-right',  [width/2 + width/5.64,0,width/5.64], [0,-Math.PI/4,0]);
}

function initArea(contentSelector, position, rotation) {
    var element = document.querySelector(contentSelector),
        area = new THREE.CSS3DObject(element);

    area.position.x = position[0];
    area.position.y = position[1];
    area.position.z = position[2];

    area.rotation.x = rotation[0];
    area.rotation.y = rotation[1];
    area.rotation.z = rotation[2];

    scene.add(area);
}


Далее опять идут стандартные для почти всех демок Three.js функции для анимации и изменения окна браузера.

function initEvents() {
    window.addEventListener('resize', onWindowResize);
}

function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();

    renderer.setSize( window.innerWidth, window.innerHeight );

    render();
}

function animate() {
    controls.update();
    render();
    requestAnimationFrame(animate);
}

function render() {
    renderer.render(scene, camera);
}


А вот дальше начинается интересное. CSS3DStereoRenderer по своей сути создает два идентичных дерева элементов, которые с помощью CSS-трансформаций выстраиваются в нужном месте. Иными словами, магии в этом рендерере нет. А то, что есть, создает проблему. Как можно взаимодействовать с интерактивными элементами, если они все продублировались? Мы не можем сфокусироваться на двух элементах одновременно, не можем сделать двойной :hover, вообщем маленькая засада. Вторая проблема — id элементов, которые могут быть только в единственном экземпляре на странице. Но если id можно и не использовать, то над взаимодействиями нужно плотно подумать.

image

Единственным способом, который позволит управлять внешним видом двух элементов одновременно — это добавление и удаление к ним каких-то CSS классов. Также мы можем имитировать click(). Кликать на несколько элементов мы можем, это не ведет к странному поведению браузера. Таким образом, мы можем сделать второй курсор в центре поля зрения (не всего экрана, а именно в центрах его половин, предназначенных для разных глаз). Для того, чтобы узнавать элемент, находящийся под курсором, мы можем использовать функцию document.elementFromPoint(x, y). В этот момент кажется очень полезным тот факт, что рендерер использует трансформации, но сами элементы остаются стандартными DOM-элементами. Нам не нужно придумывать геометрию с пересечением луча с плоскостью, на которой рендерится контент, поиском координат пересечения и определением элементов на плоскости по этим координатам. Все гораздо проще. Стандартная функция вполне справляется с этой задачей.

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

function initCursor() {
    var x1 = window.innerWidth * 0.25,
        x2 = window.innerWidth * 0.75,
        y = window.innerHeight * 0.50,
        element1 = document.body,
        element2 = document.body,
        cursor = document.querySelector('.fake-cursor');

    setInterval(function() {
        if (element1 && element1.classList) {
            element1.classList.remove('-focused');
        }

        if (element2  && element2.classList) {
            element2.classList.remove('-focused');
        }

        element1 = document.elementFromPoint(x1, y);
        element2 = document.elementFromPoint(x2, y);

        if (element1 && element2) {
            while (element1.tabIndex < 0 && element1.parentNode) {
                element1 = element1.parentNode;
            }

            while (element2.tabIndex < 0 && element2.parentNode) {
                element2 = element2.parentNode;
            }

            if (element1.tabIndex >= 0) {   
                element1.classList.add('-focused');
            }

            if (element2.tabIndex >= 0) {
                element2.classList.add('-focused');
            }
        }
    }, 100);
}


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

document.addEventListener('keydown', function(event) {
    if (event.keyCode === 13) {
        if (element1 && element2) {
            element1.click();
            element2.click();

            cursor.classList.add('-active');

            setTimeout(function() {
                cursor.classList.remove('-active');
            }, 100);
        }
    }
});


Что же там получилось?


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





Мысли вместо заключения.


Эксперимент интересный. Да, до реального применения еще очень далеко. Браузеры пока еще очень плохо поддерживают определение положения устройства в пространстве, возможности для калибрации компаса можно сказать отсутствуют (формально есть событие compassneedscalibration, но на практике толку от него не очень много). Но в целом идея создания интерфейса в трехмерном пространстве вполне реализуема. По крайней мере на десктопе мы уже точно можем такое применять. Если заменить стерео-рендерер на обычный, а камеру поворачивать просто по движению мыши, то получим что-то похожее на обычную трехмерную игрушку, только с возможностью использовать bootstrap все любимые инструменты верстальщика.

Полные исходники примера доступны на GitHub
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/333400/


Метки:  

[Из песочницы] PHP Reflection на замыканиях

Суббота, 15 Июля 2017 г. 13:32 + в цитатник

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


image


Я активно использую Laravel в своих проектах. Для тех, кто не знаком с этим framework'ом — не отчаивайтесь, потому что я объясню непонятные моменты.


В этот раз я писал некоторое расширение правил валидации:


Validator::extend('someRule', function ($attribute, $value, $parameters, $validator) {
        // some code...
        return $result; // boolean
}, ':attribute is invalid');

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


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


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


Validator::extend('someRule', function ($attribute, $value, $parameters, $validator) {

        // Это функция-ниндзя. Она врывается в валидатор и крадет приватное свойство.
        // Это очень коварно и подло но у меня нет другого выбора (есть, но там писать больше)
        $ninja = function() { 
                // именно в этом свойстве хранится массив с нужными мне данными
                return $this->initialRules;
        };
        $initialRules = $ninja->call($validator); // параметр $newThis

        // some code
        return $result;

}, ':attribute is invalid');

Если кто-то еще не понял, объясню: я создал анонимную функцию, которая возвращает некоторое свойство. А потом просто подменил контекст на контекст валидатора (laravel передает экземпляр этого класса). Тоесть, замыкание теперь имеет доступ к этому объекту изнутри и может получить доступ к любому приватному свойству и методу.


Работает вся это красота, начиная с PHP 5.4


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


Спасибо за внимание.

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

https://habrahabr.ru/post/333396/


Метки:  

Акции Яндекса взлетели после сделки с Uber

Суббота, 15 Июля 2017 г. 12:15 + в цитатник


Сервис Яндекс.Такси сообщил об объединении с Uber. Совместное предприятие, которое создадут компании, будет работать в нескольких странах СНГ. В результате заявления Яндекса стоимость его акций резко выросла как в России, так и на зарубежном рынке.

Подробности сделки


13 июля в блоге Яндекса появилась запись об объединении сервиса такси, принадлежащего компании, с Uber. Генеральный директор Яндекс.Такси Тигран Худавердян сообщил, что в результате слияния появится новая компания. Она будет работать в 127 городах России, Беларуси, Казахстана, Грузии, Армении и Азербайджана.

В июне Яндекс и Uber осуществили суммарно 35 млн поездок в этих регионах. Их общая стоимость составила 7,9 млрд рублей. Это позволяет новому игроку занять 5-6% рынка легальных перевозок на такси. Общий объем этого сегмента в 2016 году составил 502 млрд рублей.

В создание нового игрока на рынке Яндекс и Uber вложили $100 млн и $225 млн соответственно. Стоимость объединённой компании оценивается в $3,725 млрд. При этом 59,3% объединения будет владеть Яндекс, 36,6% — Uber. Ещё 4,1% достанется сотрудникам новой компании.

Стоит отметить, что Яндекс.Такси в России работает в убыток по EBITDA, хоть и появился на местном рынке в 2011 году. Эксперты прогнозировали, что компания станет прибыльной к 2021 году. В апреле сообщалось, что Яндекс.Такси ищет инвестора.

Что касается Uber, компания не раскрывает финансовых данных по России, но в целом за 2016 год её выручка составила $6,5 млрд, а чистый убыток — $2,8 млрд. До этого Uber также был убыточным.



Изображение:joiseyshowaa, CC BY-SA 2.0

Сделка с Яндекс.Такси — не первый подобный опыт для Uber. Годом ранее китайское подразделение компании было объединено местным лидером Didi Chuxing. Тогда Uber получил 17,5% новой компании, общая стоимость которо оценивалась в $35 млрд. Избавиться от китайского подразделения Uber решил, за 1,5 года работы в стране потерял более $2 млрд.

Слияние Яндекс.Такси и Uber стало неожиданностью. Компании не объявляли о ведении переговоров, а в деловых СМИ обсуждалась разве что возможность покупки Яндексом служб такси «Максим» и InDriver.

Сделку о слиянии планируется закрыть в четвертом квартале 2017 года. До этого соглашение должно быть одобрено ФАС. Антимонопольная служба опасается, что новый игрок рынка создаст угрозу конкуренции. Однако ходатайств об объединении бизнеса компаний в ФАС пока не получили. Как бы то ни было, сделка уже оказала влияние и на сами компании, и на рынок в целом. В частности, цена акций Яндекса побила исторический рекорд.

Взлёт акций Яндекса


После объявления о слиянии с Uber цена акций Яндекса поползла вверх. В ходе торгов на фондовой бирже NASDAQ она выросла на 16%, составив $31,70. Таким образом, всего за день рыночная стоимость компании на международном рынке выросла на $1,36 млрд, составив $10,73 млрд.

На российском рынке новость о слиянии двух игроков также наделала шума. О сделке стало известно 13 июля в 13.00, а уже в 13.40 стоимость ценных бумаг Яндекса на Московской бирже поднялась на 17%, составив 1915 руб.

К 14.47 МСК торговлю пришлось перевести в режим дискретного аукциона, поскольку рост цены перевалил за 20%. Максимальная стоимость акция Яндекса 13 июля составила 2039,5 руб., что на 24,97% выше цены закрытия предыдущих торгов.

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

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

https://habrahabr.ru/post/333392/


Метки:  

Конкурс по программированию: JSDash (промежуточные результаты)

Суббота, 15 Июля 2017 г. 11:54 + в цитатник
Спасибо всем, кто уже принял участие в нашем конкурсе по программированию! Приём решений ещё не окончен, но мы решили протестировать те решения, которые нам уже прислали, и опубликовать промежуточные результаты. Пока что мы получили 10 решений от 11 уникальных участников. Мы надеемся получить ещё много решений, поэтому итоговые результаты могут сильно отличаться от этих. Если нам пришлют достаточно много новых решений, проведём ещё одно промежуточное тестирование.

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

Для этого раунда тестирования мы выбрали в качестве затравочных значений (seeds) последовательность так называемых «магических чисел»: 2, 8, 20, 28, 50, 82, 126. В финальном тестировании, результаты которого определят победителей, числа будут другими, поэтому нет смысла вручную затачивать решения конкретно под эти уровни.

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

Ещё есть время, чтобы обойти нынешних лидеров. Присылайте свои решения!
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/333390/


[Из песочницы] История создания библиотеки для группового общения андроид-устройств через Wi-Fi Peer-to-Peer соединение

Суббота, 15 Июля 2017 г. 11:26 + в цитатник
image

Предыстория


Мотивом написания данного приложения послужила курсовая работа по дисциплине «Компьютерные системы и сети». Честно говоря, эта одна из самых мной нелюбимых сторон в компьютерных технологиях, и я решил «подстраивать» курсовой проект под свои интересы, а именно, под Андроид-разработку.

Было решено создать библиотеку для соединения Андроид-устройств по средством Wi-Fi Direct технологии и передачи данных между ними (Wi-Fi Peer-to-Peer соединение осуществляется как раз с помощью технологии Wi-Fi Direct).

Почему Wi-Fi Direct?


После одобрения идеи о локальном соединении устройств передо мной встал вопрос: С помощью какой технологии собираюсь я это осуществить? Рассматривались следующие варианты:

  • Bluetooth
  • Wi-Fi Hotspot
  • Wi-Fi Direct или Wi-Fi Peer-to-Peer

Bluetooth


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

Wi-Fi Hotspot


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

Однако с помощью Wi-Fi Hotspot можно добиться максимальной скорости передачи данных (приложения Portal, SHAREit).

Wi-Fi Direct или Wi-Fi Peer-to-Peer


Данный подход решает все вышеупомянутые проблемы:

  1. неограниченное кол-во клиентов (если не так, прошу меня поправить)
  2. большой радиус действия
  3. соединение с устройствами по средством Wi-Fi без создания точки доступа
  4. технология поддерживается с API 14 (Android 4.0)

Но сразу закрадывается сомнение, мол Wi-Fi Peer-to-Peer, тогда как мы собираемся создать группу с владельцем и клентами, и тем более, чтобы все друг с другом общались. Это как раз-таки и является основной причиной написания данной статьи.

Wi-Fi Aware


Этот вариант не упоминал в основном списке, т.к. не считаю, что он может полноценно подойти для выполнения поставленной задачи. Однако Wi-Fi Aware является сравнительно молодой технологией для рассылки сообщений в определенном радиусе действия.

Начнем с проблем


Скажу честно, предоставляемая документация by developer.android.com давалась мне нелегко. И я начал искать сэмплы. Перебрав кучу материала, наткнулся на наиболее интересный sample by Google.

Никогда не думал, что на официальном сайте от Google можно найти говнокод, но это как раз тот случай. Однако даже этому стоит отдать должное, так как благодаря данному ресурсу я реализовал то, что хотел.

В сэмпле продемонстрирован пример чата двух устройств, которые нашли друг друга в списке, отображающем рядом находящиеся Wi-Fi Direct устройства с запущенным приложением чата. При выборе партнера непосредственно открывается ChatActivity.

Очень важным моментом является поиск собеседников: в списке не будут отображаться такие Wi-Fi Direct устройства, как телевизор или какая-нибудь гарнитура. Отображаются только устройства с запущенным Chat-приложением.

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

Что было реализовано для демонстрации работоспособности библиотеки


Приложение представляет следующий функционал:

  1. выбор роли в процессе работы с приложением (для примера были созданы «Мафия» и «Мирный житель»)
  2. создание группы
  3. присоединение к существующей группе
  4. общение между устройствами (при нажатии на кнопку меняется ее цвет как у инициатора, так и у всех остальных, соответствующих текущей роли (либо broadcast))

image

Описание экранов слева-направо:

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

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

image

Основная концепция работы библиотеки


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

В приложении присутствуют собственные Serializer/Deserializer для преобразования передаваемых данных в массив байтов и обратно. В передаваемых данных хранится следующая информация:

  • кому отправить (мафии, мирным жителям, всем)
  • какого рода данные (например: изменение цвета кнопки)
  • сами данные (сериализованный Object)

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

Компоненты библиотеки


image

  • WifiDirectManager — основной класс библиотеки; отвечает за создание группы, поиск устройств, присоединение устройства в группу или приглашение в нее, отправка пакета данных всем участникам группы
  • WifiP2pDeviceObservable — реализация паттерна Observable; при нахождении Wi-Fi Direct устройства оповещает наблюдателя
  • WifiDirectBroadcastReceiver занимается оповещением приложения об изменениях Wi-Fi Direct соединения (например: удачно ли прошло соединение с другим устройством), состояния Wi-Fi на устройстве (например отключение должно последовать за собой предупреждение пользователя о невозможном продолжении работы приложения)
  • MessageShaper отвечает за сериализацию/десериализацию передаваемых данных; при десериализации на выходе получаем объект типа android.os.Message (obj — объект, what — для каких целей объект (например: поменять цвет кнопки), arg1 — тип доступа (для мафии, мирных жителей, либо broadcast))
  • Serializer непосредственно занимается сериализацией/десериализацией объектов
  • Status — характеризует каждое устройство как владельца группы, либо клиента
  • ChatNeedle хранит в себе сокет, по которому связаны два устройства между собой; обрабатывает input/output стримы данных; у клиента есть лишь один ChatNeedle — с владельцем, у владельца же их кол-во равняется кол-ву клиентов
  • Member — класс, описывающий участника группы (не себя самого), для дальнейшего использования в игровом сценарии; хранит в себе ChatNeedle для соединения с этим участником группы
  • MemberList — класс, хранящий в себе все устройства, с которыми связан наш девайс; в случае с владельцем группы — все клиенты, в случае клиента — владелец
  • GroupOwnerSocketHandler применяется владельцем группы для открытия определенного кол-ва сокетов, к которым подсоединяются клиенты
  • ClientSocketHandler используется для установления соединения клиента с владельцем группы

Самая сложная проблема во время разработки


Когда проект дошел до стадии тестирования мультиплеера (> 2 устройств), тут-то и началась жара. Два устройства как и прежде у меня соединялись без проблем (для чего впрочем и создан Wi-Fi Peer-to-Peer), однако при подсоединении третьего звена почти всегда происходил треш. При нажатии на кнопку у «владельца» (позже поймете, почему в кавычках) цвет менялся только у того клиента, с которым «владелец» последний раз общался.

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

До этого я считал, что тот девайс, который подсоединяется к другому, всегда будет клиентом… а это далеко не так. При соединении устройств рандомно передавались права владельца одному из них, что и побудило меня на поиск настройки config'a, который бы исправил эту ситуацию, и сделал подсоединяемое устройство клиентом.

При соединении двух устройств прописывается специальный config, который в себе содержит:

  • адрес устройства, к которому мы хотим присоединиться
  • wps.setup позволяет установить, как мы будем соединяться: с паролем или просто по нажатию кнопки
  • groupOwnerIntent — вот он (споймал!), тот, кто решил мою проблему; целочисленное поле, значение которого варьируется от 0 до 15 (0 — хотим быть клиентом, 15 — хотим быть владельцем); по умолчанию -1, что дает системе право самой выбрать роль в этой связи

        final WifiP2pConfig config = new WifiP2pConfig();
        config.deviceAddress = deviceAddress;
        config.wps.setup = WpsInfo.PBC;
        config.groupOwnerIntent = status.getIntent();
        mWifiP2pManager.connect(mWifiP2pManagerChannel, config, null);

Status'ом (enum) выше является текущее положение устройства, если он создатель группы — GroupOwner, иначе — Client.

Необходимые доработки


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

Защита. Для входа в определенную группу было бы неплохо реализовать авторизацию.

Заключение


Не думаю, что я реализовал что-то новое или революционное, однако данный проект послужил хорошим примером неординарного использования Wi-Fi Peer-to-Peer соединения. Мною была успешно построена сеть между устройствами с помощью Wi-Fi Direct, что позволило беспрепятственно общаться между ними.

Это моя первая статья, поэтому судить строго. Спасибо за внимание.

-> Ссылка на GitHub
(модуль wifidirect может быть без проблем перенесен в любой андроид-проект)
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/333388/


Метки:  

Безытеративное обучение однослойного персептрона. Задача классификации

Суббота, 15 Июля 2017 г. 10:40 + в цитатник
Я продолжаю цикл статей по разработке метода безытеративного обучения нейронных сетей. В этой статье будем обучать однослойный персептрон с сигмоидальной активационной ф-ей. Но этот метод можно применить для любых нелинейных биективных активационных ф-й с насыщением и первые производные которых симметричны относительно оси OY.

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

$\\B=\{b_1...b_m\}; \\b_k=-\sum_{i=1}^nx_k^i \cdot y^i; \\k \in [1,m];$



И тут из-за того, что имеется активационная ф-я с насыщением можно выразить веса как:

$\\W=\{w_1,...,w_m\}; \\W=K\cdot B; $



Первое, что необходимо сделать — это заменить $y^i$ на $t^i$. Т.к. в задачи классификации «y» может быть либо 1(принадлежит), либо 0(не принадлежит). То t должно быть либо 1, либо -1. Отсюда $t^i=2\cdot y^i-1$. Теперь

$b_k=-\sum_{i =1}^nx^i_k\cdot t^i;$



Теперь выразим коэффициент «K» как дробь, где в числителе функция, обратная ф-и активации от 0.99(от единицы взять нельзя т.к. будет +бесконечность), а в знаменателе усредненное значение модулей всех элементов входящих в выборку(вероятно, можно использовать квадратный корень из усредненной энергии). И умножается все это на -1.

Итоговая формула получается:

$w_k=\frac{n\cdot m\cdot f^{-1}_a(0.99)\cdot \sum_{i=1}^nx^i_k\cdot t^i}{\sum^n_{i=1}\sum^m_{j=1}|x^i_j|};$



Для сигмоиды, которая имеет вид $f_a(x) = \frac{1}{1+exp(-\beta\cdot x)}$, обратная ф-я — $f^{-1}_a(x) = -\frac{ln(\frac{1}{x}-1)}{\beta}$, при $\beta = 1; f^{-1}_a(0.99) = 4.6$

*Небольшая проверка
Пусть есть две пары $x^1 = \{1,0,1,0\}; y^1 = 1; x^2 = \{0.7,1,0.1,1\}; y^2 = 0; $. Рассчитаем веса по формуле приведенной выше:

$\\w_1= -1.83; \\w_2= -6.1; \\w_3= 5.49; \\w_4= -6.1; $



Теперь «прогоним» наши вектора через получившийся нейрон, напомню формулу отклика нейрона:

$y(x) = f_a(\sum_{i=1}^nw_ix_i);$



Первый вектор дал результат 0.997, второй — $ 2\cdot 10^{-6} $, что очень похоже на правду.

*Тестирование

Для тестирования была взята обучающая выборка 2 сигнала без шума, 1 и 2 Гц, 200 отсчетов. Одному герцу соответствует отклик НС {0,1}, двум {1,0}.

Во время тестирования распознавался сигнал + гауссов шум. ОСШ = 0.33

Ниже представлено распознавание:
1Гц, самый хороший результат
image
2 Гц, самый хороший результат

1 Гц, самый плохой результат


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

Код обучения:
	public void Train(Vector[] inp, Vector[] outp)
		{
			OutNew = new Vector[outp.Length];
			In = new Vector[outp.Length];
			Array.Copy(outp, OutNew, outp.Length);
			Array.Copy(inp, In, inp.Length);
			
			
			for (int i = 0; i < OutNew.Length; i++)
			{
				OutNew[i] = 2*OutNew[i]-1;
			}
			
			
			K = 4.6*inp[0].N*inp.Length;
			
			double summ = 0;
			
			for (int i = 0; i < inp.Length; i++)
			{
				summ += Functions.Summ(MathFunc.abs(In[i]));
			}
			
			K /= summ;
			
			
			Parallel.For(0, _neurons.Length, LoopTrain);
		}
		
		
		void LoopTrain(int i)
		{
			
			for (int k = 0; k < In[0].N; k++) {
				
				for (int j = 0; j < OutNew.Length; j++)
				{
					_neurons[i].B.Vecktor[k] += OutNew[j].Vecktor[i]*In[j].Vecktor[k];
				}
			
			}
			
			_neurons[i].W = K*_neurons[i].B;
		}


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

https://habrahabr.ru/post/333382/


Метки:  

[Из песочницы] Как крупные компании следят за работниками

Суббота, 15 Июля 2017 г. 10:08 + в цитатник
В любой организации рано или поздно наступает такой момент, когда интуитивно работать с персоналом перестает быть возможным. Чаще всего это связано с ростом организации — в компании в 10-15 человек еще можно контролировать ситуацию в компании в ручном режиме, однако с большим количеством сотрудников руководитель начинает «тонуть».

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

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

image

СКУД + Видеонаблюдение

На классических производствах для контроля сотрудников службой безопасности обычно применяется связка СКУД + видеонаблюдение. СКУД (система контроля и управления доступом) чаще всего представляет собой следующее: у каждого сотрудника есть пропуск, который он прикладывает к считывателю у входа, — время прихода и ухода с работы логируется и контролируется. В качестве второго рубежа защиты используются записи с камер.

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

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

Бесплатные и системные средства

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

Для контроля рабочего времени можно применять тот же СКУД или выгружать данные из Active Directory. Иногда контроль рабочего времени интегрирован в CRM-системы. Проблема в таком случае очевидна — все, что находится за пределами CRM-системы, контролю не поддается.

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

image

В облачных продуктах для бизнеса от Google и Microsoft (Google Apps Unlimited и Office 365 Business, соответственно) есть возможность настраивать правила, которые проверяют почту и документы сотрудников на наличие ключевых слов или типов данных. Это, конечно, не замена полноценной системы безопасности, однако применение может найти. А для контроля отдельных аспектов работы сотрудников можно использовать и бесплатные средства удаленного доступа.

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

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

Системы учета рабочего времени и контроля сотрудников

Этика анализа переписки сотрудников вызывает вопросы и споры — однако перехват применяется повсеместно, особенно в крупных компаниях. Основная задача — защита конфиденциальных данных компании от инсайдерских угроз. Также анализ внутренних коммуникаций часто используется и для выявления нелояльных сотрудников. Яркий пример — громкое увольнение «Яндексом» ряда сотрудников купленного им сервиса «Кинопоиск». По мнению уволенных, причина в острой критике перезапуска сервиса во внутреннем чате сотрудников. Согласно заявлению «Яндекса» — сотрудники в этом чате разглашали коммерческую тайну третьим лицам (бывшим коллегам). Как бы то ни было, неприятная для компании ситуация была обнаружена сотрудниками безопасности, причем наверняка вследствие использования DLP-системы (от англ. Data Leak Prevention — предотвращение утечек данных) или аналогичного продукта.

image

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

DLP-системы

Более технологически изощренными являются DLP-системы. Если снифферы и «средства контроля сотрудников» просто перехватывают информацию, то DLP-системы идут дальше — вместе с перехватов еще и автоматически анализируют перехваченную информацию. Таким образом задача по поиску «вредной» информации перекладывается с плеч сотрудника безопасности на машину. Ему нужно лишь грамотно настроить правила и обращать внимание на сообщения системы о инцидентах.

image

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

Большинство таких систем также умеют распознавать транслитерованный текст (napisannyi latinskimi bukvami), изменения в расширении файлов и прочие возможные ухищрения потенциальных злоумышленников.

При всем при этом стоит помнить, что насколько бы эффективный метод контроля не использовался — он окажется беспомощен при отсутствии в компании адекватного менеджмента и корпоративной культуры. С другой стороны, даже в самой лояльной по отношении к работникам организации всегда есть вероятность появления «слабого звена» и в отсутствии контроля это звено может причинить немалый ущерб. Поиск баланса между этими двумя крайностями и есть самая главная задача для службы безопасности и руководства.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/333384/


Метки:  

Поиск сообщений в rss_rss_hh_new
Страницы: 1437 ... 1052 1051 [1050] 1049 1048 ..
.. 1 Календарь