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

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

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

 

 -Постоянные читатели

 -Статистика

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

Habrahabr








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

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

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

Подборка интересных мероприятий на неделю в Москве

Понедельник, 02 Октября 2017 г. 13:51 + в цитатник
rvnikita сегодня в 13:51 Разное

Подборка интересных мероприятий на неделю в Москве

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

    UX-Research Meetup
    2 октября (понедельник) 19:00
    Офис Mail.ru, Ленинградский пр-т, д. 39, стр.79
    бесплатно
    corp.mail.ru/ru/press/events/393

    Бизнес-ужин ОК
    3 октября (вторник) 18:30
    ресторан Shakti Terrace, Болотная набережная 11 стр 1
    бесплатно
    corp.mail.ru/ru/press/events/394

    Performance Marketing Moscow
    4 октября (среда) 9:00
    Кинотеатр «Октябрь», Новый Арбат 24
    от 12 000
    pm-moscow.com

    Data Science завтрак
    4 октября (среда) 9:30
    Кафе-пекарня «Райский Пирожок”, Проспект мира, 26с1
    бесплатно

    Russian Affiliate Congress & Expo
    4 октября (среда) — 5 октября (четверг) с 10:00
    КВЦ «Сокольники», павильон № 7а, 5-й лучевой просек, 7с1
    от 500 р, по коду RACE_partners скидка 66% на 2 дня конференции
    goo.gl/BeNHib

    Перспективы легального ICO в России
    5 октября (четверг) 16:00
    офис QIWI, мкр. Чертаново Северное, д.1А, корп.1
    бесплатно
    qviq.timepad.ru/event/581905

    Travel Tech Conference Russia
    5 октября (четверг) 9:00
    Конгресс-центр „Технополис”, Волгоградский просп., 42к5
    15 000 р.
    traveltechcon.ru

    Бизнес-форум «АТЛАНТЫ»
    5 (четверг) — 6 (пятница) октября
    Crocus City Hall, 65-66 км МКАД
    от 6 900 р.
    atlanty.ru

    AIC Analytics Day: Fail Compilation
    6 октября (пятница) 11:00
    ФРИИ, Мясницкая, дом 13, стр 18
    бесплатно
    www.facebook.com/events/1894122860839825

    Лекция Стива Возняка в Москве
    7 октября (суббота) 12:00
    МГУ, Ленинские Горы, 1
    бесплатно
    www.facebook.com/events/1938266743080680

    Хакатон HSE VR AR Hack
    7 октября (суббота) — 8 октября (воскресенье)
    ул. Таллинская, д.34
    бесплатно
    studlife.hse.ru/announcements/209450025.html

    mABBYYlity Hackaton
    7 октября (суббота) — 8 октября (воскресенье)
    Физтехпарк, Долгопрудненское шоссе, 3
    бесплатно
    mobility.abbyy.com/hack
    Original source: habrahabr.ru (comments, light).

    https://habrahabr.ru/post/339136/


    Метки:  

    [Перевод] Как эффективно работать с рекламным форматом Playable ads: пять типичных ошибок

    Понедельник, 02 Октября 2017 г. 13:41 + в цитатник
    lera_alfimova сегодня в 13:41 Маркетинг

    Как эффективно работать с рекламным форматом Playable ads: пять типичных ошибок

    • Перевод


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

    Ошибка #1: Вы слишком сфокусированы на развлекательной части и теряете из виду общую картину
    Зачастую бренды и разработчики крайне взбудоражены самой идеей playable ads. Каждая сессия мозговых штурмов посвящена только развлекательной части рекламы. Все пытаются создать игровой опыт с нуля, забывая, что на самом деле все, что нужно пользователю — это лишь немного веселья.

    Как только дело доходит до реальных целей рекламы, далеко не все спешат детально изучить вопрос. Многие впадают в ступор, когда разговор заходит обо всех этих скучных цифрах вроде установок, СPI, CTR, доходности, воронки продаж и так далее. Помните: если вы запускаете кампанию с playable ads в формате HTML5, это чистой воды маркетинг. Следовательно, метрики имеют значение.

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



    Ошибка #2: Вы не тестируете финальное сообщение для пользователя
    Последнее сообщение — очень важное. Неправильный посыл может лишить вас потенциальной установки. Один скучный экран — и ваш CTR упадет.

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

    На каждый A/B тест расходуется совсем небольшой рекламный бюджет, однако тесты помогают заранее определить, какой креатив лучше сработает. Как только лучший креатив найден — жгите! Запускайте кампанию и постоянно мониторьте ROI каждой установки.



    Ошибка #3: Вы не оптимизируете первый пользовательский опыт (FTUE)
    The First Time User Experience (FTUE) или первый пользовательский опыт — первое действие, которое совершает пользователь с момента запуска playable ad.

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

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

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

    Как только вы разобрались с FTUE, следующий шаг — его оптимизация. Здесь стоит подумать о таких пользовательских действия, как нажатие, захват/сброс объекта, смахивание и так далее. Как правило, выигрышный FTUE вертится вокруг простейших действий — нажатие или захват/сброс объекта.



    Ошибка #4: Вам не хватает бюджета
    Эта часть больше относится к брендам, однако и разработчиками полезно знать о финансовых подводных камнях.

    Чтобы преуспеть в playable ads, брендам приходится тратить на этот формат внушительную часть маркетингового бюджета. Минуло время, когда 1000 долларов в день было достаточно. Сегодня порой недостаточно и 100 тысяч долларов в месяц, особенно, если бренд работает в сфере с высокой конкуренцией.

    Причина A: Конкуренты с бОльшими бюджетами предлагают куда более высокие расценки за привлечение внимания пользователей. Таким образом, их реклама в формате playable будет показываться вместо вашей.
    Причина B: Чем больше рекламный бюджет, тем больше данных вы сможете собрать. Следовательно, вы сможете понять, сработал ли формат playable ads в масштабе или нет.
    Мы рекомендуем как следует исследовать нишу, прежде чем разрабатывать playable ads. В случае с playable ads избегайте конкуренции на равных с приложениями из топа 10 по прибыли — как для iOS, так и для Android. Вместо этого попробуйте по-другому распределить бюджет в плане демографии, цельтесь в разные приложения, и так далее.



    Ошибка #5: Вы не думаете о маркетинговой воронке в целом
    Pеклама playable — это не просто реклама. Нельзя просто так отдать playable ads на контракт агентству и умыть руки — вас будет ждать мрачная статистика.

    Успешные кампании для playable ads учитывают все: от разработки до A/B тестирования и запуска, дальнейших итераций и измерения показателей на каждой стадии маркетинговой воронки. Профессионалы регистрируют куда более сложные события уже после установки приложения — это помогает им определить, например, какую выручку будущая установка может дать на самом деле. Нередко можно предсказать, что 1 доллар затрат на рекламу может генерировать выручку в 4 доллара, что эквивалентно 300% ROI.

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

    Источник заглавной картинки — TechCrunch
    Original source: habrahabr.ru (comments, light).

    https://habrahabr.ru/post/339106/


    VMware vCloud Director. Что нового в версии 9.0?

    Понедельник, 02 Октября 2017 г. 13:01 + в цитатник
    Cloud4Y сегодня в 13:01 Администрирование

    VMware vCloud Director. Что нового в версии 9.0?



      VMware vCloud Director (vCD) — проверенное решение, которое помогает провайдерам облачных услуг предоставлять услуги множественной аренды IT-инфраструктуры (Multi-Tenant Infrastructure-as-a-service, IaaS). vCloud Director предлагает решение для гибридных облаков «под ключ» в инфраструктуре vSphere. Какими новыми возможностями расширен функционал портала «самообслуживания» (Tenant portal) vCloud Director версии 9.0, который вышел на днях?

      Улучшенный пользовательский интерфейс


      Полностью обновлённый пользовательский интерфейс на HTML5 ориентирован на упрощение использования облака арендаторами. Веб-консоль, работающая на технологии Adobe Flex, по-прежнему доступна. Чтобы получить доступ к новому пользовательскому интерфейсу арендатора, пользователям необходимо войти в систему с URL-адресом:

      https://{vCD _URP_IP}/Tenant/{organization_name}

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




      Демонстрация возможностей vCloud Director 9.0 HTML 5 Tenant Portal

      Некоторые из улучшений, которые увидят арендаторы в новом интерфейсе:

      • Виртуальные машины теперь можно просматривать как карты. В каждой карте есть возможность выбора действий или опции, таких как Power, Properties, создание снэпшота.
      • Теперь Org vDC (Virtual Datacenter) Networks можно просматривать на вкладке «Сеть», что позволяет создавать и редактировать сети vDC.
      • Автономные виртуальные машины могут быть созданы и просматриваться вместе с виртуальными машинами, которые являются частью контейнера vApp. Также присутствует возможность фильтрации. vCD 9.0 избавляет от необходимости создания vApp для создания отдельной виртуальной машины. vCD автоматически создает виртуальный контейнер vApp для виртуальных машин.

      Multisite Management


      Функция Multisite позволяет предоставить единый вход арендатору, имеющему несколько виртуальных центров обработки данных (Org vDC) под управлением разных vCD. Арендатор за один сеанс получает доступ к нескольким Org vDC, которыми управляют разные экземпляры vCloud Director, используя одни и те же учетные данные. Поставщики услуг, управляющие двумя или более экземплярами vCD, должны будут связать / замапить один сайт с другим, устанавливая ассоциацию типа site-to-site. Сайт может иметь несколько ассоциаций, но связь между сайтами может состоять только из двух объектов.

      После того, как два сайта, управляемые отдельными экземплярами vCD, связаны Системным Администратором, Администраторы Организаций (Organization Admins) могут установить доверие между ними. Каждая Организация должна создать пару Public/Private Key, чтобы установить доверие между собой. При этом локальные и LDAP-пользователи на разных сайтах должны иметь одинаковые имена пользователей, роли и SAML-идентификацию.

      Приведенный ниже API предоставит атрибуты сайта, как показано на рисунке 1.

      GET: https://{{vcloud.example.com}}/api/site


      Рисунок 1. REST API для получения данных сайта

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

      GET: https://{{vcloud.example.com}}/api/site/association/localAssociationData


      Рисунок 2. Данные для настройки ассоциации

      Администратор системы должен будет отправить эти данные ассоциации в API сайта B и наоборот.

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

      GET: https://{{vcloud.example.com}}/api/admin/org/SiteA-OrgA/ассоциации/localAssociationData

      Distributed Logical Router


      vCD 9.0 дает возможность использовать распределенный логический маршрутизатор для управления потребностями маршрутизации между двумя или более сетями Org vDC. Распределенный логический маршрутизатор (DLR) обеспечивает более быстрый способ построения таблиц маршрутизации между сетями org vDC. Это устраняет необходимость маршрутизации трафика через пограничный шлюз (Edge Gateway). До vCD 9.0 у арендатора могло быть несколько сетей org vDC, маршрутизация между этими сетями всегда выполнялась с помощью Edge Gateway, который находился между этими и внешней сетью. vCD развертывает DLR через NSX. Функциональность DLR находится в модулях ядра на хостах ESXi, которые являются частью кластера Provider vDC. DLR логически находится между сетью Org vCD network и шлюзом Edge Gateway. vCD автоматически создаст восходящий канал для DLR, который будет подключаться к сетевому интерфейсу Edge Gateway.

      Сети арендатора с DLR смогут использовать функции DHCP и DNS пограничного шлюза через узел, который будет управляться с помощью vCD.

      По умолчанию, когда создается пограничный шлюз, арендатор может включить DLR, как показано на рисунке 3. Это позволит подключить DLR к Edge Gateway в бэкэнд для потока трафика North South (внешний трафик ЦОД) из сети org.

      После обновления до vCD 9.0 существующие пограничные шлюзы будут иметь возможность включения DLR кликом правой кнопкой мыши по Edge Gateway.


      Рисунок 3. Опция Distributed Logical Router при создании Edge Gateway

      Поддержка транкинга для внешних сетей и Routed Org Networks


      У облачного провайдера могут быть клиенты, которые хотят подключить свои vLAN к сетям Org vDC. vCloud Director имел функционал создания внешних сетей с поддержкой сетей vLAN, но не Trunked vLAN. В vCD 9.0 теперь добавляется поддержка транкинга для внешних и маршрутизируемых сетей.

      Чтобы включить поддержку транкинга, создайте внешнюю сеть в vCD, которая была сконфигурирована с поддержкой транкинговых vLANS. Для Routed Org Network установите флажок «Guest vLAN Allowed» при создании сети, как показано ниже.



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


      С помощью vCD 9.0 провайдер может определить пул/кластер ресурсов, который можно использовать для размещения виртуальных машин NSX Edge Gateway. Это делается путем определения атрибута в метаданных Provider vDC. Атрибут метаданных, называемый placement.resourcepool.edge = resourcepool moref, может быть определен в Provider vDC. Resourcepool moref — это идентификатор moRef пула ресурсов/Edge кластера. Пулы ресурсов и их moRef можно получить, запросив через API vCD (см. Рисунок 2).

      Щелкните правой кнопкой мыши Provider vDC -> Properties -> Вкладка Meta-Data


      Рисунок 4. Метаданные, созданные для размещения пограничных шлюзов в кластере moRef 'resgroup-28'

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



      Мониторинг и метрики VM


      vCloud Director может собирать и хранить различные показатели по производительности ВМ. Эти метрики включают данные по использованию CPU/памяти/хранилища виртуальной машины, средней латентности операций с дисками и прочее. Предыдущие выпуски vCloud Director использовали Kairos DB, управляемую Apache Cassandra. С vCD 9.0 необходимости в Kairos DB для хранения и сбора метрических данных нет. Данные показателей могут храниться в базе данных Cassandra напрямую.




      vCloud Director 9.0 Metrics Dashboard Demo




      vRealize Operations Manager Tenant App for vCloud Director

      Расширяемость


      vCD UI extensibility framework позволяет расширить интерфейс пользователя Tenant Portal, добавив дополнительные разделы. С помощью framework можно добавить новый раздел, который может ссылаться на сторонний портал или может быть встроенным iFrame.

      Изменения архитектуры


      Поддержка PostgreSQL


      vCloud Director 9.0, помимо Microsoft SQL и Oracle, поддерживает базу данных PostgreSQL в качестве внешней базы данных. Этот релиз поддерживает PostgreSQL версии 9.5, кластерные конфигурации, а также SSL-соединение.

      Для клиентов, имеющих базы данных MS SQL или Oracle, Cell Management Tool (CMT) поможет перенести их в предварительно установленный экземпляр базы данных PostgreSQL. Опция 'dbmigrate' в CMT поможет перенести существующую базу данных в новый экземпляр PostgreSQL.

      [bash]# cell-management-tool dbmigrate

      После миграции базы данных используйте параметр ‘reconfigure-database’ в CMT, чтобы vCD начал использовать новую базу данных PostgreSQL.


      Рисунок 5. Инструмент CMT для миграции базы данных

      vCenter Guest OS и согласованность аппаратной версии


      Когда администратор провайдера услуг начинает создавать vDC, аппаратная версия, определённая vCD, будет самой высокой, которую может поддерживать вычислительный кластер. Это позволяет vCD расширять список гостевых ОС, которые он может поддерживать. vCD будет поддерживать все гостевые ОС, которые поддерживает среда vSphere.

      vCD-vCenter Latency


      vCloud Director теперь может поддерживать латентность до 100 миллисекунд между собой и сервером vCenter. Это помогает провайдерам услуг использовать один экземпляр vCD для управления серверами vCenter, которые могут быть расположены удаленно.

      Сетевые улучшения


      Группы безопасности


      vCloud Director 8.20 представил возможности распределенного брандмауэра (Distributed Firewall — DFW) NSX арендаторам для самообслуживания. Они могут определять политики DFW, создавая индивидуальные правила для виртуальных машин или vApp. В то же время, они могут также применять эти политики в общем виде к набору IP-адресов, MAC-адресов или объектов, таких как виртуальные машины, сети Org vDC и т. д. Для использования этих возможностей необходимо точно знать эти наборы IP-адресов, MAC-адресов или объектов.

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

      vCloud Director 9.0 появляются группы безопасности (Security Groups), которые помогают динамически определять и применять политики безопасности. Администратор арендатора может определить критерий соответствия отдельных виртуальных машин через группы безопасности, а политики DFW могут применяться к этим группам безопасности.

      Чтобы создать группы безопасности, щелкните правой кнопкой мыши Edge Gateway->Edge Gateway Services->Grouping Objects->Security Groups


      Рисунок 6. Создание группы безопасности

      Усовершенствования в хранении данных


      Горячая миграция данных клиентов между хранилищами данных


      С помощью vCloud Director 9.0 Service Providers смогут выполнить горячую миграцию данных отдельных арендаторов из одного хранилища данных в другое. Все объекты, которые относятся к Организации, включая виртуальные машины, каталоги, изображения и прочее, будут перенесены в другое хранилище данных. Эта операция может выполняться только администратором облачного провайдера или пользователем, имеющим доступ.


      Рисунок 7. Миграция хранилища клиентов

      Чтобы перенастроить хранилище арендаторов, войдите в vCD
      Mange & Monitor->Organizations->Right click Organization->Migrate Tenant Data

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

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




      Рисунок 8. Выбор источников данных и целевых хранилищ для миграции данных арендатора

      Поддержка виртуальных томов (vVols)


      vCloud Director 9.0 добавляет поддержку хранилищ данных, созданных в vCenter с использованием виртуальных томов. При создании Provider vDC vCD позволяет добавить хранилища данных с поддержкой vVols.

      Вывод


      vCloud Director 9.0 полностью обновляет процесс выполнения повседневных операций с виртуальной инфраструктурой как поставщиками услуг, так и арендаторами. В этом релизе основное внимание уделяется упрощению операций провайдеров путем добавления поддержки multisite management и PostgreSQL. Клиентов облака порадует новый пользовательский интерфейс на HTML5, который стал значительно удобнее и эффективнее. Мы, конечно, планируем переезд на 9-ку. Нам потребуется некоторое время для проведения валидации инфраструктуры и тестирования. О переходе на новую версию мы сообщим позже.

      Статья составлена на основе "vCloud Director 9.0. What's New".
      Original source: habrahabr.ru (comments, light).

      https://habrahabr.ru/post/339128/


      [Перевод] [Перевод] Переосмысление drag&drop

      Понедельник, 02 Октября 2017 г. 12:57 + в цитатник
      MagisterLudi сегодня в 12:57 Дизайн

      [Перевод] Переосмысление drag&drop

      • Перевод

      Берем что-то всем давно известное и делаем это удобным и красивым


      image
      Представляем вашему вниманию react-beautiful-dnd

      Функция перетаскивания (drag&drop) — это интуитивный способ перемещения и переупорядочивания элементов. В Atlassian недавно выпустили react-beautiful-dnd, которая делает перетаскивание (drag&drop) внутри списков в вебе красивыми, естественными и доступными.

      Тактильное чувство


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

      image

      Cортировка элементов по группам.

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

      Движение


      image

      Традиционно принятое постоянное движение.

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

      image

      Более естественное движение.

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

      Знать, когда перемещать

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

      image

      Действие, основанное на позиции выбранного варианта.

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

      image

      Действие, основанное на центре притяжения.

      В react-beautiful-dnd действия перетаскиваемых элементов основаны на центре притяжения — независимо от того, откуда пользователь берет элемент. К действиям перетаскиваемых объектов применимы те же правила, что и к набору гирь. Ниже приведены некоторые правила, которые используются даже с подвижными элементами при естественном перетаскивании:

      • Список перетаскивается, когда центральное положение перетаскиваемого элемента переходит через одну из границ списка
      • Элемент, который находится в покое, должен уйти с пути перетаскиваемого элемента, когда положение центра перетаскиваемого элемента уходит за край элемента, находящегося в покое. Другими словами: как только положение центра элемента (А) выходит за край другого элемента (Б), Б сдвигается в сторону.


      Доступность


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

      Уважение к браузеру

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

      Тщательно продуманная анимация


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

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

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

      Выпадение

      Когда вы отпускаете перетаскиваемый элемент, его движение основано на физике(спасибо react-motion). Это приводит к тому, что когда элемент падает он кажется более весомым и ощутимым.

      Уходим с дороги

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

      Из чего она состоит:

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


      image

      Animation curve, используемая в момент перемещения.

      Хорошая совместимость


      Неаккуратные клики и блокировка нажатия клавиш.

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

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

      Управление фокусом

      React-beautiful-dnd упорно трудится, чтобы убедиться, что он не влияет на обычные вкладки потока документов. Например, если вы добавляете теги привязки, то пользователь по-прежнему сможет перейти непосредственно к привязке, а не к элементу, к которому осуществляли привязку. Мы добавляем tab-index к определяемым элементам, чтобы убедиться, что даже если вы не добавляете что-либо к тому, что обычно является интерактивным элементом, (например, div), то пользователь все равно сможет получить доступ к нему с помощью своей клавиатуры, чтобы перетащить его куда-либо.

      Не для всех


      Есть множество библиотек, которые позволяют осуществлять действия функции перетаскивания внутри React. Наиболее примечательной из них является замечательная react-dnd. Она проделывает невероятную работу по обеспечению огромным набором примитивов функции перетаскивания, которые особенно хорошо работают с HTML5, несмотря на то что HTML5 мало с чем совместим. React-beautiful-dnd это абстракция высокого уровня, построенная специально для вертикальных и горизонтальных списков. С таким подмножеством функциональности react-beautiful-dnd предлагает действенный, красивый и естественный опыт использования функции перетаскивания. Однако, react-beautiful-dnd не обеспечивает широтой возможностей, предоставляемых react-dnd. Таким образом, эта библиотека может быть не для вас, все зависит от того в каких целях вы собираетесь её использовать.

      Проектирование


      Чистый, мощный API

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

      Производительность

      React-beautiful-dnd спроектирована быть чрезвычайно производительной — это часть её ДНК. Она основана на предыдущих исследованиях производительности реакции, которые можно прочитать здесь и здесь. React-beautiful-dnd предназначена для выполнения минимального количества исполнений, необходимых для каждой задачи.

      Ключевые аспекты

      • Используйте связанные компоненты с хранением промежуточных значений в памяти, чтобы убедиться, что единственные компоненты, которые исполняются это те компоненты, что должны исполняться - благодаря react-redux, reselect и memoize-one.
      • Все задержки движения прерываются requestAnimationFrame - благодаря raf-schd
      • Хранение промежуточных значений в памяти используется повсеместно — благодаря memoize-one
      • Условно отключаются указатели на все элементы при перетаскивании, чтобы защитить браузер от избыточной работы — вы можете прочитать больше об этой технике здесь
      • Неосновная анимация выполняется на GPU


      image

      Минимальное количество обновлений реакций.

      image

      Минимальное количество браузерных изображений.

      Проверено

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

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

      Типизированно

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

      Заключение


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

      Огромное спасибо всем в Atlassian, кто сделал это возможным.

      Обновление#1

      Поддержка react-beautiful-dnd была невероятной! Большое спасибо. Мы уже добавили некоторые новые функции, такие как перемещение по-горизонтали.

      image

      Горизонтальное перетаскивание.

      image

      Горизонтальное перемещение в контексте доски объявлений.

      Было много запросов на поддержку сенсора (это позволило бы react-beautiful-dnd работать на мобильных и планшетных устройствах). Это всегда было в планах и мы уже очень скоро начнем над этим работать! Библиотека еще совсем новая.

      Обновление#2

      Мы выпустили поддержку для перемещаемых элементов между списками react-beautiful-dnd. Я написал блог. “Естественное движение клавиатуры между списками", в котором говорится о том, как мы пришли к тому, чтобы создать это обновление таким образом, чтобы оно ощущалось естественным.

      image

      Перетаскивание между списками.



      EDISON Software профессионально занимается разработкой софта для крупных заказчиков (например, система управления городским освещением или электронная система медицинского осмотра) и мы стараемся, чтоб внешний вид у продуктов был максимально удобен для пользователя, а «технический долг» у UX-дизайнеров сокращался. Вот подборка полезных статей по Usability:

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

      https://habrahabr.ru/post/339086/


      Метки:  

      Разбираем WeChat — второй по популярности мессенджер в мире

      Понедельник, 02 Октября 2017 г. 12:44 + в цитатник
      Sqwony сегодня в 12:44 Разработка

      Разбираем WeChat — второй по популярности мессенджер в мире



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



        Мессенджер WeChat от китайской компании Tencent

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

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

        Исследование протокола

        Было принято решение изучить мессенджер «изнутри», разобраться в коде 32-битной версии мессенджера для iOS. Имеется у нас старенький, видавший виды, iPhone 4S с версией iOS 7.2.1.

        В качестве MITM использовуем Burp Suite Free Edition.
        Скачиваем приложение и при помощи замечательной утилиты dumpdecrypted расшифровываем исполняемый файл.
        На момент начала реверс-инжиниринга WeChat была актуальна версия 6.3.13.

        Теперь осталось скопировать файл с устройства, дисассемблировать в IDA, и можно начинать.

        Рассмотрим алгоритм обмена ключами на примере регистрации.
        Запускаем приложение и видим предложение ввести номер телефона для регистрации.

        Вводим номер телефона и видим в MITM HTTP-запрос на адрес
        http:// hkshort.weixin.qq.com/bindopmobileforreg.



        Тело запроса состоит из:

        • Заголовка (желтый цвет);
        • Шифрованных данных (синий цвет).

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

        Первым сообщением передаются следующие данные:

        • Номер телефона;
        • Язык системы телефона;
        • ID устройства;
        • Версия клиента;
        • Ключ для расшифровывания ответа (случайные 16 байт);
        • Прочие данные (не очень интересующие нас).

        Сообщение сериализуется и шифруется публичным ключом сервера при помощи алгоритма RSA. Ответ сервера расшифровывается AES-ключом, переданным в запросе. В ответе сообщается, что либо все в порядке, либо указывается ошибка.

        Получаем СМС и вводим код. Формируется тот же запрос, только уже с кодом из СМС, а в ответе получаем так называемый ticket. Теперь, имея ticket, можно отправлять запрос на регистрацию. Вводим имя и нажимаем Ок.

        Обмен ключами происходит по алгоритму Диффи-Хеллмана с использованием эллиптической кривой над конечным полем «secp224r1». Генерируются закрытый и открытый ключ, и отправляется запрос на адрес hkshort.weixin.qq.com/newreg. Сервер генерирует свои ключи, а также выдает нам так называемые CryptUin и ServerID, о которых расскажем позже. В ответ сервер присылает нам свой публичный ключ и сессионный ключ.

        Теперь у нас есть публичный ключ сервера, и мы вычисляем общий ключ, с помощью которого расшифровываем сессионный ключ. С этого момента общение клиент-сервер осуществляется с помощью симметричного алгоритма AES с длиной ключа 128 бит.

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



        Теперь расскажем подробнее о каждом поле:

        1. Идентификатор протокола. Каждый пакет начинается с этого байта.

        2. Флаги. Хранит информацию о длине SrvID, длине самого заголовка и сжатии исходного сообщения.



        Флаг сжатия выставляется равным 0b10, если сообщение не сжималось, в противном случае ставится равным 0b01.

        3. Версия приложения. Без комментариев.

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

        5. SrvID. ID текущей сессии. Меняется при каждом новом подключении.

        6. uiCgi. Код команды. У каждой команды есть свой uiCgi и url. Например для команды bindopmobileforreg, uiCgi равен 0x91, а для newreg – 0x7e. Большинство чисел упаковываются, используя следующий алгоритм:
        private static void Write7BitEncodedInt(BinaryWriter store, int value)
                {
                    Debug.Assert(store != null);
                    // Write out an int 7 bits at a time.  The high bit of the byte,
                    // when on, tells reader to continue reading more bytes.
                    uint v = (uint)value;   // support negative numbers
                    while (v >= 0x80)
                    {
                        store.Write((byte)(v | 0x80));
                        v >>= 7;
                    }
                    store.Write((byte)v);
                }


        В данном примере uiCgi равен 0x17b, а в упакованном виде – fb02.

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

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

        9. Флаг.

        10. Хеш.

        Вычисляется следующим образом:

        hash1 = md5(cryptUin.shareKey);
        hash2 = md5( strlen(data).shareKey.hash1.data)
        resultHash = adler32(hash2)
        sharedKey –это общий ключ, полученный при хендшейке.
        Хеш также упаковывается.

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

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

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

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

        В процессе работы была так же обнаружена интересная уязвимость. В приложении есть возможность найти пользователя по номеру телефона. Сервер либо отвечает что такого пользователя нет, либо возвращает информацию о нем(имя, пол, город, фото итд). Но если отправлять эти запросы слишком часто, то сервер отвечает сообщением «Too many attempts. Try again later ». Этим можно воспользоваться, так как, если пользователя не существует, сервер всегда сообщит об этом, а если приходит ответ «Too many attempts. Try again later „- это значит, что пользователь существует. Используя это, можно собирать базу пользователей. Кстати обнаружились очень “интересные» пользователи, которые используют WeChat, но обычным способом их не обнаружить, и даже невозможно отправить  им приглашение, скорее всего это «особенные» люди Китая. Даже если запросить регистрацию на «интересный» номер, то сервер сообщит, что данный пользователь уже зарегистрирован и предлагает восстановить аккаунт, но уже не по СМС.

        Используя 20 000 потоков возможно с одного аккаунта за сутки собрать всю базу WeChat по Китаю, блокировки аккаунта не происходит.

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

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

        https://habrahabr.ru/post/338940/


        Метки:  

        [Перевод] Три карьерных пути в IT: основатель, руководитель или наёмный работник

        Понедельник, 02 Октября 2017 г. 12:21 + в цитатник
        m1rko сегодня в 12:21 Управление

        Три карьерных пути в IT: основатель, руководитель или наёмный работник

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

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

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

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

        Основатель


        Преимущества


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

        Недостатки


        • Невероятно высокий уровень стресса. Даже успех будет болезненным
        • Вероятно, не обеспечит вам максимальный уровень дохода
        • Значительные барьеры для начала (финансы/навыки/местоположение)
        • Масштабный успех часто требует десятилетия или больше работы с самоотдачей
        • Уровень самоотдачи значительно мешает личной жизни

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


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

        1. Определить потенциальных коллег, с которыми вы можете работать и у которых есть необходимые технические навыки, чтобы помочь вам в создании минимально жизнеспособного продукта (MVP).
        2. Обрисовать финансовый план. Например, достаточно ли у вас личных накоплений, есть ли друзья/родственники, которые могут обеспечить посевные инвестиции, хватит ли денег для запуска, можете ли вы сократить расходы и сэкономить, чтобы обеспечить 6-12 месяцев работы над своей идеей?
        3. Определить проблему, которую вы и потенциальные коллеги страстно хотите решить.
        4. Наименее важная (но всё-таки необходимая) часть — это план, как именно решить проблему.

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

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

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

        Руководитель (топ-менеджер в крупной компании)


        Преимущества


        • Стабильный доход/бенефиты/проч.
        • Высокий престиж (только самые успешные основатели пользуются б'oльшим уважением)
        • Более высокая вероятность влияния на отрасль (поскольку большинство стартапов проваливаются)
        • Не требуется создание команды и накопление денег для начала

        Недостатки


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

        Стратегии для тех, кто хочет быть руководителем


        В реальности я вижу две стратегии на этом пути.

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

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

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

        Наёмный сотрудник (отдельный участник / менеджер среднего звена)


        Преимущества


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

        Недостатки


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

        Стратегии для тех, кто хочет быть наёмным сотрудником


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

        Хотелось бы ещё сказать напоследок, что для достижения мастерства в каждой из трёх ролей требуется время. Среди ребят в колледже распространена мысль, что с 20 до 30 лет нужно искать себя и работу, которая доставляет больше всего удовольствия. Проблема в том, что если нужно 5-10 лет для достижения мастерства, а вы потратили 10 лет на поиск себя… то пройдёт очень много времени, прежде чем вы достигните успеха хоть в чём-нибудь (и получите соответствующее вознаграждение за это). Это не значит, что не нужно исследовать разные варианты, но нужно понимать цену этих исследований и планировать их соответствующим образом.
        Original source: habrahabr.ru (comments, light).

        https://habrahabr.ru/post/339118/


        Метки:  

        Аналитика Solar JSOC: как атакуют российские компании

        Понедельник, 02 Октября 2017 г. 11:57 + в цитатник
        SolarSecurity сегодня в 11:57 Разработка

        Аналитика Solar JSOC: как атакуют российские компании

          Центр мониторинга и реагирования на киберугрозы Solar JSOC опубликовал исследование киберугроз за первое полугодие 2017 г., подготовленное на базе обезличенной статистики по инцидентам ИБ у заказчиков. Полученная аналитика отвечает на вопросы о том, кто, как, в какое время и с использованием каких векторов и каналов атакует крупнейшие российские компании. Отчет предназначен для информирования служб ИТ и информационной безопасности о текущем ландшафте угроз и основных трендах.

          В первой половине 2017 года средний поток событий ИБ составлял 6,156 миллиардов в сутки, из них около 950 в сутки – события с подозрением на инцидент (172 477 за полгода). Это примерно на 28% больше, чем в первом полугодии 2016 года. Доля критичных инцидентов составила 17,2%. Таким образом, если в 2016 году критичным был каждый 9-й инцидент, то теперь – уже каждый 6-й. Предполагается, что такая динамика связана с общим повышением интенсивности массовых и целенаправленных атак на организации.



          Когда атакуют?


          Если рассматривать общее количество инцидентов, то лишь в 12,5% случаев они происходили в ночное время.



          Однако если из общей массы инцидентов выделить критичные, этот показатель возрастает до 29,4%, то есть почти трети всех случаев.



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



          Как атакуют извне?


          Основными инструментами киберпреступников оставались атаки на веб-приложения (34,2%), компрометация учетных данных внешних сервисов клиента (23,6%) и вредоносное ПО (19,2%).



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

          В первом полугодии 2017 года аналитики Solar JSOC чаще всего (в 87% случаев) сталкивались со следующей моделью атаки: после фазы первого проникновения в сеть компании (статистика описана ниже, см. стр. 7) злоумышленники пытаются выявить наиболее уязвимый сервер инфраструктуры (зачастую используя сканирование сети как промежуточный инструмент). В качестве такого уязвимого узла могут выступать серверы с необновленными версиями операционной системы. Злоумышленники стараются захватить контроль над сервером, чтобы в кратчайшие сроки получить доступ к привилегированным учетным записям сети (технологическим учетным записям, записям ИТ-администраторов), из-под которых они смогут скрытно получать доступ к большому количеству объектов инфраструктуры.

          В 13% случаев первым шагом проникновения в компанию служила атака на веб-приложение (например, онлайн-банк), в 25% – на управляющие протоколы систем (в том числе использование уязвимости Shellshock, известной с сентября 2014 года), в 62% – внедрение в организацию вредоносного программного обеспечения через email-вложения или фишинговые ссылки.



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

          Интересные наблюдения:

          • В среднем в течение месяца в общем доступе в сети Интернет публикуется от 2 до 5 сервисов заказчиков с критичными уязвимостями, не устранявшимися около года. Такие публичные сервисы позволяют злоумышленникам без особой подготовки и сложных инструментов проникнуть в корпоративную сеть компании и развивать атаку на критичные системы. Из них 2/3 публикуются администраторами ненамеренно, без ведома служб информационной безопасности, тем самым создавая существенный риск компрометации инфраструктуры.
          • Тренд к росту числа вирусов-шифровальщиков не сдает позиций. Однако если раньше аналитики чаще имели дело с вредоносным ПО, чьей единственной функцией является шифрование данных на зараженной рабочей станции, то теперь шифрование, как правило, является лишь одной из функций. Все чаще ей сопутствуют keylogger и возможность удаленного управления зараженной рабочей станцией. Таким образом, инструментарий злоумышленников становится более многозадачным.
          • Отдельно хотелось бы подчеркнуть, что, несмотря на массовые атаки Wannacry и Petya, цифры по внешним инцидентам демонстрируют высокий, но не драматический рост. Причина состоит в том, что массовые атаки на российские компании происходят регулярно, но, как правило, остаются вне поля зрения СМИ.
          • Снизилось количество случаев компрометации учетных данных удаленного доступа. Ранее первым шагом атаки на компанию часто был взлом учетных записей ее сотрудников в публичных почтовых сервисах (Mail.ru, Yandex.ru, Gmail.com), поскольку пользователи часто устанавливают один и тот же пароль для различных учетных записей. Постепенное внедрение механизмов двухфакторной аутентификации и усложнение алгоритмов доступа в российских компаниях позволило снизить эффективность этого метода атаки.

          Как атакуют изнутри?


          Инциденты, связанные с действиями внутренних злоумышленников, не претерпели существенных изменений. В 43,4% случаев это утечки информации, еще в 23,5% – компрометация внутренних учетных записей, и менее 10% приходится на использование хакерских утилит, средств удаленного администрирования и т.п.



          Интересные наблюдения:

          • Несмотря на то, что учетные записи удаленного доступа достаточно редко подвергаются компрометации, количество инцидентов, связанных с удаленной работой подрядчиков, растет. По нашим наблюдениям это связано с продолжением развития сервисов ИТ-аутсорсинга и невысоким ростом информационной безопасности в ИТ-аутсорсерах.
          • Информационная образованность пользователей растет, но не в том ключе, который хотели бы видеть офицеры безопасности: в среднем раз в два месяца у заказчиков Solar JSOC фиксируются попытки использования рядовыми сотрудниками вредоносных или хакерских утилит. Например, утилит, позволяющих получить информацию о паролях пользователей (procdump, mimikatz), систем сканирования сети и поиска уязвимостей и т.д. Помимо желания нанести прямой вред компании, сотрудниками зачастую двигает обыкновенное любопытство.

          Анализ наиболее «популярных» каналов утечек показывает, что чаще всего сотрудники компаний используют в этих целях электронную почту (31,7%), веб-ресурсы (27,2%) и съемные носители (18,6%).



          Как защищаться?


          Технические средства

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

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

          Threat Intelligence

          Источники Threat Intelligence, используемые в Solar JSOC, можно условно разделить на следующие категории:

          • Opensource – открытые базы индикаторов вредоносного ПО, серверов управления и фишинговых ссылок. Как правило, в разрезе детектирования с помощью SIEM-платформ актуальность имеют только сетевые индикаторы.
          • Reputation feeds – платные подписки на репутационные списки вредоносного ПО, серверов управления и фишинговых ссылок. Как правило, в разрезе детектирования с помощью SIEM-платформ актуальность имеют только сетевые индикаторы.
          • APT/IOC reporting – платные подписки на подробные описания 0day вредоносных тел, включающие, в том числе, и описание используемых уязвимостей, и хостовые индикаторы вредоносного ПО.
          • Information Exchange – информация, полученная в рамках информационных обменов с государственными, ведомственными и иностранными центрами реагирования на инциденты (CERT).
          • Internal Solar JSOC database – индикаторы, полученные в результате собственных исследований Solar JSOC или расследований инцидентов.
          • User experience – информация, полученная напрямую от пользователей клиентов (успешное противодействие социальной инженерии, детектирование фишинговых рассылок и т.п.).



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

          https://habrahabr.ru/post/338330/


          Отладка PL/SQL кода для внешней сессии БД

          Понедельник, 02 Октября 2017 г. 11:32 + в цитатник
          ympukhov сегодня в 11:32 Разработка

          Отладка PL/SQL кода для внешней сессии БД

            Проблематика и назначение:


            Периодически Oracle разработчики сталкиваются с проблемой отладки PL/SQL кода, когда код вызывается из веба или среднего слоя(т.е. когда сессия разработчика не совпадает с сессией в которой возникает проблема).

            Особенно актуально, если какие-либо проблемы возникают на стороне Web при двухзвенных и трехзвенная схемах взаимодействия БД и Web(ниже пример трехзвенной архитектуры взаимодействия):

            Рисунок 1 — Трехзвенная архитектура взаимодействия БД и Web.

            Метод решения проблем:


            В решение проблем с отладкой PL/SQL кода нам помогут пакеты:
            • DBMS_PIPE — Пакет который позволяет отпавлять сообщения(пайпы) между 2мя сессиями БД Oracle.
            • DBMS_ALERT — Пакет, который обеспечивает поддержку асинхронных оповещений для различных событий БД Oracle.


            Ниже код метода, который мы будем отлаживать при помощи DBMS_PIPE и DBMS_ALERT одновременно:


            create or replace procedure checkout_with_pipe_and_alert(p_cycle_size in number) is
                c_method_error         constant number := -20000;
                c_method_error_message constant varchar2(4000) := 'Cycle size should be > 0';
                l_power_value number;
                l_i_value     number := 1;
                l_pipe        pls_integer;
            begin
                if p_cycle_size > 0 then
                    for i in 1 .. p_cycle_size
                    loop
                        l_power_value := power(i, 2);
                        l_i_value := l_i_value * i;
                        --Send pipe info
                        l_pipe := dbms_pipe.create_pipe(pipename => 'pipe');
                        dbms_pipe.pack_message(i || '.l_power_value:=' || l_power_value || ' l_i_value=' || l_i_value);
                        l_pipe := dbms_pipe.send_message(pipename => 'pipe');
                        --Send alert info
                        dbms_alert.register('alert');
                        dbms_alert.signal(name => 'alert',
                                                            message => i || '.l_power_value:=' || l_power_value || ' l_i_value=' || l_i_value);
                        dbms_alert.remove(name => 'alert');
                    end loop;
                else
                    raise_application_error(c_method_error, c_method_error_message);
                end if;
            end checkout_with_pipe_and_alert;


            При отсутствие грантов на DBMS_PIPE и DBMS_ALERT раздадим их:



            Рисунок 2 — Раздача грантов c Oracle сервера схемы SYS на рабочую схему

            Отловим сообщения для DBMS_PIPE и DBMS_ALERT при помощи PL/SQL Developer:


            Отлавливание сообщений при помощи кода не рассматриваю, т.к. информации достаточно в Oracle DOC и на просторах интернета.
            Заходим в Tools->Event Monitor..., в одном окне выбираем тип события "Pipe", а в другом "Alert" в Event name указываем название пайпы и алерта, которые задали в коде и нажимаем Start:


            Рисунок 3 — Настройка окна с Pipe


            Рисунок 4 — Настройка окна с Alert

            После запуска метода checkout_with_pipe_and_alert из веба/среднего слоя(в нашем случае из другой сессии):


            begin
              checkout_with_pipe_and_alert(5);
            end;


            В окнах Pipe и Alert получим следующие результаты:



            Рисунок 5 — Результат получения информации от Pipe


            Рисунок 6 — Результат получения информации от Alert

            Выводы:
            • dbms_pipe отличный метод, для отладки pl/sql в разных сессиях, только pipe периодически забивается и приходится использовать метод: dbms_pipe.purge
            • dbms_alert я бы не советовал использовать, т.к. периодически теряются сообщения при отладке(как видно из рисунка 6), быть может не правильно его использую. Если кто-то с таким сталкивался, напишите в комментариях и я поправлю статью.
            Original source: habrahabr.ru (comments, light).

            https://habrahabr.ru/post/339122/


            Метки:  

            [Перевод] Что последует за вебом?

            Понедельник, 02 Октября 2017 г. 09:05 + в цитатник
            m1rko сегодня в 09:05 Разработка

            Что последует за вебом?

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

            Кое-кто решил, что я пишу слишком в негативном ключе и не обращаю внимания на положительные стороны веба. Так и есть: первая часть была в стиле «Обсудим факт, что мы попали в глубокую яму», а вторая часть — «Как разработать кое-что получше?» Это огромная тема, так что она на самом деле двумя частями не ограничится.

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



            Создание GUI в Matisse, редакторе UI с автоматическим выравниванием и ограничителями. Да здравствует (новый стильный) король?

            Нужно также сконцентрироваться на дешевизне. У веба многочисленные группы разработчиков. Б'oльшая часть их работы дублируется или выбрасывается, кое-что можно использовать повторно. Возможна и новая разработка в небольшом объёме… но по большому счёту любую технологию NewWeb придётся собирать из кусочков существующего программного обеспечения. Беднякам не приходится выбирать.



            Вот мой личный список пяти главных свойств веба:

            • Развёртывание и изоляция в песочнице
            • Простота в освоении пользователями и разработчиками
            • Устранение дихотомии документ/приложение
            • Продвинутое оформление и брендинг
            • Открытый код и бесплатное использование

            Это не совсем то, что принято считать главными принципами архитектуры: если опросить разработчиков, то большинство из них, вероятно, назовут сутью архитектуры веба URL, просмотр исходников, кроссплатформенность, HTTP и так далее. Но это всё просто детали реализации. Веб взял верх над Delphi и Visual Basic не потому что JavaScript настолько крут. Есть более глубокие причины.

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

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

            Принципы архитектуры


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

            1. Ясное понятие идентификаторов приложений.
            2. Единое представление данных от бэкенда к фронтенду.
            3. Бинарные протоколы и API.
            4. Аутентификация пользователей на уровне платформы.
            5. Ориентированная на IDE разработка.
            6. Компоненты, модули и отличная система вёрстки UI  — точно как в обычной разработке для настольных компьютеров или мобильных устройств.
            7. Также понадобятся вещи, с которыми хорошо справляется веб: мгновенный запуск стриминговых приложений без инсталляции или необходимости ручного обновления, изоляция этих приложений в песочнице, сложная стилизация UI, сочетание и и приведение в соответствие «документального» и «программного» материала (вроде возможности связать определённые виды приложений), возможность постепенного обучения и архитектура, которая не затрудняет разработчикам создание слишком сложных UI.

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

            Идентификаторы приложений и ссылки


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

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



            URL — основная часть дизайна любого браузера, но иногда он вносит путаницу!

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

            Вторая проблема в том, что машинам тоже сложно воспринимать URL'ы (здесь возможно создание сумасшедших эксплоитов). Даже не учитывая хитрых трюков кодирования вроде этого, в вебе есть различные способы установить идентичность приложения. Браузеру требуется некое понятие идентичности приложения для отделения друг от друга хранилищ кукисов и для отслеживания выданных разрешений. Это «источник» (origin). Со временем концепция источника в вебе эволюционировала, и теперь её в сущности невозможно сформулировать. RFC 6454 пытается сделать это, но в самом документе написано:

            Со временем многие технологии сошлись на концепции источника как на удобной единице изоляции. Однако многие из ныне используемых технологий, такие как куки [RFC6265], созданы раньше, чем современная концепция источника в вебе. У этих технологий часто другие единицы изоляции, что ведёт к уязвимостям.

            Например, подумайте, что мешает вашему серверу установить куки для домена .com. А что насчёт kamagaya.chiba.jp? (это не веб-сайт, а просто раздел иерархии, как и .com!)

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

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

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

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


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

            • Идентичность приложения определяет публичный ключ. Все документы, подписанные одним ключом, изолированы в одном домене. Для определения изоляции не используется разбор строк.
            • Приложения могут подписаться на получение строго типизированных пакетов данных, которые просят их открыться в какое-то состояние. Android называет эту концепцию «намерениями» (intents). Намерения на самом деле не очень строго типизированы в Android, но могли быть такими. Их можно использовать также для внутренней навигации, но чтобы разрешить ссылки из какого-то другого приложения, намерение должно быть опубликовано в манифесте приложения. По умолчанию приложения не реагируют на ссылки.
            • Где найти приложение для скачивания? Доменное имя — достаточно хорошая позиция для начала. Хотя мы можем поддерживать и скачивания по HTTP[S], но мы находим сервер NewWeb по хорошо известному порту и забираем код оттуда. Так что доменное имя становится начальной точкой для получения приложения, но в остальных отношениях не такой важной.

            Чтобы различать URL'ы и чужие намерения от наших собственных, назовём чужие линк-пакетами.

            Отключение приёма внешних ссылок по умолчанию понизит ссылочную связность NewWeb, но улучшит безопасность. Может быть, это плохой компромисс и он станет фатальным. Но многие ссылки, которые люди могут теоретически создавать в современном вебе, по сути бесполезны или из-за требований аутентификации, или потому что не содержат никакого осмысленного начального состояния (многие SPA). Поэтому приложения минимизируют область атаки. Вредоносная ссылка, которая является стартовой точкой такого большого количества эксплоитов, немедленно становится менее опасной. Это кажется ценным достижением.

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

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

            Как создать браузер приложений? Хотя NewWeb довольно сильно отличается от веба, базовый UI полноэкраннных приложений вполне стандартен, а пользователи захотят переключаться туда и назад. Так почему бы не форкнуть Chromium и не добавить вкладку в новом режиме?

            (Правка: некоторые поняли вышесказанное как «использовать Chrome для всего, что здесь перечислено» — это не то, что я имел в виду. Я имел в виду использование его реализации UI со вкладками, чтобы у вас были открыты рядом приложения NewWeb и OldWeb. Но UI с вкладками несложно сделать, и необязательно использовать Chromium, браузер приложений тоже может быть созданным с нуля приложением).

            Единое представление данных


            Может быть концепция линк-пакетов звучит немного туманно. Что это такое? Для более чёткого определения нам нужны структуры данных.

            В вебе существует масса способов сделать это, но все они на основе текста. Напомню тезис из моей прошлой статьи: у текстовых протоколов (не только у JSON) есть фундаментальная уязвимость: это «внутриполосная» сигнализация буфера, то есть чтобы выяснить, где заканчиваются данные, нужно прочитать их все в поиске конкретной последовательности символов. Эти последовательности могут быть законной частью данных, то есть вам нужен механизм экранирования. А потом, поскольку эти протоколы предполагаются как человекочитаемые или хотя бы нердочитаемые, часто возникают странные пограничные случаи с обработкой пробелов или канонизированным Юникодом, что приводит к эксплоитам, вроде атак с разделением заголовка HTTP.

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


            Примитивный декомпилятор

            Если честно, в последние годы веб медленно отказывается от текстовых протоколов. HTTP/2 бинарный. И разрекламированный “WebAssembly” — это бинарный способ выражения кода, хотя он на самом деле не решает проблем, о которых мы говорили. Но тем не менее.

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

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

            enum SortBy {
              Featured,
              Relevance,
              PriceLowToHigh,
              PriceHighToLow,
              Reviews
            }
            
            @PermazenType
            class AmazonSearch(
              val query: String, 
              val sortBy: SortBy?
            ) : LinkPacket

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

            Эта структура данных помечена как @PermazenType. Что это значит?

            Если мы серьёзно относимся к коду с префиксированной длиной, строгой типизацией защитой от инъекций по всему стеку, то придётся что-то сделать с SQL. Язык структурированных запросов — приятный и хорошо понятный способ выразить сложные запросы к разнообразным исключительно мощным движкам БД, поэтому его жалко. Но SQL — это текстовый API. Хотя SQL-инъекции — один из самых простых типов эксплоитов, которые легко понять и исправить, но это также один из самых распространённых багов на веб-сайтах. Ничего удивительного: если использовать SQL на веб-сервере самым очевидным образом, то он будет нормально работать, но незаметно сделает сервер уязвимым для взлома. Параметризованные запросы помогают, но это сбоку привинченное решение, которое не в каждой ситуации можно использовать. Технологический стек создаёт для всех нас хорошо замаскированный медвежий капкан, и наша цель — минимизировать соотношение рисков и функциональности.

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

            Движки NoSQL ненамного лучше: они обычно исправляют одну или две из этих проблем, но за счёт отбрасывания решений SQL для всего остального. В итоге вы часто застреваете с решением, которое иное, но не обязательно лучшее. В результате крупнейшие компании вроде Google и Bloomberg тратят много времени, пытаясь найти способ масштабировать базы данных SQL (F1, ComDB2).

            Permazen — это новый подход к хранению данных, который восхищает меня в данный момент. Цитата с их сайта:

            Permazen — совершенно новый подход к стойкому программированию. Вместо того, чтобы начинать разработку со стороны технологии хранения, он начинает со стороны языка программирования, задавая простой вопрос: «Какие проблемы присущи стойкому программированию, независимо от языка программирования или технологии СУБД, и как их можно решить на уровне языка наиболее простым, самым корректным и самым естественным с точки зрения языка способом?»

            Permazen — это библиотека Java. Однако её архитектуру и техники можно использовать на любой платформе или языке. Ей нужно сортированное хранилище «ключ-значение» такого типа, какой могут предоставить многие облачные провайдеры (она также может использовать RDBMS в качестве хранилища K/V), но всё остальное делается внутри библиотеки. У неё нет таблиц или SQL. Вместо этого она:

            • Использует операторы хостового языка для осуществления объединений и пересечений (соединений).
            • Схемы напрямую определяются классами, не требуется устанавливать объектно-реляционное отображение.
            • Может производить пошаговую эволюцию схемы «точно в срок», устраняя необходимость в заморозке таблицы для изменения представления данных в хранилище.
            • Транзакции установлены однозначно, а копирование данных из транзакции и назад чётко контролируется разработчиком.
            • Изменяет мониторинг, так что вы можете получать обратные вызовы, когда изменяются лежащие в основе данные, в том числе между процессами (если хранилище K/V это поддерживает, а часто так и есть).
            • Есть интерфейс командной строки, позволяющий осуществлять запросы и работать с хранилищем данных (например, инициировать миграцию данных, если вас не устраивает миграция по расписанию), и GUI.

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

            Одна из интересных особенностей Permazen — то, что вы можете использовать «снимки транзакций» для сериализации и десериализации графа объекта. Этот снимок включает в себя даже индексы, то есть вы можете транслировать данные в локальное хранилище, если памяти мало, и уже над ним выполнять запросы по индексу. Теперь должно стать понятным, как эта библиотека унифицирует хранение данных с поддержкой офлайновой синхронизации. Разрешение конфликтов можно осуществлять транзакционно, поскольку все операции Permazen способны выполняться внутри сериализуемых транзакций (если хотите бесконфликтную работу в стиле Google Docs, которая требует библиотеки операционного преобразования).

            Необязательно в NewWeb использовать именно такой подход. Вы можете выбрать что-то немного более традиционное вроде protobuf, но тогда придётся использовать специальный IDL, что одинаково неудобно во всех языках, а также помечать тегами поля. Вы могли бы использовать CBOR или ASN1. В моём текущем проекте Corda мы создали собственный движок для сериализации объектов, построенный на AMQP/1.0. В нём по умолчанию сообщения описывают сами себя, так что для каждого конкретного бинарного пакета вы всегда получаете схему — и поэтому там доступна функция просмотра исходников, как в XML или JSON. AMQP предпочтителен, потому что это открытый стандарт, а базовая система типов довольно хороша (например, он узнаёт даты и аннотации).

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

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

            Простота и поэтапное обучение


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

            Требование: простота в освоении

            Уверен, что значительная часть успеха веба объясняется тем, что он по сути не типизирован. Всё здесь — просто строки. Плохо для безопасности, производительности и удобства обслуживания, но очень хорошо для обучения.

            Один из способов обращения с такой структурой в мире веба — постепенная типизация в версиях JavaScript. Это хорошая и ценная исследовательская работа, но такие диалекты не нашли широкого применения, и большинство новых языков хотя бы отчасти строго типизированы (Rust, Swift, Go, Kotlin, Ceylon, Idris…).

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

            Конечно, такой подход обеспечивает меньшую безопасность и удобство обслуживания, чем если заставить разработчика самого заранее продумывать типы, но даже относительно слабые эвристически выставленные типы, которые часто приводят к ошибкам во время выполнения, всё равно защищают против большого количества эксплоитов. Среды выполнения вроде JVM и V8 уже собирают информацию о типах такого рода. В Java 9 есть новый API, позволяющий контролировать виртуальную машину на низком уровне (JVMCI), он занимается таким профилированием — сейчас было бы гораздо проще экспериментировать с такого рода инструментами.

            Языки и виртуальные машины


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

            За прошедшие годы предпринималось много попыток ввести в веб другие языки, кроме JavaScript, но все они оказались неудачными, не получив консенсуса со стороны разработчиков браузеров (в основном, со стороны Mozilla). На самом деле, в этом отношении веб возвращается в прошлое — вы могли запускать Java, ActionScript, VBScript и другие языки, но производители браузеров систематически удаляли с платформы все не-JavaScript плагины. Это какой-то позор. Безусловно, можно же было сохранить конкуренцию. Грустный приговор веб-платформе, что WebAssembly — единственная попытка добавить новый язык, и этим языком является C… на котором, я надеюсь, вы не захотите писать веб-приложения! Достаточно нам XSS, чтобы добавлять сверху ещё уязвимости типа двойного освобождения одной и той же памяти.

            Всегда проще согласиться с проблемой, чем с решением, но ничего страшного — пришло время выдвинуть (более) противоречивый тезис. Ядром моего личного дизайна NewWeb стала бы JVM. Это не удивит тех, кто меня знает. Почему JVM?

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

              Да, это значит, что я хочу оставить возможность использовать JavaScript (на высокой скорости), помимо Ruby, Python, Haskell, и да  — C, C++ и Rust тоже останутся в игре. Всё это возможно благодаря двум действительно классным проектам, которые называются Graal и Truffle, о которых я подробно рассказывал. Эти проекты позволяют JVM запускать даже код на неожиданных языках (таких как Rust) в виртуализированной среде, быстро и и интероперабельно. Мне неизвестна никакая другая виртуальная машина, которая органично смешивает вместе так много языков и делает это с такой высокой производительностью.
            • Песочница OpenJDK годами подвергалась упорным атакам, и разработчики браузеров усвоили ряд болезненных уроков. Последний 0-day эксплоит датируется 2015-м годом, а предыдущий был в 2013-м. Всего два 0-day эксплоита в песочнице за пять лет — неплохо, на мой взгляд, особенно с учётом того, что после каждого из них были усвоены уроки и со временем сделаны фундаментальные улучшения в безопасности. Ни у какой песочницы нет идеальной репутации, так что в реальности всё сводится к личным предпочтениям — какой уровень безопасности считать достаточным?
            • Существует огромное количество высококачественных библиотек, которые складывают ключевые фрагменты головоломки, такие как Permazen и JavaFX.
            • Так получилось, что я достаточно хорошо знаю JVM и мне нравится Kotlin, который подходит для бэкенда JVM.

            Я понимаю, что многие не согласятся с моим выбором. Без проблем — те же самые идеи архитектуры можно реализовать на базе Python или V8, или Go, или Haskell, или чего угодно другого, в чём вы плаваете. Лучше выбрать что-нибудь с открытыми спецификациями и наличием конкурирующих реализаций (как у JVM).

            Политика Oracle меня не беспокоит, потому что у Java открытые исходники. Среди высококачественных и высокопроизводительных open source рантаймов небольшой выбор. Существующие проекты созданы крупными корпорациями, которые замарали себя спорными решениями в прошлом. На различных этапах своего развития веб находился под влиянием или прямым контролем Microsoft, Google, Mozilla и Apple. Все они совершали поступки, которые я считаю предосудительными: это свойственно крупным компаниям. Вам не захочется вечно соглашаться с их поступками. Oracle вряд ли выиграет конкурс популярности, но преимущество открытого кода в том, что ей и не придётся в нём участвовать.

            Конкретно из Google Chrome я бы кое-что позаимствовал. Мой браузер приложений должен поддерживать эквивалент WebGL (т.е. eGL), и проект Chromium ANGLE подходит для этой цели. Браузер приложений должен незаметно автоматически обновляться, как это делает Chrome, а движки автоматических обновлений Google тоже распространяются под свободной лицензией. В конце концов, хотя формат Pack200 сильно сжимает код, не повредило бы использование качественных кодеков вроде Zopfli.

            RPC


            Бинарных структур данных недостаточно. Нужны ещё и бинарные протоколы. Стандартный способ связать клиента с сервером является RPC.

            В настоящее время один из самых крутых британских стартапов — Improbable. Недавно разработчики опубликовали отличный пост в блоге о том, как они перешли с REST+JSON на gRPC+protobuf от браузера к серверу. Improbable описывает результат как «нирвану безопасной типизации». Браузеры справляются с этим не так легко, как с HTTP+XML или JSON, но с использованием нужных библиотек JavaScript вы можете прикрутить сверху нужный стек. Это хорошая мысль. Если вернуться в реальный мир, где мы все пишем веб-приложения, однозначно следует рассмотреть такой вариант.

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

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

            Опять же, в проекте Corda мы проектируем стек RPC именно с такими свойствами. Мы ещё не выпустили его в виде отдельной библиотеки, но надеемся в будущем сделать это.
            HTTP/2 — одна из самых последних и наиболее проработанных частей веба, это достаточно приличный фреймовый транспортный протокол. Но он унаследовал слешком много хлама от HTTP. Только представьте, какие хаки становятся возможными, если отказаться от методов HTTP, которые всё равно никогда не используются. Странный подход HTTP к описанию состояния не нужен. HTTP сам по себе не меняет состояние в процессе исполнения, а вот приложениям нужны сессии с хранением состояния, так что разработчикам приложений приходится добавлять поверх протокола собственную реализацию, используя мешанину легко воруемых кукисов, токенов и так далее. Это ведёт к проблемам вроде атак фиксации сессии.

            Лучше более чётко разделить всё по слоям:

            • Шифрование, аутентификация и управление сессиями. TLS неплохо справляется. Можно просто использовать его.
            • Транспорт и контроль потока. Этим занимается HTTP/2, но протоколы обмена сообщениями вроде AMQP тоже справляются с задачей, и без груза наследия прошлого.
            • RPC

            Очевидно, стек RPC интегрирован с фреймворком структуры данных, так что все передачи данных типизированы. Разработчикам никогда не понадобится выполнять парсинг вручную. Именование в RPC — это простое сравнение строк. Следовательно, отсутствуют уязвимости с выходом за пределы текущего каталога (path traversal).

            Аутентификация пользователей и сессии


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

            Аутентификация пользователя — одна из самых сложных вещей, которые трудно правильно реализовать в веб-приложении. Я ранее высказал несколько мыслей по этому поводу, так что не буду повторяться. Достаточно сказать, что привязку сессии к почтовому адресу лучше выполнять на стороне базовой платформы, а не постоянно изобретать велосипед на уровне приложений. Сертификата TLS на клиентской стороне вполне достаточно, чтобы реализовать базовую систему единого входа, где поток операций вроде «отправить письмо и подписать сертификат в случае получения» настолько дёшев, что провайдеры бесплатных сертификатов в стиле Let's Encrypt станут вполне реальными.

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

            Заключение


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

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

            Обсудим эти вопросы в следующей статье.
            Original source: habrahabr.ru (comments, light).

            https://habrahabr.ru/post/339112/


            [Перевод] Симуляция физического мира

            Понедельник, 02 Октября 2017 г. 08:58 + в цитатник


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

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

            1. Состояние всего в момент начала симуляции.
            2. Как это состояние меняется из одного момента времени в другой?
            Читать дальше ->

            https://habrahabr.ru/post/338992/


            В абзаце всё должно быть прекрасно

            Понедельник, 02 Октября 2017 г. 08:19 + в цитатник

            Метки:  

            Профилирование PL/SQL кода при помощи IDE PL/SQL Developer

            Понедельник, 02 Октября 2017 г. 08:01 + в цитатник
            ympukhov сегодня в 08:01 Разработка

            Профилирование PL/SQL кода при помощи IDE PL/SQL Developer

              Проблематика и назначение:


              Периодически Oracle разработчики сталкиваются с проблемой производительности PL/SQL кода. Возникают проблемы с тем, чтобы найти место pl/sql кода, в котором возникают проблемы.

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

              Методы решения проблемы:


              В решение проблем с производительность в БД Oracle нам помогут:

              • PL/SQL Developer — Популярное IDE для Oracle разработчиков.
              • DBMS_PROFILE — Oracle пакет для профилирования (не будет рассматриваться в рамках данной статьи, т.к. информации достаточно на просторах интернета).


              Метод(процедура) для профилирования:


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

              Создадим метод для профилирования:
              create or replace procedure check_cycle_performance(p_cycle_size in number) is
                  c_method_error         constant number := -20000;
                  c_method_error_message constant varchar2(4000) := 'Cycle size should be > 0';
                  l_power_value number;
                  l_dual_value  number;
              begin
                  if p_cycle_size > 0 then
                      --Cycle with power calculation
                      for i in 1 .. p_cycle_size
                      loop
                          l_power_value := power(i, 2);
                      end loop;
                      --Cycle with switching context(sql-pl/sql)
                      for i in 1 .. p_cycle_size
                      loop
                          select i into l_dual_value from dual;
                      end loop;
                  else
                      raise_application_error(c_method_error, c_method_error_message);
                  end if;
              end check_cycle_performance;

              Профилирование через IDE PL/SQL Developer:


              В pl/sql Developer запускаем Test Window:

              Рисунок 1 — Запуск Test Window

              В тестовом окне наберём код для запуска метода check_cycle_performance, заполним входную переменную l_cycle_size и нажмем кнопку для запуска профилирования:

              Рисунок 2 — Запуск профилирования в PL/SQL Developer

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

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

              Рисунок 3 — Окно профайлера в PL/SQL.

              Из рисунка 3 видно, что основная проблема по производительности состоит в строке 16.

              Не трудно понять, что основная проблема производительности кроется в переключениях контекста SQL — PL/SQL.

              При этом возведение в степень: строка 11, занимает гораздо меньше времени.

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

              https://habrahabr.ru/post/339108/


              Метки:  

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

              Понедельник, 02 Октября 2017 г. 07:05 + в цитатник
              zzeng сегодня в 07:05 Разработка

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



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

                В развитие темы (1, 2, 3, 4, 5, 6, 7).

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

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

                А вот GiST умеет использовать для индексации временнЫх интервалов (tsrange) R-деревья.

                create table reservations(during tsrange);
                insert into reservations(during) values
                ('[2016-12-30, 2017-01-09)'),
                ('[2017-02-23, 2017-02-27)'),
                ('[2017-04-29, 2017-05-02)');
                create index on reservations using gist(during);
                
                select * from reservations where during && '[2017-01-01, 2017-04-01)';

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

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

                А можно ли интервал превратить в точку? Считая, например, его начало за X, а конец за Y. Формально можно, в конце концов, кто может запретить нам использовать два числа в качестве двумерной точки? Но в таких данных возникнет внутренняя зависимость. А семантика в данных приведет к семантике в поисковых запросах и интерпретации результатов.

                Проще всего разобраться в ситуации, поглядев на неё глазами.
                Вот 100 случайных интервалов размером от 0 до 10 000 с началом интервала от 0 до 100 000


                Фиг.1

                Поисковый запрос — [41 000… 47 000], нас интересуют все интервалы, пересекающиеся с заданным диапазоном.

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

                Итак, по зонам:

                1. сюда попадают интервалы, которые находятся строго внутри поискового запроса
                2. здесь всё, что началось и закончилось до нужного нам интервала
                3. эти интервалы начались до, а закончились во время поискового запроса
                4. здесь те интервалы, которые целиком покрывают поисковый
                5. эти интервалы начались во время, а закончились после запроса
                6. здесь всё, что началось и закончилось после него

                Таким образом, для поиска всех пересечений запрос надо расширить до [0...47 000, 41 000… 100 000], т.е. он должен включать зоны 1,3,4,5.

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

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

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

                Впрочем, это уже относится не к R-дереву, а к любому пространственному индексу. В том числе и Z-curve (построенному на Z-order B-дереву), использованному нами ранее. Для Z-curve не имеет значение вырождение данных, ведь это просто числа с их естественным порядком.

                Помимо прочего, Z-curve еще и компактнее R-дерева. Поэтому попробуем прояснить его перспективы в обозначенной области.

                Вот например, мы приняли, что X-координата — это начало сегмента, а Y-его конец. А что если наоборот? R-дереву должно быть всё равно, для Z-curve тоже мало что изменится. Обход страниц будет организован по-другому, но число прочитанных страниц в среднем окажется тем же.

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

                Возьмем 1000 случайных интервалов и разобьем их на 10 страниц в зависимости от Z-значения. Т.е. отсортируем и поделим по 100 штук, после посмотрим что у нас получилось. Приготовим 2 набора — X,Y и max(X)-X, Y


                Фиг.2 Обычная Z-curve


                Фиг.3 Зеркально отображенные данные.

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

                Почему так получилось? В данном случае причина лежит на поверхности. Для 2-мерного прямоугольника Z-value левого нижнего угла <= чем для правого верхнего. Поэтому идеальный способ поаккуратнее порезать на страницы почти линейные данные — расположить их вдоль прямой X=Y.

                А если индексировать не начало-конец диапазона, а его центр-длину? В этом случае данные вытянутся вдоль оси X, как если бы мы повернули Фиг.2 по часовой стрелке на 45 градусов. Проблема в том, что при этом и поисковая область тоже повернется на 45 градусов и по ней уже нельзя будет искать единым запросом.

                Можно ли так индексировать интервалы с более чем одной размерностью? Конечно. 2-мерный прямоугольник превращается в 4-мерную точку. Главное не забывать, в какую из координат что мы положили.

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

                Численный эксперимент


                Попробуем проверить работоспособность Z-curve в условиях, приближенных к “макаронному монстру”. Модель данных такова:

                • 8-мерный индекс, работоспособность и производительность которого мы уже проверяли
                • как обычно, 100 млн точек
                • объекты — 3-х мерные параллелепипеды — занимают 6 размерностей
                • оставшиеся 2 размерности мы отдадим под интервал времени
                • параллелепипедов 100 штук — они образуют по X&Y решетку 10Х10
                • каждый параллелепипед живёт одну единицу времени
                • за каждую единицу времени параллелепипед вырастает на 10 единиц по Z, начиная с высоты 0


                Фиг.4 срез данных в момент времени T=1000

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

                Создаем 8-мерную таблицу, заливаем данные и индексируем

                create table test_points_8d (p integer[8]);
                COPY test_points_8d from '/home/.../data.csv';
                create index zcurve_test_points_8d on test_points_8d (zcurve_num_from_8coords (p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8]));

                Порядок ключа: xmax,xmin,ymax,ymin,zmax,zmin,tmax,tmin
                файл данных (data.csv):

                {210000,200000,210000,200000,0,0,0,0}                                           
                {210000,200000,210000,200000,10,0,1,1}                                           
                {210000,200000,210000,200000,20,0,2,2}                                           
                {210000,200000,210000,200000,30,0,3,3}                                           
                {210000,200000,210000,200000,40,0,4,4}                                           
                {210000,200000,210000,200000,50,0,5,5}                                           
                {210000,200000,210000,200000,60,0,6,6}                                           
                {210000,200000,210000,200000,70,0,7,7}                                           
                {210000,200000,210000,200000,80,0,8,8}                                           
                {210000,200000,210000,200000,90,0,9,9}
                ...

                Тестовый запрос [200 000...300 000; 200 000 … 300 000; 100...1000; 10...11]:

                select c, t_row from (select c, (select p from test_points_8d t where c = t.ctid) t_row 
                from zcurve_8d_lookup_tidonly('zcurve_test_points_8d', 
                200000,0,200000,0,100,0,10,0,
                1000000,300000,1000000,300000,1000000,1000,1000000,11
                ) as c) x;

                Ответ:

                       c     |                   t_row                   
                -------------+-------------------------------------------
                 (0,11)      | {210000,200000,210000,200000,100,0,10,10}
                 (0,12)      | {210000,200000,210000,200000,110,0,11,11}
                 (103092,87) | {260000,250000,210000,200000,100,0,10,10}
                 (103092,88) | {260000,250000,210000,200000,110,0,11,11}
                 (10309,38)  | {210000,200000,260000,250000,100,0,10,10}
                 (10309,39)  | {210000,200000,260000,250000,110,0,11,11}
                 (113402,17) | {260000,250000,260000,250000,100,0,10,10}
                 (113402,18) | {260000,250000,260000,250000,110,0,11,11}
                 (206185,66) | {310000,300000,210000,200000,100,0,10,10}
                 (206185,67) | {310000,300000,210000,200000,110,0,11,11}
                 (216494,93) | {310000,300000,260000,250000,100,0,10,10}
                 (216494,94) | {310000,300000,260000,250000,110,0,11,11}
                 (20618,65)  | {210000,200000,310000,300000,100,0,10,10}
                 (20618,66)  | {210000,200000,310000,300000,110,0,11,11}
                 (123711,44) | {260000,250000,310000,300000,100,0,10,10}
                 (123711,45) | {260000,250000,310000,300000,110,0,11,11}
                 (226804,23) | {310000,300000,310000,300000,100,0,10,10}
                 (226804,24) | {310000,300000,310000,300000,110,0,11,11}
                (18 rows)

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

                На свеже-поднятом сервере тот же запрос через EXPLAIN (ANALYZE,BUFFERS)
                показывает,: что была прочитана 501 страница.

                Ок, пошевелим индекс. А что если посмотреть тот же запрос на индексе с порядком ключа — xmin,ymin,zmin,xmax,ymax,zmax,tmin,tmax. Запуск показывает 531 чтение. Многовато.

                Хорошо, устраним геометрический перекос, пусть теперь колонны растут не на 10, а на 1 единицу за такт. Запрос (ключ: xmax,xmin,ymax,ymin,zmax,zmin,tmax,tmin)

                EXPLAIN (ANALYZE,BUFFERS) select c, t_row from (select c, (select p from test_points_8d t where c = t.ctid) t_row 
                from zcurve_8d_lookup_tidonly('zcurve_test_points_8d', 
                200000,0,200000,0,0,0,10,0,
                1000000,300000,1000000,300000,1000000,1000,1000000,11) as c) x;

                говорит, что было прочитано 156 страниц!

                Теперь немного статистики, посмотрим среднее число чтений/попаданий в кэш для разных типов ключей в серии из 10 000 случайных запросов
                размером 100 000Х100 000Х100 000Х10

                При порядке ключа —
                (xmin,1 000 000-xmax, ymin,1 000 000-ymax,zmin,1 000 000-zmax,tmin,1 000 000-tmax)
                Среднее число чтений — 21.8217, попаданий в кэш — 2437.51.
                При этом среднее число объектов в выдаче — 17.81

                При порядке ключа — (xmax,xmin,ymax,ymin,zmax,zmin,tmax,tmin)
                Среднее число чтений — 14.2434, попаданий в кэш — 1057.19.
                При этом среднее число объектов в выдаче — 17.81

                При порядке ключа — (xmin,xmax,ymin,ymax,zmin,zmax,tmin,tmax)
                Среднее число чтений — 14.0774, попаданий в кэш — 1053.22.
                При этом среднее число объектов в выдаче — 17.81

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

                И напоследок посмотрим глазами, просто из любопытства, как алгоритм Z-curve справляется с 8-мерным пространством.
                Ниже представлены проекции разбора запроса в экстенте —
                [200 000...300 000; 200 000 … 300 000; 0...700 001; 700 000...700 001].
                Всего 18 результатов, 1687 подзапросов. Показаны порождённые подзапросы, зелёные крестики — чтения в B-дереве, синие крестики — найденные результаты.
                Под каждым крестиком может скрываться несколько отметок. Близкорасположенные отметки сливаются, например время 700 000 и 700 001.


                Фиг.5 X-ось


                Фиг.6 Y-ось


                Фиг.7 Z-ось


                Фиг.8 Время
                Original source: habrahabr.ru (comments, light).

                https://habrahabr.ru/post/339060/


                Метки:  

                Смарт контракты Ethereum: что делать при ошибке в смартконтракте или техники миграции

                Понедельник, 02 Октября 2017 г. 02:02 + в цитатник
                isvirin сегодня в 02:02 Разработка

                Смарт контракты Ethereum: что делать при ошибке в смартконтракте или техники миграции

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



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

                  Миграция с ERC20-совместимого контракта


                  Начнем рассмотрение с самого простого и распространенного случая, когда исходный контракт, уже загруженный в блокчейн, не содержит каких-либо специальных механизмов для того, чтобы помочь нам с миграцией, т.е. по сути мы имеем обычный ERC20-совместимый контракт. Единственное, что мы полезного можем взять из исходного контракта, это балансы всех держателей токенов и общее количество выпущенных токенов для проверки, что мы никого не забыли при миграции.
                  contract ERC20base {
                      uint public totalSupply;
                      function balanceOf(address _who) public constant returns(uint);
                  }

                  К сожалению, интерфейс ERC20-совместимого контракта не позволяет узнать список всех держателей токенов, поэтому при миграции нам придется выяснить полный список держателей из какого-то другого источника, например, выгрузив его из etherscan.io. Пример контракта, на который осуществляется миграция, приведен в следующем листинге:
                  contract NewContract {
                      uint public totalSupply;
                      mapping (address => uint) balanceOf;
                  
                      function NewContract(address _migrationSource, address [] _holders) public {
                          for(uint i=0; i<_holders.length; ++i) {
                              uint balance = ERC20base(_migrationSource).balanceOf(_holders[i]);
                              balanceOf[_holders[i]] = balance;
                              totalSupply += balance;
                          }
                          require(totalSupply == ERC20base(_migrationSource).totalSupply());
                      }
                  }

                  Конструктор контракта получает в качестве параметров адрес исходного ERC20-совместимого контракта, а также список держателей токенов, выгруженный вручную через etherscan.io. Следует обратить внимание, что в последней сроке конструктора проверяем, что количество токенов после миграции не изменилось, а следовательно, ни один держатель токенов не забыт. Необходимо учитывать, что такая миграция возможна лишь в том случае, если количество держателей токенов невелико и цикл по ним всем возможен в рамках одной транзакции (лимита газа, установленного в Ethereum для одной транзакции). Если все же количество держателей токенов не позволяет мигрировать за одну транзакцию, то эту функциональность придется вынести в отдельную функцию, которую можно будет вызвать необходимое количество раз, а контракт в этом случае будет выглядеть так:
                  contract NewContract {
                      uint public totalSupply;
                      mapping (address => uint) balanceOf;
                      address public migrationSource;
                      address public owner;
                  
                      function NewContract(address _migrationSource) public {
                          migrationSource = _migrationSource;
                          owner = msg.sender;
                      }
                  
                      function migrate(address [] _holders) public
                          require(msg.sender == owner);
                          for(uint i=0; i<_holders.length; ++i) {
                              uint balance = ERC20base(_migrationSource).balanceOf(_holders[i]);
                              balanceOf[_holders[i]] = balance;
                              totalSupply += balance;
                          }
                      }
                  }

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

                  Недостатки данного решения заключаются в следующем:
                  1. На старом смартконтракте токены останутся у их владельцев, а на новом просто продублируются их балансы. Насколько это плохо, зависит от того, как составлен ваш Tokens sale agreement или любой другой документ, описывающий объем ваших обязательств перед держателями токенов вашего проекта, и не удвоятся ли ваши обязательства перед ними после создания «дубликата».
                  2. На миграцию вы расходуете собственный газ, но это, вобщем-то, логично, т.к. делать миграцию придумали вы и в любом случае доставляете неудобства вашим пользователям, хоть оно и ограничивается тем, что им надо переписать в своих кошельках адрес смартконтракта со старого на новый.
                  3. В процессе осуществления миграции, если она конечно не умещается в одну транзакцию, могут произойти трансферы токенов между адресами их владельцев, а следовательно, могут добавиться новые держатели и может измениться баланс существующих.

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

                  Миграция между этапами краудсейла


                  В мире современных ICO довольно распространена практика, когда для различных этапов сбора средств делают отдельные контракты, мигрируя выданные токены на новые контракты нового этапа. Это, конечно, можно делать так, как мы рассмотрели выше, но, если мы точно знаем, что нам придется мигрировать, то почему бы сразу не упростить себе жизнь? Для этого достаточно ввести публичное поле
                      address [] public holders;

                  В это поле необходимо добавлять всех держателей токенов. Если контракт уже на ранних этапах сбора разрешает делать держателям перемещения токенов, т.е. реализует transfer(), необходимо позаботиться о том, чтобы массив обновлялся, например, как-то так
                      mapping (address => bool) public isHolder;
                      address [] public holders;
                      ….
                      if (isHolder[_who] != true) {
                          holders[holders.length++] = _who;
                          isHolder[_who] = true;
                      }

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

                  Миграция со сжиганием исходных токенов


                  Все-таки раз мы говорим про миграцию, а не про дублирование токенов в новом смартконтракте, то необходимо озаботиться вопросом уничтожения (сжигания) токенов на исходном контракте при создании их копии на новом. Очевидно, что недопустимо оставлять в смартконтракте «дыру», которая позволила бы кому угодно, будь он даже владельцем смартконтракта, сжигать токены других держателей. Такой смартконтракт будет просто скамовым! Осуществлять такого рода манипуляции над своими токенами может только их держатель, а следовательно, и осуществлять миграцию должен сам держатель. Владелец смартконтракта в данном случае может только запустить эту миграцию (перевести смартконтракт в состояние миграции). Пример реализации такой миграции я встретил в проекте GOLEM (ссылка на их гитхаб в конце поста), затем реализовал ее в нескольких своих проектах.
                  В исходном контракте определим интерфейс MigrationAgent, который впоследствии должен быть реализован в контракте, на который осуществляется миграция.
                  contract MigrationAgent {
                      function migrateFrom(address _from, uint256 _value);
                  }

                  В исходном контракте токена должна быть реализована следующая дополнительная функциональность:
                  contract TokenMigration is Token {
                      address public migrationAgent;
                  
                      // Migrate tokens to the new token contract
                      function migrate() external {
                          require(migrationAgent != 0);
                          uint value = balanceOf[msg.sender];
                          balanceOf[msg.sender] -= value;
                          totalSupply -= value;
                          MigrationAgent(migrationAgent).migrateFrom(msg.sender, value);
                      }
                  
                      function setMigrationAgent(address _agent) external {
                          require(msg.sender == owner && migrationAgent == 0);
                          migrationAgent = _agent;
                      }
                  }

                  Таким образом, владелец исходного смартконтракта должен вызвать setMigrationAgent(), передав ему в качестве параметра адрес смартконтракта, на который осуществляется миграция. После этого все держатели токенов исходного смартконтракта должны вызвать функцию migrate(), которая осуществит уничтожение их токенов в исходном смартконтракте и добавление в новом (путем вызова функции migrateFrom() нового контракта). Ну а новый контракт должен собственно содержать реализацию интерфейса MigrationAgent, например, так:
                  contract NewContact is MigrationAgent {
                      uint256 public totalSupply;
                      mapping (address => uint256) public balanceOf;
                      address public migrationHost;
                   
                      function NewContract(address _migrationHost) {
                          migrationHost = _migrationHost;
                      }
                  
                      function migrateFrom(address _from, uint256 _value) public {
                          require(migrationHost == msg.sender);
                          require(balanceOf[_from] + _value > balanceOf[_from]); // overflow?
                          balanceOf[_from] += _value;
                          totalSupply += _value;
                      }
                  }

                  В этом решении прекрасно все! Кроме того, что пользователю надо вызвать функцию migrate(). Ситуация существенно осложняется тем, что вызов функций поддерживают лишь единицы кошельков и они, как правило, не являются самыми удобными. Поэтому, поверьте, если среди держателей ваших токенов есть не только криптогики, но и простые смертные люди, они вас просто проклянут, когда вы будете объяснять им, что надо установить какой-нибудь Mist, а затем вызвать какую-то функцию (слава Богу, хоть без параметров). Как же быть?
                  А можно поступить очень просто! Ведь любой пользователь криптовалюты, даже самый-самый начинающий, умеет хорошо делать одно – отправлять крипту со своего адреса на какой-то другой. Так пусть таким адресом будет адрес нашего смартконтракта, а его fallback функция в режиме «миграции» будет просто вызвать migrate(). Таким образом, держателю токенов для осуществления миграции будет достаточно перевести хотя бы 1 wei на адрес смартконтракта, находящегося в режиме «миграции», чтобы произошло чудо!
                  function () payable {
                      if (state = State.Migration) {
                          migrate();
                      } else { … }
                  }


                  Заключение


                  Рассмотренные решения концептуально покрывают все возможные способы осуществления миграции токенов, хотя возможны вариации в конкретных реализациях. Отдельного внимания достоин подход «перегонного сосуда» (ссылка в конце поста). Независимо от используемого вами подхода к миграции, помните, что смартконтракт – это не просто программа, выполняемая внутри виртуальной машины Ethereum, а это некий отчужденный независимый договор, а любая миграция предполагает, что вы меняете условия этого договора. Уверены ли вы, что держатели токенов хотят поменять условия договора, который заключили, приобретая токены? Это на самом деле хороший вопрос. И существует очень правильная практика, «спрашивать» держателей токенов о том, хотят ли они «переехать» на новый контракт. Именно осуществление миграции через голосование я реализовал в смартконтракте своего проекта PROVER, с текстом контракта можно познакомиться на моем GitHub-е. Ну и конечно приглашаю присоединяться к ICO моих проектов PROVER и OpenLongevity.

                  Надеюсь, что все это кому-то полезно и нужно :).

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


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

                  https://habrahabr.ru/post/339102/


                  Метки:  

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

                  Понедельник, 02 Октября 2017 г. 01:47 + в цитатник
                  NickPasko сегодня в 01:47 Управление

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

                    Предисловие


                    Не секрет, что правильно выстроенные бизнес-процессы нужны всем.
                    Отдельные граждане, отделы и целые компании с холдингами бегают кругами и воют о необходимости правильного обустройства всех и всяческих процессов. Всё должно быть посчитано, измерено, запланировано и выполнено в срок, в строгих рамках бюджета. Метрики и KPI, предсказуемость и прозрачность.
                    Везде должен быть “внедрён” Agile. Все должны мыслить категориями Lean. Все должны думать о Business Value.
                    И, будучи разбуженными ночью, — мгновенно ответить на вопрос: “каков LTV нашего пользователя?”

                    Отличный, рациональный подход.

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

                    Отличный, рациональный подход.

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

                    Итак, знакомьтесь с нашими героями


                    Компания Anytime Rational Inc.


                    До мозга костей рациональна, следует обоим принципам. Вся по Agile, везде Scrum, каждый разработчик точно знает, какой Business Value имеет каждая его задача. Все озабочены повышением эффективности, общим индексом счастья и прибылью организации.
                    Не компания, а сказка. Любой владелец IT-бизнеса, глядя на неё, пускает слюнки. Сплошная конфетка.
                    Ведь таких отличных компаний в реальном мире просто не существует.

                    Компания Somehow Someway Ltd

                    .
                    Ну, здесь, — традиционный бардак. Инженеры поминутно травят свои инженерные байки в курилках, любят инженерные задачи, и чихать хотели на User LIfetime Value. Время от времени изобретают велосипеды, хотя в целом держатся в тренде “повторного использования” сторонних компонент.
                    На словах в компании Scrum, и даже есть итерации. На деле же, — разработка ведётся, как бог на душу положит.
                    Словом, — чего уж там. Обычная инженерная компания.

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

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

                    Хронология проблемы


                    Day 1


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

                    В Somehow Someway перед инженером, — для простоты Петром Вторым, — встаёт точно такая же проблема.
                    На стендапе он привычно отбарабанивает: “сегодня продолжаю работать над таской SM-134, помощь не требуется”. Он не особо задумывается над смыслом своих слов. Ведь весь его мозг поглощён обдумыванием “этой херни, которая происходит в долбаном модуле, написанном криворукими даунами из Third Party Component Solutions”.
                    На очередном перекуре он издалека задаёт вопрос ведущему системщику Ярославу Мудрому из смежного отдела, и они, неспешно покуривая, минут 20 обсуждают подробности. Ярослав даёт пару советов, но в глубине души знает, что Пётру они не помогут. Потому что Пётр, конечно, классный парень и всё такое, — но дизассемблер Ярослав ему бы ни за что не доверил.

                    Day 2


                    Anytime Rational


                    Пётр Первый ковыряется со своей проблемой уже второй день. Он понимает, что микроспринт, видимо, будет профукан, и на утреннем стендапе говорит, что ему необходима помощь.
                    “Кто тебе для этого нужен?” — участливо спрашивает скрам мастер.
                    “В идеале, — Ярослав Мудрый из смежного отдела. Он крутой системщик, и это как раз его профиль” — отвечает Пётр Первый, уже точно зная ответ на этот запрос.
                    “Оооо, Ярослааав..” — огорчённо тянет скрам мастер, — “ты же знаешь, он очень занят серьёзнейшими задачами, которые очень важны для нашей компании.”
                    “У тебя же есть ещё один день”, — встревает владелец продукта, — “Давай посмотрим, что получится по результатам микроспринта, и будем принимать решение.”

                    Somehow Someway


                    Пётр Второй в это время, безуспешно перепробовав всё, что посоветовал ему Ярослав, задумчиво дымит в курилке.
                    “Чего такой смурной?” — благодушно интересуется зашедший на дымок тимлид Иван Грозный.
                    “Да так… одна херовинка тут..” — мнётся Петр. Ивана Васильевича он уважает, но побаивается, и расписываться в своей неспособности решить задачу не очень-то спешит.
                    “Ну-ну”, — хитро усмехается Иван, — “небось, опять взялся за дело не по своей квалификации?”
                    Иван, посмеиваясь, удаляется, а посрамлённый Пётр идёт ковыряться дальше.

                    Day 3


                    Anytime Rational


                    “Микроспринт не принёс результатов”, — сообщает Петр Первый. “Мне не удалось докопаться до источника проблемы. Требуется либо привлечение Ярослава, либо дополнительное время на изучение.”
                    “Ты и так уже два дня..” — начинает закипать владелец продукта, но скрам мастер умело перехватывает управление потенциальным конфликтом.
                    “Как мы и договорились, был проведён микроспринт на изучение проблемы, и теперь нам необходимо принять решение. Мы либо выделяем дополнительное время на изучение, либо запрашиваем помощь у отдела системной разработки, либо эскалируем проблему и предоставляем принятие решения вышестоящему руководству.”
                    “А что мы будем эскалировать?” — буркает недовольный владелец продукта. “Какова стоимость решения проблемы? Мы же так ничего и не выяснили.”
                    “Хорошо, значит, у нас остаётся два варианта.” — примирительно улыбается скрам мастер. “Будем запрашивать помощь или продолжим разбираться сами?”
                    Все выжидательно смотрят на Петра.
                    Он нервно сглатывает, но, будучи верным сторонником идеалов Agile, честно и открыто сообщает, что ему нужна помощь.
                    “Отлично.” — говорит скрам мастер, делая пометку в Evernote. “Я узнаю у отдела системной разработки, когда они смогут нам с этим помочь.”
                    “Пётр, пока что переключайся на следующую по приоритету задачу. Так, это у нас… SM-135, если я не ошибаюсь.”

                    Someway Somewhat


                    Пётр Второй, привычно отбарабанив дежурную фразу, продолжает размышлять над поведением модуля, зафиксированным вчера вечером. Однако Иван прерывает его размышления.
                    “Пётр, а как там твоя проблемка? Уже решил?”
                    “Эмм… пока нет, сегодня ещё попробую пару подходов..” — глаза Петра избегают внимательного, с прищуром, взгляда Ивана.
                    “Ну-ну..” — без улыбки произносит Иван.

                    Day 5


                    Anytime Rational


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

                    Somewhat Somewhere


                    Петр Второй, поминутно матерясь, сидит за своим рабочим столом, неощутимо слушает в наушниках какой-то тяжеляк и пытается разобраться, “что же, мать его, происходит внутри этой грёбаной помойки!”
                    На одном экране открыт отладчик, на другом, — дизассемблированный код. Сосредоточенный взгляд Петра постепенно наполняется безнадёгой, и левый глаз уже начинает подёргиваться.
                    Он не замечает, что за его спиной вот уже десять минут задумчиво молчит Ярослав, — покуда тот, наконец, не похлопывает Петра по плечу.
                    “А? Что? Какого..” — срывает с головы наушники Пётр. “А, Ярослав… ты чего тут?”
                    “Да вот, думал тут над твоей проблемкой на досуге… кстати, смотри, тебе бы вот здесь JNE пробросить, — а то ты дальше не продвинешься.”
                    “Где? А, вот тут вот… и что это даст? Ааа, вона как..” — Пётр снова входит в поток. “А это тут что за хрень?”
                    “Кривая работа с регистрами. Давай вот так попробуем..” — подключается к нему Ярослав.

                    Day 10


                    Anytime Rational


                    “Итак, скорость нашей команды в этом спринте упала на 3 стори поинта. Учитывая, что фича SM-134 была нами в итоге выброшена из спринта, — это вполне ожидаемо. Кстати, Пётр, ты молодец, я не ожидал, что ты успеешь реализовать SM-135.” — скрам мастер привычно проводил ретроспективу, когда в комнату стремительно влетел Ярослав.
                    “Ребята, я буквально на минуту, извините. Микроспринт согласован, на три дня мы вам выделим Ефима. Он хороший системщик, вдвоём с Петром проблему наверняка успешно решите. Ну, всё, я побежал, извините ещё раз, что прервал ваше ретро.”
                    Пётр Первый растерянно хлопает глазами. Проблема? Ах, да, вон та, страшная и сложная… бррр…

                    Somewhere Someone


                    “Пётр, что там с твоей проблемой??” — грозно вопрошает Иван.
                    “Нормально всё, Иван Васильевич. Один небольшой глюк остался, — ну, и код потом вылизать. Дня за три точно управлюсь.” — спокойно отвечает Пётр Второй.
                    “Знаю я твои три дня..” — ворчит Иван. “Давай быстрее заканчивай, у меня уже руководство интересуется, почему мы эту фичу так сильно затягиваем. Скоро ведро вазелина надо будет заготавливать!”
                    “Да знаю я, Иван Васильевич. Затащим!” — улыбается Пётр.

                    Day 13


                    Anytime Rational


                    “По результатам микроспринта с Ефимом оказалось, что на решение проблемы потребуется ещё половина спринта. Или даже целый спринт.” — не вполне уверенно говорит Пётр Первый. Вдвоём с Ефимом они ковырялись над этой проблемой три полновесных дня, но уверенного решения так и не нашли. — “Есть несколько наметок..”
                    “Наметок, шнаметок!” — взрывается владелец продукта, — “Где решение? Ты точно за неделю это сделаешь??”
                    “Так, коллеги, давайте успокоимся.” — вмешивается скрам мастер, укоризненно глядя на владельца продукта. “Пётр, я правильно понимаю, что за половину спринта ты можешь не успеть, но уж за целый спринт точно решишь проблему?”
                    “Да, всё верно.” — отвечает Пётр, пытаясь говорить уверенно.
                    “Это всё хорошо и здорово, конечно.” — немного успокоившись, рассуждает владелец продукта. “Но готовы ли мы тратить дополнительное время на эту фичу? Мы и так уже потратили силы и время. Мне кажется, надо эскалировать. Рациональность дополнительных затрат лично мне кажется неочевидной.”
                    “Хорошо, давайте так и сделаем.” — подытоживает скрам мастер.

                    Someone Sometime


                    “Ну, я тут почти закончил. Всё работает, только subroutine бы ещё причесать.” — отчитывается Пётр Второй. “Благо, скиллы по C я мальца подтянул, там фигня осталась.”
                    “Ну, вот и молодец.” — улыбается Иван. “Причёсывать-то обязательно, или просто очень хочется? Может быть, лучше фичу наконец-то закроешь?”
                    “А как же моё чувство прекрасного?” — показушно оскорбляется Пётр, потрясая в воздухе руками.
                    Все инженеры дружно ржут.

                    Day 17


                    Anytime Rational


                    “Руководство пришло к выводу, что возобновлять работу над фичей в данный момент нерационально. Business Value не настолько велико, чтобы вкладывать в неё дополнительные ресурсы, да и по срокам получается, что к следующему релизу никак не успеваем.” — сообщает владелец продукта.
                    “Ну, и слава богу.” — бурчит себе под нос довольный Пётр Первый. “Можно забыть, как страшный сон.”

                    Sometime Something


                    “Пётр, фича твоя идёт в релиз. Тестами-то покрыл?” — интересуется Иван.
                    “Ну, так… надо бы ещё добавить..” — мнётся Пётр Второй.
                    “Вот и добавь.” — веско говорит Иван. “Всё, разошлись, работаем.”

                    Итог


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

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

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

                    https://habrahabr.ru/post/339104/


                    Метки:  

                    Дайджест свежих материалов из мира фронтенда за последнюю неделю №282 (25 сентября — 1 октября 2017)

                    Воскресенье, 01 Октября 2017 г. 23:32 + в цитатник

                    Электронные документы в российских судах, как критерий электронной зрелости России

                    Воскресенье, 01 Октября 2017 г. 21:40 + в цитатник
                    akolesov вчера в 21:40 Управление

                    Электронные документы в российских судах, как критерий электронной зрелости России

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

                      Подтверждением такого суждения стал для меня прошедший на прошлой неделе вебинар компании Synerdocs по теме «Электронные документы в суде: от представления до решения».

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

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

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

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

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

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

                      «Что же вы хотите – мы еще только осваиваем использование электронных документов!» – я уже много лет слышу такой ответ по поводу сетований относительно применения электронных документов в наших судах.

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

                      Летом 2000-го года в Москву из США приехал молодой человек 27 лет, который за четыре года до этого после окончания МГУ уехал работать за океан. Одна из целей визита была «разобраться в сердечных делах». Двух недельная разборка закончилась тем, что он в авральном порядке женился на своей однокласснице (я тут опускаю длинную историю их отношений). Он уехал обратно, а молодая жена подала в посольство США документы на визу для поездки к мужу. И в визе ей было отказано, со ссылкой на то, что они заключили фиктивный брак (именно, чтобы устроить ее перемещение в Америку). Обратиться за визой повторно можно было только через три месяца. Через три месяца муж опять приехал в Москву, чтобы пойти на собеседование вместе с женой. Но при этом он еще привез CD, на котором было записана все их электронная переписка за последние семь лет (как появилась электронная почта) и который он приложит к документам, сдаваемым в посольство.

                      Я не знаю, насколько этот CD помог в положительном решении вопроса. Но тут важно другое – это диск консульские работники приняли в качестве документа. Они не требовали распечатать письма на бумаге, заверить их у нотариуса. Они просто их приняли для рассмотрения. Это было в 2000-м году. Мы к такой работе с электронными документами еще не пришли.
                      Original source: habrahabr.ru (comments, light).

                      https://habrahabr.ru/post/339096/


                      Метки:  

                      [Перевод] ggplot2: как легко совместить несколько графиков в одном, часть 3

                      Воскресенье, 01 Октября 2017 г. 20:07 + в цитатник
                      qc-enior сегодня в 20:07 Разработка

                      ggplot2: как легко совместить несколько графиков в одном, часть 3

                      • Перевод
                      • Tutorial
                      Эта статья шаг за шагом покажет, как совместить несколько ggplot-графиков на одной или нескольких иллюстрациях, с помощью вспомогательных функций, доступных в пакетах R ggpubr, cowplot и gridExtra. Также опишем, как экспортировать полученные графики в файл.

                      Cмешиваем таблицу, текст и ggplot2-графики


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

                      Начнем с создания таких графиков:
                      1. график плотности переменной Sepal.Length. Функция R: ggdensity()ggpubr]
                      2. сводная таблица, содержащая описательные статистики (среднее, стандартное отклонение, т.д.) Sepal.Length
                        • Функция R для вычисления описательных статистик: desc_statby()ggpubr]
                        • Функция R для создания таблицы с текстом: ggtexttable()ggpubr]
                      3. абзац текста. Функция R: ggparagraph()ggpubr]

                      Завершим, скомбинировав все три графика с помощью функции ggarrange()ggpubr].
                      # График плотности "Sepal.Length"
                      #::::::::::::::::::::::::::::::::::::::
                      density.p <- ggdensity(iris, x = "Sepal.Length", 
                                             fill = "Species", palette = "jco")
                      # Вывести сводную таблицу Sepal.Length
                      #::::::::::::::::::::::::::::::::::::::
                      # Вычислить описательные статистики по группам
                      stable <- desc_statby(iris, measure.var = "Sepal.Length",
                                            grps = "Species")
                      stable <- stable[, c("Species", "length", "mean", "sd")]
                      # График со сводной таблицей, тема "medium orange" (средний оранжевый)
                      stable.p <- ggtexttable(stable, rows = NULL, 
                                              theme = ttheme("mOrange"))
                      # Вывести текст
                      #::::::::::::::::::::::::::::::::::::::
                      text <- paste("iris data set gives the measurements in cm",
                                    "of the variables sepal length and width",
                                    "and petal length and width, respectively,",
                                    "for 50 flowers from each of 3 species of iris.",
                                   "The species are Iris setosa, versicolor, and virginica.", sep = " ")
                      text.p <- ggparagraph(text = text, face = "italic", size = 11, color = "black")
                      # Разместить графики на странице
                      ggarrange(density.p, stable.p, text.p, 
                                ncol = 1, nrow = 3,
                                heights = c(1, 0.5, 0.3))


                      Добавляем графический элемент в ggplot


                      Для добавления таблиц, графиков или других элементов на основе таблиц в рабочую область ggplot есть функция annotation_custom()ggplot2]. Упрощенный формат:
                      annotation_custom(grob, xmin, xmax, ymin, ymax)

                      • grob: внешний графический элемент для отображения
                      • xmin, xmax: x-расположение в координатах (горизонтальное расположение)
                      • ymin, ymax: y-расположение в координатах (вертикальное расположение)

                      Помещаем таблицу в ggplot


                      Используем графики density.p и stable.p, созданные в предыдущем разделе.
                      density.p + annotation_custom(ggplotGrob(stable.p),
                                                    xmin = 5.5, ymin = 0.7,
                                                    xmax = 8)


                      Помещаем диаграмму рассеивания в ggplot


                      1. Создаем диаграмму разброса для y = “Sepal.Width” по x = “Sepal.Length” из набора данных iris. Функция R: ggscatter() [ggpubr].
                      2. Создаем отдельно диаграмму рассеивания переменных х и у с прозрачным фоном. Функция R: ggboxplot() [ggpubr].
                      3. Преобразуем диаграмму рассеивания в графический объект под названием “grob” в терминологии Grid. Функция R: ggplotGrob() [ggplot2].
                      4. Поместим grob-ы диаграммы рассеивания внутрь диаграммы разброса. Функция R: annotation_custom() [ggplot2].

                      Поскольку помещенная внутрь диаграмма рассеивания накладывается в нескольких точках, для нее используется прозрачный фон.
                      # Диаграмма разброса по группам ("Species")
                      #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
                      sp <- ggscatter(iris, x = "Sepal.Length", y = "Sepal.Width",
                                      color = "Species", palette = "jco",
                                      size = 3, alpha = 0.6)
                      # Диаграммы рассеивания переменных x/y
                      #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
                      # Диаграмма рассеивания переменной x
                      xbp <- ggboxplot(iris$Sepal.Length, width = 0.3, fill = "lightgray") +
                        rotate() +
                        theme_transparent()
                      # Диаграмма рассеивания переменной у
                      ybp <- ggboxplot(iris$Sepal.Width, width = 0.3, fill = "lightgray") +
                        theme_transparent()
                      # Создать внешние графические объекты
                      # под названием “grob” в терминологии Grid
                      xbp_grob <- ggplotGrob(xbp)
                      ybp_grob <- ggplotGrob(ybp)
                      # Поместить диаграммы рассеивания в диаграмму разброса
                      #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
                      xmin <- min(iris$Sepal.Length); xmax <- max(iris$Sepal.Length)
                      ymin <- min(iris$Sepal.Width); ymax <- max(iris$Sepal.Width)
                      yoffset <- (1/15)*ymax; xoffset <- (1/15)*xmax
                      # Вставить xbp_grob внутрь диаграммы разброса
                      sp + annotation_custom(grob = xbp_grob, xmin = xmin, xmax = xmax, 
                                             ymin = ymin-yoffset, ymax = ymin+yoffset) +
                        # Вставить ybp_grob внутрь диаграммы разброса
                        annotation_custom(grob = ybp_grob,
                                             xmin = xmin-xoffset, xmax = xmin+xoffset, 
                                             ymin = ymin, ymax = ymax)



                      Добавляем фоновое изображение в ggplot2-графики


                      Импортировать фоновое изображение. Используйте или функцию readJPEG() [в пакете jpeg], или функцию readPNG() [в пакете png] в зависимости от формата фоновой картинки.

                      Чтобы протестировать пример ниже, убедитесь, что пакет png установлен. Можно его установить, используя команду install.packages(“png”).
                      # Импорт картинки
                      img.file <- system.file(file.path("images", "background-image.png"),
                                              package = "ggpubr")
                      img <- png::readPNG(img.file)

                      Скомбинировать ggplot с фоновой картинкой. Функция R: background_image()ggpubr].
                      library(ggplot2)
                      library(ggpubr)
                      ggplot(iris, aes(Species, Sepal.Length))+
                        background_image(img)+
                        geom_boxplot(aes(fill = Species), color = "white")+
                        fill_palette("jco")


                      Изменим прозрачность заливки в диаграммах разброса заданием аргумента alpha. Значение должно быть в промежутке [0, 1], где 0 — полная прозрачность, а 1 — отсутствие прозрачности.
                      library(ggplot2)
                      library(ggpubr)
                      ggplot(iris, aes(Species, Sepal.Length))+
                        background_image(img)+
                        geom_boxplot(aes(fill = Species), color = "white", alpha = 0.5)+
                        fill_palette("jco")


                      Еще один пример, накладывание карты Франции на ggplot2:
                      mypngfile <- download.file("https://upload.wikimedia.org/wikipedia/commons/thumb/e/e4/France_Flag_Map.svg/612px-France_Flag_Map.svg.png", 
                                                 destfile = "france.png", mode = 'wb') 
                      img <- png::readPNG('france.png') 
                      ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width)) +
                        background_image(img)+
                        geom_point(aes(color = Species), alpha = 0.6, size = 5)+
                        color_palette("jco")+
                        theme(legend.position = "top")



                      Располагаем графики на нескольких страницах


                      Если у вас длинный список ggplot-ов, скажем, n=20, возможно, вы захотите упорядочить их, разместив на нескольких страницах. Если на странице будет 4 графика, для 20 понадобится 5 страниц.

                      Функция ggarrange()ggpubr] предоставляет удобное решение, чтобы расположить несколько ggplot-ов на нескольких страницах. После задания аргументов nrow и ncol функция ggarrange() автоматически рассчитывает количество страниц, которое потребуется, чтобы разместить все графики. Она возвращает список упорядоченных ggplot-ов.

                      Например, код ниже
                      multi.page <- ggarrange(bxp, dp, bp, sp,
                                              nrow = 1, ncol = 2)

                      возвращает две страницы с двумя графиками на каждой. Можно вывести каждую страницу вот так:
                      multi.page[[1]] # Вывести страницу 1
                      multi.page[[2]] # Вывести страницу 2

                      Упорядоченные графики можно экспортировать в pdf-файл с помощью функции ggexport()ggpubr]:
                      ggexport(multi.page, filename = "multi.page.ggplot2.pdf")

                      PDF-файл

                      Многостраничный вывод можно получить и с функцией marrangeGrob()gridExtra].
                      library(gridExtra)
                      res <- marrangeGrob(list(bxp, dp, bp, sp), nrow = 1, ncol = 2)
                      # Экспорт в pdf-файл
                      ggexport(res, filename = "multi.page.ggplot2.pdf")
                      # Интерактивный вывод
                      res

                      Вложенное взаиморасположение с ggarrange()


                      Упорядочим графики, созданные в предыдущих разделах.
                      p1 <- ggarrange(sp, bp + font("x.text", size = 9),
                                      ncol = 1, nrow = 2)
                      p2 <- ggarrange(density.p, stable.p, text.p, 
                                      ncol = 1, nrow = 3,
                                      heights = c(1, 0.5, 0.3))
                      ggarrange(p1, p2, ncol = 2, nrow = 1)


                      Экспорт графиков


                      Функция R: ggexport()ggpubr].

                      Сначала создадим список из 4 ggplot-ов, соответствующих переменным Sepal.Length, Sepal.Width, Petal.Length и Petal.Width в наборе данных iris.
                      plots <- ggboxplot(iris, x = "Species",
                                         y = c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width"),
                                         color = "Species", palette = "jco"
                                         )
                      plots[[1]]  # Вывести первый график
                      plots[[2]]  # Вывести второй график и т.д.

                      После можно экспортировать отдельные графики в файл (pdf, eps или png) (один график на странице). Можно упорядочить графики (2 на страницу) при экспорте.

                      Экспорт отдельных графиков в pdf (по одному на странице):
                      ggexport(plotlist = plots, filename = "test.pdf")

                      Упорядочьте и экспортируйте. Задайте nrow и ncol, чтобы вывести несколько графиков на одной странице:
                      ggexport(plotlist = plots, filename = "test.pdf",
                               nrow = 2, ncol = 1)
                      Original source: habrahabr.ru (comments, light).

                      https://habrahabr.ru/post/339090/


                      Метки:  

                      Классический 2д квест или как прошли наши два года разработки. Часть 3

                      Воскресенье, 01 Октября 2017 г. 18:34 + в цитатник
                      MaikShamrock сегодня в 18:34 Разработка

                      Классический 2д квест или как прошли наши два года разработки. Часть 3

                        Снова привет всем, в этой, третьей, части будет рассказ о том как программировался «Swordbreaker The Game», почему был выбран тот или иной фреймворк, подробности под катом.





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


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

                        Как было рассказано ранее проект пережил следующие вехи развития:
                        • Был создан прототип на бумаге в виде диздока, были определены платформы, и примерный геймплей
                        • Были созданы прототипы на различных игровых движках с целью определить какой из них подойдёт лучше всего для реализации идей
                        • Была создана демо-версия для предварительной оценки игры со стороны коммьюнити
                        • Игра была реализована для основных платформ (Windows, Android OS)
                        • Игра была реализована для вторичных платформ (Linux, Mac, iOS)


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

                        Смотрите сами – вы работаете на работе – это 8 часов, вам нужно нормально отдыхать, иначе в голове будет постоянная каша и стресс вас доконает – это как минимум еще 8 часов, еще 8 остаётся вроде как на проекты, но жизнь складывается зачастую так, что из этих 8 на проект получится выделять часа по 4 в лучшем случае. И в эти короткие сроки придётся изучать много и практически «на лету». Поэтому прежде чем начинать что-то делать постарайтесь трезво оценить, готовы ли вы писать код по 12 часов в сутки, чтобы реализовать проект.

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

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

                        На тот момент когда всё началось (начало 2014) жизнь в интернете происходила под лозунгами а-ля «Флеш умирает, что же делать, а давайте переходить на html5, но он однако какой-то сырой…», также на горизонтах лихо проносились андроиды выпуская всё новые версии системы, охватить хотелось конечно всё и сразу, но для начала были определены две платформы – Android и Windows (в виде Steam Greenlight, если пройдём конечно), соответственно нужен был кроссплатформенный движок. На тот момент были следующие кандидаты на которых я попробовал реализовать базовый уровень – Construct2, Libgdx, Unity3d, ImpactJS, Cocos2d, еще какая-то пара Flash-движков, AndEngine, CoronaSDK. Из всей кучи более-менее адекватными по совместимости, документации и простоте освоения были только два – это LibGDX и CoronaSDK, в Unity3d на тот момент работа с 2д графикой делалась набором костылей (но пару демок я написал и на нём, но по сравнению с теми двумя он не был таким удобным).

                        Как вообще выбрать движок для начального прототипирования игры? Заметьте, что для прототипа, именно прототипа, когда нужно составить виденье будущей игры, подходит фактический любой движок, который вы сумеете освоить хотя бы за пару недель и начать уже-то что-то на нём писать. LibGDX в этом плане имел хорошую wiki-документацию, отличный форум, с живым коммьюнити, а его авторов Mario Zechner написал даже две книги по программированию игр, с использованием LibGDX, (ищите на packtpub) всё это довольно сильно помогало на начальном этапе, ведь опыта программирования игр у меня не было. Примерно такая же ситуация с CoronaSDK – простая и доступная документация, сравнительно богатый для 2d набор API, язык программирования Lua – простой в освоении, но с большим количеством нюансов.


                        Первая демка, с тестовыми кнопками, собранная на CoronaSDK, шрифт тестовый, кнопки тоже

                        Сначала я вообще думал писать на CoronaSDK, но постоянная работа со сборщиком на стороне сервера, компиляция, потом загрузка на Android (всё это не быстро), да и довольно “жидкая” структура языка lua, чем то напоминающее javascript, заставили продолжить освоение движка LibGDX.

                        Собственно LibGDX был хорош всем. Во первых там был хороший туториал который позволял понять основной игровой цикл, были демки (около 100 шт.) с различными функциями API, которые можно было запустить и посмотреть, всё это дело собиралось на Windows и делало это очень быстро, плюс при компиляции на Android проект выглядел 100% также (у Corona бывали глюки, на эмуляторе так, а на телефоне по-другому). К тому же это была Java – мейстримовый ООП язык программирования, надо сказать очень удобный для реализации проектов любого уровня, и практически такой же как C#, на котором я писал (и пишу) на работе. К тому же это было всё управлением Android Studio (создатели Resharper и кучи других инструментов), которая была также крайне удобной IDE для разработки.

                        Собственно какие выводы я из всего этого сделал – если вы только начинающий в разработке игр, берите тот движок, который наиболее приемлем для вас с точки зрения простоты освоения, да, я понимаю, что выбрав бы допустим Unity3d я бы освоил более мощный инструмент, но в целом для игры, как для программного продукта, важно – сама геймплейная составляющая, на чём она будет реализована – дело вторичное, все движки примерно одинаково работают с 2д и 3д, поэтому выбирайте то, что подходит именно вам (может быть по опыту ЯП, может по удобству), единственный критерий на данном этапе – скорость разработки прототипа.


                        Найди AdMob на фотографии

                        Описывать сам процесс программирования для игры наверно нет смысла, для LibGDX всё доступно расписано в Wiki, хотя последнее время проект немного подзатих, но думаю для начинающих я бы порекомендовал его для “пробы пера”.

                        Итак на LibGDX мы доехали до выпуска демо-версии, здесь сыграло важную роль то, что у движка было:
                        • Лёгкая интеграция с рекламным API, можно было легко и без проблем встроить рекламные модули AdMob в проект с использованием готовых API.
                        • Это была фактически родная для Android – Java
                        • Собственно запуск демо прошёл фактически без всяких технических проблем, были пару вопросов почему-то криво формировалось отображение, но в целом – всё нормально.
                        • Далее начался марафон до релиза основной версии игры.
                        • На всём этом долгом пути очень полезными были следующие вещи:
                        • Android Studio – которая ну очень удобная штука со всеми фишками рефакторинга, подсветки синтаксиса, быстрых переходов, отладки и.т.д. JetBrains – one love! Всё это позволяло удобно управлять кодом и быстро находить ошибки экономя время и нервы.
                        • Структура проектов в LibGDX – так получилось, что данный фреймворк отлично спроектирован под создание 2д игр, почти под всё API были либо Demo либо статьи в Wiki, так что проблем технического характера было мало, также порадовала локализация, которая тоже имела свой API. На финальном этапе интеграции в Steam, также оказалось, что есть свободные компоненты для реализации Steam API в игре, аналогично было и с google play services. В целом LibGDX был этаким фреймворком наподобие стандартной библиотеки .NET с кучей готовых классов из которых ты можешь лепить всё, что тебе требуется, там есть практически всё (в рамках OpenGL ES, наверно =])
                        • Моральная Санина поддержка, особенно когда мы переписывали диалоги и тестировали всё это дела на баги. =]


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

                        Постепенно правя последние баги мы подошли к релизу в Steam, запуск Android версии решено было отложить, поскольку там было пара технических моментов и мы всё никак не могли решить делать ли её бесплатной с рекламой или paid-app. Подготовка к запуску в Steam заняла тоже своём время, нужно было заполнит много информации – личные данные, ачивки, подготовить материалы (как оказалось нужны картинки на ачивки, значки, смайлики для чата, обои для профилей пользователей), а также протестировать работу API в игре. Steam вообще в этом плане очень удобная платформа, море документации, которая доступна после регистрации (и которая не подлежит разглашению o_O), делаю процесс довольно простым, к тому же, как я уже говорил, были готовые библиотеки для LibGDX. Вобщем пару раз нас отклоняла модерация из-за несоответствия материалов, но таки мы прошли и стартовали! :D

                        Тут процесс перетёк из состояния «разработка» в состояние «поддержка», и посыпались первые долгожданные «баги» — у некоторых неправильно отрабатывал FitViewport, у кого-то терялись сохранения, кому-то не давались ачивки, вобщем у кого что болит. Часть багов была оперативно поправлена, а часть… увы, но с некоторыми я так и не смог разобраться до сих пор.


                        Типичная отладка

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

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


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


                        Карта всей игры

                        Вобщем это были напряженные деньки предфинальной полировки почти готового продукта. Спустя некоторое время была создана версия для Android, и запущена в виде paid-app, трансформация благодаря функционалу LibGDX произошла довольно безболезненно, все функции для if-else условий настройки интерфейса там были, поэтому часть управления была подстроена под пальцевый тач и всё закрутилось-завертелось.

                        Оставалось еще одно незаконченное дело – это версия для Mac, а именно для iOS, вообще Android для paid-приложения показал себя довольно хорошо, была надежда, что iOS версия будет как минимум не хуже.

                        Сейчас уже не помню в чём конкретно была причина, по которой я решил версию для iOS писать не на LibGDX, а на CoronaSDK, но вроде это были какие-то нюансы в совместимости. Был также куплен Mac, для того, чтобы пройти регистрацию на портале и для тестирования на виртуалке.
                        Достаточно быстро, хотя и не без проблем с Lua игра была переписана и запускалась на эмуляторе вполне хорошо, сказались некоторые отличия в компонентах, что-то пришлось оптимизировать, что-то переделать, но в целом движок с возложенной на него задачей справился, плюс CoronaSDK обладает хорошим и шустрым эмулятором. Место Android Studio заменил Sublime Text под который у CoronaSDK существует плагин, получилось что-то наподобие IDE, в котором было тоже довольно удобно. В целом у CoronaSDK плюсом и минусом является язык – это скриптовый Lua с динамической типизацией, к которой не сразу привыкаешь и иногда путаешься в областях видимости, определении переменных, и.т.д., постепенно к этому привыкаешь, всё становится таблицей в которую можно затолкать всё – начиная от данных и заканчивая функциями, в целом тут есть своя логика, но отлаживать всю эту чертовщину – не очень то круто. Коронка тоже имеет богатый API в котором есть много всего для создания 2д игр, очень проста в освоении, содержит много примеров в самой документации, плюс к этому есть плагины для встраивания монетизации, и прочих сервисов (некоторые платные). Для создания простеньких игрушек под телефоны – самое то, для чего-то более крупного, я бы наверно запутался в всём этом балагане, при отсутствии нормальной IDE.


                        Три тысячи чертей (на самом деле триста мечеломов) и одна маленькая сценка!

                        Запуск iOS версии прошёл стабильно, написав и протестировав всё под Windows на эмуляторе, осталось заполнить регистрационную информацию, сделать билд и запустить сборку на iOS. Profit! :D

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

                        https://habrahabr.ru/post/339092/


                        Метки:  

                        Liquibase: пример автоматизированного наката изменений на реляционную БД

                        Воскресенье, 01 Октября 2017 г. 17:32 + в цитатник
                        akk0rd87 сегодня в 17:32 Разработка

                        Liquibase: пример автоматизированного наката изменений на реляционную БД

                          Вместо предисловия


                          Статья будет интересна тем, кто хоть раз задумывался о вопросе наката изменений (патча) на реляционную БД. Статья не будет интересна тем, кто уже освоил и использует Liquibase. Главной целью данной статьи является указание ссылки на репозиторий с примером использования. В качестве примера я выбрал накат sample-схемы HR на БД Oracle (список всех поддерживаемых БД) — любой желающий может скачать себе репозиторий и поиграться в домашних условиях. Желание продемонстрировать пример вызвано обсуждением этого вопроса на ресурсе sql.ru.


                          Что такое Liquibase


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


                          Почему я использую Liquibase


                          Мой выбор остановился на этом инструменте, так как:
                          1) Инструмент отслеживает, какие changeset-ы уже были применены к данному экземпляру БД и накатывает только те, которые еще не накатывались и какие нужно еще донакатить. Если в процессе наката применение какого-либо изменения упало с ошибкой, то, после устранения причины вы перезапускаете накат и Liquibase продолжает выполнение с того changeset-а, на котором остановился.
                          2) Возможность выставить changeset-у атрибуты runOnChange и runAlways существенно упрощает управление изменениями, в частности, recreatable-объектов.
                          3) Свойство context позволяет выполнять/не выполнять changeset-ы в зависимости от текущего окружения (например, не запускать юнит-тесты на проде).


                          Это был не полный список фич.


                          Репозиторий


                          Он здесь. В нем приведены "hard" (таблицы, индексы, ограничения целостности) и "soft" (триггеры, процедуры, представления) объекты, changeset-ы с тегами sql и sqlFile, c атрибутами runOnChange и runAlways и без.


                          Чего нет в репозитории


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


                          • Preconditions — позволяют задавать условие выполнения changeset-a;
                          • Компилирование объектов схемы в конце наката. В Oracle это dbms_utility.compile_schema(user, false);
                          • Запуск юнит-тестов.
                          Original source: habrahabr.ru (comments, light).

                          https://habrahabr.ru/post/339084/


                          Метки:  

                          Поиск сообщений в rss_rss_hh_full
                          Страницы: 1824 ... 1554 1553 [1552] 1551 1550 ..
                          .. 1 Календарь