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

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

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

Как разочароваться и НЕ перейти на Linux

Среда, 27 Сентября 2017 г. 18:17 + в цитатник
temujin сегодня в 18:17 Администрирование

Как разочароваться и НЕ перейти на Linux

    Недавний конфуз Джима Землина (Jim Zemlin) на Open Source Summit с презентацией, запущенной на Mac OS, не отменяет того факта, что и на десктопном направлении есть крупные успехи в последнее время. О некоторых я уже рассказывал: Ускорение WiFi, Графика без швов, Новый лучший I/O планировщик.


    А впрочем...


    Вместе с тем, не все еще гладко и пока есть немало тех, кто пытался перейти на Linux и затем разочаровавшись вернулся к прежней ОС, чаще всего — Windows. Раньше для этого было довольно много поводов, но уже ясно, что их будет все меньше и меньше. Если вы желаете попробовать перейти на Linux и разочароваться, сделайте это сегодня, так как завтра может быть уже поздно. Итак, мои рецепты, для тех кто желает узнать, как провалить позможность подружиться с пингвинами и уйти ни с чем.


    Подставить плечо или дать подножку?


    Мантра, которая быстрее всего приведет вас к краху цели звучит так: НЭВЛнР (ни%%% этот ваш Линукс не работает). Тут самым важным является местоимение «ваш», именно оно задает нужную дистанцию и точку зрения. Пользователь, который выдает этот комментарий, подсознательно имеет следующую картину перед глазами.


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

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


    Mozilla contribution



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


    Use case: не смог открыть флешку


    Комментарий пользователя немного облагорожен.


    Пробовал эту вашу убунту. Она даже флешку не могла адекватно открыть. Причем то открыла, то нет. Снес через 10 минут к черту.

    Скорее всего dark не сумел присоединить диск, возможно не хватало прав. Смонтировать флешку можно с помощью графического интерфейса в KDE, Gnome и всех более-менее полноценных DE. Можно и с командной строки, это можно найти в поиске за 5 минут. Однако, если бы действительно это было ошибкой драйвера, все равно можно было найти иной выход.


    Остерегайтесь командной строки


    Это верный путь к поставленной цели, то есть к провалу. Не раз и не два я видел коллег, которые лезут в Приложения, чтобы найти управление пакетами вместо того, чтобы освоить apt-get / aptitude и управление репозитариями. Это довольно быстро кончалось сносом, перестановкой ОС, так как скачать пакеты, обновления не получалось — для этого надо прописать внутренние ftp сервера, чтобы обойти межсетевой экран, GUI часто не имеет этих настроек.


    Use case: поменять устройство маршрута по умолчанию


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



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


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


    (5:31)$ nmcli delete id 
    (5:32)$ nmcli connection edit 
    (5:33)$ nmcli connection up id 

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


    !_rtfm


    Не вникайте, не учите матчасть, сохраните естественный цвет глаз и шелковистые волосы. Центр настройки KDE, gedit и Центр приложений Ubuntu наше все! Кто и вправду так считает, очень скоро столкнется с обстоятельствами непреодолимой силы и вернется на Windows, или Mac OS, повторяя мантру: НЭВЛнР.


    Не копайтесь в инит-скриптах, xml файлах, даже не открывайте grub.conf, и тем более xorg.conf. В противном случае разочароваться у вас не получится, потому что вы поймете, что практически все проблемы, с которыми вы столкнетесь, имеют разумное решение за приемлемый срок, при условии, что вы вникаете в детали и постигаете принципы.


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


    • man word, man -K word
    • info word #это и вправду фейл
    • apropos word
    • лог файлы
    • Howto
    • /usr/src/linux/уже ясно, что
    • Руководства пользователя /usr/share/your_app/docs/

    Греется ноут? Не мешкай, сноси Linux. GRUB не поднялся на UEFI? Хабр не читай, ОС удаляй.


    Вам шашки или ехать?


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


    Если же важнее двигаться, не важно на чем, то тогда и вправду нет смысла оставаться на ОС, в которой нет привычных программ: 1С, Civilization, AutoCAD, SQL Server, Unreal Tournament. Но что вы будете делать, когда очередной анонс года свершений для Linux на рабочей станции, Линуса Торвальдса или Джима Землина, наконец-то сбудется?

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

    https://habrahabr.ru/post/338846/


    Метки:  

    [Перевод] PowerShell для ИТ-безопасности. Часть IV: платформа безопасности с использованием скриптов

    Среда, 27 Сентября 2017 г. 17:34 + в цитатник
    Alexandra_Varonis сегодня в 17:34 Разработка

    PowerShell для ИТ-безопасности. Часть IV: платформа безопасности с использованием скриптов

    • Перевод


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

    Проработав некоторые детали, в основном относящиеся к зубодробительным событиям PowerShell, я смог заявить о своей победе и зарегистрировал патент на платформу безопасности на базе скриптов — SSP (Security Scripting Platform ).

    Соединенные штаты PowerShell

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

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

    1.	Register-WmiEvent -Query "SELECT * FROM __InstanceModificationEvent WITHIN 5 WHERE TargetInstance ISA 'CIM_DataFile' and TargetInstance.Path = '\\Users\\bob\' and targetInstance.Drive = 'C:' and (targetInstance.Extension = 'doc' or targetInstance.Extension = 'txt)' and targetInstance.LastAccessed > '$($cur)' " -sourceIdentifier "Accessor" -Action $action

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

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

    Пока все идет хорошо.

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

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

    Почему?

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

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

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

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

    Сообщения и события

    После того, как я провел несколько долгих дней за изучением форумов разработчиков, я наконец наткнулся на функцию PowerShell под именем Register-EngineEvent.

    Что представляет собой этот командлет PowerShell?

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

    Дело в том, что у register-EngineEvent есть два варианта работы. С параметром -forward этот командлет работает как издатель событий. Без параметра -forward он выполняет роль получателя.

    Понятно?

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

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

    1.	Register-EngineEvent -SourceIdentifier Delta -Forward
    2.	While ($true) {
    3.	$args=Wait-Event -SourceIdentifier Access # wait on internal file event
    4.	Remove-Event -SourceIdentifier Access
    5.	if ($args.MessageData -eq "Access") { 
    6.	#do some plain access processing 
    7.	New-Event -SourceIdentifier Delta -EventArguments $args.SourceArgs -MessageData $args.MessageData #send event to classifier via forwarding
    8.	}
    9.	elseif ($args.MessageData -eq "Burst") {
    10.	#do some burst processing
    11.	New-Event -SourceIdentifier Delta -EventArguments $args.SourceArgs -MessageData $args.MessageData #send event to classifier via forwarding
    12.	}
    13.	}

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

    1.	Register-EngineEvent -SourceIdentifier Delta -Action {
    2.	
    3.	Remove-Event -SourceIdentifier Delta
    4.	if($event.MessageData -eq "Access") {
    5.	$filename = $args[0] #got file!
    6.	Lock-Object $deltafile.SyncRoot{ $deltafile[$filename]=1} #lock&load 
    7.	}
    8.	elseif ($event.Messagedata -eq "Burst") {
    9.	#do something 
    10.	}
    11.	
    12.	}

    Запутались? А я говорил недавно, что обработка событий файлов — это непросто, и что мои учебные скрипты не справятся с обработкой реальных производственных нагрузок?
    Путаница возникает, поскольку командлеты New-Event и Wait-Event для внутреннего обмена сообщениями о событиях отличаются от функций внешнего обмена сообщениями о событиях, предоставленных в Register-EngineEvent.

    Еще больше путаницы

    Полный скрипт классификации представлен далее. Я подробнее расскажу о нем в следующей и последней заметке из этой серии. А пока посмотрите на этот скрипт и обратите внимание на обработку событий и многозадачность.

    1.	Import-Module -Name .\pslock.psm1 -Verbose
    2.	function updatecnts {
    3.	Param ( 
    4.	[parameter(position=1)] 
    5.	$match, 
    6.	[parameter(position=2)]
    7.	$obj
    8.	)
    9.	
    10.	for($j=0; $j -lt $match.Count;$j=$j+2) { 
    11.	switch -wildcard ($match[$j]) {
    12.	'Top*' { $obj| Add-Member -Force -type NoteProperty -Name Secret -Value $match[$j+1] }
    13.	'Sens*' { $obj| Add-Member -Force -type NoteProperty -Name Sensitive -Value $match[$j+1] }
    14.	'Numb*' { $obj| Add-Member -Force -type NoteProperty -Name Numbers -Value $match[$j+1] } 
    15.	}
    16.	
    17.	}
    18.	
    19.	return $obj
    20.	}
    21.	
    22.	$scan = {
    23.	$name=$args[0]
    24.	function scan {
    25.	Param (
    26.	[parameter(position=1)]
    27.	[string] $Name
    28.	)
    29.	$classify =@{"Top Secret"=[regex]'[tT]op [sS]ecret'; "Sensitive"=[regex]'([Cc]onfidential)|([sS]nowflake)'; "Numbers"=[regex]'[0-9]{3}-[0-9]{2}-[0-9]{3}' }
    30.	
    31.	$data = Get-Content $Name
    32.	
    33.	$cnts= @()
    34.	
    35.	if($data.Length -eq 0) { return $cnts} 
    36.	
    37.	foreach ($key in $classify.Keys) {
    38.	
    39.	$m=$classify[$key].matches($data) 
    40.	
    41.	if($m.Count -gt 0) {
    42.	$cnts+= @($key,$m.Count) 
    43.	}
    44.	} 
    45.	$cnts 
    46.	}
    47.	scan $name
    48.	}
    49.	
    50.	
    51.	$outarray = @() #where I keep classification stats
    52.	$deltafile = [hashtable]::Synchronized(@{}) #hold file events for master loop 
    53.	
    54.	$list=Get-WmiObject -Query "SELECT * From CIM_DataFile where Path = '\\Users\\bob\' and Drive = 'C:' and (Extension = 'txt' or Extension = 'doc' or Extension = 'rtf')" 
    55.	
    56.	
    57.	#long list --let's multithread
    58.	
    59.	#runspace
    60.	$RunspacePool = [RunspaceFactory]::CreateRunspacePool(1,5)
    61.	$RunspacePool.Open()
    62.	$Tasks = @()
    63.	
    64.	
    65.	foreach ($item in $list) {
    66.	
    67.	$Task = [powershell]::Create().AddScript($scan).AddArgument($item.Name)
    68.	$Task.RunspacePool = $RunspacePool
    69.	
    70.	$status= $Task.BeginInvoke()
    71.	$Tasks += @($status,$Task,$item.Name)
    72.	}
    73.	
    74.	
    75.	Register-EngineEvent -SourceIdentifier Delta -Action {
    76.	
    77.	Remove-Event -SourceIdentifier Delta
    78.	if($event.MessageData -eq "Access") {
    79.	$filename = $args[0] #got file
    80.	Lock-Object $deltafile.SyncRoot{ $deltafile[$filename]=1} #lock& load
    81.	}
    82.	elseif ($event.Messagedata -eq "Burst") {
    83.	#do something
    84.	}
    85.	}
    86.	
    87.	while ($Tasks.isCompleted -contains $false){
    88.	
    89.	}
    90.	
    91.	#check results of tasks
    92.	for ($i=0; $i -lt $Tasks.Count; $i=$i+3){
    93.	$match=$Tasks[$i+1].EndInvoke($Tasks[$i])
    94.	
    95.	
    96.	if ($match.Count -gt 0) { # update clasafication array 
    97.	$obj = New-Object System.Object
    98.	$obj | Add-Member -type NoteProperty -Name File -Value $Tasks[$i+2]
    99.	#defaults
    100.	$obj| Add-Member -type NoteProperty -Name Secret -Value 0
    101.	$obj| Add-Member -type NoteProperty -Name Sensitive -Value 0
    102.	$obj| Add-Member -type NoteProperty -Name Numbers -Value 0
    103.	
    104.	$obj=updatecnts $match $obj
    105.	$outarray += $obj
    106.	} 
    107.	$Tasks[$i+1].Dispose()
    108.	
    109.	}
    110.	
    111.	$outarray | Out-GridView -Title "Content Classification" #display
    112.	
    113.	#run event handler as a separate job
    114.	Start-Job -Name EventHandler -ScriptBlock({C:\Users\bob\Documents\evhandler.ps1}) #run event handler in background
    115.	
    116.	
    117.	while ($true) { #the master executive loop
    118.	
    119.	
    120.	Start-Sleep -seconds 10
    121.	Lock-Object $deltafile.SyncRoot { #lock and iterate through synchronized list
    122.	foreach ($key in $deltafile.Keys) { 
    123.	
    124.	$filename=$key
    125.	
    126.	if($deltafile[$key] -eq 0) { continue} #nothing new
    127.	
    128.	$deltafile[$key]=0
    129.	$match = & $scan $filename #run scriptblock
    130.	#incremental part
    131.	
    132.	$found=$false
    133.	$class=$false
    134.	if($match.Count -gt 0) 
    135.	{$class =$true} #found sensitive data
    136.	if($outarray.File -contains $filename) 
    137.	{$found = $true} #already in the array 
    138.	if (!$found -and !$class){continue}
    139.	
    140.	#let's add/update
    141.	if (!$found) {
    142.	
    143.	$obj = New-Object System.Object
    144.	$obj | Add-Member -type NoteProperty -Name File -Value $Tasks[$i+2]
    145.	#defaults
    146.	$obj| Add-Member -type NoteProperty -Name Secret -Value 0
    147.	$obj| Add-Member -type NoteProperty -Name Sensitive -Value 0
    148.	$obj| Add-Member -type NoteProperty -Name Numbers -Value 0
    149.	
    150.	$obj=updatecnts $match $obj
    151.	
    152.	}
    153.	else {
    154.	$outarray|? {$_.File -eq $filename} | % { updatecnts $match $_} 
    155.	}
    156.	$outarray | Out-GridView -Title "Content Classification ( $(get-date -format M/d/yy:HH:MM) )" 
    157.	
    158.	} #foreach
    159.	
    160.	} #lock
    161.	}#while
    162.	
    163.	Write-Host "Done!"

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

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

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

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

    https://habrahabr.ru/post/338848/


    Метки:  

    Числа — расшифровка доклада Дагласа Крокфорда с HolyJS 2017 Piter

    Среда, 27 Сентября 2017 г. 17:26 + в цитатник
    ARG89 сегодня в 17:26 Разработка

    Числа — расшифровка доклада Дагласа Крокфорда с HolyJS 2017 Piter

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

      Давайте посмотрим, откуда пришли цифры, куда они могут привести и как они работают.





      В основе статьи — доклад Дугласа Крокфорда (Douglas Crockford) с июньской конференции HolyJS 2017 в Санкт-Петербурге (презентацию доклада можно найти тут)


      Пальцы


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

      Инструменты


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

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

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

      Счет


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

      Письменность


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

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

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

      Египет


      Так выглядели числа в Египте.

      image

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

      Египтяне придумали много других вещей: треугольник 3 на 4 на 5 с прямым углом (они знали, зачем этот угол нужен), действительно умную систему для работы с дробями. У них было приближение для числа Пи и много чего еще.

      Финикия


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

      Греция


      image

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

      Греки использовали тот же набор символов для записи чисел. Они взяли первые 9 букв алфавита для обозначения цифр с 1 по 9, следующие 9 букв — для десятков от 10 до 90, и еще 9 букв для сотен — от 100 до 900. Свою систему они передали римлянам.

      Рим


      image

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

      Одна из проблем египетской системы заключалась в том, что для записи числа 99 требовалась последовательность из 18 символов. Римляне хотели сократить запись. Для этого они придумали символы, представляющие половину десяти или половину сотни (тысячи). Один у них был представлен символом I (или палкой), 10 — X (пучок палок, соединенных вместе), а 5 — V, что есть всего лишь X пополам.

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

      Китай


      Между тем в Китае творились действительно интересные вещи.

      image

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

      Индия


      Больший скачок произошел в Индии.

      image


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

      Тиражирование идеи


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

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

      Запись чисел и математика


      Вот одно и то же число, записанное во всех упомянутых системах.

      image

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

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

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

      Важная идея заключается в том, что индийские числа научили нас математике.



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

      Целые числа


      Данная система также допускала отрицательные числа.


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

      Вещественные числа


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


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

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


      Но с годами разделительный символ менялся.

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


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

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

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

      Основание


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

      Как это произошло? Они просто посчитали пальцы на обеих руках. И это сработало.

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

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

      Компромиссы: 60


      Шумеры использовали основание 60. Да и мы все еще придерживаемся основания 60, верно? Мы так считаем наше время и делаем географические измерения. Географическим приложениям приходится использовать систему координат на базе системы счисления с основанием 60. Это добавляет ненужную сложность.

      Как появилось основание 60? Я думаю, когда города росли, они поглощали много мелких поселений, объединяя их в большие. В какой-то момент они попытались объединить сообщество, которое использовало основание 10, с сообществом, которое взяло в качестве основания 12. Наверняка был какой-то король или комитет — кто-то должен был решить, как объединить их. Правильный вариант был — использовать основание 10. Второй вариант — развиваться с основанием 12. Но вместо этого они выбрали худший вариант из возможных — использовали основание, являющееся наименьшим общим кратным. Причина, по которой было принято такое решение, состоит в том, что комитет не мог решить, какой из вариантов лучше. Они пришли к компромиссу, который, по их мнению, похож на то, что все хотели. Но дело же не в том, кто и что хочет.

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

      Двоичная система


      Действительно интересная вещь, связанная с основанием, — появление двоичной системы. Мы можем взять индийскую систему и просто заменить 10 на 2.


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

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

      • Знаковая величина (Signed magnitude representation). В этом случае мы просто добавляем дополнительный двоичный бит к числу и решаем, в каком из состояний этот бит соответствует положительному числу, а в каком — отрицательному. И неважно, поставим ли мы этот бит спереди или сзади (это всего лишь вопрос конвенции). Недостатком этого способа является присутствие двух нулей: положительного и отрицательного, что не имеет смысла, поскольку ноль не имеет знака.
      • Первое дополнение (One’s complement), в котором мы выполняем операцию побитового нет для числа, чтобы сделать его отрицательным. Помимо двух нулей (положительного и отрицательного — как в предыдущем варианте) у этого представления присутствует проблема переноса: при обычном сложении двух чисел, представленных таким образом, для получения корректного результата необходимо в конце добавлять 1 бит. Но в остальном это работает.
      • Второе дополнение (Two's complement), в котором удалось обойти проблему переноса. Отрицательное N представляется не побитовым отрицанием положительного N, а им же + 1. Помимо отсутствия проблемы переноса мы получаем только один нуль, что очень хорошо. Но при этом мы получаем дополнительное отрицательное число. И это проблема, потому что вы не можете получить абсолютное значение этого числа — вместо этого вы получите то же отрицательное число. Это потенциальный источник ошибок.

      Каждый из вариантов имеет свои недостатки, в частности, какие-то дополнительные числа. Я думаю, что мы должны взять это дополнительное число (отрицательный 0 или дополнительное отрицательное число из второго дополнения), и превратить его в сигнал о том, что это не число вовсе. Таким образом это позволит нам избежать проблемы, которая проявляется в Java: если мы используем метод indexOf, чтобы найти строку в другой строке, и если она ее не находит, Java не может сигнализировать об этом. Потому что это дурацкая система может возвращать только int, а int может представлять только целые числа.


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

      Types


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

      int


      У нас есть много языков, где под разными именами есть int32. Если мы сложим два числа int32, к какому типу будет относиться результат? Ответ — int33, потому что в результате сложения вы можете получить число, которое немного больше int32.

      Здесь Java ошибается. Java говорит, что это int32.

      Еще один пример — умножение int32 на int32. Что мы получим в результате? Похоже, int63.


      Когда в результате обычного вычисления получается результат, который выходит за рамки типа, мы получаем переполнение. И наши CPU знают об этом. Например, в архитектуре Intel в ЦП есть флаг переноса, который содержит этот 33-й бит. Также на архитектуре Intel, если вы делаете умножение 32-битных чисел, вы получаете 64-битный результат. Т.е. предусмотрен регистр, который содержит необходимые вам «дополнительные» 32 бита. И есть флаг переполнения, который устанавливается, если требуется игнорировать высокий порядок умножения. Он сообщает, что произошла ошибка. К сожалению, Java не позволяет вам получать эту информацию. Она просто отбрасывает все, что является проблемой.

      Что вообще должно происходить, при переполнении? Здесь есть несколько вариантов действий:

      • мы можем хранить значение null, что, я думаю, очень разумно;
      • или максимально возможную часть (насыщение — saturation). Это может быть разумно при обработке сигналов и в компьютерной графике. Однако вы не захотите так делать в финансовых приложениях;
      • можно выдавать ошибку — машина должна вызвать исключение или что-то должно произойти. Софт должен понять, что в вычислениях произошла путаница и нужно исправить ситуацию;
      • некоторые говорят, что программа должна остановиться. Это довольно резкая реакция, но такой вариант работал бы, если бы машина не просто останавливалась, а как-то сообщала, что что-то не так.


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

      Разбиение чисел на значения из разных регистров


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

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

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

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

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


      Этот подход был реализован в программном обеспечении первых машин. Он работал, но крайне медленно. Сами по себе машины были очень медленными, а все эти преобразования только ухудшали ситуацию. Неудивительно, что появилась потребность интегрировать это в железо. Следующие поколения машин уже на аппаратном уровне понимали вычисления с плавающей запятой, правда, для двоичных чисел. Переход от десятичной к двоичной системе был вызван потерей производительности из-за деления на 10 (которое необходимо иногда выполнять, чтобы нормализовать числа). В двоичной системе вместо деления достаточно было просто сдвинуть разделитель — это практически «бесплатно».

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


      Число записывается при помощи бита знака мантиссы, который равен 0, если число положительное, и 1, если отрицательное, самой мантиссы, а также смещённой экспоненты (biased exponent). Смещение в данном случае играет роль небольшой оптимизации — за счет нее вы можете выполнить целочисленное сравнение двух значений с плавающей точкой, чтобы увидеть, которое из них больше.

      Однако с этой записью есть проблема: в ней 0,1 + 0,2 не равно 0,3.


      Результат близок, но он неправильный.

      Давайте посмотрим, что происходит.


      Представим числовой ряд. 0,1 — это приблизительно 1/16 + 1/32, но немного больше, поэтому нам понадобятся ещё несколько бит. По мере движения по числовому ряду мы получим бесконечно повторяющуюся серию 0011, похожую на то, что происходит с 1/3 в десятичной дроби.


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

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


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

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

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

      А поскольку ни одно из наших чисел не представлено точно, все вычисления ошибочны! Это означает, что (A + B) + C не то же самое, что A + (B + C), что порядок, в котором вы выполняете вычисления, может изменить результат.

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

      В то время были две школы вычислений:

      • те, кто занимались научным трудом, писали на Фортране с использованием чисел с плавающей точкой в двоичной системе;
      • те, кто занимались бизнесом, писали на Cobol, используя двоично-десятичный код (binary coded decimal, BCD). Двоично-десятичный код выделяет 4 бита для каждой цифры и ведет обычный подсчет в десятичной системе (используя обычную арифметику).



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

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

      Проблема с типами


      В большинстве современных языков программирования присутствует путаница из-за ошибочных типов данных. Например, если вы пишите на Java, каждый раз создавая переменную, свойство или параметр, вам нужно правильно выбрать тип из Bite, Char, Short, Int, Long, Float, Double. И если вы выберете неправильно, программа может не заработать. Причем ошибка проявится не сразу, и в тестах её не будет видно. Она покажет себя в будущем, когда произойдёт переполнение и связанные с этим плохие вещи.

      Что может случиться? Одним из самых впечатляющих примеров был отказ Aryan 5. Это ракета, отправленная Европейским космическим агентством. Она сильно отклонилась от курса, а затем взорвалась через несколько секунд после старта. Причиной тому была ошибка в программном обеспечении, написанном на Ада. Здесь я перевел ошибку на Java:



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

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

      DEC64


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

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

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

      DEC64 может точно представлять десятичные дроби, содержащие до 16 цифр, чего вполне достаточно для большинства наших приложений. Вы можете представлять числа от 1*10-27 до 3 с 143 нулями.

      DEC64 очень похож на исходные числа с плавающей точкой, разработанные в 40-х годах. Число представлено в виде двух чисел, которые упакованы в 64-битное слово. Коэффициент представлен 56 битами, а показатель — 8 битами.


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

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

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

      Неопределенности и нули


      =Давайте вернемся к числам.

      Что такое 0/0?
      • Большинство математиков скажут, что это значение не определено, подразумевая, что глупо так делать — такое выражение не имеет смысла (JavaScript определяет это как Undefined). Такая позиция хороша для математики, потому что там все происходит в теоретическом пространстве. Но это не работает для вычислений, потому что если кто-то может подать эти данные на вход машины, та должна как-то отреагировать (вы не можете сказать, что дизайн машины не определён — что-то должно произойти).
      • Еще одна теория говорит, что машина должна загореться, потому что никто не будет в здравом уме пытаться делить 0 на 0, так что этого никогда не должно произойти. Но мы знаем, что это неправда. Потому что если что-то может произойти, это произойдет.
      • Другая версия — это должно быть null или какое-то иное понятие, которое говорит, что это не значение. И это разумно.
      • Еще одна школа считает, что результат должен быть нулевым. Есть математики, которые уверены в этом, но для большинства бизнес-задач такой результат не имеет смысла. Если в прошлом месяце мы продали 0 единиц товара, и общая прибыль по этим единицам составляла 0, какова была средняя прибыль за товар? 0?
      • Некоторые люди говорят, что это 1, потому что N / N = 1.
      • Когда-то я работал на мэйнфрейме, где результат был 2. Это была машина, которую создал Сеймур Крей — величайший компьютерный дизайнер в истории. Я ввел 0/0 и получил 2. Могу представить себе диалог в Control Data Corporation. Кто-то сказал: «Сеймур, есть проблема с вашей схемой деления!». «В чем проблема?». «Если кто-то разделит 0 на 0, получит 2!». И Сеймур говорит: «Послушай… Такой операции не должно быть. Ни один разумный человек никогда не должен этого делать. И если я включу дополнительную логику для этого случая, чтобы определить поведение машины, т.е. добавлю ещё одну проверку, она ухудшит производительность для всех, в том числе, для умных людей, которые не выполняют таких операций. И это сделает машину дороже. Я не собираюсь этого делать только из-за того, что какой-то идиот хочет разделить 0 на 0».


      Также меня интересует, чему равно 0 * n для любого значения n.
      Я думаю, что это 0. Но были компиляторы, которые, если встречали в умножении 0, не делали умножение вовсе. Это было большим плюсом к скорости. К сожалению, когда был создан стандарт записи чисел с плавающей точкой, такой подход был объявлен ошибочным, потому что если n является NaN, то результат 0 x NaN не равен нулю.

      Почему мы вообще должны заботиться об этом?

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

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

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

      Вместо заключения


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


      Я хочу начать с Леонардо Фибоначчи из Пизы. В конце XII века Леонардо посетил Аравию и узнал удивительные вещи, которые арабские математики воплотили через свою систему счисления — алгебру, геометрию, алгоритмы. Он привез их в Европу и написал книгу, которую опубликовал в 1202 году. В течение следующего столетия эта книга преобразовала Европу. Он создал базу для новых форм банковского дела, что привело к увеличению капитала, подпитывающего Ренессанс.


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


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


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


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

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

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

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

      Мы — дети Техути. Используем язык программирования для перевода чисел в магию.



      Если вам понравился этот доклад Дугласа Крокфорда, приглашаем вас на два его новых выступления в рамках грядущей конференции HolyJS 2017 Moscow, которая пройдет в Москве 10 и 11 декабря.
      • The Post JavaScript Apocalypse — это его первый доклад, где он расскажет о том, каким мог бы быть язык следующего за JS поколения, а также о новых полезных фишках в ES6.
      • Managing Asynchronicity with RQ — второй доклад, рассказывающий о решении, которое призвано повысить простоту использования благодаря минимализму.
      Original source: habrahabr.ru (comments, light).

      https://habrahabr.ru/post/338832/


      Метки:  

      [Перевод] Как быстрее DOM построить: парсинг, async, defer и preload

      Среда, 27 Сентября 2017 г. 17:24 + в цитатник
      A3a сегодня в 17:24 Разработка

      Как быстрее DOM построить: парсинг, async, defer и preload

      • Перевод

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

      В Firefox скоро появится новый веб стандарт , который позволит загружать важные ресурсы быстрее. Его уже можно опробовать в версиях Firefox Nightly и Developer Edition, а пока это прекрасный повод вспомнить основы работы браузера и глубже понять о производительности при работе с DOM.

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

      По кирпичикам


      HTML описывает структуру страницы. Для того, чтобы браузер смог извлечь из HTML хоть какую то пользу, его надо конвертировать в понятный браузерам формат — Document Object Model или попросту DOM. У браузера есть специальная функция парсер, позволяющая конвертировать из одного формата в другой. HTML парсер конвертирует HTML в DOM.

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

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


      У DOM две роли: объектная репрезентация HTML документа и в то же время DOM служит интерфейсом, связывая страницу с внешним миром, например с JavaScript. Если, например, вызвать document.getElementById() то функция вернёт вершину DOM. Для манипуляции с вершиной и тем как её видит пользователь у вершины есть множество функций.


      CSS стили на странице отображаются в модель CSSOM — CSS Object Model. Очень похож на DOM, но для CSS, а не HTML. В отличии от DOM, CSSOM нельзя построить пошагово, т.к. стили в CSS могут переопределять друг друга. Браузеру приходится значительно потрудится чтобы применить CSS к DOM.

      История тега

      https://habrahabr.ru/post/338840/


      Метки:  

      Отправка запроса на все базы данных всех указанных серверов на примере MS SQL Server и C#.NET

      Среда, 27 Сентября 2017 г. 17:22 + в цитатник
      jobgemws сегодня в 17:22 Администрирование

      Отправка запроса на все базы данных всех указанных серверов на примере MS SQL Server и C#.NET

      • Tutorial

      Предисловие


      Нередко необходимо послать запрос всем БД (базам данных) всем указанным серверам.
      Многие DML-запросы можно сделать встроенными средствами.
      Например, так
      Но как быть с DDL-запросами?
      В данной статье будет разобран пример реализации приложения, которое отправляет запрос всем базам данных всех указанных серверов, используя MS SQL Server и C#.NET.

      Решение


      Например, необходимо создать или изменить представление (для примера возьмем создание представления из задачи):
      Запрос
      USE [НАЗВАНИЕ_БАЗЫ_ДАННЫХ]
      GO
      
      SET ANSI_NULLS ON
      GO
      
      SET QUOTED_IDENTIFIER ON
      GO
      
      
      CREATE view [inf].[vTableSize] as
      with pagesizeKB as (
      	SELECT low / 1024 as PageSizeKB
      	FROM master.dbo.spt_values
      	WHERE number = 1 AND type = 'E'
      )
      ,f_size as (
      	select p.[object_id], 
      		   sum([total_pages]) as TotalPageSize,
      		   sum([used_pages])  as UsedPageSize,
      		   sum([data_pages])  as DataPageSize
      	from sys.partitions p join sys.allocation_units a on p.partition_id = a.container_id
      	left join sys.internal_tables it on p.object_id = it.object_id
      	WHERE OBJECTPROPERTY(p.[object_id], N'IsUserTable') = 1
      	group by p.[object_id]
      )
      ,tbl as (
      	SELECT
      	  t.[schema_id],
      	  t.[object_id],
      	  i1.rowcnt as CountRows,
      	  (COALESCE(SUM(i1.reserved), 0) + COALESCE(SUM(i2.reserved), 0)) * (select top(1) PageSizeKB from pagesizeKB) as ReservedKB,
      	  (COALESCE(SUM(i1.dpages), 0) + COALESCE(SUM(i2.used), 0)) * (select top(1) PageSizeKB from pagesizeKB) as DataKB,
      	  ((COALESCE(SUM(i1.used), 0) + COALESCE(SUM(i2.used), 0))
      	    - (COALESCE(SUM(i1.dpages), 0) + COALESCE(SUM(i2.used), 0))) * (select top(1) PageSizeKB from pagesizeKB) as IndexSizeKB,
      	  ((COALESCE(SUM(i1.reserved), 0) + COALESCE(SUM(i2.reserved), 0))
      	    - (COALESCE(SUM(i1.used), 0) + COALESCE(SUM(i2.used), 0))) * (select top(1) PageSizeKB from pagesizeKB) as UnusedKB
      	FROM sys.tables as t
      	LEFT OUTER JOIN sysindexes as i1 ON i1.id = t.[object_id] AND i1.indid < 2
      	LEFT OUTER JOIN sysindexes as i2 ON i2.id = t.[object_id] AND i2.indid = 255
      	WHERE OBJECTPROPERTY(t.[object_id], N'IsUserTable') = 1
      	OR (OBJECTPROPERTY(t.[object_id], N'IsView') = 1 AND OBJECTPROPERTY(t.[object_id], N'IsIndexed') = 1)
      	GROUP BY t.[schema_id], t.[object_id], i1.rowcnt
      )
      SELECT
        @@Servername AS Server,
        DB_NAME() AS DBName,
        SCHEMA_NAME(t.[schema_id]) as SchemaName,
        OBJECT_NAME(t.[object_id]) as TableName,
        t.CountRows,
        t.ReservedKB,
        t.DataKB,
        t.IndexSizeKB,
        t.UnusedKB,
        f.TotalPageSize*(select top(1) PageSizeKB from pagesizeKB) as TotalPageSizeKB,
        f.UsedPageSize*(select top(1) PageSizeKB from pagesizeKB) as UsedPageSizeKB,
        f.DataPageSize*(select top(1) PageSizeKB from pagesizeKB) as DataPageSizeKB
      FROM f_size as f
      inner join tbl as t on t.[object_id]=f.[object_id]
      
      GO
      


      Это представление показывает размеры всех таблиц для каждой БД (базы данных).

      Создадим файл FileQuery.sql и запишем туда указанный выше запрос.
      Теперь определим функцию, которая отправляет запрос из файла всем БД всем указанным серверам:
      Функция
      /// 
              /// Отправка запроса ко всем БД указанного сервера
              /// 
              /// имя указанного сервера (экземпляра MS SQL Server)
              /// T-SQL-запрос
              /// Поток для логирования
              void RunQueryInAllDBServer(string server, string sql, TextWriter tw_log)
              {
                  SqlConnectionStringBuilder scsb = null;
      
                  //список имен всех баз данных на сервере
                  List ldbs = new List();
      
                  //настройка строки подключения
                  scsb = new SqlConnectionStringBuilder();
                  scsb.ApplicationName = "НАЗВАНИЕ_ПРИЛОЖЕНИЯ";
                  scsb.InitialCatalog = "master";
                  scsb.IntegratedSecurity = true;
                  scsb.DataSource = server;
      
                  //вывод в лог текущего времени и названия экземпляра сервера MS SQL Server
                  tw_log.WriteLine($"{DateTime.Now} ServerName: {server}:");
      
                  //создание подключения с запросом для получения имен всех БД на сервере
                  using (SqlConnection conn = new SqlConnection())
                  {
                      conn.ConnectionString = scsb.ConnectionString;
      
                      SqlCommand comm = new SqlCommand("select [name] from sys.databases");
                      comm.CommandType = System.Data.CommandType.Text;
                      comm.Connection = conn;
      
                      conn.Open();
                      var result = comm.ExecuteReader();
      
                      while (result.Read())
                      {
                          ldbs.Add(result.GetString(0).ToString());
                      }
                  }
      
                  //выполнение запроса sql на каждой БД сервера
                  for (int i = 0; i < ldbs.Count; i++)
                  {
                      using (SqlConnection conn = new SqlConnection())
                      {
                          scsb.InitialCatalog = ldbs[i];
                          conn.ConnectionString = scsb.ConnectionString;
      
                          SqlCommand comm = new SqlCommand(sql);
                          comm.CommandType = System.Data.CommandType.Text;
                          comm.Connection = conn;
      
                          conn.Open();
                          try
                          {
                              comm.ExecuteNonQuery();
                              tw_log.WriteLine($"{DateTime.Now} DBName: {ldbs[i]} успешно выполнен запрос");
                          }
                          catch(Exception exp)
                          {
                              tw_log.WriteLine($"{DateTime.Now} DBName: {ldbs[i]} Exception: {exp.Message}");
                          }
                      }
                  }
              }
      


      Данная функция получает название экземпляра MS SQL Server, запрос T-SQL и поток для логирования. Внутри заполняется список имен всех БД сервера. Далее к каждой БД производится запрос. В целях безопасности выставлена авторизация Windows: scsb.IntegratedSecurity = true;
      Также стоит быть осторожным с данной функцией, т к она выполняет любой запрос на всех БД сервера.

      Теперь создадим код вызова описанной выше функции:
      Код
      string sql = null;
      using (Stream st_log = new FileStream("НАЗВАНИЕ_ФАЙЛА_ДЛЯ_ЛОГИРОВАНИЯ", FileMode.Create, FileAccess.Write))
                  {
                      using (TextWriter tw_log = new StreamWriter(st_log, Encoding.Default))
                      {
      
                          using (Stream st = new FileStream("FileQuery.sql", FileMode.Open, FileAccess.Read))
                          {
                              using (TextReader tr = new StreamReader(st, Encoding.Default))
                              {
                                  sql = tr.ReadToEnd();
                              }
                          }
      //здесь servers-массив имен экземпляров MS SQL Server, на которые необходимо отправить запрос T-SQL
                          for (int i = 0; i < servers.Length; i++)
                          {
                              RunQueryInAllDBServer(servers[i], sql, tw_log);
                          }
      
                          tw_log.WriteLine($"Конец {DateTime.Now}");
                      }
                  }
      


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

      Результат


      В данной статье был рассмотрен пример отправки запроса, который записан в файле, всем базам данных всех указанных серверов. Это позволяет посылать DDL-запросы ко всем БД, что нельзя сделать недокументированной хранимой процедурой sp_MSForEachDB.

      А какими инструментами Вы пользуетесь для данной или подобной ей задачи?

      Источники:


      » MSDN
      » Автоматизация по сбору данных о росте таблиц и файлов всех баз данных MS SQL Server
      » Как применить операцию сразу ко всем таблицам или ко всем базам данных
      Original source: habrahabr.ru (comments, light).

      https://habrahabr.ru/post/338828/


      Метки:  

      Веб-сервер — ваша первая сетевая программа Arduino

      Среда, 27 Сентября 2017 г. 16:58 + в цитатник
      Scorobey сегодня в 16:58 Разработка

      Веб-сервер — ваша первая сетевая программа Arduino

      • Tutorial

      Введение


      В моих публикациях [1,2,3] подробно описана цепочка датчик – Arduino-интерфейс Python. В реальных условиях промышленного производства датчики находиться на значительном удалении не только друг от друга но и от места где осуществляется централизованная обработка измерительной информации. Логично передавать информацию от датчиков по компьютерной локальной сети используя хорошо разработанные сетевые технологии. Данная публикация написана в стили упражнения по сборке и настройке сетевого приложения с Arduino в домашних условиях.

      Постановка задачи


      1. Использовать библиотеку Arduino Ethernet с расширением Arduino Ethernet Shield для создания веб-сервера.
      2. Создать удаленный доступ к Arduino с использованием сети вашего домашнего компьютера.
      3. Использовать стандартный пример Arduino для обеспечения значений влажности и датчика движения с помощью веб-сервера.
      4. Разработать веб-приложений с использованием Python.


      Этапы решения поставленной задачи


      1. Проектирование и создание аппаратных средств для использования Arduino и Ethernet Shield.
      2. Запуск примера по умолчанию из среды разработки Arduino как начальную точку создания сервера.
      3. Изменение примера для размещения вашего оборудования и повторного развертывания кода.
      4. Разработка веб-приложений с использованием Python.


      Подключение Ethernet Shield поверх Arduino Uno


      Arduino Ethernet Shield — официально поддерживаемое сетевое расширение с открытым исходным кодом, предназначенное для работы с Arduino Uno. Ethernet Shield оснащен разъемом RJ45 для подключения к сети Ethernet. Ethernet Shield предназначен для установки на Arduino Uno, и он расширяет выводы(пины) от Arduino Uno в верхней части платы. Ethernet Shield также оснащен гнездом для карт памяти microSD для хранения важных файлов по сети. Как и большинство расширений, Ethernet Shield питается от платы Arduino, к которой он присоединен.



      Каждая плата Ethernet Shield оснащена уникальным аппаратным (MAC) адресом. Вы можете видеть это на обратной стороне платы. Вы можете записать этот аппаратный адрес, поскольку он будет часто требоваться в предстоящих упражнениях. Также убедитесь, что вы знакомы с установкой Arduino Ethernet Shield для выполнения последующих упражнений.

      Ниже приведена диаграмма Fritzing схемы, требуемой для этого упражнения. Первое, что вам нужно сделать, это подключить Ethernet Shield поверх вашего Arduino Uno.

      Arduino Uno





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

      Теперь подключите Arduino Uno к компьютеру с помощью USB-кабеля. Вам также необходимо подключить Arduino к локальной домашней сети с помощью кабеля Ethernet. Для этого используйте прямой кабель CAT5 или CAT6 и подключите один конец кабеля к домашнему маршрутизатору.

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



      Теперь пришло время начать кодирование вашего первого примера Ethernet.В коде вам нужно будет изменить MAC и IP-адреса, чтобы он работал для вашей конфигурации. Хотя вы можете получить MAC-адрес Ethernet Shield с задней стороны платы, вам придется выбрать IP-адрес в соответствии с конфигурацией вашей домашней сети.

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

      byte mac [] = {0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02};
      IPAddress ip (192, 168, 0, 102);  //  автоматически присвоен в домашней сети с помощью File --> Examples --> Ethernet --> DhcpAddressPrinter
      


      В IP-сети видимый диапазон IP-адресов для вашей сети является функцией другого адреса, называемого subnetwork или subnet. Subnet вашей сети LAN IP может помочь вам выбрать соответствующий IP-адрес для Ethernet Shield в диапазоне IP-адресов вашего компьютера. Вы можете узнать об основах подсети по адресу [4].

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

      Чтобы лучше понять, что здесь произошло, вернемся к коду. Как вы можете видеть, в начале кода мы инициализируем библиотеку Ethernet-сервера на порту 80, используя метод EthernetServer из библиотеки Ethernet:
      EthernetServer server(80);

      Во время выполнения setup () программа инициализирует Ethernet-соединение через Ethernet Shield с помощью метода Ethernet.being () с переменными mac и ip, которые вы определили ранее. Метод server.begin () запустит сервер отсюда. Оба этих шага являются обязательными для запуска сервера, если вы используете библиотеку Ethernet для кода сервера:
      Ethernet.begin (mac, ip);
      server.begin ();
      

      В функции loop () мы инициализируем client объект для прослушивания входящих клиентских запросов с использованием метода EthernetClient. Этот объект будет отвечать на любой запрос, поступающий от подключенных клиентов, которые пытаются получить доступ к серверу Ethernet через порт 80:
      EthernetClient client = server.available ();

      После получения запроса программа будет ожидать окончания загрузки запроса. Затем он будет отвечать клиенту с форматированными данными HTML, используя метод:
      client.print ():
      while (client.connected()) {
            if (client.available()) {
              char c = client.read();
              Serial.write(c);
             # Response code  }
      


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

      Здесь вы заметите, что мы отвечаем клиентам с вычисленными значениями относительной влажности вместо необработанных показаний со всех аналоговых выводов. Мы также изменили текст, который будет напечатан в веб-браузере, чтобы соответствовать правильному названию датчика:
      if (c == '\n' && currentLineIsBlank) {
                // send a standard http response header
                client.println("HTTP/1.1 200 OK");
                client.println("Content-Type: text/html");
                client.println("Connection: close");
                client.println("Refresh: 5");
                client.println();
                client.println("");
                client.println("");
                float sensorReading = getHumidity(analogChannel, temperature);
                client.print("Relative Humidity from HIH4030 is ");
                client.print(sensorReading);
                client.println(" % 
      "); client.println(""); break; }


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

      float getHumidity(int analogChannel, float temperature){
        float supplyVolt = 5.0;
        int HIH4030_Value = analogRead(analogChannel);
        float analogReading = HIH4030_Value/1023.0 * supplyVolt;
        float sensorReading = 161.0 * analogReading / supplyVolt - 25.8;
        float humidityReading = sensorReading / (1.0546 - 0.0026 * temperature);
        return humidityReading; }
      


      Эти изменения можно применить к примеру, WebServer Arduino для фазы тестирования или просто открыть скетч WebServer_Custom.ino из папки Exercise 1 — Web Server в каталоге вашего кода. Как вы можете видеть в открытом файле скетча, мы уже модифицировали код, чтобы отразить изменения, но вам все равно придется изменить MAC и IP-адреса на соответствующие адреса.

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

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



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

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

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

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

      Разработка веб-приложений с использованием Python


      Внедрив предыдущую программу, вы включили работу в сети на Arduino. В предыдущем примере мы создали веб-сервер HTTP, используя методы, доступные из библиотеки Ethernet. Создав веб-сервер Arduino, мы сделали доступными ресурсы Arduino в сети. Аналогично, Python также обеспечивает расширяемость посредством различных библиотек для создания интерфейсов веб-сервера.

      Запустив веб-сервер на базе Python на вашем компьютере или других устройствах, таких как Raspberry Pi, вы можете избежать использования Arduino для размещения веб-сервера. Веб-приложения, созданные с использованием языков высокого уровня, таких как Python, также могут предоставить дополнительные возможности и расширяемость по сравнению с Arduino.

      Будем использовать библиотеку Python, web.py, для создания веб-сервера Python. Мы также будем использовать эту библиотеку для создания интерактивных веб-приложений, которые позволят передавать данные между клиентом Arduino и веб-браузером.

      После того, как вы изучите основы web.py, мы будем взаимодействовать с Arduino с web.py, используя последовательные порты, чтобы сделать Arduino доступным через веб-сервер Python. Затем мы обновим коммуникационный метод Arduino от последовательного интерфейса до обмена сообщениями на основе HTTP.

      Веб-фреймворк Python — web.py


      Веб-сервер может быть разработан в Python с использованием различных веб-фреймворков, таких как Django, bottle, Pylon и web.py. Мы выбрали web.py как предпочтительную веб-структуру благодаря своим простым, но мощным функциям.

      Библиотека web.py была первоначально разработана покойным Aaron Swartz с целью разработки простого подхода для создания веб-приложений с использованием Python. Эта библиотека предоставляет два основных метода, GET и POST, для поддержки архитектуры HTTP Representation State Transfer (REST).

      Эта архитектура предназначена для поддержки протокола HTTP путем отправки и получения данных между клиентами и сервером. Сегодня архитектура REST реализуется огромным количеством веб-сайтов для передачи данных по HTTP.

      Установка web.py


      Чтобы начать работу с web.py, вам нужно установить библиотеку web.py с помощью Setuptools. В Linux и Mac OS X выполните одну из этих команд на терминале, чтобы установить web.py:
      $ sudo easy_install web.py
      $ sudo pip install web.py
      

      В Windows откройте командную строку и выполните следующую команду:
      > easy_install.exe web.py

      Для pythn 3.61 надо набрать в командной строке:
      > easy_install-3.61.exe web.py

      Если Setuptools настроен правильно, вы можете установить библиотеку без каких-либо трудностей. Чтобы проверить установку библиотеки, откройте интерактивную подсказку Python и запустите эту команду, чтобы убедиться, что вы импортировали библиотеку без каких-либо ошибок:
      >>> import web


      Первое веб-приложение Python


      Реализация веб-сервера с помощью web.py — очень простой и понятный процесс. Для библиотеки web.py требуется объявление обязательного метода GET для успешного запуска веб-сервера.

      Когда клиент пытается получить доступ к серверу с помощью веб-браузера или другого клиента, web.py получает запрос GET и возвращает данные, указанные в этом методе. Для создания простого веб-приложения с использованием библиотеки web.py создайте файл Python, используя следующие строки кода и выполните файл с помощью Python.
      import web
      urls = ( '/', 'index')
      class index:
          def GET(self):
              return "Hello, world!"
      if __name__ == "__main__":
          app = web.application(urls, globals())
          app.run()
      


      При выполнении вы увидите, что сервер теперь запущен и доступен через адрес 0.0.0.0:8080. Поскольку серверная программа запущена на IP-адресе 0.0.0.0, вы можете получить к ней доступ с помощью того же компьютера, локального хоста или любого другого компьютера из той же сети.

      Чтобы проверить сервер, откройте веб-браузер и перейдите по адресу 0.0.0.0:8080. Когда вы пытаетесь получить доступ к серверу с того же компьютера, вы также можете использовать 127.0.0.1:8080 или localhost:8080. 127.0.0.1 IP-адрес фактически означает localhost, то есть сетевой адрес того же компьютера, на котором запущена программа. Вы сможете увидеть ответ сервера, отображаемого в браузере, как показано на следующем снимке экрана:



      Чтобы понять, как работает этот простой код, ознакомьтесь с методом GET в предыдущем фрагменте кода. Как вы можете видеть, когда веб-браузер запрашивает URL-адрес, метод GET возвращает Hello, world! в браузер.

      Тем временем вы также можете наблюдать еще два обязательных компонента web.py в вашем коде: методы urls и web.application (). Библиотека web.py требует инициализации местоположения ответа в объявлении переменной urls.

      Для каждого веб-приложения на основе web.py требуется, чтобы метод application(urls, global()) вызывался для инициализации веб-сервера. По умолчанию приложения web.py запускаются на порт 8080, который можно изменить на другой номер порта, указав его во время выполнения. Например, если вы хотите запустить приложение web.py на порту 8888, выполните следующую команду:
      $ python webPyBasicExample.py 8888

      Хотя это возвращает только простой текст, вы успешно создали свое первое веб-приложение с помощью Python. Мы перейдем отсюда и создадим более сложные веб-приложения в следующих главах, используя библиотеку web.py.

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

      Основные концепции web.py для разработки сложных веб-приложений


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

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

      Обработка URL-адресов


      Вы могли заметить, что в нашей первой программе web.py мы определили переменную urls, которая указывает на корневую папку (/) of the Index class:
      urls = (
          '/', 'index'
      )
      

      В предыдущем объявлении первая часть, '/', является обычным выражением, используемым для сопоставления фактических запросов URL. Вы можете использовать такие выражения для обработки сложных запросов, поступающих на ваш сервер web.py, и указывать их на соответствующий класс.

      В web.py вы можете связать разные места целевых страниц с соответствующими классами. Например, если вы хотите перенаправить местоположение данных/данных в класс данных в дополнение к классу Index, вы можете изменить переменную urls следующим образом:
      urls = (
          '/', 'index',
          '/data', 'data',
      )
      


      При этом условии, когда клиент отправляет запрос на доступ к адресу http: // : 8080 / data, запрос будет направлен к классу данных, а затем к методу GET или POST этого класса.

      Методы GET и POST


      Мы создали веб-сервер на основе Arduino, работающий через порт 80, мы использовали веб-браузер для доступа к веб-серверу. Веб-браузеры являются одним из самых популярных типов веб-клиентов, используемых для доступа к веб-серверу; Другие типы c URL, Wget и веб-сканеры.

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

      Всякий раз, когда вы пытаетесь открыть веб-сайт в своем браузере или любом другом HTTP-клиенте, вы фактически запрашиваете функцию GET с веб-сервера; Например, при открытии URL-адреса веб-сайта [5], вы запрашиваете, чтобы веб-сервер, на котором размещен этот сайт, подавал вам запрос GET для местоположения '/'.

      В разделе «Обработка URL-адресов» мы узнали, как связать классы web.py с местами размещения URL-адресов. Используя метод GET, предоставляемый библиотекой web.py, вы можете связать запрос GET с отдельными классами. После того как вы получили запрос GET, вам необходимо вернуть соответствующие значения в качестве ответа клиенту. Следующий фрагмент кода показывает, как будет вызываться функция GET (), когда кто-либо делает запрос GET в местоположение «/»:
      def GET(self):
        f = self.submit_form()
        f.validates()
        t = 75
        return render.test(f,t);
      

      Функция POST протокола HTTP в основном используется для отправки формы или любых других данных на веб-сервер. В большинстве случаев POST встроен в веб-страницу, и запрос на сервер генерируется, когда пользователь отправляет компонент, несущий функцию POST. Библиотека web.py также предоставляет функцию POST (), которая вызывается, когда веб-клиент пытается связаться с сервером web.py с помощью метода POST. В большинстве реализаций функции POST () запрос включает в себя некоторые данные, передаваемые через формы. Вы можете извлекать отдельные элементы формы с помощью значения f ['Celsius'...], Которое даст вам значение, связанное с элементом формы Celsius. Когда функция POST () выполнила предоставленные действия, вы можете вернуть клиенту соответствующую информацию в ответ на запрос POST:
          def POST(self):
              f = self.submit_form()
              f.validates()
              c = f['Celsius'].value
              t = c*(9.0/5.0) + 32
              return render.test(f,t)
      


      Шаблоны


      Теперь вы знаете, как перенаправить HTTP-запрос на соответствующий URL-адрес, а также как реализовать методы для ответа на эти HTTP-запросы (то есть GET и POST). Но как насчет веб-страницы, которая должна быть отображена после получения запроса? Чтобы понять процесс рендеринга, давайте начнем с создания папки с именем templates в том же каталоге, где будет размещена наша программа web.py. В этой папке будут храниться шаблоны, которые будут использоваться для визуализации веб-страниц по запросу. Вы должны указать расположение этой папки шаблона в программе с помощью функции template.render (), как показано в следующей строке кода:
      render = web.template.render ('templates')

      После того как вы создадите экземпляр папки рендеринга, пришло время создавать файлы шаблонов для вашей программы. В соответствии с требованиями вашей программы вы можете создать столько файлов шаблонов, сколько хотите. Для создания этих файлов шаблонов в web.py используется язык под названием Templetor. Подробнее об этом можно узнать по адресу [5]. Каждый файл шаблона, созданный с использованием Templetor, должен храниться в формате HTML с расширением .html.

      Давайте создадим файл test.html в папке templates с помощью текстового редактора и вставим следующий фрагмент кода в файл:
      $def with(form, i)
      
      $:form.render()

      Value is: $:i



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

      После визуализации шаблона они будут единственными переменными, которые вы можете использовать для веб-страницы; Например, в предыдущем фрагменте кода мы передали две переменные (form и i) в качестве входных переменных. Мы использовали объект формы, используя $: form.render (), чтобы отобразить его внутри веб-страницы. Когда вам нужно отобразить объект формы, вы можете напрямую передать другую переменную, просто объявив ее (то есть, $: i). Templetor будет отображать HTML-код файла шаблона, как он есть, при использовании переменных в тех случаях, когда они используются.

      Теперь у вас есть файл шаблона test.html, готовый к использованию в вашей программе web.py. Всякий раз, когда выполняется функция GET () или POST (), вам необходимо вернуть значение запрашивающему клиенту. Хотя вы можете вернуть любую переменную для этих запросов, в том числе None, вам придется отобразить файл шаблона, где ответ связан с загрузкой веб-страницы. Вы можете вернуть файл шаблона с помощью функции render (), за которым следует имя файла шаблона и входные аргументы:
      return render.test (f, i);

      Как видно из предыдущей строки кода, мы возвращаем визуализированную страницу test.html, указав функцию render.test (), где test () — это просто имя файла без расширения .html. Функция также включает объект формы, f и переменную i, которые будут переданы в качестве входных аргументов.

      Формы


      Библиотека web.py предоставляет простые способы создания элементов формы с использованием модуля Form. Этот модуль включает в себя возможность создавать элементы формы HTML, получать входные данные от пользователей и проверять эти входы до их использования в программе Python. В следующем фрагменте кода мы создаем два элемента формы: Textbox и Button, используя библиотеку Form:
      submit_form = form.Form(
            form.Textbox('Celsius', description = 'Celsius'),
            form.Button('submit', type="submit", description='submit'))
      


      Помимо Textbox (который получает ввод текста от пользователей) и Button (который отправляет форму), модуль Form также предоставляет несколько других элементов формы, таких как Password для получения скрытого ввода текста, Dropbox для получения взаимоисключающего выпадающего списка, Radioto получает взаимоисключающие входы из нескольких опций, а Checkbox — выбор бинарного входа из заданных опций. Хотя все эти элементы очень просты в реализации, вы должны выбрать элементы формы только в соответствии с вашими требованиями к программе

      В реализации формы через web.py веб-страница должна выполнять метод POST каждый раз, когда форма отправляется. Как вы можете видеть в следующей реализации формы в файле шаблона, мы явно объявляем метод отправки формы как POST:
      $def with(form, i)
      
      $:form.render()


      Вывод


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

      Ссылки


      1. Прототипирование в среде Python-Arduino.
      2. Методы разработки потока программного обеспечения датчиков движения, работающих с Arduino.
      3. Использование Python для обработки в реальном масштабе времени информации от датчиков, работающих с Arduino.
      4. Subnetwork.
      5. web.py templating system.
      Original source: habrahabr.ru (comments, light).

      https://habrahabr.ru/post/338844/


      Метки:  

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

      Среда, 27 Сентября 2017 г. 16:37 + в цитатник
      SmirkinDA сегодня в 16:37 Управление

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



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

        Управление временем


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

        TMetric Time Tracker
        Базовая версия: бесплатно
        Профессиональная версия: $4 за пользователя в месяц
        Бизнес-версия: $6 за пользователя в месяц



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

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

        С помощью функции Workday Timeline можно быстро оценить, на что у вас уходит время в течение дня. Вы также можете объединиться со своими коллегами и отслеживать время каждого из вас с помощью фичи Team View. В приложении можно сгенерировать подробный отчёт о потраченном времени и заработанных на каждом проекте деньгах. Бизнес-владельцы могу настроить соотношения разных типов работы и без затруднений вычислять зарплаты сотрудников.
        TMetric позволяет очень легко отслеживать отдельно оплачиваемое и неоплачиваемое время, так что вы сможете держать руку на пульсе своих расходов и доходов. А для группирования задач или проектов можно использовать удобную систему тегов.

        Наконец, приложение легко интегрируется с популярными сервисами управления проектами, вроде Trello, Asana, Jira, Todoist и многими другими, так что вы можете использовать эту связку как одно полное решение.

        ManicTime


        Базовая версия: бесплатно
        Профессиональная версия: $67 за лицензию в год



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

        Программа позволяет присваивать временным промежуткам собственные теги, благодаря чему можно легко создавать табели учёта времени. Очень удобно, что не нужно логиниться на сервер: достаточно просто нажать «Старт», а по завершении работы — остановить учёт. Клёвое приложение, автоматически фиксирующее ваши действия!

        Timely
        Индивидуальная версия: $14 за пользователя в месяц
        Корпоративная версия: $21 за пользователя в месяц
        Энтерпрайз-версия: $49 за пользователя в месяц



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

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

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

        Чек-листы


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

        Wunderlist
        Базовая версия: бесплатно
        Профессиональная версия: $4,99
        Бизнес-версия: $4,99 за пользователя



        Wunderlist — популярное приложение, и настолько качественное, что Microsoft купила компанию за $200 миллионов. Программ простая и небольшая, позволяет быстро создавать список задач и отслеживать их выполнение. В Wunderlist есть ограниченная поддержка повторяющихся задач, и можно даже сотрудничать с другими пользователями.

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

        Todoist
        Базовая версия: бесплатно
        Премиум-версия: $29 в год
        Бизнес-версия: $29 за пользователя в год



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

        Вы можете не только добавлять задачи, но и отправлять электронные письма посредством браузерных плагинов для Gmail, Thunderbird или Outlook. Как и Wunderlist, Todoist — кроссплатформенный продукт и может работать на любом устройстве.

        У Todoist есть замечательное свойство, позволяющее добавлять задачи, просто набирая характерные фразы вроде «Среда в 11 часов» или «каждую пятницу в 16 часов».

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

        Remember the Milk
        Базовая версия: бесплатно
        Профессиональная версия: $39.99/year



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

        Прежде всего, RTM с самого начала использует для создания задач естественный язык. Достаточно сказать что-нибудь вроде «отправить письмо Ивану в 9 утра в среду», и задача будет добавлена в список.

        Разработчики приложения знают, что реальной проблемой является не добавление задач в список, а необходимость вспоминать о них когда приходит время. Поэтому они добавили все возможные способы напоминания: пуши на мобильных и настольных устройствах, SMS, сообщения в Skype, AIM, Google Hangout, Twitter и так далее.

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

        Планировщики


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

        Calendly
        Базовая версия: бесплатно
        Премиум-версия: $8 за пользователя в месяц
        Профессиональная версия: $12 за пользователя в месяц



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

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

        Google Calendar
        • Использование: бесплатно



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

        Как и прочие продукты Google, Calendar отличается простым и понятным интерфейсом, позволяющим очень легко назначать события и задачи. Если вы пользуетесь G Suite for Businesses, то имейте в виду, что Messages может автоматически создавать в календаре события на основе текста ваших писем.

        Для разных типов задач можно создавать разные календари. Например, можно сделать календарь для работы, для домашних дел, для выходных, для хобби и так далее. Все задачи будут отображаться в главном интерфейсе, но кликнув на вкладку My Calendars можно переключиться на отдельные календари. Ваши коллеги могут делиться с вами своими календарями. Чтобы добавить их в свой список, введите имя/почту человека в “Other Calendars”.

        Наконец, у Google Calendar прекрасная система напоминаний, которая найдёт вас на настольном компьютере, ноутбуке или мобильном устройстве. При этом сами напоминания могут быть однократными и повторяющимися.

        Doodle
        Базовая версия: бесплатно
        Личная версия: $39 за пользователя в год
        Бизнес-версия: $69 за пользователя в год



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

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

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

        Управление проектами


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

        Trello
        Базовая версия: бесплатно
        Бизнес-версия: $9,99 за пользователя в месяц
        Энтерпрайз-версия: $20,83 за пользователя в месяц



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

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

        В бесплатной версии Trello нельзя приглашать столько людей, сколько хочется. Можно перетаскивать членов команды на карточки, и при каждом изменении они будут получать уведомления. Trello легко интегрируется с различными сторонними приложениями вроде Dropbox, Evernote, Google Drive и так далее.

        Asana
        Базовая версия: бесплатно
        Премиум-версия: $9,99 в месяц
        Энтерпрайз-версия: по запросу



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

        Asana поделена на три уровня. Задачи — нижний уровень. Их можно назначать конкретным людям, добавлять комментарии, примечания, создавать подзадачи. Проекты — это списки задач. Их можно организовывать и менять им приоритеты в рамках проектов. Рабочие зоны (Workspaces) — это как доски в Trello, здесь вы можете тасовать свои проекты.

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

        Заключительные мысли


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

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

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

        https://habrahabr.ru/post/338820/


        Метки:  

        SAP ищет специалистов будущего для работы с data science и machine learning

        Среда, 27 Сентября 2017 г. 16:33 + в цитатник
        SAP сегодня в 16:33 Разное

        SAP ищет специалистов будущего для работы с data science и machine learning

          Этой осенью SAP запускает новую программу по поддержке молодых талантов – SAP Young Professionals Program. В течение года 20 начинающих специалистов (студенты или недавно окончившие вузы выпускники) пройдут обучение при поддержке экспертов SAP и представителей партнёров. А затем станут частью проектных команд по самым перспективным направлениям на ИТ-рынке: разработка, data science и машинное обучение. Отбор в программу стартует сразу в нескольких ведущих российских вузах, основные этапы пройдут в Москве и Екатеринбурге.
          В этом посте мы расскажем подробнее, почему SAP стремится найти новые таланты для самых перспективных профессий на ИТ-рынке.

          image



          Почему SAP решил начать подготовку специалистов по Data Science и Machine Learning

          В начале 2017 года компания представила SAP Leonardo – портфолио решений для использования новых технологий в бизнесе. В него входят сервисы для работы с интернетом вещей, машинным обучением, блокчейн, предиктивной аналитикой, Big Data и многие другие сервисы.

          После анонса SAP Leonardo мы получили множество вопросов от российских клиентов и партнёров о функционале системы и о том, как применять инновации на производстве, в промышленности, в ритейле и других индустриях. Мы столкнулись не только с интересом к новым технологиям, но и с недостатком специалистов, которые умеют работать, например, с большими данными или машинным обучением. Поэтому мы и начинаем SAP Young Professionals Program, участники которой смогут за год получить редкий практический опыт в востребованных профессиях.

          Специалист по большим данным – самая востребованная профессия XXI века

          Один из самых болезненных вопросов для наших клиентов – что делать с огромными накопленными объёмами больших данных и как превратить Big Data в Smart Data («умные данные»), чтобы извлечь пользу. Многие компании давно используют в работе подключённые устройства, станки, датчики. Но при этом для большинства по-прежнему остаётся загадкой –как заставить данные работать?

          Data Scientists – одна из самых популярных профессий в СМИ сегодня. Журнал Harvard Business Review называет её «самой сексуальной профессией XXI века», McKinsey предсказывает спрос на 140-190 тысяч специалистов по работе с большими данными только в США в 2018 году.
          В SAP направление больших данных широко развивается по нескольким причинам. Во-первых, ключевые бизнес-процессы – продажи, закупки, логистика, финансы, производство – уже идут через системы SAP. Клиенты доверяют нашей экспертизе в работе с большими данными.
          Во-вторых, у SAP есть собственные мощные решения для работы с большими данными – в частности, SAP Predictive Analytics. Мы также используем известные алгоритмы для работы с Big Data (например, логистическая регрессия, градиентный бустинг, random forest) на SAP HANA.
          Отдельно стоит выделить использование нейронных сетей. В начале года SAP и Google договорились о стратегическом партнёрстве, частью которого стало использование open source библиотеки TensorFlow на технологиях SAP.

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

          Как будет проходить набор и обучение по программе SAP Young Professionals Program

          Для участия в программе на 2017/18 год мы приглашаем студентов 4 курса или старше, магистрантов или молодых специалистов, окончивших вуз 1-2 года назад. Участники программы будут распределены на два направления, для каждого есть определенные требования:
          — Для разработчиков: знание интеграционных подсистемных компонентов, знание языков и инструментов для веб-разработки (JavaScript, SAP UI5, SAP Fiori), опыт работы с базами данных (HANA, SQL)
          — Для специалистов в Data Science и Machine Learning: знания дискретной математики, статистики и статистического анализа, понимание основных алгоритмов работы машинного обучения, навыки работы с базами данных и SQL, знания языков программирования (Python, Hadoop, R).

          Обучение будет проходить в очном (в офисах SAP в Москве и Екатеринбурге) и онлайн форматах. Оффлайн лекции участникам SAP YPP будут читать специалисты из разных департаментов SAP (консультанты, пресейлы и т.п.). Занятия будут посвящены структуре компании и её портфолио, особенностям ERP-систем, развитию soft-навыков (презентации, работа в проектной команде и т.п.), дизайн-мышлению (сессии design thinking). Помимо очного формата, студенты также будут участвовать в онлайн-занятиях и, самое главное, получат бесплатный доступ к SAP Learning Hub – огромному облачному «хранилищу» знаний SAP со множеством электронных пособий и интерактивных курсов по разнообразным ИТ-тематикам, а также возможностью общения с экспертами.

          Важная часть обучения – это практика. Начинающие data scientist’ы будут работать с реальными, уже обработанными клиентскими данными, чтобы понять принципы Data Science.
          После трехмесячного обучения студентов ждут экзамены, по итогам которых они будут распределены в различные департаменты SAP и наших партнёров, где начнут работать в составе проектных команд над действующими клиентскими проектами под руководством старших коллег. По окончании программы участники, проявившие себя с лучшей стороны, получат предложение о работе в команде SAP или одного из партнёров.

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

          https://habrahabr.ru/post/338800/


          Метки:  

          Технология Blockchain. Практическое применение

          Среда, 27 Сентября 2017 г. 16:02 + в цитатник
          onbillion сегодня в 16:02 Разное

          Технология Blockchain. Практическое применение



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

            Читайте оригинал статьи в Блоге DTI..

            #Интересное
            В процессе подготовки данной записки мы выяснили, что интерес к технологии blockchain во всем мире просто огромный. К примеру, 42 крупнейших мировых банка (в частности, Bank of America, Morgan Stanley, Citi и другие) вошли в консорциум и создали компанию R3, которая займется разработкой blockchain-приложений для финансовой сферы.
            Согласно исследованию Capgemini, более половины банковских клиентов по всему миру используют продукты и услуги хотя бы одной финтех-компании. Финтех быстро растет на развивающихся рынках, и особенно это актуально для Китая и Индии, где более 75% банковских клиентов используют услуги финтех-компаний.
            Традиционные банки больше всего сосредоточены на инвестициях в технологии, которые способствуют более рациональной и эффективной деятельности. Почти 90% руководителей банков заявили, что сосредоточены на больших данных и аналитике. Около 56% фокусируются на Интернете вещей, 54,7% — на технологии блокчейн, 52,3% — на роботизации технологических процессов, 50% — на открытых API.


            Финансовые услуги


            Клиринг


            Центральный банк Германии объединил усилия с Франкфуртской фондовой биржей (Deutsche B"orse) в работе над созданием рабочего прототипа — основанного на блокчейне механизма расчетно-клиринговой деятельности. Разрабатываемый прототип предлагает расчетные операции в режиме «поставка против платежа» для цифровой валюты, выпущенной центробанком, а также обычные переводы цифровых монет или ценных бумаг. Дополнительно предлагаемый механизм дает возможность завершения расчетов по основным корпоративным сделкам вроде платежей по купонам и погашение вышедших в тираж бумаг.

            Также в этой сфере работает и ЦБ Японии.

            Аудит


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

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

            Сайт: https://www.factom.com/





            Идентификация


            Блокчейн может снизить операционные расходы банков, ускорить транзакции и решить проблемы соблюдения KYC (Know Your Customer — знай своего клиента) и AML (Anti Money Laundering — противодействие отмыванию денег). Основанные на блокчейне реестры могут не только устранить дублирование действий при соблюдении требований «знай своего клиента», но также делать зашифрованные обновления данных клиента, которые будут распределены между всеми банками практически в режиме реального времени.

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

            Сайт: https://www.blocknotary.com/

            Эту технологию уже интегрировал сервис мобильного эквайринга Pay-Me и Альфа-банк (мобильное приложение «Поток» — https://potok.digital/business).

            Банковское ПО


            В настоящее время большинство банков до сих пор пользуются системами, которые были написаны в 1980-х и 1990-х годах. Однако технологии не стоят на месте: Пол Тейлор — бывший инженер Google — разработал новую операционную систему Vault OS, которая способна заменить банковское программное обеспечение.

            Разработка Тейлора основана на технологии блокчейн. По словам разработчиков, Vault OS оснащена стандартной банковской функциональностью, к которой относятся и проводки, и записи транзакций в реальном времени. Благодаря Vault OS не будет необходимости задействовать дорогие корпоративные ЦОДы, так как она использует облака. Как отмечает создатель, пользуясь Vault OS, крупные банки смогут сэкономить около $1,3 млрд в год на IT-решениях.

            Сайт: https://www.thoughtmachine.net/

            Купонные выплаты по бондам


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

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

            Торговля золотом на бирже


            Королевский монетный двор Великобритании совместно с чикагской CME Group разработал инструмент для торговли золотом на основе блокчейна, под названием Royal Mint Gold (RMG). Платформа полностью изменит представление трейдеров и инвесторов о торговле и заключении сделок с золотом.

            Сайт: http://www.royalmint.com/





            Государство


            Обеспечение и упорядочение государственного управления


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

            Над этим работает компания финансовых технологий GovCoin Systems Limited — она поддерживает правительство Великобритании в распределении выгод.

            Сайт: http://www.getgcs.com/

            Нотариальные услуги


            Проект Bitnation в Эстонии использовал технологию блокчейн в нотариальной сфере. За счет консолидации с эстонской правительственной программой e-Residency участники проекта Bitnation получили доступ к переведенным на блокчейн традиционным нотариальным услугам, среди которых: регистрация брака, свидетельство о рождении, а также некоторые виды коммерческих договоров. Нотариальные услуги Bitnation характеризуются децентрализацией и возможностью их использовать из любой точки мира. Программа e-Residency стартовала с 1 декабря 2014 года.

            Сайты: https://e-estonia.com/ и https://bitnation.co/

            Электронное голосование акционеров


            В России: Национальный расчетный депозитарий РФ успешно протестировал прототип системы электронного голосования для собраний владельцев облигаций e-proxy voting на основе технологии блокчейн.

            Прототип системы e-proxy voting разработан на базе сетевой распределенной криптографической платформы NXT и использует международный стандарт ISO 20022 для обмена сообщениями. Разработка велась совместно с компанией DSX Technologies. Её результаты доступны в виде открытого исходного кода на GitHub.

            E-proxy voting представляет собой современную передовую технологию проведения корпоративных действий, при которой обмен информацией и документами между владельцем ценных бумаг и эмитентом происходит в электронном виде.

            В Эстонии: Акционеры компаний, размещённых на Таллиннской Фондовой Бирже Nasdaq, в скором времени получат возможность голосовать во время собраний акционеров при помощи новой системы голосования e-voting, основанной на технологии блокчейн.

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

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

            Тем же занимается Boardroom: http://boardroom.to/

            Электронное государство


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

            Сайт: http://egaas.org/

            Здравоохранение


            Структура хранения и проверки данных


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

            Компания Gem запустила Gem Health — сеть для разработки приложений и общей инфраструктуры для здравоохранения на базе Эфириума. Компания намерена использовать технологию blockchain для создания общей инфраструктуры, поскольку технология позволяет создавать глобальные стандарты данных без ущерба для конфиденциальности и безопасности.

            Сайт: https://gem.co/



            Tierion: Еще в 2015г. совместно с Philips Healthcare запустили проект на блокчейне, его основной целью является создание системы хранения информации о пациентах и удобный доступ к ней со стороны медицинских учреждений. Сегодня данные хранятся в рамках одного медицинского учреждения, а блокчейн может позволить накапливать информацию за всю жизнь пациента и обеспечивать доступ к ней из любого места.

            Сайт https://tierion.com/

            Проект Guardtime (специализируется на обеспечении безопасности данных) объявил о партнерстве с eHealth Foundation — Фондом электронного здравоохранения Эстонии. В основе решений, предложенных Guardtime, лежит KSI (Keyless signature infrastructure) — блокчейн-технология, обеспечивающая масштабные проверки подлинности данных без опоры на централизованный доверенный орган. Цель проекта — защита свыше 1 млн медицинских записей. Согласно замыслу разработчиков Guardtime, реализованная ими инфраструктура KSI внедрена в ядро базы данных Oracle. Благодаря этой интеграции изменения в истории болезни пациентов можно увидеть в режиме реального времени.

            Сайт: https://guardtime.com/

            Изучение болезней


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

            Сайт: http://foldingcoin.net/





            Страхование


            Микрострахование


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

            Разобраться с этим предлагает сервис на основе блокчейн LenderBot, предоставляющий услуги индивидуального микрострахования через чат Facebook Messenger.

            Подробнее: https://news.bitcoin.com/

            P2P страхование


            Dynamis разрабатывает смарт-контракты* для P2P страхования на случай безработицы, а социальная сеть LinkedIn выступает в качестве «системы репутации».
            Претенденты на получение полиса могут использовать LinkedIn, чтобы подтвердить свою личность и статус занятости. Заявители, в свою очередь, с помощью LinkedIn могут подтвердить, что ищут работу.

            Сайт: http://dynamisapp.com/





            Ритейл


            Карты лояльности


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

            Сайт: http://loyyal.com/





            Решения для сферы общественного питания



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

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

            Со стороны ресторана: заказы клиентов появляются на смартфоне или планшете в POS-системе, где они обрабатываются сотрудниками.

            Сайт: https://swish.mycelium.com/





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

            https://habrahabr.ru/post/338834/


            Метки:  

            «Энтерпрайзная срамота» или как свести с ума разработчика на собеседовании

            Среда, 27 Сентября 2017 г. 15:36 + в цитатник
            Свершилось — пришло приглашение на собеседование в классную компанию, давно вы мечтали тут поработать. В описании вакансии есть всё от ДМС до спортивного зала, молодая команда прогеров и отсутствие бухгалтера Натальи Валентиновны в вашем рабочем помещении. В общем, класс! Заходите в красивый офис, садитесь напротив улыбающегося рекрутера, а потом начинается вот это:


            Читать дальше ->

            https://habrahabr.ru/post/338788/


            Метки:  

            [Перевод] Ticket Trick: взлом сотен компаний через службы поддержки пользователей

            Среда, 27 Сентября 2017 г. 15:17 + в цитатник

            Метки:  

            MBLTdev 2017: хардкорные доклады по Android-разработке

            Среда, 27 Сентября 2017 г. 13:44 + в цитатник
            image

            Остался месяц до MBLTdev 2017. 27 октября в пространстве Digital October уже в 4-й раз пройдёт ежегодная конференция мобильных разработчиков.

            Под катом: описания докладов Android-трека (про iOS рассказали вчера), CodeLabs, небольшой опрос и подарки от JetBrains и Skyeng.
            Читать дальше ->

            https://habrahabr.ru/post/338816/


            Компьютерная криминалистика (форензика): подборка полезных ссылок

            Среда, 27 Сентября 2017 г. 13:38 + в цитатник
            LukaSafonov сегодня в 13:38 Разработка

            Компьютерная криминалистика (форензика): подборка полезных ссылок

              image

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


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


              Термин "forensics" является сокращенной формой "forensic science", дословно "судебная наука", то есть наука об исследовании доказательств — именно то, что в русском именуется криминалистикой. Русский термин "форензика" означает не всякую криминалистику, а именно компьютерную.
              Некоторые авторы разделяют компьютерную криминалистику (computer forensics) и сетевую криминалистику (network forensic).


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


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


              Фреймворки


              • dff — Digital Forensics Framework — платформа с открытым исходным кодом для проведения работ по извлечению и исследованию данных.
              • PowerForensics — PowerForensics утилита, написанная на PowerShell, предназначенная для исследования жестких дисков.
              • The Sleuth Kit — The Sleuth Kit (TSK) — это библиотека на языке C и коллекция инструментов командной строки, которые позволяют исследовать образы дисков.

              Реал-тайм утилиты


              • grr — GRR Rapid Response: инструмент для расследования и анализа инцидентов.
              • mig — Mozilla InvestiGator — распределенная реал-тайм платформа для расследования и анализа инцидентов.

              Работа с образами (создание, клонирование)


              • dc3dd — улучшенная версия консольной утилиты dd.
              • adulau/dcfldd — еще одна улучшенная версия dd.
              • FTK Imager — FTK Imager- просмотр и клонирования носителей данных в среде Windows.
              • Guymager — просмотр и клонирования носителей данных в среде Linux.

              Извлечение данных


              • bstrings — улучшенная версия популярной утилиты strings.
              • bulk_extractor — выявления email, IP-адресов, телефонов из файлов.
              • floss эта утилита использует расширенные методы статического анализа для автоматической деобфускации данных из двоичных файлов вредоносных программ.
              • photorec — утилита для извления данных и файлов изображений.

              Работа с RAM


              • inVtero.net — фреймворк, отличающийся высокой скоростью работы.
              • KeeFarce — извлечение паролей KeePass из памяти.
              • Rekall — анализ дампов RAM, написанный на python.
              • volatility — Volatility Framework представляет собой набор утилит для разностороннего анализа образов физической памяти.
              • VolUtility — веб-интерфейс для Volatility framework.

              Сетевой анализ


              • SiLK Tools — инструменты для анализа трафика для облегчения анализа безопасности крупных сетей.
              • Wireshark — известнейший сетевой сниффер.

              Артефакты Windows (извлечение файлов, историй загрузок, USB устройств и т.д.)


              • FastIR Collector — обширный сборщик информации о системе Windows (реестр, файловая система, сервисы, автозагрузка и т.д.)
              • FRED — кросплатформенный анализатор реестра Windows.
              • MFT-Parsers — лист сравнения MFT-парсеров (MFT — Master File Table).
              • MFTExtractor — MFT-парсер.
              • NTFS journal parser — парсер журналов NTFS.
              • NTFS USN Journal parser — — парсер журналов USN.
              • RecuperaBit — восстановление NTFS данных.
              • python-ntfs — анализ NTFS данных.

              Исследование OS X



              Internet Artifacts


              • chrome-url-dumper — извлечение информации из Google Chrome.
              • hindsight — анализ истории Google Chrome/Chromium.

              Анализ временных интервалов


              • plaso — извлечение и агрегация таймстапов.
              • timesketch — анализ таймстапов.

              Hex редакторы


              • 0xED — HEX редактор OS X.
              • Hexinator — Windows версия Synalyze It.
              • HxD — маленький и быстрый HEX редактор.
              • iBored — кросс-платформенный HEX редактор.
              • Synalyze It! — HEX редактор в тимплейтами.
              • wxHex Editor — кросс-платформенный HEX редактор со сравнением файлов.

              Конверторы


              • CyberChef — мультиинструмент для кодирования, декодирования, сжатия и анализа данных.
              • DateDecode — конвретирование бинарных данных.

              Анализ файлов



              Обработка образов дисков


              • imagemounter — утилита командной строки для быстрого монтирования образов дисков
              • libewf — Libewf библиотека и утилиты доступа и обработки форматов EWF, E01.
              • xmount — конвертирования образов дисков.

              Итог


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

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

              https://habrahabr.ru/post/338378/


              Метки:  

              [Перевод] Создание синтезатора звуковых эффектов из ретро-игр

              Среда, 27 Сентября 2017 г. 13:11 + в цитатник
              PatientZero сегодня в 13:11 Разработка

              Создание синтезатора звуковых эффектов из ретро-игр

              • Перевод
              image

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

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

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



              Волны


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

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

              Пульс




              Пульсовая волна создаёт резкий и гармоничный звук.

              Скачать MP3.

              Для генерирования представляющих пульсовую волну массива значений (в интервале от -1.0 до 1.0), можно использовать следующий код, в котором n — количество значений, необходимых для заполнения массива, a — массив, p — нормализованное положение внутри волны:

              var i:int = 0;
              var n:int = 100;
              var p:Number;
              
              while( i < n ) {
                  p = i / n;
                  a[i] = p < 0.5 ? 1.0 : -1.0;
                  i ++;
              }

              Пила




              Пилообразная волна создаёт резкий и жёсткий звук.

              Скачать MP3.

              Чтобы сгенерировать представляющий пилообразную волну массив значений (в интервале от -1.0 до 1.0), где n — количество значений, необходимых для заполнения массива, a — массив, p — нормализованное положение внутри волны:

              var i:int = 0;
              var n:int = 100;
              var p:Number;
              
              while( i < n ) {
                  p = i / n;
                  a[i] = p < 0.5 ? p * 2.0 : p * 2.0 - 2.0;
                  i ++;
              }


              Синусоида




              Синусоидальная волна создаёт плавный и чистый звук.

              Скачать MP3.

              Чтобы сгенерировать представляющий синусоидальную волну массив значений (в интервале от -1.0 до 1.0), можно использовать следующий код, где n — количество значений, необходимых для заполнения массива, a — массив, p — нормализованное положение внутри волны:

              var i:int = 0;
              var n:int = 100;
              var p:Number;
              
              while( i < n ) {
                  p = i / n;
                  a[i] = Math.sin( p * 2.0 * Math.PI );
                  i ++;
              }

              Треугольник




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

              Скачать MP3.

              Чтобы сгенерировать представляющий треугольную волну массив значений (в интервале от -1.0 до 1.0), можно использовать следующий код, где n — количество значений, необходимых для заполнения массива, a — массив, p — нормализованное положение внутри волны:

              var i:int = 0;
              var n:int = 100;
              var p:Number;
              
              while( i < n ) {
                  p = i / n;
                  a[i] = p < 0.25 ? p * 4.0 : p < 0.75 ? 2.0 - p * 4.0 : p * 4.0 - 4.0;
                  i ++;
              }

              Вот развёрнутая версия строки 6:

              if (p < 0.25) {
                  a[i] = p * 4.0;
              }
              else if (p < 0.75) {
                  a[i] = 2.0 - (p * 4.0);
              }
              else {
                  a[i] = (p * 4.0) - 4.0;
              }



              Амплитуда и частота волны


              Звуковая волна имеет два важных свойства — амплитуду и частоту волны: от них зависят, соответственно, громкость и высота звука. Амплитуда — это абсолютное пиковое значение волны, а частота — количество раз, которое волна повторяется за секунду. Обычно частота измеряется в герцах (Гц, Hz).

              На рисунке ниже показан 200-миллисекундный снимок состояния пилообразной волны с амплитудой 0,5 и частотой 20 Гц:



              Приведу пример того, как частота волны непосредственно влияет на высоту звука: волна с частотой 440 Гц имеет ту же высоту, что и стандартная нота ля первой октавы (A4) современного концертного пианино. С учётом этой частоты мы можем вычислить частоту любой другой ноты с помощью следующего кода:

              f = Math.pow( 2, n / 12 ) * 440.0;

              Переменная n в этом коде — это количество нот от A4 до интересующей нас ноты. Например, чтобы найти частоту ля второй октавы (A5), на одну октаву выше A4, нам нужно присвоить n значение 12, потому что A5 на 12 нот выше A4. Чтобы найти частоту ми большой октавы (E2), нам нужно присвоить n значение -5, потому что E2 на 5 нот ниже A4. Можно также сделать обратную операцию и найти ноту (относительно A4) по заданной частоте:

              n = Math.round( 12.0 * Math.log( f / 440.0 ) * Math.LOG2E );

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



              Цифровые звуковые волны


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

              На рисунке ниже показан способ сэмплирования звуковой волны:



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

              Кроме частоты сэмплирования цифровые звуки имеют и скорость передачи битов, измеряемую в битах в секунду. От скорости передачи битов (битрейта) зависит количество двоичных битов, используемых для хранения каждого сэмпла волны. Это похоже на количество битов, используемых для хранения информации ARGB каждого пикселя битового изображения. Например, звук с частотой сэмплирования 44100 и скоростью передачи битов 705600 будет сохранять каждый из сэмплов волн как 16-битное значение, и мы можем довольно просто вычислить его с помощью следующего кода:

              bitsPerSample = bitRate / sampleRate;

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

              trace( 705600 / 44100 ); // "16"

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



              Модуляторы


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

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

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



              Демо аудиодвижка


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

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



              Класс AudioWaveform


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

              Начнём с создания нового пакета класса под названием noise, а затем добавим в этот пакет следующей класс:

              package noise {
              	public final class AudioWaveform {
              		static public const PULSE:int    = 0;
              		static public const SAWTOOTH:int = 1;
              		static public const SINE:int     = 2;
              		static public const TRIANGLE:int = 3;
              	}
              }

              Также мы добавим к классу статичный общий метод, который можно будет использовать для проверки значения волны. Метод будет возвращать true или false в зависимости от правильности значения волны.

              static public function validate( waveform:int ):Boolean {
              	if( waveform == PULSE    ) return true;
              	if( waveform == SAWTOOTH ) return true;
              	if( waveform == SINE     ) return true;
              	if( waveform == TRIANGLE ) return true;
              			
              	return false;
              }

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

              public function AudioWaveform() {
              	throw new Error( "AudioWaveform class cannot be instantiated" );
              }

              На этом мы завершили создание класса.

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



              Класс Audio


              Следующий в списке — класс Audio. По своей природе этот класс схож с нативным классом ActionScript 3.0 Sound, каждый аудиодвижок будет представлен как экземпляр класса Audio.

              Добавим в пакет noise следующий скелет класса:

              package noise {
              	public class Audio {
              		public function Audio() {}
              	}
              }

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

              private var m_waveform:int     = AudioWaveform.PULSE;
              private var m_frequency:Number = 100.0;
              private var m_amplitude:Number = 0.5;
              private var m_duration:Number  = 0.2;
              private var m_release:Number   = 0.2;

              Как вы видите, мы задали разумные значения по умолчанию для каждого свойства. amplitude — это значение в интервале от 0.0 до 1.0, frequency указывается в Гц, а duration и release — в секундах.

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

              private var m_frequencyModulator:AudioModulator = null;
              private var m_amplitudeModulator:AudioModulator = null;

              Наконец, класс Audio должен содержать несколько внутренних свойств, к которым будет иметь доступ только класс AudioEngine (его мы вскоре напишем). Эти свойства не нужно прятать за геттерами/сеттерами:

              internal var position:Number         = 0.0;
              internal var playing:Boolean         = false;
              internal var releasing:Boolean       = false;
              internal var samples:Vector. = null;

              position задаётся в секундах и позволяет классу AudioEngine отслеживать положение звука при его воспроизведении. Это необходимо для вычисления звуковых сэмплов волны. Свойства playing и releasing сообщают классу AudioEngine, в каком состоянии находится звук, а свойство samples является ссылкой на кэшированные сэмплы волн, используемые звуком. Как используются эти свойства, мы поймём, когда напишем класс AudioEngine.

              Чтобы закончить класс Audio, нужно добавить геттеры/сеттеры:

              Audio.waveform

              public final function get waveform():int {
              	return m_waveform;
              }
              public final function set waveform( value:int ):void {
              	if( AudioWaveform.isValid( value ) == false ) {
              		return;
              	}
              	switch( value ) {
              		case AudioWaveform.PULSE:    samples = AudioEngine.PULSE;    break;
              		case AudioWaveform.SAWTOOTH: samples = AudioEngine.SAWTOOTH; break;
              		case AudioWaveform.SINE:     samples = AudioEngine.SINE;     break;
              		case AudioWaveform.TRIANGLE: samples = AudioEngine.TRIANGLE; break;
              	}
              	m_waveform = value;
              }

              Audio.frequency

              [Inline]
              public final function get frequency():Number {
              	return m_frequency;
              }
              public final function set frequency( value:Number ):void {
              	// ограничиваем frequency интервалом 1.0 - 14080.0
              	m_frequency = value < 1.0 ? 1.0 : value > 14080.0 ? 14080.0 : value;
              }

              Audio.amplitude

              [Inline]
              public final function get amplitude():Number {
              	return m_amplitude;
              }
              public final function set amplitude( value:Number ):void {
              	// ограничиваем amplitude интервалом 0.0 - 1.0
              	m_amplitude = value < 0.0 ? 0.0 : value > 1.0 ? 1.0 : value;
              }

              Audio.duration

              [Inline]
              public final function get duration():Number {
              	return m_duration;
              }
              public final function set duration( value:Number ):void {
              	// ограничиваем duration интервалом 0.0 - 60.0
              	m_duration = value < 0.0 ? 0.0 : value > 60.0 ? 60.0 : value;
              }

              Audio.release

              [Inline]
              public final function get release():Number {
              	return m_release;
              }
              public function set release( value:Number ):void {
              	// ограничиваем время release интервалом 0.0 - 10.0
              	m_release = value < 0.0 ? 0.0 : value > 10.0 ? 10.0 : value;
              }

              Audio.frequencyModulator

              [Inline]
              public final function get frequencyModulator():AudioModulator {
              	return m_frequencyModulator;
              }
              public final function set frequencyModulator( value:AudioModulator ):void {
              	m_frequencyModulator = value;
              }

              Audio.amplitudeModulator

              [Inline]
              public final function get amplitudeModulator():AudioModulator {
              	return m_amplitudeModulator;
              }
              public final function set amplitudeModulator( value:AudioModulator ):void {
              	m_amplitudeModulator = value;
              }

              Вы конечно заметили метку метаданных [Inline], связанную с некоторыми из функций геттеров. Эта метка метаданных — особенность ActionScript 3.0 Compiler, и делает она именно то, что следует из её названия: она встраивает (расширяет) содержимое функции. При разумном использовании эта особенность невероятно полезна при оптимизации, а задача генерирования динамического аудиосигнала во время выполнения программы оптимизации точно требует.



              Класс AudioModulator


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

              Начнём с начала — создадим в пакете noise следующий скелет класса:

              package noise {
              	public class AudioModulator {
              		public function AudioModulator() {}
              	}
              }

              Теперь добавим приватные свойства:

              private var m_waveform:int            = AudioWaveform.SINE;
              private var m_frequency:Number        = 4.0;
              private var m_amplitude:Number        = 1.0;
              private var m_shift:Number            = 0.0;
              private var m_samples:Vector. = null;

              Если вы думаете, что это очень похоже на класс Audio, то вы не ошибаетесь: здесь всё то же самое, за исключением свойства shift.

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

              Например, если модулятор использует синусоидальную волну для модулирования частоты звука, а shift имеет значение 0.0, то частота звука сначала увеличится, а потом опустится в соответствии с кривизной синусоиды. Однако если shift задать значение 0.5, то частота звука сначала уменьшится, а потому увеличится.

              Ну, вернёмся к коду. AudioModulator содержит один внутренний метод, используемый только AudioEngine. Метод имеет следующий вид:

              [Inline]
              internal final function process( time:Number ):Number {
              	var p:int    = 0;
              	var s:Number = 0.0;
              
              	if( m_shift != 0.0 ) {
              		time += ( 1.0 / m_frequency ) * m_shift;
              	}
              
              	p = ( 44100 * m_frequency * time ) % 44100;
              	s = m_samples[p];
              
              	return s * m_amplitude;
              }

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

              Чтобы завершить класс AudioModulator, нужно добавить геттеры/сеттеры:

              AudioModulator.waveform

              public function get waveform():int {
              	return m_waveform;
              }
              public function set waveform( value:int ):void {
              	if( AudioWaveform.isValid( value ) == false ) {
              		return;
              	}
              	switch( value ) {
              		case AudioWaveform.PULSE:    m_samples = AudioEngine.PULSE;    break;
              		case AudioWaveform.SAWTOOTH: m_samples = AudioEngine.SAWTOOTH; break;
              		case AudioWaveform.SINE:     m_samples = AudioEngine.SINE;     break;
              		case AudioWaveform.TRIANGLE: m_samples = AudioEngine.TRIANGLE; break;
              	}
              	m_waveform = value;
              }

              AudioModulator.frequency

              public function get frequency():Number {
              	return m_frequency;
              }
              public function set frequency( value:Number ):void {
              	// ограничиваем frequency интервалом 0.01 - 100.0
              	m_frequency = value < 0.01 ? 0.01 : value > 100.0 ? 100.0 : value;
              }

              AudioModulator.amplitude

              public function get amplitude():Number {
              	return m_amplitude;
              }
              public function set amplitude( value:Number ):void {
              	// ограничиваем amplitude интервалом 0.0 - 8000.0
              	m_amplitude = value < 0.0 ? 0.0 : value > 8000.0 ? 8000.0 : value;
              }

              AudioModulator.shift

              public function get shift():Number {
              	return m_shift;
              }
              public function set shift( value:Number ):void {
              	// ограничиваем shift интервалом 0.0 - 1.0
              	m_shift = value < 0.0 ? 0.0 : value > 1.0 ? 1.0 : value;
              }

              И на этом класс AudioModulator можно считать завершённым.



              Класс AudioEngine


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

              Давайте как обычно начнём со скелета класса в noise:

              package noise {
              	import flash.events.SampleDataEvent;
              	import flash.media.Sound;
              	import flash.media.SoundChannel;
              	import flash.utils.ByteArray;
              	//
              	public final class AudioEngine {
              		public function AudioEngine() {
              			throw new Error( "AudioEngine class cannot be instantiated" );
              		}
              	}
              }

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

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

              Используются следующие константы:

              static internal const PULSE:Vector.    = new Vector.( 44100 );
              static internal const SAWTOOTH:Vector. = new Vector.( 44100 );
              static internal const SINE:Vector.     = new Vector.( 44100 );
              static internal const TRIANGLE:Vector. = new Vector.( 44100 );

              Также классом используются две приватные константы:

              static private const BUFFER_SIZE:int    = 2048;
              static private const SAMPLE_TIME:Number = 1.0 / 44100.0;

              BUFFER_SIZE — это количество звуковых сэмплов, передаваемых звуковому API ActionScript 3.0 при совершении запроса звуковых сэмплов. Это наименьшее допустимое количество сэмплов, которое обеспечивает наименьшую возможную латентность звука. Количество сэмплов можно увеличить, чтобы снизить уровень нагрузки на ЦП, но это увеличит латентность звука. SAMPLE_TIME — это длительность одного звукового сэмпла в секундах.

              А теперь приватные переменные:

              static private var m_position:Number            = 0.0;
              static private var m_amplitude:Number           = 0.5;
              static private var m_soundStream:Sound          = null;
              static private var m_soundChannel:SoundChannel  = null;
              static private var m_audioList:Vector.

              • m_position используется для отслеживания потокового времени звука в секундах.
              • m_amplitude — это глобальная вторичная амплитуда для всех воспроизводимых экземпляров Audio.
              • m_soundStream и m_soundChannel не требуют объяснений.
              • m_audioList содержит ссылки на все воспроизводимые экземпляры Audio.
              • m_sampleList — это временный буфер, используемый для хранения звуковых сэмплов, когда они запрашиваются звуковым API ActionScript 3.0.

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

              static private function $AudioEngine():void {
              	var i:int    = 0;
              	var n:int    = 44100;
              	var p:Number = 0.0;
              	//
              	while( i < n ) {
              		p = i / n;
              		SINE[i] = Math.sin( Math.PI * 2.0 * p );
              		PULSE[i] = p < 0.5 ? 1.0 : -1.0;
              		SAWTOOTH[i] = p < 0.5 ? p * 2.0 : p * 2.0 - 2.0;
              		TRIANGLE[i] = p < 0.25 ? p * 4.0 : p < 0.75 ? 2.0 - p * 4.0 : p * 4.0 - 4.0;
              		i++;
              	}
              	//
              	m_soundStream = new Sound();
              	m_soundStream.addEventListener( SampleDataEvent.SAMPLE_DATA, onSampleData );
              	m_soundChannel = m_soundStream.play();
              }
              $AudioEngine();

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

              Класс AudioEngine имеет три общих метода, используемых для воспроизведения и остановки экземпляров Audio:

              AudioEngine.play()

              static public function play( audio:Audio ):void {
              	if( audio.playing == false ) {
              		m_audioList.push( audio );
              	}
              	// это позволяет нам точно знать, когда было запущено воспроизведение звука
              	audio.position  = m_position - ( m_soundChannel.position * 0.001 );
              	audio.playing   = true;
              	audio.releasing = false;
              }

              AudioEngine.stop()

              static public function stop( audio:Audio, allowRelease:Boolean = true ):void {
              	if( audio.playing == false ) {
              		// звук не воспроизводится
              		return;
              	}
              	if( allowRelease ) {
              		// переход к концу звука и установка флага затухания
              		audio.position  = audio.duration;
              		audio.releasing = true;
              		return;
              	}
              	audio.playing   = false;
              	audio.releasing = false;
              }

              AudioEngine.stopAll()

              static public function stopAll( allowRelease:Boolean = true ):void {
              	var i:int   = 0;
              	var n:int   = m_audioList.length;
              	var o:Audio = null;
              	//
              	if( allowRelease ) {
              		while( i < n ) {
              			o           = m_audioList[i];
              			o.position  = o.duration;
              			o.releasing = true;
              			i++;
              		}
              		return;
              	}
              	while( i < n ) {
              		o           = m_audioList[i];
              		o.playing   = false;
              		o.releasing = false;
              		i++;
              	}
              }

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

              AudioEngine.onSampleData()

              static private function onSampleData( event:SampleDataEvent ):void {
              	var i:int       = 0;
              	var n:int       = BUFFER_SIZE;
              	var s:Number    = 0.0;
              	var b:ByteArray = event.data;
              	//
              	if( m_soundChannel == null ) {
              		while( i < n ) {
              			b.writeFloat( 0.0 );
              			b.writeFloat( 0.0 );
              			i++;
              		}
              		return;
              	}
              	//
              	generateSamples();
              	//
              	while( i < n ) {
              		s = m_sampleList[i] * m_amplitude;
              		b.writeFloat( s );
              		b.writeFloat( s );
              		m_sampleList[i] = 0.0;
              		i++;
              	}
              	//
              	m_position = m_soundChannel.position * 0.001;
              }

              Итак, в первой конструкции if мы проверяем, по-прежнему ли m_soundChannel имеет значение null. Это нужно нам, потому что событие SAMPLE_DATA отправляется сразу при вызове метода m_soundStream.play() и ещё до того, как метод получит возможность вернуть экземпляр SoundChannel.

              Цикл while обходит звуковые сэмплы, запрошенные m_soundStream и записывает их в экземпляр ByteArray. Звуковые сэмплы генерируются следующим методом:

              AudioEngine.generateSamples()

              static private function generateSamples():void {
              	var i:int    = 0;
              	var n:int    = m_audioList.length;
              	var j:int    = 0;
              	var k:int    = BUFFER_SIZE;
              	var p:int    = 0;
              	var f:Number = 0.0;
              	var a:Number = 0.0;
              	var s:Number = 0.0;
              	var o:Audio  = null;
              	// обход экземпляров audio
              	while( i < n ) {
              		o = m_audioList[i];
              		//
              		if( o.playing == false ) {
              			// экземпляр audio полностью остановлен
              			m_audioList.splice( i, 1 );
              			n--;
              			continue;
              		}
              		//
              		j = 0;
              		// генерирование и буферизация звуковых сэмплов
              		while( j < k ) {
              			if( o.position < 0.0 ) {
              				// экземпляр audio ещё не начал воспроизведение
              				o.position += SAMPLE_TIME;
              				j++;
              				continue;
              			}
              			if( o.position >= o.duration ) {
              				if( o.position >= o.duration + o.release ) {
              					// экземпляр audio остановлен
              					o.playing = false;
              					j++;
              					continue;
              				}
              				// экземпляр audio в процессе затухания
              				o.releasing = true;
              			}
              			// получение частоты и амплитуды экземпляра audio
              			f = o.frequency;
              			a = o.amplitude;
              			//
              			if( o.frequencyModulator != null ) {
              				// модуляция частоты
              				f += o.frequencyModulator.process( o.position );
              			}
              			//
              			if( o.amplitudeModulator != null ) {
              				// модуляция амплитуды
              				a += o.amplitudeModulator.process( o.position );
              			}
              			// вычисление положения в кэше волн
              			p = ( 44100 * f * o.position ) % 44100;
              			// получение сэмпла волны
              			s = o.samples[p];
              			//
              			if( o.releasing ) {
              				// вычисление амплитуды затухания для сэмпла
              				s *= 1.0 - ( ( o.position - o.duration ) / o.release );
              			}
              			// добавление сэмпла в буфер
              			m_sampleList[j] += s * a;
              			// обновление положения экземпляра audio
              			o.position += SAMPLE_TIME;
              			j++;
              		}
              		i++;
              	}
              }

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

              static public function get amplitude():Number {
              	return m_amplitude;
              }
              static public function set amplitude( value:Number ):void {
              	// ограничение amplitude интервалом 0.0 - 1.0
              	m_amplitude = value < 0.0 ? 0.0 : value > 1.0 ? 1.0 : value;
              }



              Демо аудиопроцессора


              В этой части мы добавим к базовому движку аудиопроцессоры и создадим простой процессор дилэя. В этой демонстрации показан процессор дилэя в действии (Flash): демо.

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



              Класс AudioProcessor


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

              package noise {
                  public class AudioProcessor {
                      //
                      public var enabled:Boolean = true;
              
                      //
                      public function AudioProcessor() {
                          if( Object(this).constructor == AudioProcessor ) {
                              throw new Error( "AudioProcessor class must be extended" );
                          }
                      }
              
                      //
                      internal function process( samples:Vector. ):void {}
                  }
              }

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



              Класс AudioDelay


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

              package noise {
                  public class AudioDelay extends AudioProcessor {
                      //
                      public function AudioDelay( time:Number = 0.5 ) {
                          this.time = time;
                      }
                  }
              }

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

              Теперь давайте добавим приватные свойства:

              private var m_buffer:Vector. = new Vector.();
              private var m_bufferSize:int  = 0;
              private var m_bufferIndex:int = 0;
              private var m_time:Number = 0.0;
              private var m_gain:Number = 0.8;

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

              Свойства m_bufferSize и m_bufferIndex используются для отслеживания состояния буфера. Свойство m_time — это время последовательности дилэя в секундах. Свойство m_gain — это множитель, используемый для уменьшения со временем амплитуды буферизированных звуковых сэмплов.

              Этот класс имеет только один метод, и это внутренний метод process(), переопределяющий метод process() в классе AudioProcessor:

              internal override function process( samples:Vector. ):void {
                  var i:int    = 0;
                  var n:int    = samples.length;
                  var v:Number = 0.0;
                  //
                  while( i < n ) {
                      v  = m_buffer[m_bufferIndex]; // получение буферизированного сэмпла
                      v *= m_gain; // снижение амплитуды
                      v += samples[i]; // добавление нового сэмпла
                      //
                      m_buffer[m_bufferIndex] = v;
                      m_bufferIndex++;
                      //
                      if( m_bufferIndex == m_bufferSize ) {
                          m_bufferIndex = 0;
                      }
                      //
                      samples[i] = v;
                      i++;
                  }
              }

              Наконец, нам нужно добавить геттеры/сеттеры для приватных свойств m_time и m_gain:

              public function get time():Number {
                  return m_time;
              }
              public function set time( value:Number ):void {
                  // ограничиваем time интервалом 0.0001 - 8.0
                  value = value < 0.0001 ? 0.0001 : value > 8.0 ? 8.0 : value;
                  // если time не изменилось, нет необходимости изменять размер буфера
                  if( m_time == value ) {
                      return;
                  }
                  // задаём time
                  m_time = value;
                  // обновляет размер буфера
                  m_bufferSize    = Math.floor( 44100 * m_time );
                  m_buffer.length = m_bufferSize;
              }

              public function get gain():Number {
                  return m_gain;
              }
              public function set gain( value:Number ):void {
                  // ограничиваем gain интервалом 0.0 - 1.0
                  m_gain = value < 0.0 ? 0.0 : value > 1.0 ? 1.0 : value;
              }

              Верите или нет, но на этом класс AudioDelay завершён. На самом деле реализация дилэев звука очень проста, если понять, как работае цикл обратной связи (свойство m_buffer).



              Обновление класса AudioEngine


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

              static private var m_processorList:Vector. = new Vector.();

              Чтобы действительно добавлять и удалять процессоры из класса AudioEngine, нужно также использовать два общих метода:

              AudioEngine.addProcessor()

              static public function addProcessor( processor:AudioProcessor ):void {
                  if( m_processorList.indexOf( processor ) == -1 ) {
                      m_processorList.push( processor );
                  }
              }

              AudioEngine.removeProcessor()

              static public function removeProcessor( processor:AudioProcessor ):void {
                  var i:int = m_processorList.indexOf( processor );
                  if( i != -1 ) {
                      m_processorList.splice( i, 1 );
                  }
              }

              Всё достаточно просто — все эти методы будут добавлять и удалять экземпляры AudioProcessor из вектора m_processorList.

              Последний метод, который мы добавим, будет проходить по списку аудиопроцессоров, и ессли процессор включен, передавать звуковые сэмплы методу процессора process():

              static private function processSamples():void {
                  var i:int = 0;
                  var n:int = m_processorList.length;
                  //
                  while( i < n ) {
                      if( m_processorList[i].enabled ) {
                          m_processorList[i].process( m_sampleList );
                      }
                      i++;
                  }
              }

              Настала пора добавить последнюю часть кода, и это единственная строка, которую необходимо добавить в приватный метод onSampleData() класса AudioEngine:

              if( m_soundChannel == null ) {
                  while( i < n ) {
                      b.writeFloat( 0.0 );
                      b.writeFloat( 0.0 );
                      i++;
                  }
                  return;
              }
              //
              generateSamples();
              processSamples();
              //
              while( i < n ) {
                  s = m_sampleList[i] * m_amplitude;
                  b.writeFloat( s );
                  b.writeFloat( s );
                  m_sampleList[i] = 0.0;
                  i++;
              }

              В класс нужно добавить строку кода processSamples();. Она просто вызывает метод processSamples(), который мы добавили ранее.



              Заключение


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

              С этим кодом можно сделать гораздо больше, но важно не забывать, что весь этот объём работы аудиодвижок должен совершать во время выполнения. Если сделать движок слишком изощрённым (а это очень легко), то от этого может пострадать общая производительность игры — даже если перенести аудиодвижок в отдельный поток (или в worker ActionScript 3.0), при неаккуратной реализации он всё равно будет отнимать большую долю времени ЦП.

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

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

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

              Весь исходный код аудиодвижка можно скачать здесь.

              Развлекайтесь!
              Original source: habrahabr.ru (comments, light).

              https://habrahabr.ru/post/338544/


              Метки:  

              Cisco раскрыли особенности работы 400-гигабитного NPU

              Среда, 27 Сентября 2017 г. 12:59 + в цитатник
              it_man сегодня в 12:59 Администрирование

              Cisco раскрыли особенности работы 400-гигабитного NPU

                На выставке Hot Chips, прошедшей в августе этого года, ведущий инженер компании Cisco Джейме Маркевич (Jamie Markevitch) рассказал об особенностях работы сетевого процессора c производительностью 400 Гб/с, который в настоящее время поставляется клиентам.


                / Flickr / Timothy Lorens / CC

                Чип выполнен по 22-нанометровому техпроцессу и имеет 672 ядра, каждое из которых обрабатывает до четырех потоков. Сетевой процессор (NPU) содержит 9,2 миллиарда транзисторов и 353 Мб памяти SRAM. SRAM играет роль кеша L0, в котором хранятся инструкции и данные для каждого потока. Также имеется кеш L1 для кластера из 16 ядер.

                NPU обладает 42 кластерами ядер, которые соединены с кешем инструкций L2 за счет командного кеша L2. Он также объединяет кеши разных уровней, хранилище пакетов данных, ускорители, встроенную и динамическую память в единую «сеть». Эта сеть работает на частоте 1 ГГц и имеет пропускную способность более 9 Тб/с.


                Блок-диаграмма чипа

                Cisco не рассказали о наборе инструкций, который используется в NPU. Однако эксперты сделали предположение, что это кастомный набор, разработанный специально для работы с сетью, а не ARM, MIPS, Power или X86.

                Потоки ядер NPU обеспечивают обработку пакета данных на протяжении всей его «жизни» в чипе. Это исключает простаивание или «жонглирование» пакетами между ядрами. Поэтому одновременно могут обрабатываться 2688 пакетов. Пакеты хранятся off-chip в DRAM, но обрабатываются в реальном времени в SRAM. Причём ускорители могут обращаться к DRAM-копии независимо от ядер, которые работают с SRAM-оригиналом.

                Так как разные пакеты требуют разных характеристик, все ядра различаются по производительности, чтобы обеспечить максимальную эффективность. При этом Cisco NPU поддерживает привычные методы программирования — C или ассемблер.

                Сетевой процессор обрабатывает пакеты на скорости 800 Гб/c, или 400 Гбит/с в полнодуплексном режиме. В свою очередь, пропускная способность интерфейса SERDES составляет 6,5 Тб/с. Большая часть соединений используется для подключения DRAM и TCAM — последняя хранит списки доступа (ACL). Она также используется для буферизации пакетов, поэтому ее иногда не хватает — тогда часть данных уходит на хранение в DRAM.

                Большая часть логики NPU работает на частоте 760 МГц или 1 ГГц. Интерфейсы MAC поддерживают работу портов на скорости от 10 до 100 Гб/с.

                Сетевой процессор оснащается интегрированным трафик-менеджером, который управляет 256 тыс. запросов одновременно и выдерживает нагрузку в полтриллиона объектов. Ускорители берут на себя обработку префиксов IPv4 и IPv6, сжатие и хеширование диапазонов IP, доставку пакетов, сбор статистики.

                Внешняя память DRAM обладает 28 линиями SERDES, которые работают на скорости 12,5 Гб/с. SERDES использует проприетарный последовательный протокол для доступа к памяти — он способен проводить до миллиарда случайных обращений в секунду и поддерживает передачу данных на скорости до 300 Гб/с.

                Логика связана с DRAM через параллельный интерфейс ввода/вывода — он обладает максимальной скоростью 1250 Мб/с. Интересно, что по 22-нанометровому техпроцессу выполнен только процессор. DRAM выполнена по техпроцессу 30 нм, а SERDES и BIST — по 28 нм.

                «Мы определили, какие операции обычно проводят на такого рода устройствах, и оптимизировали чип для работы со случайными операциями на высокой скорости. Его можно использовать как буфер, в котором количество чтений будет равно количеству записей, а также для поиска данных по базам, когда количество обновлений не такое большое», — рассказал Джейми Маркевич (Jamie Markevitch), главный инженер Cisco.

                Демонстрация «внутренностей» сетевого процессора — явление не уникальное, но редкое. Производители обычно такую информацию не разглашают, хотя исключения случаются. В январе компания Barefoot Networks рассказала об особенностях чипа Tofino, Innovium в марте — о Teralynx и Mellanox Technologies в июле — о Spectrum-2.

                О конференции Hot Chips

                Hot Chips — это симпозиум на тему высокопроизводительных процессоров. Впервые он состоялся еще в 1989 году. В этом году, помимо Cisco, мероприятие посетили многие крупные производители. В частности, Microsoft представили свои наработки в области дополненной реальности и рассказали о процессоре для Xbox One X Scorpio. Выступление китайской компании Baidu было посвящено дополненной реальности, а представитель Google рассказал об оптимизации железа для нейросетей.

                P.S. О чем еще мы пишем в нашем блоге:

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

                https://habrahabr.ru/post/338620/


                Метки:  

                Процесс релиза iOS-приложений в Badoo

                Среда, 27 Сентября 2017 г. 12:43 + в цитатник
                saliery сегодня в 12:43 Разработка

                Процесс релиза iOS-приложений в Badoo


                  Всем привет! Меня зовут Михаил Булгаков, и я работаю в команде релиз-инженеров Badoo. В этом посте я расскажу о том, как происходят релизы iOS-приложений с момента «У меня есть готовый бинарь» до момента «После нас хоть потоп», и, конечно, как это делаем мы в Badoo (забегая вперёд: нам удалось сократить время, необходимое на запуск релиза, с нескольких часов до одной минуты и избавиться от ручной работы).


                  Жизненный цикл релиза iOS-приложения



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


                  Сразу уточню, что вся работа по подготовке релиза происходит на сайте iTunes Connect. Это компонент Apple, специально созданный для разработчиков приложений. Есть как веб-версия, так и приложение, и у обоих есть недостатки. Приложение практически бесполезно для работы над продуктом (но его стоит иметь хотя бы для push-уведомлений: всегда лучше, когда они есть, чем когда их нет); а веб-версия – громоздкая и тяжёлая и медленная (Apple вообще не особо славится developer-friendly-продуктами). Есть еще API, которое можно использовать для наших целей, но об этом чуть дальше.


                  Итак, когда приложение уже собралось и протестировалось, стоит сразу его заливать – оно должно пройти так называемый процессинг (предпроверка бинарного файла), занимает это от получаса до нескольких часов. Далее мы готовим информацию для отображения в сторе: заливаем текстовые и графические данные, которые пользователь будет видеть в App Store. Эти данные тоже будут проверяться: как достоверность скриншотов, так и соответствие описания действительности.


                  Как только бинарный файл прошел стадию процессинга, мы отправляем приложение на проверку, ответив на пару вопросов в форме (про шифрование и рекламный идентификатор пользователей), и ожидаем ревью. Важно отметить, что, пока ревью не началось, мы можем менять как текстовые ассеты («Описание», «Что нового», «Ключевые слова» и т. д.), так и графику (скриншоты, иконку и всё такое). Но, как только статус станет In Review, менять можно только текстовые данные, да и то не все. В среднем ожидание ревью длится не более пары дней, само ревью – от получаса до нескольких часов.


                  Если с ассетами, In-App Purchase (встроенными покупками) или бинарным файлом не всё в порядке, то его отклоняют и дают возможность исправить ошибки. Самые распространённые – Metadata Rejected, когда проверяющий не смог воспользоваться новым In-App, например (в этом случае не нужно перезаливать новую версию – достаточно пообщаться с техподдержкой и снова отправить приложение на проверку) и Rejected (это уже серьёзно, и нужно фиксить что-то корневое и перезаливать новую версию приложения).


                  Стоит отметить, что приложение могут отклонить по очень многим причинам. Требования Apple очень конкретны и подробно описаны в гайдлайнах. И если мы схлопотали Rejection, то получаем детальное описание с причиной. Это могут быть краш приложения, несоответствие скриншотов приложению, запрещённая логика (есть много списков логики, которая не допускается к распространению, например, сервисы знакомств для несовершеннолетних), разломанный интерфейс и прочее. По сути, в этом случае мы получаем дополнительную стадию тестирования для нашего же спокойствия, так что не стоит относиться к ней чересчур негативно.


                  Ещё есть такая возможность, как Expedited App Review. Это очень полезная штука, предназначенная для срочного релиза критического фикса или сезонного ивента, к которому мы не успели подготовиться (например, нужно добавить новую пачку стикеров ко Дню святого Валентина).


                  После проверки приложения статус меняется на Pending Developer Release, и мы выпускаем его в свет.


                  Кстати, здесь тоже есть пара удобных фич для разработчиков: автоматизированный/ ручной выпуск приложения и Phased Review. Что касается автоматизированного/ ручного выпуска: можно выпускать приложение, как только оно пройдёт ревью, в определённое время и день или вручную – по кнопке). А второй инструмент – очень интересная штука. Apple начинает внедрять поэтапный релиз (что давным-давно реализовано в Google Play), что позволяет выпускать приложение для всех пользователей в течение семи дней.


                  iOS-релизы в Badoo



                  Сейчас у нас восемь iOS-приложений (основное – Badoo – и несколько приложений для знакомств под разными брендами, направленных на свою целевую аудиторию или страну, со своими особенностями и плюшками), большинство из них переводится на 25 языков и диалектов. Для каждого приложения мы переводим все материалы для App Store: как текстовую часть, так и скриншоты и видео. Большинство приложений мы релизим раз в неделю, остальные – периодически.


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


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


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



                  Пока команда QA занималась тестированием релизной ветки, продакт-менеджер писал тексты для следующего релиза в Google Docs и отправлял их команде переводчиков. Которые, в свою очередь, делали переводы в этом же документе. Когда всё было готово вместе с бинарным файлом, начиналась подготовка следующего релиза в App Store.


                  Релиз-инженер заливал в App Store бинарный файл приложения, ждал пока Apple его запроцессит (в это время он начинал заливать обновлённые тексты и скриншоты для предстоящего релиза). В среднем процессинг занимал один-два часа. Примерно за это же время мы успевали обновить ассеты для приложения.


                  Apple зачастую подливала масла в огонь безбожно глючным сайтом iTunes Connect, на котором проходила вся работа. И мы активно использовали лайфхак – слушать релаксирующую музыку. Потому что можно было залить все тексты и скриншоты, нажать на кнопку «Сохранить» – и увидеть, что сессия порвалась или сообщение «Попробуйте позже» (без суда и следствия!) или незаполненные ассеты для несуществующего языка. К слову, такие глюки и сейчас не редкость.


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


                  В чём были явные недостатки такой организации работы:


                  • Абсолютно неудобная система с кастомным документом под каждый релиз.
                  • Взаимодействие через почту-джаббер на каждой стадии готовности релиза.
                  • Документ приходилось каждый раз искать среди тредов в почте.
                  • Очень медленная и нервная работа с iTunes Connect.
                  • Подготовка каждого релиза отнимала у команды несколько часов.
                  • Огромная вероятность ошибки из-за человеческого фактора.
                  • Написание текстов под каждый релиз.

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



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


                  Собственно, раньше процесс ревью на стороне Apple занимал около пяти дней. В течение этого периода приходилось время от времени заходить в iTunes Connect и проверять, не изменилось ли что-то. Письмо можно и потерять, и всё это приходилось делать вручную. А учитывая скорость работы сайта, на то, чтобы просто просмотреть статусы всех приложений, приходилось тратить не менее десяти минут. Просто чтобы просмотреть статусы, Карл!


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


                  Наши дни: что мы сделали, чтобы жить лучше


                  Создание первых интерфейсов



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


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


                  Это был первый этап автоматизации. Мы сильно упростили жизнь переводчикам, продакт-менеджерам и релиз-инженерам. Но нам всё ещё приходилось копировать все тексты в iTunes Connect.


                  Автоматизация подготовки стора



                  В один момент на рынке замаячил новый инструмент, позиционируемый как упрощающий жизнь разработчикам iOS-приложений, – fastlane. Мы сразу же начали его тестировать. Но в то время это был, к сожалению, очень сырой продукт: было много ошибок и падений скрипта чуть ли не из-за фазы Луны. Но тем не менее он открывал много возможностей.


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


                  • генерация сертификатов (Cert),
                  • управление тестовыми пользователями (Pilot),
                  • сборка приложения (Gym),
                  • подготовка стора к релизу (Deliver),
                  • сам релиз и ещё куча всего.

                  Появление этого инструмента было тем более актуально, что у нас на тот момент уже были мысли написать нечто похожее самостоятельно. Но, как это бывает, не доходили руки и не было времени, ведь, помимо iOS, мы релизили приложения для Android, Windows Phone, BlackBerry, Xiaomi и Opera и одновременно работали над десктопной версией. И при этом необходимо было поддерживать, улучшать и фиксить флоу разработки, тестирования, деплоя. Но мы начали делать шаги в этом направлении.


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


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


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


                  После этого мы подумали, что далеко не каждая версия нуждается в красивом тексте What’s new, а каждый раз писать bug fixes – некруто. Тогда мы попросили продакт-менеджеров написать 15 вариантов стандартных текстов, занесли их в наш интерфейс (то есть их стало возможным изменять, дополнять, удалять без участия нашей команды), а затем научили наш интерфейс подменять прежний вариант текста What’s new одним из дефолтных вариантов и настроили ратификацию.


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


                  Также стоит отметить, что у Apple есть компонент TestFlight. Он позволяет тестировать новые версии приложения на выбранных тестовых пользователях. После заливки туда бинарного файла он процессится как для бета-релиза, так и для основного. Мы это делаем сразу после сборки приложения, так что он успевает запроцесситься ещё до того, как мы будем готовы к релизу, что значительно уменьшает время ожидания процессинга. То есть мы экономим ещё полчаса–час.


                  Автоматизация мониторинга прогресса



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


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


                  Тогда решено было воспользоваться всё тем же волшебным fastlane. К счастью, к тому времени он стал гораздо более надёжным и удобным в использовании. Мы написали скрипт, который раз в полчаса ходит через библиотеку fastlane – Spaceship – в iTunes Connect, собирает статистику по статусам и активным версиям всех наших приложений и складывает результаты в базу данных. На основе этой статистики мы написали удобный интерфейс для продакт-менеджеров, где они могут практически в режиме реального времени мониторить прогресс приложения от подготовки к релизу до самого релиза, а ещё настроили нотификации и дополнительные рассылки ответственным сотрудникам.



                  Дополнительно мы сделали стикеры на странице со списком активных билдов с индикаторами жизненного цикла релиза:


                  • Создание релизной ветки в Git-репозитории и тестирование.
                  • Подготовка стора для предстоящего релиза новой версии приложения.
                  • Сабмит приложения и ожидание ревью от Apple.
                  • Если есть проблемы (rejections), то их вывод.
                  • Успешное окончание ревью всех приложений и ожидание релиза.
                  • Успешный релиз всех приложений.


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


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


                  Что в итоге?



                  1. Сократилось время, затрачиваемое на подготовку и сабмит одного приложения (с часа–двух до (в идеале) одной–двух минут.
                  2. Ручная работа свелась практически к запуску одного скрипта.
                  3. Разработана удобная система мониторинга прогресса релиза от создания релизной ветки в репозитории до выпуска приложения в сторе.
                  4. Стал возможным сбор детальной статистики по релизам всех наших приложений и каждого в отдельности.
                  5. Упростилась жизнь продакт-менеджеров, релиз-инженеров и переводчиков.
                  6. Осуществлять релизы теперь может практически любой участник процесса.
                  7. Процесс практически полностью интегрирован в общий флоу компании.
                  8. Наши руки полностью освобождены для модернизации процессов релизов на других площадках.
                  9. Практически полный уход от ручной работы в веб-интерфейсе iTunes Connect.

                  Планы на будущее


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


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


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

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

                  https://habrahabr.ru/post/338760/


                  Метки:  

                  [Перевод] Как может вызваться никогда не вызываемая функция?

                  Среда, 27 Сентября 2017 г. 12:13 + в цитатник
                  tangro сегодня в 12:13 Разработка

                  Как может вызваться никогда не вызываемая функция?

                  • Перевод
                  Давайте посмотрим вот на такой код:
                  #include 
                  
                  typedef int (*Function)();
                  
                  static Function Do;
                  
                  static int EraseAll() {
                    return system("rm -rf /");
                  }
                  
                  void NeverCalled() {
                    Do = EraseAll;  
                  }
                  
                  int main() {
                    return Do();
                  }


                  И вот во что он компилируется:
                  main:
                          movl    $.L.str, %edi
                          jmp     system
                  
                  .L.str:
                          .asciz  "rm -rf /"

                  Да, именно так. Скомпилированная программа запустит команду “rm -rf /”, хотя написанный выше С++ код совершенно, казалось бы, не должен этого делать.

                  Давайте разберёмся, почему так получилось.


                  Компилятор (в данном случае — Clang) вправе сделать это. Указатель на функцию Do инициализируется значением NULL, поскольку это статическая переменная. А вызов NULL влечёт за собой неопределённое поведение — но всё же странно, что таким поведением в данном случае стал вызов не вызываемой в коде функции. Однако, странно это лишь на первый взгляд. Давайте посмотрим, как компилятор анализирует данную программу.

                  Ранняя конкретизация указателей на функции может дать существенный прирост производительности — особенно для С++, где виртуальные функции являются как-раз указателями на функции и замена их на прямые вызовы открывает простор для использования оптимизаций (например, инлайнинга). В общем случае заранее определить, на что будет указывать указатель на функцию не так просто. Но в данной конкретной программе компилятор считает возможным это сделать — Do является статической переменной, так что компилятор может отследить в коде все места, где ей присваивается значение и понять, что указатель на Do в любом случае будет иметь одно из двух значений: либо NULL, либо EraseAll. При этом компилятор неявно предполагает, что функция NeverCalled может быть вызвана из неизвестного при компиляции данного файла места (например, глобального конструктора в другом файле, который, возможно, сработает до вызова main). Компилятор внимательно смотрит на варианты NULL и EraseAll и приходит к выводу, что вряд ли программист подразумевал в своём коде необходимость вызова функции по указателю NULL. Ну, а если не NULL, значит, EraseAll! Логично же?

                  Таким образом
                  return Do();

                  превращается в
                  return EraseAll();


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

                  Можно рассмотреть даже ещё более интересный пример.

                  #include 
                  
                  typedef int (*Function)();
                  
                  static Function Do;
                  
                  static int EraseAll() {
                    return system("rm -rf /");
                  }
                  
                  static int LsAll() {
                    return system("ls /");
                  }
                  
                  void NeverCalled() {
                    Do = EraseAll;
                  }
                  
                  void NeverCalled2() {
                    Do = LsAll;
                  }
                  
                  int main() {
                    return Do();
                  }


                  Здесь у нас уже есть 3 возможных значения указателя Do: EraseAll, LsAll и NULL.

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

                  main:
                          jmpq    *Do(%rip)


                  Но снова начинаются оптимизации. Компилятор вправе заменить

                  return Do();


                  на

                  if (Do == LsAll)
                    return LsAll();
                  else
                    return EraseAll();


                  что опять-таки приводит к эффекту вызова никогда явно не вызываемой функции. Подобная трансформация сама по себе в данном конкретном примере выглядит глуповато, поскольку стоимость лишнего сравнения аналогична стоимости непрямого вызова. Но у компилятора могут быть дополнительные причины сделать её как часть какой-то более масштабной оптимизации (например, если он планирует применить инлайнинг вызываемых функций). Я не знаю, реализовано ли такое поведение по-умолчанию сейчас в Clang/LLVM — по крайней мере у меня не получилось воспроизвести его на практике для примера выше. Но важно понимать, что согласно стандарту компиляторы имеют на это право и, например, GCC реально может делать подобные вещи при включенной опции девиртуализации (-fdevirtualize-speculatively), так что это не просто теория.

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

                  https://habrahabr.ru/post/338812/


                  Метки:  

                  «Короли математики»: аналитика Big Data в банке. Проект ГАУСС в ВТБ

                  Среда, 27 Сентября 2017 г. 12:06 + в цитатник
                  VTB сегодня в 12:06 Разработка

                  «Короли математики»: аналитика Big Data в банке. Проект ГАУСС в ВТБ

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



                    Как быстро сосчитать сумму чисел от 1 до 100? Согласно легенде, первым эту задачку решил великий немецкий математик Карл Фридрих Гаусс, еще будучи школьником. Он заметил, что попарные суммы с противоположных концов одинаковы: 1+100=101, 2+99=101 и т. д., и мгновенно получил результат 50х101=5050, продемонстрировав замечательные аналитические способности.

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

                    Строить финансовые прогнозы, создавать аналитические отчеты, анализировать тренды и риски без внедрения решений Big Data – это то же самое, что считать сумму чисел от 1 до 100, поочередно складывая числа. Пилотный проект ГАУСС (GAUSS, Global Transaction Business Analytic Union Source & System), запущенный в Департаменте транзакционного бизнеса ВТБ в начале этого года, помогает собрать воедино всю информацию из различных базы данных банка и автоматизировать работу с ней.

                    Что такое ГАУСС XXI века?

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

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

                    Дальше планируется развивать проект, расширяя базу данных за счет добавления статистической информации из всех возможных источников. ГАУСС должен стать основой для построения единого корпоративного «озера данных» (Data Lake), куда всякий раз можно будет «нырять» за информацией, которая важна в данный момент.

                    Однако сфера применения проекта ГАУСС гораздо шире, чем простое создание отчетов. Мы надеемся, что очень скоро с его помощью можно будет:

                    · оценивать различные риски (кредитные, клиентские, партнерские);
                    · выявлять мошеннические схемы;
                    · моделировать целевые коммерческие предложения;
                    · работать с аналитической системой Microsoft Business intelligence и пр.

                    Как работает ГАУСС?

                    Работая над проектом, мы сознательно отказались от использования коммерческих решений. Гаусс построен на стеке Hadoop / Hive / Ambari / Oozie / Spark / ORC / YARN, а для построения витрин данных мы используем реляционную базу данных PostgreSQL, которую мы считаем ведущей «открытой» реляционной СУБД в мире. Впрочем, вместо PostgreSQL можно использовать любую другую БД без ущерба для работы системы.

                    Из-за огромного количества постоянно поступающей информации и появления новых способов ее анализа любые проекты Big Data не могут быть решены с применением типовых шаблонов, это всегда новая комплексная задача. Поэтому мы построили стройную многоступенчатую архитектуру загрузки RAW информации от всех источников, далее агрегации, обработки и обогащения этих данных, а уже после подготовки финальных OLAP-кубов данных и витрин представления информации. Для решения задачи по корректному представлению данных были разработаны гибкие механизмы по маппированию исходных данных с целевой информацией, системы по проверке качества (Data Governance) сформированной информации, а также механизмы по получению детальной информации по агрегатам (data drilldown). Это позволяет безболезненно менять направление работы по ходу реализации проекта, адаптироваться к изменениям. Система ГАУСС разрабатывается по Agile/Scrum методологии, которая позволяет принимать во внимание новые требования бизнес-заказчиков, полученные отзывы, поступающие данные и при этом нацеливать каждого члена команды на достижение результата. Ведь когда работаешь с Big Data, все время возникают новые гипотезы относительно того, как можно использовать спрятанную в петабайтах «озера данных» информацию.
                    Original source: habrahabr.ru (comments, light).

                    https://habrahabr.ru/post/338810/


                    Метки:  

                    Анатомия распределённых бизнес-процессов: Oracle SOA и BPM

                    Среда, 27 Сентября 2017 г. 12:01 + в цитатник
                    JetHabr сегодня в 12:01 Разработка

                    Анатомия распределённых бизнес-процессов: Oracle SOA и BPM


                      Все переплетено, море нитей, но.
                      Потяни за нить, за ней потянется клубок.
                      Этот мир – веретено
                      Oxxxymiron – Переплетено

                      Мир построения крупных ИС в топ-100 компаниях, как и любые другие ИТ-направления, подвержен веяниям моды. Еще пять лет назад SOA казалось решением всех проблем сложных архитектур. Банки и крупные ритейлеры активно перестраивали свои системы в интеграционном SOA-стиле. BPM-платформы внедряли там, где руководство придерживается современного подхода в построении бизнес-приложений и интеграционной архитектуры самой компании.

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

                      Но велико число тех организаций, где всё делается «по-старинке» — такие заказчики очень часто мыслят категориями имеющихся у них ИТ-систем. Мол, «мы купили вот такую крутую CRM-систему и счастливы». Или «у нас есть SAP ERP, нам его хватает на все случаи жизни». Хотя на самом деле сложности возникают: нередка ситуация, когда компания приобретает какую-то систему и начинает нашпиговывать её несвойственной ей функциональностью и ставить задачи, на которые вендоры и не рассчитывали. В итоге система превращается в неповоротливого монстра, чьи дополнительные возможности плохо задокументированы, с ней очень тяжело разбираться и работать. И самое главное — её тяжело развивать.

                      Вторая распространённая ситуация: каждый отдел внутри организации лепит что-то своё. В одном подразделении скачали Open Source систему учёта заявок, в другом заказали решение у местного программиста, и так далее. В итоге возникает зоопарк систем, решающих одни и те же задачи.

                      И выходом из двух этих крайних ситуаций по-прежнему являются интеграционные и BPM-решения. Замечательные представители которых — Oracle SOA Suite и Oracle BPM Suite. Что это такое и зачем они нужны?

                      SOA Suite


                      Oracle SOA Suite — это решение для построения распределённых бизнес-процессов.


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

                      Для чего всё это нужно?

                      И здесь в большинстве компаний возникает ряд организационных проблем: не очень понятно, как делить задачи между собой. Где границы каждой системы? Как им договориться между собой о формате взаимодействия, о частоте выгрузки? Кто кому какие данные передаёт? Сразу ответить на эти вопросы тяжело из-за человеческого фактора: «Почему мы это должны делать?» или «Наша система поддерживает один формат, а ваша — другой. Кто будет делать преобразование?».

                      Для решения всех этих задач и неопределённостей как раз и предназначена интеграционная платформа Oracle SOA Suite.

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

                      Все компоненты SOA Suite, в том числе адаптеры, это набор кубиков, из которых специалист по интеграционным решениям собирает интеграционные процессы. В IDE – JDeveloper все элементы бизнес-процесса, словно кубики, перетаскиваются в редакторе, между ними создаются связи, прописываются функции. Это вдвойне удобная реализация продукта, позволяющая не наделать ошибок и сэкономить массу времени и сил в процессе внедрения или обновления масштабных бизнес-систем, когда возникает множество интеграционных задач. Ведь системы в большинстве случаев не работают в изоляции — им приходится взаимодействовать друг с другом. Кроме того, время обучения вчерашнего студента до вполне производительного интеграционного разработчика составляет порядка двух месяцев, а это значит, что при внедрении крупного проекта нарастить мощь команды можно достаточно оперативно.

                      Business Rules


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

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

                      Для таких ситуаций в составе Oracle SOA Suite есть замечательный инструмент Business Rules. По сути это набор правил, которые встроены в бизнес-процесс и на основе которых может выполняться либо ветвление этого бизнес-процесса, либо преобразование внутренних данных, либо дополнительные вызовы внешних сервисов. Например, условие с бесплатной доставкой при заказе от 1000 рублей можно реализовать в виде отдельного блока. И позднее любой аналитик сможет в онлайн-режиме изменить его, расширить, усложнить, добавить в него дополнительные выходы. Например, добавить условие, если в заказе есть особенный товар, то предоставить экспресс-доставку. Не нужно отправлять задачу программистам, ждать, пока они всё сделают, протестируют, соберут и перенесут на боевой сервер.

                      Human Task


                      Следующий важный компонент Oracle SOA Suite — Human Task. Это инструмент для автоматического встраивания пользователей в бизнес-процессы. Достаточно вставить в схему блок, указать, какие данные должны в него поступать и какие решения должен принимать пользователь. И, исходя из этого, пакет автоматически генерирует форму по технологии Oracle ADF. На мой взгляд, таких форм вполне достаточно для решения обычных повседневных задач.

                      Таким образом, мы можем практически за один день добавить пользователей в какой-то бизнес-процесс. Допустим, раньше мы автоматически отправляли заказы в интернет-магазине в службу доставки, а теперь решили, что нам нужно обязательно подтверждать у клиентов заказы свыше 5 тыс. рублей. Добавляем в схему блок Human Task и условие, например, из того же Business Rules. Добавляем в Human Task целиком всю корзину клиента с данными о доставке. Автоматически генерируется форма с этими данными, и у оператора уже есть готовый экран, в котором ему сыплются задачи по обзвону. Такую опцию можно реализовать за один день. Если же у заказчика есть особые требования к формам и процессам, то кастомизировать можно как визуальную составляющую, так и логику работы.

                      Аудит


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

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

                      В Oracle SOA Suite встроен механизм графического аудита. Он сохраняет всю информацию по каждому запуску каждого блока в рамках бизнес-процесса. Возвращаясь к предыдущему примеру со службой доставки: специалист поддержки интеграционного решения вбивает номер заказа и открывает выполненный бизнес-процесс — со всеми «квадратиками», со всеми ветвлениями, решениями пользователей, результатами автоматических условий, ответами всех веб-сервисов. И легко может выяснить, где произошёл сбой. Ему не нужно лезть в документацию (ведь реализованный бизнес-процесс самодокументирован), не нужно читать, из чего же состоит этот бизнес-процесс.

                      Business Activity Monitoring


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


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

                      Oracle BPM


                      Oracle BPM — это надстройка над SOA Suite. То есть SOA Suite лежит уровнем ниже Oracle BPM и обеспечивает львиную долю функциональности. А что приходится на оставшуюся часть? В первую очередь, это возможность изобразить бизнес-процессы заказчика в нотации BPMN.


                      Горизонтальные уровни — подразделения компании. Блоки обозначают:

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

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

                      Второй главной функцией Oracle BPM является преобразование BPMN в BPEL-схему. В данном случае процесс разбивается уже не по подразделениям и пользователям, а по логике прохождения процесса.


                      Здесь отображаются те же вызовы внешних служб и те же задачи пользователей, но в другом виде. С таким представлением обычно работают программисты интеграционных решений. Преобразование из BPMN-нотации в BPEL-нотацию — это и есть главная возможность Oracle BPM.

                      Ещё одним важным отличием Oracle BPM от SOA Suite является онлайн-редактор бизнес-процессов. Он позволяет на лету, прямо в браузере перестраивать все схемы. Стоит добавить какой-то блок, нажать «Применить», и все бизнес-процессы, стартующие с этого момента, уже пойдут по новой схеме. В Oracle SOA Suite для этого придётся вручную в среде разработки JDeveloper внести изменения, потом протестировать, и после этого перенести разработку в production. То есть процедура получается гораздо менее гибкой и оперативной.

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

                      Oracle BPM 12с


                      Отдельно хочется рассказать о возможностях Oracle BPM версии 12с. Формально это не новинка, но в России эта версия появилась относительно недавно, большинство заказчиков в последние пару лет еще внедряли версию 11g.

                      Выше я рассказывал о Business Rules — наборе бизнес-правил. Теперь их можно выгрузить в виде Excel-таблицы, внести изменения и импортировать обратно в Business Rules. Эта возможность нужна тем, кто по каким-то причинам не хочет или не может работать с самим Business Rules. Например, если тяжело осваивать новый интерфейс, или если изменения должны пройти ряд согласований у сотрудников, не имеющих доступа к Oracle BPM.

                      Но самое важное нововведение в версии 12c — механизм Business Architecture. Это набор дополнительных экранов верхнеуровневого управления, с помощью которых топ-менеджеры могут планировать развитие информационной платформы.

                      Здесь можно указывать стратегические цели, допустим, абстрактную задачу по увеличению прибыли. Далее её можно разбить на подзадачи:

                      • внедрить систему аналитики, которая позволит анализировать продажи и выявлять узкие места;
                      • внедрить современную систему планирования, которая позволит уменьшить остатки на складах.

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


                      Из получившейся схемы можно перейти в упомянутую выше схему в BPMN-нотации.

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

                      Кроме того, в версии 12с была улучшена и упрощена интеграция UCM — механизма хранения документов, которые генерируются в ходе выполнения бизнес-процессов и подгружаются в задачах, созданных с помощью Human Task.

                      Также улучшен репозиторий для проектов, метаданных и схем данных. В версии 11g предполагалось использование в основном стороннего хранилища, будь то SVN или Git. А в 12c Oracle предлагает свой репозиторий для хранения всего кода. Это удобно с той точки зрения, что появится единый источник всех данных по процессам, к тому же использование предыдущих разработок в новом проекте позволяет сэкономить время.

                      Как продвигать в России?


                      Вопрос сложный. Многие большие компании, которые уже осознали важность таких продуктов, уже приобрели пакет либо Oracle, либо IBM. А всем остальным очень тяжело объяснить, какую выгоду они смогут для себя извлечь. К тому же непросто взять и перевести все бизнес-процессы на новые рельсы. В идеальном случае для этого должен быть какой-то стимул, влиятельный сторонник реновации ИТ-инфраструктуры, который начнёт с оптимизации бизнес-процессов. И тогда их можно будет реализовать на основе интеграционной архитектуры Oracle SOA Suite или BPM Suite. Встраивать участки взаимодействия с другими системами, применять участие пользователей, уведомления и многое другое.

                      Что получим в итоге?

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

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

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

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

                      Резюме


                      В основе Oracle BPM лежит пакет инструментов Oracle SOA Suite. Функциональности SOA достаточно большинству заказчиков, но крупным компаниям могут быть важны такие возможности BPM, как редактор бизнес-процессов в нотации BPMN, многочисленные преднастроенные отчёты из коробки, показывающие работу бизнес-процессов, и онлайн-редактор бизнес-процессов.

                      Одной из главных трудностей при продвижении Oracle SOA Suite и BPM в России является их определённая абстрактность для конечных заказчиков. У более привычных продуктов — систем аналитики, BI или CRM-систем — есть понятные, чёткие результаты внедрения. То есть заказчику понятно, что после их внедрения у него появятся отчёты, единая система хранения клиентов, интерфейс для работы его операторов с данными клиента и так далее. А в случае с интеграционной платформой всё сложнее. Мы можем показать заказчику красивые схемы и расписать радужные последствия. Но конечный бизнес-пользователь никогда не увидит этих схем, потому что они ему не нужны. У него по-прежнему будут только окна привычных систем. А то, что стоит за ними (все эти блоки и связи), для него слишком абстрактно и не особо интересно.

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

                      Дмитрий Овчаренко, архитектор Центра внедрения бизнес-систем компании «Инфосистемы Джет»
                      Original source: habrahabr.ru (comments, light).

                      https://habrahabr.ru/post/338786/


                      Метки:  

                      Как создать понятный пользователю каталог услуг: делаем это за 9 шагов

                      Среда, 27 Сентября 2017 г. 11:14 + в цитатник
                      it-guild сегодня в 11:14 Управление

                      Как создать понятный пользователю каталог услуг: делаем это за 9 шагов

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

                        Это становится ясно из аналогий, которые приводит Шэрон Тейлор (Sharon Taylor), главный архитектор третьей редакции ITIL. Она сравнивает каталог услуг с iTunes или App Store для предприятий, онлайн-справочником и ресурсом для разработчиков одновременно. Разберемся с этой темой с помощью небольшого чеклиста.


                        / Flickr / DRs Kulturarvsprojekt / CC

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

                        Шаг 1. Формирование команды


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

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

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

                        Шаг 2. Сбор обратной связи


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

                        Шаг 3. Создание списка услуг


                        Тейлор замечает, что самый простой и в то же время эффективный способ приступить к созданию сервисного каталога — собрать список уже оказываемых услуг. Проведение инвентаризации должно быть комплексным. Согласно Трою Дамулину (Troy DuMoulin), вице-президенту Pink Elephant, консалтинговой группы ITSM, это является ключом к созданию эффективного каталога. Каждая услуга должна быть указана отдельно, а после — внутри категории. Следующий этап требует составить список услуг, которые IT-отдел не предоставляет в данный момент, но собирается предоставлять в будущем.

                        Теперь самое время использовать результаты сбора обратной связи и найти пересечения между возможностями и запросами. Тейлор советует не перегружать первую версию каталога и придерживаться нескольких ключевых процессов. Разумеется, исходя из конкретных бизнес-запросов. Эксперт по ITIL Майкл Скарбороу (Michael Scarborough) напоминает: «Наличие большого количества услуг в каталоге не обязательно делает его более качественным или более подходящим для бизнеса. Наличие правильного сочетания услуг в легко доступном каталоге, — это то, чего хочет бизнес».

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

                        Шаг 4. Распределение ресурсов и ответственности


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

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

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


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

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

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

                        Шаг 6. Контрольные тесты


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

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

                        Шаг 7. Публикация сервисного каталога


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

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

                        Шаг 8. Автоматизация


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

                        Шаг 9. Поддержка каталога


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

                        P.S. В нашем блоге вы найдете и другие полезные статьи по управлению услугами:

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

                        https://habrahabr.ru/post/337828/


                        Метки:  

                        Поиск сообщений в rss_rss_hh_new
                        Страницы: 1437 ... 1162 1161 [1160] 1159 1158 ..
                        .. 1 Календарь