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

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

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

[Перевод] Продвинутые перечисления с Ruby

Вторник, 08 Августа 2017 г. 20:48 + в цитатник
Перечисления (enumeration) по определению это — «действие упоминания некоторого количества чего-либо один за одним». В программировании, вместо упоминания, мы выбираем любое действие, которое хотим произвести, будь то простой вывод на монитор или выполнение некоторого рода выборки и/или преобразования над элементом.

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

Как работают перечисления в Ruby


В этом посте, я дам Вам краткий обзор о том, что делают блоки (block) и yield'ы. Блоки в Ruby, в которых мы заинтересованы, является кусками кода, определенными внутри методов или proc/lambda. Вы можете думать о yield, как о текущем блоке кода, куда вставляется другой блок кода откуда-то еще. Позвольте мне продемонстрировать.

def my_printer
  puts "Hello World!"
end

def thrice
  3.times do
    yield
  end
end

thrice &method(:my_printer)
# Hello World!
# Hello World!
# Hello World!

thrice { puts "Ruby" }
# Ruby
# Ruby
# Ruby

Методы принимают две формы блоков для команды yield: proc'ы или блоки. Метод method трансформирует определение метода в proc, который затем может быть передан внутрь как блок, как в примере my_printer выше.

Выше на том месте, где написана команда yield, равнозначно, как если бы код передающийся как блок, был бы на месте yield. Так что в первом случае представьте вызов yield, замененным на puts «Hello World!» и второй yield замененным на puts «Ruby».

yield может также работать как простой перечислитель. Вы можете передать любое значение внутрь как параметр к block/proc добавляя их после yield.

def simple_enum
  yield 4
  yield 3
  yield 2
  yield 1
  yield 0
end

simple_enum do |value|
  puts value
end
# 4
# 3
# 2
# 1
# 0

Требования к минимальному перечислителю


Стандартный способ создания перечислителя в Ruby это — each, выдает/йилдит (yields) значения. С учетом этого, вы можете объявить метод each на любом Ruby объекте и получить все преимущества более чем 50 методов для обработки и исполнения коллекций от модуля Enumerable. Просто добавьте include Enumerable внутрь объекта, который имеет валидный метод each, и вы можете полностью использовать все эти методы (имеется в виду методы модуля Enumerable).

Перечислители не ограничены простым коллекциями типа Array (массивы), они могут работать с любыми коллекциями, которые имеют в себе объявленный метод each (и обычно будет иметь модуль Enumerable в своих «прародителях/предках»).

Array.ancestors
# => [Array, Enumerable, Object, Kernel, BasicObject]
Hash.ancestors
# => [Hash, Enumerable, Object, Kernel, BasicObject]
Hash.method_defined? :each
# => true
require "set"
Set.ancestors
# => [Set, Enumerable, Object, Kernel, BasicObject]

«Ленивые» и не «ленивые» перечислители


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

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

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

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

Создание «ленивого» перечислителя в Ruby также просто как вызов lazy на объекте с включенным в него модулем Enumerable или вызов to_enum.lazy на объекте, с объявленным внутри него методом each.

class Thing
  def each
    yield "winning"
    yield "not winning"
  end
end

a = Thing.new.to_enum.lazy

Thing.include Enumerable
b = Thing.new.lazy

a.next
# => "winning"
b.next
# => "winning"

Вызов to_enum возвращает объект, который является как Enumerator так и Enumerable, и который будут иметь доступ ко всем их методам.

Важно обратить внимание, какие методы перечислителя будут «потреблять» всю коллекцию за раз, а какие будет «потреблять» (выполнять) её — «лениво». Для примера, метод partition потребляет всю коллекцию за раз, так что она не приемлема для бесконечных коллекций. Лучший выбор для ленивого выполнения, могли бы быть такие методы как chunk или select.

x = (0..Flot::INFINITY)

y = x.chunk(&:even?)
# => #:each>>
y.next
# => [true, [0]]
y.next
# => [false, [1]]
y.next
#=> [true, [2]]

z = x.lazy.select(&:even?)
# => #:select>
z.next
# => 0
z.next
# => 2
z.next
# => 4

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

Создание «ленивого» перечислителя


В Ruby есть класс Enumerator::Lazy, который позволяет писать Вам собственные методы перечислителя как take в Ruby.

(0..Float::INFINITY).take(2)
# => [0, 1]

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

def divisible_by?(num)
  ->input{ (input % num).zero? }
end

def fizzbuzz_from(value)
  Enumerator::Lazy.new(value..Float::INFINITY) do |yielder, val|
    yielder << case val
    when divisible_by?(15)
      "FizzBuzz"
    when divisible_by?(3)
      "Fizz"
    when divisible_by?(5)
      "Buzz"
    else
      val
    end
  end end

x = fizzbuzz_from(7)
# => #

9.times { puts x.next }
# 7
# 8
# Fizz
# Buzz
# 11
# Fizz
# 13
# 14
# FizzBuzz

С помощью Enumerator::Lazy, неважно, что вы подаете на yielder — будет значение возвращаемое на каждом шаге в последовательности. Перечислитель следит за текущим прогрессом, когда вы используете next. Но когда вы вызываете each после нескольких вызовов next, он начнет с самого начала коллекции.

Параметр, который вы передаете в Enumerator::Lazy.new — это коллекция через который мы пройдем перечислителем. Если вы написали этот метод для Enumerable или совместимого объекта, вы можете просто передать self как параметр. val будет единственным значением, производимым в единицу времени методом коллекции each, а yielder будет единственным точкой входа для любого блока кода, который вы хотите передать, как если бы это было с each.

Продвинутое использование перечислителя


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

require "prime"
x = (0..34).lazy.select(&Prime.method(:prime?))
x.next
# => 2
x.next
# => 3
x.next
# => 5
x.next
# => 7
x.next
# => 11

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

Группировка


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

[0,1,2,3,4,5,6,7,8].group_by.with_index {|_,index| index % 3 }.values
# => [[0, 3, 6], [1, 4, 7], [2, 5, 8]]

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

0    3    6
1    4    7
2    5    8

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

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

threes = (0..2).cycle
[0,1,2,3,4,5,6,7,8].slice_when { threes.next == 2 }.to_a
# => [[0, 1, 2], [3, 4, 5], [6, 7, 8]]

Перечислитель threes просто проходит бесконечно от 0 до 2, в «ленивой» манере. В итоге мы получим следующий вывод:

0    1    2
3    4    5
6    7    8

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

x = [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
x = x.transpose
# => [[0, 3, 6], [1, 4, 7], [2, 5, 8]]
x = x.transpose
# => [[0, 1, 2], [3, 4, 5], [6, 7, 8]]

«Сворачивание»


Давайте посмотрим на способы компоновки коллекций в результат. В других языках, это обычно делается через метод fold. В Ruby это долго делалось при помощи reduce и inject. Более свежее решение, и предпочтительный способ делать это с помощью each_with_object. Основная идея — это обработка одной коллекции в другую, выступающей как результат.

Суммирование целых чисел также просто как:

[1,2,3].reduce(:+)
# => 6

[1,2,3].inject(:+)
# => 6

class AddStore
  def add(num)
    @value = @value.to_i + num
  end

  def inspect
    @value
  end
end

[1,2,3].each_with_object(AddStore.new) {|val, memo| memo.add(val) }
# => 6

# As of Ruby 2.4
[1,2,3].sum
# => 6

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

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

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

collection = [:a, 2, :p, :p, 6, 7, :l, :e]

collection.reduce("") { |memo, value|
  memo << value.to_s if value.is_a? Symbol
  memo # Note the return value needs to be the object/collection we're building
}
# => "apple"

collection.each_with_object("") { |value, memo|
  memo << value.to_s if value.is_a? Symbol
}
# => "apple"

Структуры


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

class Pair < Struct.new(:first, :second)
  def same?;    inject(:eql?)  end
  def add;      inject(:+)     end
  def subtract; inject(:-)     end
  def multiply; inject(:*)     end
  def divide;   inject(:/)     end

  def swap!
    members.zip(entries.reverse) {|a,b| self[a] = b}
  end

end

x = Pair.new(23, 42)
x.same?
# => false

x.first
# => 23

x.swap!

x.first
# => 42

x.multiply
# => 966

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

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

Подытожим


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

Если производительность важна, тогда измерьте производительность отдельных реализаций и убедитесь, что установили фильтры и ограничения/лимиты в процесс обработки, как раннее, если конечно на то, есть возможность. Рассмотрите ограничение ваших входных данных в маленькие куски, используя метод readline на файлах, нежели read или readlines или используйте LIMIT number в SQL.

«Ленивая» итерация может оказать огромную помощь в разделение задач на различные потоки или фоновые задания обработки. Концепция «ленивых» итераций на самом деле не имеет недостатков, так что вы можете выбирать их для потребления любой коллекции в любом месте. Она предлагает гибкость, и некоторые языки, как Rust с итераторами, взяли за стандарт быть «лениво» реализованными (implemented lazily).

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

https://habrahabr.ru/post/335072/


Метки:  

[Из песочницы] Централизованное хранилище логов для Squid Proxy или как мы логи в базу заворачивали

Вторник, 08 Августа 2017 г. 19:05 + в цитатник
image

Привет %username%,

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

Что имеем:

  1. Squid-hq
  2. Squid-br1
  3. Squid-br2
  4. Squid-br3
  5. Squid-br4
  6. Squid-db

Как видно из списка, в наличии 5 серверов squid proxy в разных удаленых офисах, и 1 база данных для сбора логов. Все OS CentOS 7.3, squid proxy от 3.3.8 до 3.5.26, Squid-db — с установленной mariadb 5.6

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

  1. Ставим зависимости на сервера squid proxy:
    yum install perl perl-Readonly* perl-URI perl-YAML perl-DBI perl-Carp perl-DBD-mysql
  2. После чего раскладываем по местам скрипты и конфиг для подключения к базе:

    cp log_mysql_daemon.pl /usr/libexec/squid/log_mysql_daemon.pl

    Даем права:

    chmod +x /usr/libexec/squid/log_mysql_daemon.pl
    chown squid:squid /usr/libexec/squid/log_mysql_daemon.pl


  3. Далее создаем конфиг файл для подключения скрипта к базе:

    vi /etc/squid/log_mysql_daemon.conf

    host: ""
    database: "squid_log"
    table: "access_log"
    user: "squid"
    pass: ""


  4. Создаем базу, импортируем схему и создаем юзера:

    mysql -p
    create database squid_log;
    CREATE USER 'squid'@'%' IDENTIFIED BY '';
    GRANT ALL PRIVILEGES ON squid_log.* TO 'squid'@'';
    GRANT ALL PRIVILEGES ON squid_log.* TO 'squid'@'';
    GRANT ALL PRIVILEGES ON squid_log.* TO 'squid'@'';
    GRANT ALL PRIVILEGES ON squid_log.* TO 'squid'@'';
    GRANT ALL PRIVILEGES ON squid_log.* TO 'squid'@'';
    exit

    cat log_mysql_daemon-table.sql log_mysql_daemon-views.sql | mysql -p squid_log



  5. Переходим на сторону зла squid proxy конфига

    Добавляем конфигурацию для демона

    vi /etc/squid/squid.conf
    acl dontLog http_status 403 407
    logformat squid_mysql %ts.%03tu %6tr %>a %Ss %03Hs % access_log /var/log/squid/access.log squid
    access_log daemon:/etc/squid/log_mysql_daemon.conf squid_mysql !dontLog
    logfile_daemon /usr/libexec/squid/log_mysql_daemon.pl


    Разбираем:
    acl dontLog http_status 403 407 — опциональная строка, убирает ошибки из лога идущих в базу данных связаные с эрор кодами 403, 407. База будет расти в геометрической последовательности, а для репортинга не будет нести никакой ценности

    logformat squid_mysql %ts.%03tu %6tr %>a %Ss %03Hs %b> — задаем формат логу, одно из важных условий для множественных squid серверов последнее значение с названием сервера с которого приходят логи. В оригинальных скриптах функционал отсутствует поэтому подкручиваем эту строку и сам скрипт следующим образом:

    в /usr/libexec/squid/log_mysql_daemon.pl в настройку колонок добавляем squid-server

    # fields that we should have in the database table
    # this list depends on the log format configuration
    my @required_fields = qw(
    id
    time_since_epoch
    response_time
    client_src_ip_addr
    squid_request_status
    http_status_code
    reply_size
    request_method
    request_url
    username
    squid_hier_status
    server_ip_addr
    mime_type
    squid_server
    );


    access_log /var/log/squid/access.log squid — Оставляем локальные логи для отладок и случаев проблем с базой, у них включен ротейшен поэтому лишним не будет

    access_log daemon:/etc/squid/log_mysql_daemon.conf squid_mysql !dontLog — собственно сама строка к конфигурации демона. Обратите внимание что !dontLog отменяет логирование 403,407 только для базы данных, так что в случае отладки можно легко использовать локальные логи

    logfile_daemon /usr/libexec/squid/log_mysql_daemon.pl — путь к перловому демону

  6. Перечитываем конфиги squid proxy

    squid reconfigure
    squid -k reconfigure


    и получаем желаемый результат:
    image

    Доступные таблицы и вьюшки:
    image

Заключение:


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

Было ли бы вам интересно почитать продолжения цикла статей про Squid Proxy?
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/335204/


Метки:  

И снова Huawei Cloud Fabric: что такое SDN-архитектура и с чем её едят

Вторник, 08 Августа 2017 г. 18:46 + в цитатник


Не так давно мы рассказывали об интеграции SDN-решения Huawei Cloud Fabric с платформой VMware vSphere и рассуждали о выгодах, которые эта самая интеграция несёт.

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

Отрасль диктует свои правила


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

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

Логическая цепочка довольно проста:

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

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

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

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

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

Huawei отвечает


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

Интеллектуальный центр системы – Agile Controller. Он обеспечивает централизованные, высокоустойчивые и интеллектуальные возможности управляющей плоскости для сетевой структуры ЦОД, построенной на коммутационной платформе CloudEngine от Huawei.

Agile Controller от Huawei для ЦОД разработан как полностью открытое решение, обеспечивающие эффективную интеграцию с популярными промышленными решениями сторонних разработчиков через открытый и стандартизованный программный интерфейс (API).

Какие же ключевые преимущества влечёт за собой правильное применение программного сетевого подхода к инфраструктуре центров обработки данных в целом, и SDN-решения Cloud Fabric в частности?

И самое главное — какое влияние эти преимущества могут оказать на бизнес?

Внутренние процессы


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

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

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

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

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

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

Эффективность использования ресурсов


Улучшения в IT-процессах ЦОД обеспечивают естественный прирост эффективности организации в целом.

1. Помимо роста операционной эффективности SDN позволяет сети самостоятельно обеспечивать внутренний баланс и вносить корректировки для оптимизации потоков трафика через инфраструктуру.

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

2. Кроме объединения корпоративных облачных ресурсов, распределенных по различным географическим объектам, грамотно оптимизированное DCI обеспечивает гораздо более высокий коэффициент использования доступных ресурсов, увеличивая его с 30% в среднем до 90%.

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

Повышение конкурентоспособности


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

Открытые решения


По своей открытости и интеграционным возможностям SDN-решение Huawei является передовым в отрасли. Что это значит для бизнеса?

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

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

В итоге


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

Несмотря на то, что многие из перечисленных здесь преимуществ характерны для технологии SDN в целом и присущи большинству SDN-решений, два важных отличия решения Huawei для ЦОД выделяют его среди прочих:

1. Параметры комплексного унифицированного SDN-решения Huawei Cloud Fabric обеспечивают единообразные интеграционные возможности SDN как для локальной сети ЦОД, так и для межсетевых взаимодействий (DCI) и в сетевых системах хранения данных (SAN).

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

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

В связи со всем выше сказанным нам критически важен ваш пользовательский опыт взаимодействия с Huawei Cloud Fabric, и мы просим вас активнее с нами им делиться.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/334920/


Метки:  

[Перевод] Криптовалюта Dash приглашает… взломать свой блокчейн

Вторник, 08 Августа 2017 г. 17:50 + в цитатник

Цифровая валюта Dash голосованием сообщества через Систему самофинансирования одобрила найм краудсорсинговой команды тестеров Bugcrowd для выявления уязвимостей в открытом коде своего программного обеспечения. Тысячи независимых исследователей Bugcrowd будут работать над выявлением потенциальных уязвимостей, которые Bugcrowd будет сортировать, проявлять, а затем предоставлять команде Dash Core для исправления.

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

“Наша цель – стать более безопасной и защищённой платёжной сетью”, – говорит Джим Бёрш, создатель бюджетных предложений «Dashincubator» и «Bugcrowd». “Речь идёт о деньгах – цифровом эквиваленте реальных наличных средств. Значительные суммы цифровых денег порождают мощный стимул для воров активизироваться в глобальном масштабе.

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

“Поскольку криптовалюта Dash развивается динамично и привлекает к себе всё больше внимания, то выявление и своевременное устранение уязвимостей становится абсолютно необходимо”, – говорит генеральный директор DAO «Dash Core» Райан Тейлор. “Программы поиска багов – это свежий взгляд на код, и он гарантирует, что “белые” хакеры помогут выявить любые недостатки в нашей системе безопасности. Предоставление сильных стимулов для привлечения опытных программистов является одним из многих инструментов, которыми мы располагаем, чтобы обеспечить максимальную надёжность кодовой базы Dash.”

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

“В настоящее время наблюдается огромный дефицит специалистов по кибербезопасности”, – говорит генеральный директор Bugcrowd Кейси Эллис. “Сопоставьте это с расширяющейся набором векторов атак, и вы поймёте, почему компании оказываются в невыгодном с точки зрения безопасности положении.”

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

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

“Наш знаковый предстоящий релиз – Dash Эволюция – нацелен на то, чтобы полностью переосмыслить функционирование цифровой валюты, и он будет доступен для альфа-тестирования уже в Декабре 2017. Он демонстрирует, как оптимизация пользовательского опыта требует значительных изменений в базовых технологиях. Чем больше улучшений Dash вносит в оригинальный код Биткойна, на котором Dash базируется, тем ближе мы становимся к тому, что наш продукт будет соответствовать самым высоким стандартам. Поскольку цифровые валюты содержат в себе большую ценность и облегчают денежные переводы, крайне важно принять все возможные меры, чтобы быть абсолютно уверенными в том, что выявлены все, даже незначительные ошибки программного обеспечения.”

“Независимо от своего размера, организации, пытающиеся самостоятельно выявлять уязвимости в своём ПО, быстро понимают, что это очень сложная задача”», – говорит г-н Эллис. «Определение проблемных областей, определение уровней доступа, создание программы управления выявлением уязвимостей и даже определение сроков устранения проблем в рамках этой программы – всё это требует времени и ресурсов как при запуске программы, так и на постоянной основе по мере её развития. Выбрав Bugcrowd для управления поиском багов, команда Dash отделила свою работу от этого процесса, так что всё, что они увидят, – это результаты.”
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/335196/


Метки:  

За глобальные переменные замолвите слово?

Вторник, 08 Августа 2017 г. 17:31 + в цитатник

Мне, как и многим другим, в университете, рассказали про то, что глобальные переменные использовать плохо. Конечно, я пытался задавать вопрос: "Почему?", на который получил пространное объяснение про плохо структурированный код. Ответ я не понял до конца, но инстинкт самосохранения мне подсказал, что надо делать как говорят. Только спустя много лет, я нашел в статье E. M. Clarke Programming Language Constructs for Which It Is Impossible To Obtain Good Hoare Axiom Systems теорему, которая, на мой взгляд, проясняет ситуацию с глобальными переменными.


Итак, собственно, теорема Clarke:


It is impossible to obtain a system of Hoare axioms H which is sound and
complete in the sense of Cook for a programming language which allows:
(I) procedures as parameters of procedure calls,
(II) recursion,
(III) static scope,
(IV) global variables,
(V) internal procedures.

небольшие пояснения по тексту:



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


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

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


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


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

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

https://habrahabr.ru/post/335190/


Метки:  

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

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

Более половины современных сайтов содержат критически опасные уязвимости, которые позволяют злоумышленникам проводить различные атаки, включая отказ в обслуживании и кражу персональных данных. Такие выводы содержатся в исследовании компании Positive Technologies на основе работ по анализу защищенности веб-приложений за 2016 год.

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

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

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

Еще одно важное наблюдение - веб-приложения, находящиеся в процессе эксплуатации, оказались более уязвимыми, чем тестовые: критически опасные уязвимости выявлены в 55% продуктивных систем и в 50% тестовых систем. Это свидетельствует о том, что необходимо проводить анализ защищенности не только в процессе разработки, но и после внедрения в эксплуатацию. Для защиты уже эксплуатируемых приложений рекомендуется использовать межсетевые экраны уровня приложений (web application firewalls).

В исследовании также представлено сравнение эффективности различных методов анализа защищенности приложений («белый ящик» против «черного ящика») и приведены примеры выявления уязвимостей автоматизированным анализатором кода PT Application Inspector. Анализ исходного кода показывает намного более высокие результаты, чем исследование защищенности без доступа к коду приложения. Кроме того, тестирование исходного кода в процессе разработки позволяет значительно повысить защищенность конечного приложения. Для анализа исходного кода на различных стадиях разработки целесообразно применять автоматизированные средства, поскольку это позволяет выявить максимальное число ошибок в кратчайшее время.

Полная версия исследования: blog.ptsecurity.ru/2017/08/web-attacks.html
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/335186/


Метки:  

[Из песочницы] ML Boot Camp V, история решения на 3 место

Вторник, 08 Августа 2017 г. 17:23 + в цитатник
В середине июля закончился контест по машинному обучению ML Boot Camp V от Mail.Ru. Нужно было предсказать наличие сердечно-сосудистых заболеваний по результатам классического врачебного осмотра. Метрикой являлась логарифмическая функция потерь. Полное описание задачи доступно по ссылке.

Знакомство с машинным обучением для меня началось с ML Boot Camp III где-то в феврале 2017 года и какое-то подобие представления что с такими задачами делать начинает складываться у меня только сейчас. Многое из сделанного в 5 контесте — результат в первую очередь изучения собрания статей на kaggle и обсуждений и примеров кода оттуда же. Ниже — слегка переработанный отчет о том, что пришлось сделать, чтобы занять 3 место.

Данные задачи


Датасет сформирован из 100.000 реальных клинических анализов. Даны возраст, рост, вес, пол, артериальное давление верхнее и нижнее, холестерин и глюкоза в крови.

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

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

Инструменты


Задача решалась на python с использованием стандартных для такого случая библиотек:

  • pandas – чтение-запись и обработка табличных данных (на самом деле много чего еще, но в данном случае остальное не понадобилось);
  • NumPy – операции над массивами чисел;
  • scikit-learn – набор инструментов для машинного обучения, включая базовые алгоритмы МО, разбиение данных, валидацию;
  • XGBoost – одна из наиболее ходовых реализаций градиентного бустинга;
  • LightGBM – альтернатива XGBoost;
  • TensorFlow + Keras — библиотека для обучения и использования нейронных сетей и обертка к ней;
  • Hyperopt – библиотека для оптимизации функций в заданном пространстве аргументов;

Csv vs pickle


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

with gzip.open('../run/local/pred_1.pickle.gz', 'wb') as f:
    pickle.dump((x, y), f)

Репозиторий


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

Первые 2 недели


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

Вторые 2 недели


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

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

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

Общий план


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

Самое простое при таком подходе — обработать данные несколькими способами, придумать несколько наборов дополнительных признаков и использовать их комбинации. Получится куцый вариант Random subspace method, отличающийся от полноценного тем, что он совсем не random и признаки выбираются сразу группами. Так при небольшом количестве дополнительных признаков можно получить сотни вариантов обработанных данных (собственно количество способов чистки * (2 ^ количество групп признаков)). Предполагалось, что такой подход даст достаточно разные решения простых моделей, использующих разные подмножества признаков, чтобы каждое из них улучшало качество моделей 2 уровня.

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


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

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

Варианты обработки:

  1. Исходные данные в которых испорченные значения субъективной части теста заменены на 0.0001, чтобы привести их к числовому виду, но отличать от нетронутых.
  2. Испорченные субъективные признаки заменены: потребление алкоголя — 0, активность — 1. Далее по остальным колонкам данных было «восстановлено» курение.
  3. В данных с восстановленными субъективными признаками почищены экстремальные значения давлений.
  4. В данных с восстановленными субъективными признаками (из п.2) почищены экстремальные значения давлений, веса и роста.
  5. В данных только с очищенными давлениями (из п.3) дополнительно почищены вес, рост, давления.
  6. Данные с очищенными давлениями дополнительно преобразованы — любое отдельное неправдоподобное значение роста, веса или давления заменены на NaN.

Признаки


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

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

Группы дополнительных признаков:

  1. Простейшие осмысленные признаки — ИМТ, пульсовое давление, усредненные значения давлений вида $inline$\frac{ap\_hi+x*ap\_lo}{x+1}$inline$ для разных значений x. Также взяты приближенные формулы вычисления давлений по возрасту/весу и для каждого пациента вычислены ожидаемые давления (формулы вида $inline$ap\_X = a + b * age + c * weight$inline$). Вычислено на основе необработанных значений.

  2. То же, что в п.1, но дополнительно на основе имеющихся давлений сделана попытка восстановить вес пациента. Для каждого из предсказанных таким образом признаков добавлена разница с «реальным» значением. Вычислено на основе необработанных значение.
  3. Текстовое представление колонок необработанных данных, разбитое посимвольно — сначала с выравниванием слева, потом справа. Символы заменены их числовыми значениями (ord()). Где строка была слишком короткая и на все колонки не хватило — ставилось -1.

  4. То же, что в п.3, но полученные колонки бинарно закодированы (one-hot encoding).

  5. Данные из п.4, но пропущенные через PCA – тяжкое наследие недавно прошедшего на kaggle соревнования от mercedes, где модели с этим шаманством неплохо выглядели на паблике и печально на привате.

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

  7. То же что в п.6, но средние вычислялись еще и для признаков из п.2.

  8. То же что в п.7, но в качестве исходных данных взяты очищенные по варианту №5.

  9. То же что в п.7, но в качестве исходных данных взяты очищенные по варианту №3.

  10. Необработанные данные кластеризованы методом k-means, количества кластеров выбраны произвольно — 2, 5, 10, 15, 25. Номер кластера для каждого из таких случаев — бинарно закодирован.

  11. То же что в п.10, но использовались данные, очищенные по варианту №3.

Модели


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

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

Основное разделение сохраняемых моделями данных — по времени жизни этих данных. Для каждой такой группы данных предусмотрен свой базовый путь для сохранения. Всего таких 3 группы:

  1. Временные, которые не будут использованы при следующих запусках, например лучшие веса нейросетей для отдельных фолдов;
  2. Данные модели, которые при следующих запусках понадобятся — почти все остальное;
  3. Глобально полезные данные, которые могут пригодиться нескольким моделям, например дополнительные признаки;

Интерфейс у всех моделей общий и позволяет не только запускать их отдельно как обычные скрипты, но и грузить как модули python. Если некоторой модели нужны результаты работы других моделей — она их грузит и выполняет. Как результат — описание каждой из моделей 2 уровня удалось свести к списку имен моделей, чьи результаты надо объединить, и признаку необходимости отбора признаков жадным алгоритмом.

Среди моделей были основанные на нейросетях, которые на выходе могли дать очень уверенные 0 или 1 или очень близкие к крайним значения. Так как в случае ошибки подобная самоуверенность штрафуется logloss-ом очень сильно — значения всех моделей при сохранении обрезались так, чтобы до 0 или 1 оставалось не менее 1e-5. Проще всего оказалось добавить np.clip(z, 1e-5, 1-1e-5) и забыть об этом. В результате обрезались данные всех моделей, но большинство и так давали результаты в диапазоне примерно 0.1-0.93.

hyperopt


Для подгонки параметров моделей пришлось задействовать hyperopt (подробности). Результаты улучшались, но при этом долгое время для особенно медленных моделей я выставлял количество попыток порядка 20. И дня за 2 до конца в статье нашел упоминание hyperopt bootstrapping — по умолчанию первые 20 запусков моделей производится со случайными параметрами, что можно увидеть в исходниках. Пришлось срочно пересчитывать часть моделей.

Модели 1 уровня


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

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

  • нейросети (keras)
  • деревья (XGBoost, LightGBM, rf, et)

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

Нейросети


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

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

  • вход;
  • несколько сотен нейронов (обычно 256);
  • какая-нибудь нелинейность, дропаут (где был — брал значения порядка 0.7, потому что считал, что слишком много параметров и сеть переобучается); если при обучении модель расходилась в nan-ы — добавлял batch normalization — подробности здесь или здесь;
  • сотня-другая нейронов (64-128);
  • нелинейность;
  • десяток-другой нейронов (16);
  • нелинейность;
  • 1 выходной нейрон с классической сигмоидой на выходе.

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

Выбор функций активации для внутренних слоев очень простой — из доступного набора исключил все варианты сигмоиды (из-за близких к 0 градиентов у границ значений), «чистый» ReLU (из-за того, что нейрон, начавший выдавать на выходе 0, из обучения выпадает) и брал что-то из оставшихся. Изначально это было Parametric Relu, в последних моделях начал брать Scaled Exponential Linear Units. Каких-либо значимых различий от такой замены заметить не удалось.

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

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

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

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

Модели, основанные на деревьях


Использовалось 2 варианта «древесных» моделей — основанные на bagging random forest и extra trees и 2 реализации градиентного бустинга — XGBoost и LightGBM. Оба варианта случайного леса плохо проявили себя и на кросс-валидации и на паблике, так что остались просто из-за того, что на них пришлось потратить много машинного времени и была надежда, что они пригодятся при объединении результатов моделей. LightGBM и XGBoost проявили себя гораздо лучше и большая часть предсказаний на первом уровне была получена от них.

Каждая из «древесных» моделей после подгонки параметров рассчитывалась для нескольких (обычно — 3) исходных состояний генератора случайных чисел. Все такие результаты сохранялись отдельно для использования моделями 2 уровня. Предсказания же моделей 1 уровня получалось из результата для последнего использованного состояния ГСЧ.

В LightGBM и XGBoost предусмотрена возможность останавливать обучение, если качество обучения не улучшается на валидации за заданное число итераций. За счет этого можно было просто разрешить им обучаться 10000 шагов и останавливаться когда результаты на валидации перестанут улучшаться. В результате при подборе параметров таких моделей количество деревьев подбирать не было необходимости. Для random forest и extra trees от sklearn такой возможности нет, так что пришлось переложить подбор количества деревьев на hyperopt, который, похоже, за недостаточное количество попыток с задачей полностью не справился. Можно было обучать их по одному шагу, каждый раз проверяя качество на валидации самому, но помешала лень.

Несколько сидов


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

Модели 2 уровня


За счет того, что каждая из моделей 1 уровня давала от 1 до 4 предсказаний, на 2 уровне данные содержали до 190 колонок. Исходные данные и признаки туда не попали — только уже предсказанные вероятности. Каждая из моделей 2 уровня объединяла некоторое подмножество из моделей 1 уровня (некоторые использовали еще результаты ранних моделей 2 уровня).

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

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

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

Для итогового подсчета изначально прогонялся выбор через hyperopt всех доступных регрессоров, но более-менее прилично себя проявили только BayesianRidge и Ridge из sklearn, так что в итоге код выродился до определения насколько хорошо комбинирует модели BayesianRidge и попыток улучшить этот результат подгонкой параметров Ridge.

Валидация


Изначально валидировался на разбиении на 10 фолдов. При этом некоторые модели начали показывать cv под 0.534-0.535 при результатах на паблике за 0.543-0.544, а то и хуже. Ближе к концу конкурса, чтобы сблизить результаты при валидации и на паблике я пробовал увеличить разбиение до 30 фолдов. Выбор числа 30 основан на возможностях процессора — выбирал максимальное значение при котором вычисления одной модели требовали менее 10 часов.

При этом все равно часть моделей валидировались на уровне 0.535-0.536, что на фоне результатов на паблике порядка 0.543 на паблике вызывало сомнения в адекватности схемы валидации. Дня за 3 до окончания соревнования к разбиению на 30 фолдов пришлось добавить 30 случайных разбиений на 0.7 и 0.3 от тренировочных данных. Выбор именно 30 — та же причина что и для cv — возможности процессора. Все разбиения были зафиксированы по random_state. После этого лучший результат на валидации был порядка 0.537.

Это тоже было далеко от желаемого, но до конца оставалось несколько дней, которых хватало только чтобы дождаться пока досчитаются последние модели, так что пришлось на этом остановиться. В итоге выбирал 2 сабмита с результатами лучше 0.543 на паблике и 0.538 на валидации. Как выяснилось позже, из 12 таких сабмитов 7 давали 3 место, так что оставалось просто не промахнуться.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/335188/


Метки:  

Очень легкая система мониторинга с Телеграмом и Консулом

Вторник, 08 Августа 2017 г. 17:11 + в цитатник

Метки:  

Асинхронный дешифратор

Вторник, 08 Августа 2017 г. 16:22 + в цитатник
Как и обещал в предыдущей статье, речь в этой статье пойдет о представлении в асинхронном виде операций над адресами. В качестве примера опишу операцию дешифрации адреса. Сразу же хочу предупредить инсинуации, с которыми столкнулся после опубликования предыдущей статьи. Речь пойдет о целиком и полностью асинхронном устройстве. И прошу, не надо ссылаться на реферат узбекского университета. Якобы асинхронный дешифратор можно получить из синхронного с помощью нехитрых манипуляций. Заодно вопрос тем, кто утверждает, что асинхронный процессор произведен 20 лет назад. Как это удалось без асинхронного дешифратора?

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

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

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

image

Входные сигналы:
d — сигнал — команда на операцию дешифрации адреса;
r1, r2 — сигналы разрядов регистра адреса.

Выходные сигналы:
q1 — переключается если r1=1 и r2=1;
q2 — переключается если r1=1 и r2=0;
q3 — переключается если r1=0 и r2=1;
q4 — переключается если r1=0 и r2=0.

Поэтапно выполнение операции дешифрации выглядит следующим образом:
0. Когда сигнал d равен 0, внешняя управляющая схема (ВУС) произвольным образом переключает сигналы r1 и r2. Схема дешифратора (СД) не отслеживает изменения сигналов r1 и r2.
1. ВУС вырабатывает сигнал d+, команду на операцию дешифрации. К этому моменту ВУС устанавливает сигналы r1 и r2 в какое-то конкретное значение. ВУС обеспечивает, что до окончания операции дешифрации сигналы r1 и r2 менять свое значение не будут.
2. В зависимости от значения сигналов r1 и r2, СД вырабатывает один из сигналов: либо q1+, либо q2+, либо q3+, либо q4+.
3. ВУС вырабатывает сигнал d-.
4. СД вырабатывает один из сигналов в соответствии с пунктом 2: либо q1-, либо q2-, либо q3-, либо q4-. Этот сигнал является сигналом окончания операции дешифрации. После этого ВУС снова может изменять сигналы r1 и r2 произвольным образом.

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

image

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

В результате по представленному графу итогового поведения можно получить логические функции для каждого сигнала:

$e=NOT(o1)$; $e1=AND(o1,j1)$; $e2=AND(o2,h1)$; $e3=NAND(e,i1)$;
$e4=OR(o2,h1)$; $f1=AND(d,r1)$; $f2=AND(d,r2)$; $g=NOT(d)$;
$h1=NOR(g,r1)$; $h2=NOR(g,r2)$; $i1=NOR(f1,j1)$; $i2=NOR(f2,j2)$;
$j1=NOR(g,i1)$; $j2=NOR(g,i2)$; $k1=AND(e1,j2)$; $k2=AND(e1,h2)$;
$k3=AND(e2,j2)$; $k4=AND(e2,h2)$; $l1=AND(t1,i2)$; $l2=NOR(t2,h2)$;
$l3=AND(t3,i2)$; $l4=NOR(t4,h2)$; $m1=NOR(k1,n1)$; $m2=NOR(k2,n2)$;
$m3=NOR(k3,n3)$; $m4=NOR(k4,n4)$; $n1=NOR(l1,m1)$; $n2=NOR(l2,m2)$;
$n3=NOR(l3,m3)$; $n4=NOR(l4,m4)$; $o1=NOR(p1,p2)$; $o2=NOR(p3,p4)$;
$p1=NOR(m1,s1)$; $p2=NOR(m2,s2)$; $p3=NOR(m3,s3)$; $p4=NOR(m4,s4)$;
$s1=NOR(n1,l1)$; $s2=NOR(n2,l2)$; $s3=NOR(n3,l3)$; $s4=NOR(n4,l4)$;
$t1=NOR(e3,s1)$; $t2=OR(e3,s2)$; $t3=NOR(e4,s3)$; $t4=OR(e4,s4)$;
$q1=NOR(s1,k1)$; $q2=NOR(s2,k2)$; $q3=NOR(s3,k3)$; $q4=NOR(s4,k4)$.

Как видно, все уравнения помещаются в базис 2И-НЕ, 2ИЛИ-НЕ.

А вот собственно и сама SI схема двухразрядного асинхронного дешифратора.

image

У меня нет возможности проверить схему в реальном воплощении. Но если кто-то этим заинтересуется, я буду это только приветствовать. Чтобы произвести начальную установку, надо входной сигнал d установить в 0. Внутренние сигналы m1, m2, m3, m4 надо установить в 1. Чтобы не выходить из двухвходового базиса, сделать это можно следующим образом для каждого из элементов m1, m2, m3, m4.

image

Элемент слева преобразуется в подсхему справа. Входные сигналы r1, r2 можно установить произвольным образом.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/335178/


Метки:  

[Перевод - recovery mode ] Применение PowerShell для ИТ-безопасности. Часть I: отслеживание событий

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


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

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

Важное событие

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

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

Сейчас речь не об этом.

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

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

Ниже я объясню, как это делается.

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

Операционная система (неважно, Linux или Windows) обрабатывает действия устройства на нижнем уровне, от чтения диска до получения пакетов, и скрывает это от рядовых приложений, запущенных на ПК.

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

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

Инструментальный язык ОС

Рассмотрим инструментарий управления Windows (WMI), который является попыткой Microsoft обеспечить последовательный просмотр объектов операционной системы.

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

Как же выглядит и работает WMI?

Для наших целей инструментарий представляет собой язык запросов, как SQL, но вместо доступа к столбцам баз данных он дает комплексную информацию об операционной системе в виде иерархии классов WMI. Разумеется, язык запросов называется WQL.

В Windows имеется служебная программа WBEMTest, с помощью которой можно взаимодействовать с WQL. На изображении ниже показан запрос объекта Win32_Process, содержащий информацию о текущем запущенном процессе.

image
Тренировочная работа с WQL в WBEMTest

Фактически это программный эквивалент монитора задач Windows. Впечатляет, не так ли? Если хотите узнать больше о WQL, загрузите превосходную электронную книгу Рави Чаганти (Ravi Chaganti), посвященную этой теме.

PowerShell и командлет Register-WmiEvent

Но это еще не все. От тренировочных заданий в WBEMTest можно перейти к запросам непосредственно в PowerShell.

Для этого подойдет командлет PowerShell Get-WMIObject. Он позволяет отправлять запрос WQL непосредственно в виде параметра.

На изображении ниже показаны первые несколько результатов запуска select Name, ProcessId, CommandLine from Win32_Process в тестовой среде AWS.


gwmi — это Get-WmiObject в PowerShell

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

Для улучшения работы с Win32_Process я переместил результат запроса в Out-GridView — командлет PowerShell, который форматирует данные в аккуратную таблицу на основе графического интерфейса.



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

Как я упоминал ранее, она дает доступ к соответствующим событиям этих объектов. В WMI эти события ориентировочно разделены на три типа: создание, изменение и удаление.

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

Теперь командлет Register-WmiEvent в PowerShell 2.0 позволяет реагировать на события в более приемлемой манере. Иными словами, когда происходит событие, срабатывает вызов, который можно зарегистрировать.

Вернемся к моей вымышленной (и уже знаменитой) компании Acme, чья ИТ-инфраструктура работает в среде AWS.

Системный администратор (назовем его Бобом) время от времени замечает, что место на сервере Salsa заканчивается. Он подозревает, что генеральный директор Acme Тед Блоутли загружает большие файлы, такие как аудиозаписи, в один из каталогов Боба, а затем перемещает на свой сервер Taco.

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

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


В PowerShell можно получить непосредственный доступ к объекту CIM_DataFile

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

Register-WmiEvent -Query "SELECT * FROM __InstanceModificationEvent WITHIN 5 WHERE TargetInstance isa 'CIM_DataFile' and TargetInstance.FileSize > 2000000 and TargetInstance.Path = '\\Users\\bob\' and targetInstance.Drive = 'C:' "-sourceIdentifier "Accessor3" -Action { Write-Host "Large file" $EventArgs.NewEvent.TargetInstance.Name "was created”}

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

В следующей публикации я расскажу об этом подробнее. Фактически я использую WQL для запроса из каталога \Users\bob любого объекта CIM_DataFile, превышающего 2 млн байтов. При создании файла, соответствующего условиям, появится уведомление, для которого активируется InstanceModificationEvent.

В любом случае, играя роль Боба, я запустил скрипт из командной строки PowerShell, а затем, как и Тед из нашей истории, я скопировал большой файл MP4 в каталог Боба. Результат вы можете увидеть ниже.


Теперь мы знаем, что Тед — фанат Мелоди Гардо. Кто бы мог подумать!

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

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

https://habrahabr.ru/post/335176/


Метки:  

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

Вторник, 08 Августа 2017 г. 15:57 + в цитатник

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


В рамках данной статьи мне бы хотелось напомнить, что такое программные клоны, какие они влекут за собой проблемы и как с ними можно бороться. В статье приводятся примеры рефакторинга реальных клонов из популярного фреймворка Spring. В качестве инструментов используются Java 8, IDE IntelliJ IDEA 2017.1 и плагин Duplicate Detector 1.1.



Откуда берутся клоны?


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


Можно выделить следующие основные причины возникновения клонов:


  • Умышленное копирование фрагментов программы
  • Многократное использование сложного API
  • Повторная реализация существующей функциональности
  • Слабая выразительность используемого языка
  • Недостаток прав для модификации исходного кода

Нужно ли бороться с клонами?


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


С другой стороны, удаление дубликатов также может привести к ошибкам, особенно, если для этого необходимо вносить существенные изменения в текст программы. Однако главным аргументом против удаления клонов является то, что такое удаление часто приводит к увеличению числа зависимостей. Довольно интересно про это написано в статье "Redundancy vs dependencies: which is worse?".







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


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


Инструменты для поиска клонов


Существует довольно много инструментов для поиска клонов: PMD, CCFinder, Deckard, CloneDR, Duplicate finder (maven plugin), и многие другие.


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


Данная статья преследует две цели. С одной стороны, с ее помощью мне бы хотелось внести свой скромный вклад в борьбу с дублированием исходного кода. С другой стороны, я бы хотел познакомить читателя с плагином Duplicate Detector, разработчиком которого я и являюсь. На данный момент, по сравнению со стандартными инспекциями, этот плагин обнаруживает в 3-4 раза больше клонов, предоставляет более удобный интерфейс и доступен для некоммерческой версии IntelliJ IDEA.


Основные возможности плагина Duplicate Detector:


  • Анализ кода на лету (во время редактирования)
  • Анализ проектов промышленного масштаба (с миллионами строк кода)
  • Удобная навигация и сравнение дубликатов
  • Поддержка языков Java и Kotlin

Для чего может пригодится инструмент обнаружения клонов?
  • Для работы с legacy кодом
  • Для удобного code review
  • Для отслеживания клонов, которые нельзя удалить
  • Для рефакторинга, если Вы используете методологию, схожую с XP

Рефакторинг клонов


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


Давайте рассмотрим несколько конкретных примеров из популярного фреймворка Spring. Для этого воспользуемся средой разработки IntelliJ IDEA и плагином Duplicate Detector.


Возможности среды разработки и плагина


Среда разработки IntelliJ IDEA и плагин Duplicate Detector предоставляют множество возможностей, которые упростят рефакторинг клонов. Например, довольно много функций можно найти в контекстном меню Refactor или в подсказках к инспекциям кода (Alt + Enter в рамках инспекции).


Показать панель сравнения дубликатов



Обобщить фрагмент в виде метода


Подставить тип возвращаемого значения


Пример 1. Начнем с очевидного.





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


Рефакторинг. Вариант 1.
void setVariableNameOrType(String name, Consumer setName, Consumer> setType) {
    if (isVariableName(name)) {
        setName.accept(name);
    }
    else {
        try {
            setType.accept(ClassUtils.forName(name, getAspectClassLoader()));
        }
        catch (Throwable ex) {
            throw new IllegalArgumentException("Class name '" + name  +
                    "' is neither a valid argument name nor the fully-qualified " +
                    "name of a Java type on the classpath. Root cause: " + ex);
        }
    }
}

void setThrowingNameNoCheck(String name) {
    setVariableNameOrType(name, variableName -> this.throwingName = name, type -> this.discoveredThrowingType = type);
}

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


Рефакторинг. Вариант 2.
Class

https://habrahabr.ru/post/335172/


Метки:  

Что творится с HEVC (h265)

Вторник, 08 Августа 2017 г. 15:20 + в цитатник
В своё время разработка кодека H264 стала настоящим прорывом, потому что получилось посадить за один стол людей, занимающихся телевидением, IP камерами, конференц-связью и родить стандарт, которого в целом хватило всем.

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

Так вот H264 — это сочетание хорошего кодека, хороших энкодеров и массы приличных декодеров. Но что же происходит с H265?

H265 — это стандарт, который приходит на смену H264. Его прибытие стало омрачено сомнительной авантюрой гугла с их VP6, VP9, VP10 и сказками о том, что кодеки серии VP лучше любого H264 и т.п.

Главная суть H265 в том, что он продается как решение для размеров экранов выше чем FullHD. Для чего он реально годится мы поговорим ниже, но мир устроен так, что сначала надо продать. Вот для 4K он и продается.

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

Кодирование


На сегодняшний день H265, он же HEVC уже поддерживается на большом количестве энкодеров: софтверные, обычные аппаратные (Nvidia NVENC, Intel QSV) и железные аппаратные.

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

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

Здесь надо быть очень аккуратными с тем, что именно будет уметь железка или софтина. Так, например, Hisilicon достаточно давно выпустил первый чипсет с поддержкой H265 для IP-камер, а вот софт отстал чуть ли не на полтора года от них. Сегодня до сих пор продается полно камер, у которых написано H265, а они не могут его отдавать в реальном времени — только экспортировать файлы через нерабочий китайский софт. В чём тут выражается поддержка H265, продавцы ответить не могут, но упорно кивают головой: да, да, можем h265.

Аналогичная проблема и с RTMP энкодерами. Один из частейших вопросов: «а что, ваш софт не умеет H265 по RTMP?».

Это не наш софт «не умеет», а RTMP не умеет H265. В RTML используется flv-подобная упаковка кадров и H265 ни в одном, ни в другом стандарте как доступные не отмечены. Есть всякие хитрые хаки, позволяющие запихать H265 в протокол, не рассчитанный на это, но называть это RTMP уже будет перебор — это будет проприетарный, закрытый протокол. Подобные изменения существуют, делаются они китайцами, а это как правило означает просто истеричное отношение к предложениям поделиться спецификацией на протокол.

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

Вещание


Сейчас в дикой природе H265 проще всего встретить на IP-камерах: там оно уже есть и уже потихоньку распространяется, спасибо HUAWEI. Так же можно на спутниках найти 30-мегабитные каналы, сжатые в H265.

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

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

Т.е. важно запомнить: MPEG-TS давно и надежно умеет передавать H265, а значит то, что называют UDP или HTTP с большой вероятностью тоже сможет.

Так же H265 передается по RTSP: есть упаковка и в SDP, и в RTP. Остается старый нюанс с передачей bframes по RTSP, но это отдельная головная боль.

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

Проигрывание


Пока забудьте =)

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

Есть проигрывание на телевизионных приставках, SmartTV и в программах/приложени, но браузеры пока очень сильно отстают.

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

Конкуренция


H265 сравнивают с h264: ведь разницу в битрейте надо ещё увидеть, а поддержка h264 сейчас есть абсолютно везде

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

H265 начали сравнивать с AV1, но это пока вообще можно не рассматривать — слишком новая штука. Очень интересно, подождем несколько лет.

Резюме


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

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

https://habrahabr.ru/post/333028/


Метки:  

[Перевод] Программирование /= информатика

Вторник, 08 Августа 2017 г. 14:37 + в цитатник

Метки:  

[Из песочницы] Полиморфизм и указатели на функции

Вторник, 08 Августа 2017 г. 14:35 + в цитатник
Читая учебники по программированию, убеждаюсь в том, как сильно усложняется восприятие материала, если автор подчиняет себя концепциям и инструментам, забывая о том, насколько важен контекст, в котором раскрывается материал. И, в то же время, насколько естественно и легко приходит понимание, когда ощущаешь реальное удобство от применения нового инструмента.

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

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

const int n = 15;
string cities[n] = {
	"Красноярск", "Москва", "Новосибирск", "Лондон", "Токио", 
	"Пекин", "Волгоград", "Минск", "Владивосток", "Париж", 
	"Манчестер", "Вашингтон", "Якутск", "Екатеринбург", "Омск"
};

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

А как же иначе быть, если мы не можем передать функцию в качестве аргумента в функцию сортировки? Или, все-таки, можем? Здесь и приходят на помощь указатели на функции. Это как раз то средство, которое позволяет работать с функциями так же, как и с переменными. Ну, или почти так же.

Итак, вот он указатель на функцию. Встречайте:

typedef bool(*CompareFunction) (int i, int j);

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

bool compareUp(int i, int j) {
	return cities[i] < cities[j];
}

bool compareDown(int i, int j) {
	return cities[i] > cities[j];
}

bool compareLengthUp(int i, int j) {
	return cities[i].length() < cities[j].length();
}

bool compareLengthDown(int i, int j) {
	return cities[i].length() > cities[j].length();
} 

Теперь помещаем их в массив:

CompareFunction compares[] = {compareUp, compareDown, compareLengthUp, compareLengthDown};

А затем создаем функцию сортировки:

void sortCities(CompareFunction compare) {
	for (int i = 0; i < n - 1; i++) {
		int j_min = i;
		for (int j = i+1; j < n; j++) {
			if (compare(j, j_min)) {
				j_min = j;
			}
		}
		string temp = cities[i];
		cities[i] = cities[j_min];
		cities[j_min] = temp;
	}
}

А что же там выделено жирным? Это и есть полиморфный вызов: переменной compare можно подсунуть любую функцию сравнения, и вызываемая функция будет определяться динамически, обеспечивая требуемый способ сортировки.

И, наконец, нужен какой-нибудь простенький user interface, чтобы все протестировать.

int _tmain(int argc, _TCHAR* argv[]) {
	setlocale(LC_ALL, "Russian");
	
	for (;;) {
		int choice;
		cout << "Ваш выбор: ";
		cin >> choice;
		sortCities(compares[choice]);
		printCities();
	}
	system("pause");
	return 0;
}

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

P.S. Функция printCities() виртуальная, ее реализация выпадает на долю читателя.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/335162/


Метки:  

Оптимизация и автоматизация тестирования веб-приложений

Вторник, 08 Августа 2017 г. 13:37 + в цитатник

image


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


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


  • автоматизированное тестирование;
  • ручное тестирование.

Плюсы и минусы автоматизированного тестирования


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


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


Перебор файлов и папок, подбор паролей — тут, я думаю все понятно и так.


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


Минусы:
False positive срабатывания. Очень часто сканеры руководствуясь формальными признаками выявляют уязвимости, которых нет. Классика жанра — при сканировании Single Page Application сканер получает код ответа 200 на все свои запросы и выводит длинный список уязвимостей, которых на самом деле нет.


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


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


Блокирование средствами защиты. Как правило, признаки автоматизированных систем хорошо знакомы разработчикам и они учитывают их при проектировании. Как итог — происходит блокировка (по User Agent, маркерам сканера или частоте запросов).


Не учитывают ошибки логики.


Требуют ручной валидации уязвимостей.


Построение эффективных автоматизированных систем, оптимизированных под веб-приложение


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


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

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


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


Прокачиваем утилиты


В качестве оптимальной основы предлагаю остановится на двух кроссплатформенных системах для тестирования веб-приложений (как в ручном, так и в автоматизированном режиме): OWASP ZAP (free версия) и BurpSuite (free + платная версии).


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


Огромным плюсом этих приложений является возможность расширения с помощью плагинов/компонентов:


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

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


  • известная CMS;
  • поддержка плагинов/компонентов;
  • содержит уязвимости (в том числе OWASP A1 — sql injection);
  • содержит средства защиты.

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


Owasp ZAP:
Установленные:



Необходимо установить:



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


Burp Suite:
Честно признаюсь, Burp мне нравится больше чем Owasp Zap, поэтому остановлюсь на нем подробнее.


Нам необходимо выполнить задачу по идентификации CMS и установленных компонентов, выявить устаревшие версии, попытаться обойти WAF и проэксплуатировать SQL-инъекцию.


В первую очередь необходимо придерживаться методологии тестирования веб-приложения. В этом нам поможет представленный на последнем Def Con HUNT Burp Suite Extension:


  • Определяем общие параметры для определенных классов уязвимостей.
  • Организовываем методологию тестирования внутри Burp Suite.

image


Далее нам пригодится плагин (уже добавленный в BApp store плагин от Vulners.com (@isox, avleonov — спасибо за замечательный инструмент).



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


Далее, ускорить "раскручивание" инъекции нам поможет sql map — для его интеграции необходимо воспользоваться плагином SQLiPy:



Нам известно, что веб-приложение защищено WAF — могут пригодится расширения What the WAF и Waf bypass.


Также рекомендую плагин от Владимира Иванова: burp-xss-sql-plugin.


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



Требования:


  • burp-rest-api
  • Burp Suite Professional
  • slackclient

Этот инструмент позволит автоматизировать проверки, использую в качестве основы Burp Suite:


$ python burpa.py -h

###################################################
            __                          
           / /_  __  ___________  ____ _
          / __ \/ / / / ___/ __ \/ __ `/
         / /_/ / /_/ / /  / /_/ / /_/ / 
        /_.___/\__,_/_/  / .___/\__,_/  
                        /_/             
         burpa version 0.1 / by 0x4D31  

###################################################
usage: burpa.py [-h] [-a {scan,proxy-config}] [-pP PROXY_PORT] [-aP API_PORT]
                [-rT {HTML,XML}] [-r {in-scope,all}]
                [--include-scope [INCLUDE_SCOPE [INCLUDE_SCOPE ...]]]
                [--exclude-scope [EXCLUDE_SCOPE [EXCLUDE_SCOPE ...]]]
                proxy_url

positional arguments:
  proxy_url             Burp Proxy URL

optional arguments:
  -h, --help            show this help message and exit
  -a {scan,proxy-config}, --action {scan,proxy-config}
  -pP PROXY_PORT, --proxy-port PROXY_PORT
  -aP API_PORT, --api-port API_PORT
  -rT {HTML,XML}, --report-type {HTML,XML}
  -r {in-scope,all}, --report {in-scope,all}
  --include-scope [INCLUDE_SCOPE [INCLUDE_SCOPE ...]]
  --exclude-scope [EXCLUDE_SCOPE [EXCLUDE_SCOPE ...]]

Как результат вы получите отчет о проведенном сканировании:




Заключение


Я намеренно не рассматривал готовые сканеры типа w3af (или платные аналоги), позволяющие проводить такие работы, где использование сводится к существующему функционалу (и установки чекбоксов у опций), а постарался раскрыть интересные плагины и доработки для проксирующей утилиты Burp Suite — как наиболее популярного и эффективного инструмента.


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

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

https://habrahabr.ru/post/335140/


Метки:  

Мобильные приложения: как избежать бана от рекламной сети?

Вторник, 08 Августа 2017 г. 13:31 + в цитатник

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

Все ли вы делаете правильно?


  • Первым делом мы рекомендуем убедиться, что вы лично управляете типами рекламы в приложении, и именно вы выбирали, какая реклама будет показываться — то есть, нет никаких сторонних неизвестных баннеров, видео, и т.д.
  • Никогда не выпрашивайте у пользователей клики — в приложении не должно быть специальных CTA-сообщений, которые просят игроков взаимодействовать с любой рекламой.
  • Реклама не должна перекрывать интерактивные элементы в приложении. Например, баннер не должен закрывать часто используемую кнопку меню, или полноэкранная реклама не должна выскакивать после каждого нажатия или жеста. Реклама не должна скрывать основной контент и мешать пользователю взаимодействовать с приложением.
  • Реклама не должна показываться сразу при запуске приложения, а также при возврате устройства из спящего режима или когда сама игра находится в “cвернутом” режиме.
  • Не показывайте рекламу на экранах без контента — например, на экранах входа/выхода (log in/log out), или же на экранах с ошибками, словами благодарности или информацией о создателях. Логика здесь такая: перечисленные типы экранов обычно всплывают при открытии или закрытии приложения, после внутриигровой покупки или загрузки каких-либо действий — во всех этих случаях рекламу показывать запрещено.
  • Не показывайте полноэкранную рекламу в рандомные моменты игры, когда возрастает вероятность случайных кликов.
  • Не показывайте полноэкранную рекламу один за другим — после того, как игрок уже закрыл одну рекламу, его не должна преследовать следующая.
  • На экране должен быть только один баннер за раз — никогда не накладывайте баннеры друг на друга.

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

Стратегия оптимизации


  • Анализируйте, подходят ли рекламные форматы именно для вашего приложения и насколько они совместимы с теми, что уже работают. Помните, что слишком много рекламы негативно сказывается на удержании пользователей (retention rate) и eCPM, поэтому важно учитывать, какую именно рекламу вы показываете и в каких объемах. К примеру, известно, что Rewarded Video положительно влияют на удержание пользователей. Подробнее об этом формате и лучших сценариях показа можно прочитать по ссылке.
  • Если одна и та же реклама показывается слишком часто, подумайте о том, чтобы установить минимальный уровень цен (price floor) или ограничение частоты показов (frequency caps), чтобы минимизировать негативный эффект.
  • Для некоторых приложений 15-секундный период обновления баннеров, который установлен по умолчанию, может оказаться слишком коротким. В таком случае могут быть полезными эксперименты с длительностью периода обновления и мониторинг показателя ARPDAU.
  • Если ваше приложение — неигровое, и его интерфейс, в основном, представляет собой тексты или списки, рассмотрите вариант с нативной рекламой в дополнение к баннерам. Такой прием должен хорошо повлиять на retention rate.
  • Если в вашем приложении есть внутренние покупки, попробуйте усилить их эффект с помощью Rewarded Video (просмотра видео за вознаграждение). Встроенные покупки эффективны только для совсем небольшого процента пользователей — всего 2-3% от большинства. Rewarded Video ощутимо увеличивают выручку и побуждают не платящих пользователей взаимодействовать с рекламой, таким образом принося недоступный ранее доход.

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

Если вы хотите копнуть глубже и повысить Display Rate (и выручку) за счет грамотной загрузки рекламы — читайте нашу статью по ссылке.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/335154/


[Из песочницы] Сравнение REST и GraphQL

Вторник, 08 Августа 2017 г. 13:18 + в цитатник

Два способа отправки данных по протоколу HTTP: в чем разница?


Перевод статьи Sashko Stubailo GraphQL vs. REST


GraphQL часто представляют как революционно новый путь осмысления API. Вместо работы с жестко определенными на сервере конечными точками (endpoints) вы можете с помощью одного запроса получить именно те данные, которые вам нужны. И да — GraphQL гибок при внедрении в организации, он делает совместную работу команд frontend- и backend-разработки гладкой, как никогда раньше. Однако на практике обе эти технологии подразумевают отправку HTTP-запроса и получение какого-то результата, и внутри GraphQL встроено множество элементов из модели REST.


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


Так что давайте сразу к делу. Мы определим некоторые свойства API, а затем обсудим, как они реализованы в GraphQL и REST.

Ресурсы


Ключевое для REST понятие — ресурс. Каждый ресурс идентифицируется по его URL, и для получения ресурса надо отправить GET-запрос к этому URL. Скорее всего, ответ придет в формате JSON, так как именно этот формат используется сейчас в большинстве API. Выглядит это примерно так:


GET /books/1
{
  "title": "Блюз черных дыр и другие мелодии космоса",
  "author": { 
    "firstName": "Жанна",
    "lastName": "Левин"
  }
  // ... другие поля
}

Замечание: для рассмотренного выше примера некоторые REST API могут возвращать данные об авторе (поле «author») как отдельный ресурс.


Одна из заметных особенностей REST состоит в том, что тип, или форма ресурса, и способ получения ресурса сцеплены воедино. Говоря о рассмотренном выше примере в документации по REST API, вы можете сослаться на него как на «book endpoint».


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


type Book {
  id: ID
  title: String
  published: Date
  price: String
  author: Author
}

type Author {
  id: ID
  firstName: String
  lastName: String
  books: [Book]
}

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


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


type Query {
  book(id: ID!): Book
  author(id: ID!): Author
}

Теперь мы можем отправить запрос, аналогичный REST-запросу, рассмотренному выше, но на этот раз с помощью GraphQL:


GET /graphql?query={ book(id: "1") { title, author { firstName } } }

{
  "title": "Блюз черных дыр и другие мелодии космоса",
  "author": {
    "firstName": "Жанна",
  }
}

Отлично, это уже что-то! Мы немедленно видим несколько особенностей GraphQL, весьма отличающих его от REST, даже несмотря на то, что оба они могут быть запрошены через URL, и оба могут вернуть одну и ту же форму JSON-ответа.


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


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


Выводы


Мы уже обнаружили некоторые сходства и различия:


  • Сходство: есть понятие ресурса, есть возможность назначать идентификаторы для ресурсов.
  • Сходство: ресурсы могут быть извлечены с помощью GET-запроса URL-адреса по HTTP.
  • Сходство: ответ на запрос может возвращать данные в формате JSON.
  • Различие: в REST вызываемая вами конечная точка (endpoint) — это и есть сущность объекта. В GraphQL сущность объекта отделена от того, как именно вы его получаете.
  • Различие: в REST структура и объем ресурса определяются сервером. В GraphQL сервер определяет набор доступных ресурсов, а клиент указывает необходимые ему данные прямо в запросе.

Если вы уже использовали GraphQL и/или REST, пока все было довольно просто. Если раньше вы не использовали GraphQL, можете поиграть на Launchpad с примером, подобным приведенному выше.


URL-маршруты и схемы GraphQL


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


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


В существующих сегодня REST API чаще всего API описывается как список конечных точек (endpoints):


GET /books/:id
GET /authors/:id
GET /books/:id/comments
POST /books/:id/comments

Можно сказать, что «форма» API линейна — это просто список доступных вам вещей. При извлечении данных или сохранении какой-либо информации первый вопрос, который вы задаете себе: «Какой endpoint мне следует вызвать»?


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


type Query {
  book(id: ID!): Book
  author(id: ID!): Author
}

type Mutation {
  addComment(input: AddCommentInput): Comment
}

type Book { ... }
type Author { ... }
type Comment { ... }
input AddCommentInput { ... }

Здесь есть несколько интересных особенностей по сравнению с маршрутами REST для аналогичного набора данных. Первое: вместо выполнения HTTP-запросов одного и того же URL-адреса с помощью разных методов (GET, PUT, DELETE и т.п.) GraphQL использует для различения чтения и записи разный начальный тип — Mutation или Query. В GraphQL-документе вы можете выбрать, какой тип операции вы отправляете, с помощью соответствующего ключевого слова:


query { ... }
mutation { ... }

Более детально язык запросов разбирается в более ранней моей статье «Анатомия запросов GraphQL» (англ.), перевод на Хабрахабре.


Как видите, поля типа Query довольно хорошо совпадают с маршрутами REST, рассмотренными выше. Это потому, что данный специальный тип является входной точкой для доступа к нашим данным, так что в GraphQL это наиболее близкий эквивалент понятию «URL конечной точки (endpoint URL)».


Способ получения начального ресурса от GraphQL API довольно похож на то, как это делается в REST: вы передаете имя и некоторые параметры; но главное отличие здесь в том, куда вы сможете двинуться после этого. В GraphQL вы можете отправить сложный запрос, который извлечет дополнительные данные согласно связям, определенным в схеме, а в REST вам для этого пришлось бы сделать несколько запросов, встроить связанные данные в начальный запрос, или же включить какие-то особые параметры в URL-запрос для модификации ответа.


Выводы


В REST пространство доступных данных описывается как линейный список конечных точек (endpoints), а в GraphQL это схема со связями между ее элементами.


  • Сходство: список конечных точек в REST API похож на список полей в типах Query и Mutation, используемых в GraphQL API. Оба они являются точками входа для доступа к данным.
  • Сходство: есть возможность различать запросы к API на чтение и на запись данных.
  • Различие: в GraphQL вы можете внутри одиночного запроса перемещаться от точки входа к связанным данным, следуя связям, определенным в схеме. В REST для получения связанных ресурсов вам придется выполнить запросы к нескольким конечным точкам.
  • Различие: в GraphQL нет разницы между полями типа Query и полями любого другого типа, за исключением того, что в корне запроса доступен только тип query. Например, у вас в запросе любое поле может иметь аргументы. В REST не существует понятия первого класса в случае вложенного URL.
  • Различие: в REST вы определяете запись данных, меняя HTTP-метод запроса с GET на что-то вроде POST. В GraphQL вы меняете ключевое слово в запросе.

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


Обработчики маршрутов и распознаватели


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


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


Рассмотрим пример реализации «Hello World» с помощью express, популярного фреймворка для построения API на Node:


app.get('/hello', function (req, res) {
  res.send('Hello World!')
})

Как видите, мы создали конечную точку /hello, которая возвращает строку 'Hello World!'. Из этого примера становится понятен жизненный цикл HTTP-запроса на сервере REST API:


  1. Сервер получает запрос и извлекает HTTP-метод (в нашем случае GET) и путь URL
  2. API-фреймворк сопоставляет метод и путь с функцией, зарегистрированной в серверном коде
  3. Функция выполняется один раз и возвращает результат
  4. API-фреймворк преобразует результат, добавляет соответствующие код и заголовки ответа и отправляет все это обратно клиенту

GraphQL работает очень похожим способом, и для того же примера код практически тот же самый:


const resolvers = {
  Query: {
    hello: () => {
      return 'Hello world!';
    },
  },
};

Как видите, вместо предоставления функции для выбранного URL мы указываем функцию, которая сопоставляет отдельное поле типу, в нашем случае — поле hello типу Query. В GraphQL функция, реализующая такое сопоставление, называется распознавателем (resolver).


Чтобы получить данные, нам нужен запрос (query):


query {
  hello
}

Итак, что происходит, когда наш сервер получает GraphQL-запрос:


  1. Сервер получает HTTP-запрос и извлекает из него GraphQL-запрос
  2. Запрос (query) проходится насквозь, и для каждого поля вызывается соответствующий распознаватель (resolver). В нашем случае поле всего одно, hello, и ему соответствует тип Query.
  3. Функция вызывается и возвращает результат
  4. Библиотека GraphQL и сервер прикрепляют полученный результат к ответу, который соответствует форме запроса (query)

Вы получаете от сервера ответ:



{ "hello": "Hello, world!" }

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


query {
  hello
  secondHello: hello
}

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


Объяснение не было бы полным без примера с вложенными распознавателями («nested» resolvers):


{
  Query: {
    author: (root, { id }) => find(authors, { id: id }),
  },
  Author: {
    posts: (author) => filter(posts, { authorId: author.id }),
  },
}

Эти распознаватели способны разрешить запрос вроде такого:


query {
  author(id: 1) {
    firstName
    posts {
      title
    }
  }
}

Итак, хотя список распознавателей на самом деле плоский, из-за прикрепления их к различным типам вы можете построить из них вложенные запросы. Подробнее о том, как работает выполнение GraphQL, читайте в статье «GraphQL Explained».


Можете посмотреть полный пример и протестировать его, запуская разные запросы!




Художественная интерпретация извлечения ресурсов: в REST множество данных гоняются туда и обратно, в GraphQL все делается одним-единственным запросом


Выводы


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


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

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


Что все это значит?


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


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


С другой стороны, для GraphQL пока нет такого множества инструментов и решений по интеграции, как для REST. Например, у вас не получится с помощью HTTP-кэширования кэшировать результаты работы GraphQL API так же легко, как это делается для результатов работы REST API. Однако сообщество упорно работает над улучшением инструментов и инфраструктуры, а для кэширования GraphQL вы можете использовать такие инструменты, как Apollo Client и Relay.


Если у вас есть еще мысли по поводу различий между REST и GraphQL — высказывайтесь в комментариях.

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

https://habrahabr.ru/post/335158/


Метки:  

Так кто вернулся, братиш?

Вторник, 08 Августа 2017 г. 12:54 + в цитатник
Просматривая в очередной раз код habr
Натолкнулся на сей фрагмент:
image

Так кто вернулся-то? Куда — понятно, но зачем?
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/335152/


Метки:  

[Перевод] Вредоносный код в npm-пакетах и борьба с ним

Вторник, 08 Августа 2017 г. 12:37 + в цитатник

Метки:  

Генерация Галактики и обучение начальным знаниям астрономии

Вторник, 08 Августа 2017 г. 12:29 + в цитатник

Введение



Некоторое время назад я дома решил посмотреть, что нового появилось на тему космоса за последнее время. За этим делом меня застал мой 7 летний сын, проявив большой интерес к этой тематике. Пока я ломал голову, как просто и доходчиво, а также в каком именно объеме дать ребенку информацию по космосу, я наткнулся на статью, где написано, что принято решение вернуть в российские школы предмет «Астрономия» в 2017-2018 учебном году, но только с 11 класса. Это и стало тем событием, которое подвигло меня написать эту статью, чтобы помочь ознакомить с азами астрономии детей до 11 класса.
По сути 7 летний ребенок является представителем определенной выборки пользователей, которая либо интересуется астрономией уже сейчас, либо заинтересуется ей в будущем. Именно для них, а также для тех, кто будет давать знания о звездах я предлагаю попробовать приведенных ниже способ. Основной идей является генерация Галактики с использованием реальных данных (эту часть я беру на себя), и последующее использование результата генерации либо в играх, либо в качестве учебного пособия теми, кто хотел бы сделать изучение астрономии более интересным…




Теория



Основной и наиболее полной информацией, описывающих звезды, в настоящее время являются:
  • Основная (гарвардская) спектральная классификация звезд.
  • Йеркская классификация с учётом светимости (МКК).
  • Диаграмма «Герцшпрунга – Рассела» (см. рисунок ниже).



Диаграмма «Герцшпрунга – Рассела»

Гарвардская классификация определяет абсциссу диаграммы Герцшпрунга – Рассела, а Йеркская – положение звезды на этой диаграмме.
Основная информация, которую можно подчерпнуть из этих источников, это то, что все звезды разделены на классы по их цвету, что они бывают разных размеров и что класс и размер зависят друг от друга. Чтобы не путаться в размерах, можно дополнительно ввести всем понятную градацию размера от 1 (любые карлики) до 5 (любые гиганты), где размеры от 2 до 4 достаются звездам основной последовательности.
Теперь довольно большой объем информации можно свести в очень простую систему «Класс, Цвет, MIN размер, MAX размер»:

  • O, Голубой, 2, 4
  • B, Бело-голубой, 1, 4
  • A, Белый, 1, 4
  • F, Жёлто-белый, 1, 5
  • G, Жёлтый, 1, 5
  • K, Оранжевый, 1, 5
  • M, Красный, 2, 5


Теперь, когда мы знаем какие бывают звезды, остается учесть некоторые наиболее распространенные или просто вызывающие интерес особенности звезд:
  • Сверхновая звезда – это звезда, заканчивающие свою эволюцию в катастрофическом взрывном процессе. Вспышка при этом может быть на несколько порядков больше чем в случае новой звезды. Столь мощный взрыв есть следствие процессов, протекающих в звезде на последний стадии эволюции.
  • Двойная звезда – это две гравитационно связанные звезды, обращающиеся вокруг общего центра масс. Иногда встречаются системы из трех и более звезд, в таком общем случае система называется кратной звездой. В тех случаях, когда такая звездная система не слишком далеко удалена от Земли, в телескоп удается различить отдельные звезды. Если же расстояние значительное, то понять, что перед астрономами двойная звезда удается только по косвенным признакам — колебаниям блеска, вызываемым периодическими затмениями одной звезды другою и некоторым другим.
  • Пульсары – космические источники электромагнитных излучений, приходящих на Землю в виде периодических всплесков (импульсов). Согласно доминирующей астрофизической модели, пульсары представляют собой вращающиеся нейтронные звёзды с магнитным полем, которое наклонено к оси вращения. Когда Земля попадает в конус, образуемый этим излучением, то можно зафиксировать импульс излучения, повторяющийся через промежутки времени, равные периоду обращения звезды. Некоторые нейтронные звёзды совершают до 600 оборотов в секунду.
  • Черные дыры относятся к наиболее странным и привлекательным объектам космического пространства. Они являют собой чрезвычайно плотные формации, сила притяжения которых настолько велика, что даже свет не способен избежать этих объятий. Когда звезда использует свое последнее топливо, начинается процесс ее отмирания. У светил меньших размеров (около одной третьей массы Солнца) новое ядро набирает формы нейтронной звезды или белого карлика. Но, когда умирает большая звезда, она обрушивается внутрь самой себя, создавая, таким образом, звездную черную дыру.


Требования к генерации



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

Самым лучшим образом знания запоминаются во время игры, для этого в Галактику нужно добавить немного того, что есть почти во всех современных играх на космическую тематику.
Давайте представим, что есть некая гипотетическая игра «Deep Deep Space», в которой все звезды в Галактике соединены звездными путями друг с другом, где есть Wormhole и много другого интересного. Тогда к указанным выше требованиям добавятся следующие:
  • Галактика должна быть плоской, с равномерным распределением звезд по всех площади, либо заполнением только определенной области, задаваемой шаблоном.
  • На карте любого размера должны присутствовать все возможные типы звезд (без учета реального процентного соотношения между классами)
  • Все звезды Галактики должны быть соединены звездными путями друг с другом.
  • Количество путей для звезды должно быть от 1 до 5.
  • Пути между звездами не должны пересекаться между собой или пересекать другие звезды.
  • В Галактике должны быть несколько Wormhole, которые могут пересекать звездные пути, но не могут пересекаться между собой или пересекать другие звезды.
  • Цвета звездных путей и Wormhole должны отличаться.

Осталось добавить требования к результату:
  • Результат генерации должен быть представлен в виде карты Галактики графическом виде (либо другом формате, который можно просто визуализировать) для визуального контроля и выбора для дальнейшего использования.
  • На карте в графическом виде, размеры, спектральные классы и особенности звезд должны быть четко видны и однозначно идентифицироваться.
  • Карта в графическом виде должна иметь обозначения (легенду), для всех размеров, спектральных классов и особенностей звезд, которые могут встретиться на карте.
  • Должна быть возможность корректировать и просматривать карту в графическом виде без использования проприетарного софта на любой конфигурации компьютера, которые ставят в школы и дома.
  • Результат генерации должен быть представлен в XML для дальнейшего использования разработчиками.


Генерация



Я не буду акцентироваться на этом моменте, все-таки статья не про это. Скажу только, что после некоторого размышления я пришел к тому, что генерация Галактики состоит из следующих шагов:
  • Генерация слоя туманностей.
  • Установка звезд группами по 3х3 секторов, в каждом из которых добавляется по одной звезде для каждого класса и несколько черных дыр – всего 65 звезд. Этим выполниться требование по равномерности.
  • Установка созвездий, в которой звездам присваиваются имена и атрибуты реальных звезд.
  • Установка особенностей в определенном количестве звездам, не принадлежащим к созвездиям.
  • Добавление звездных путей и wormholes.
  • Формирования результата в графическом виде.
  • Формирования результата в XML формате.

В результате получаем вот такую случайную карту для размера 1х1:



Размеры карты могут быть любые от 1х1 (65 звезд) до 10х10 (6500 звезд).

Использование результата в практических занятиях



Когда в известном фильме мастер Йода говорил: «И да пребудет с Вами Сила!», возможно он имел ввиду в т. ч. и мощь формата SVG. Это текстовый векторный формат, который поддерживается всеми современными браузерами. Карта, приведенная выше, почти полностью нарисована в нем (кроме туманностей и фона).
Идея использование результата в том, чтобы на занятиях ребенок сам нарисовал сектор Галактики или созвездие. Для этого понадобится:

  • Компьютер.
  • Заготовка текстового SVG файла с пустой картой Галактики.
  • Карточка с координатами и атрибутами звезд (либо другим вариантом задания)


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



Здесь 1-я строка выводит наименование звезды, 2-я – кольцо вокруг звезды, имитирующее излучение и третья – саму звезду. Таким образом нужно поменять координаты объектов, для «circle» задать радиусы и номер «fill:url», который соответствует классу. При необходимости звезды соединяются линиями. Пример описания линии приведен ниже:



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



Результатом подобных занятий станет то, что дети получат твердые базовые знания по классификации звезд, смогут отлично ориентироваться в созвездиях и никогда не спутают Бело-голубой «Ригель» с красным «Бетельгейзе», шокируя взрослых неожиданно глубокими знаниями созвездий, звезд и их особенностей. На этом все – оригинальных Вам идей и интересных занятий!
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/335098/


Метки:  

Поиск сообщений в rss_rss_hh_new
Страницы: 1437 ... 1086 1085 [1084] 1083 1082 ..
.. 1 Календарь