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

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

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

 

 -Статистика

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

Habrahabr/New








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

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

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

Как не дать отвлекать себя от работы. Советы и слэк-бот

Пятница, 04 Августа 2017 г. 09:43 + в цитатник
Отвлекаться плохо, очень плохо! Все это знают, но не все знают, что с этим делать и каков реальный масштаб проблемы. Поэтому я решил собрать вместе несколько техник по снижению числа отвлечений и даже написал небольшого бота, помогающего мне в этом.
Первая часть статьи — о причинах прерываний и методах борьбы с ними. Тех, кому больше интересно, как поднять своего Python-бота для Slack на Heroku с автоматизированным тестированием на Travis, прошу сразу переходить ко второй части. А мы перейдем к сути проблемы.

Проблема не в тебе, проблема во мне.



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

Видеть тебя больше не хочу!


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

Ну че ты пилишь? Сказал же: вынесу елку!


Что если это не лайки в фейбуке, а что-то более важное и ваш раздражитель уже внешний — коллега, или может быть даже начальник? Откладываем на потом! Если сервера не загораются прямо сейчас в дата-центре, а джуниор-интерн не решает конфликт в мастер-ветке через 'git push --force', отвлечение можно отложить, и тем самым предотвратить переключение контекста. Слак позволяет о любом сообщении напомнить через несколько минут или часов. Что-то важное — откладываем на полчаса-час, что-то действительно важное — на 5–20 минут, за это время мы успеем довести задачу до точки, или хотя бы дописать метод. Ваш месенжер не поддерживает напоминания? Отмечаем сообщения непрочитанными и/или создаем таймер, теперь точно не забудем.
Почему вообще стоит откладывать дела на потом? Потому что это «потом» предполагает не больше часа-двух, а в течении часа мы все равно прервемся, но полминуты, чтобы прочитать сообщение и отложить его, лучше чем 5–10 минут, так как уже не сбивают с контекст задачи. Исследование на основе реальных рабочих сессий в Eclipse и Visual Studio показало, что два часа подряд мы работаем максимум один раз в день, при этом цена одного отвлечения равна десяти-пятнадцати минутам, чтобы снова начать писать код, и только каждый десятый программист умудряется начать снова писать код быстрее чем за минуту, если его отвлекли прямо в середине метода. А для тех, кому офисная среда совсем не позволяет поработать без отвлечений и один час придумали технику помидорок: дробим день на мелкие отрезки, каждые 25 минут фокусируемся на задаче, потом 10 минут на всем остальном, повторяем. Уж 25 минут обычно могут подождать 99% процентов даже очень важных вещей.

Дорогая, до полудня ты — у меня единственная!


Если вы уже отправили одного коллегу ждать, но уже пишет другой со своей задачей? Ваше сердце принадлежит тому, кто написал первым. Второго ставим в очередь. При этом сообщаем, что можно и нужно написать про задачу подробнее, но читать вы будете, только когда разберетесь с первой.
Многозадачность человеку дается гораздо хуже, чем процессору. По правде говоря, даже процессору многозадачность удается хуже, чем однозадачность (читаем прекрасных Джоэла и Демарко). Даже если вторая задача приоритетнее, но не настолько, чтобы её было нужно сделать за 10 минут, она может ждать. С меньшим числом прерываний, вы завершите обе задачи даже быстрее.

Почему ты не хочешь поговорить со мной?


Вы только что сделали, как я посоветовал, а коллега на вас обиделся? Ну да! Мало кому понравится, что его просят не мешать, особенно если он не понимает причину. Поэтому ваши коллеги должны знать и о том, насколько вредны прерывания, и о том, что вы иногда откладываете часть вопросов на потом, только для того, чтобы в итоге сделать все задачи быстрее и качественнее. Поэтому шарим линки из статьи со всем офисом, дарим директору книжку Демарко и не боимся обсуждать на работе, как общаться продуктивнее. Например, не разбивать одну мысль в чате на несколько предложений и не здороваться без дела, всегда давать контекст вместе с вопросом и т.д. Ну и самим не злоупотреблять доверием — сказали, что ответите через 10–15 минут, ответьте! Одна из причин, которую я слышал в оправдание идеи поздороваться и потом ждать, была такой: «а иначе мне могут вообще не ответить». Не будьте таким человеком! Если коллеги поймут, что вам можно доверять, они просто буду реже напоминать о своих задачах. Ну и не отвлекайте других без дела.

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

Всем спасибо, и привет!

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

https://habrahabr.ru/post/334674/


Метки:  

[Перевод] Размышления о токенах

Пятница, 04 Августа 2017 г. 09:15 + в цитатник

Сегодня для токенов рано, но за ними — будущее технологий



В 2014 году мы писали: «Биткойн — это больше, чем деньги, и больше, чем протокол. Это модель и платформа для настоящего краудфаундинга — полностью открытого, распределенного и легко реализуемого».
 
И эта новая модель уже реализована — на идее «аппкойна», или «токена», который представляет собой дефицитный цифровой актив, опирающийся на вдохновленную «Биткойном» технологию. На момент написания статьи рыночная капитализация сектора токенов оценивалось в десятки миллиардов долларов (безусловно, этот сектор переоценен, и тем не менее). Такие «толстые протоколы» могут в конечном итоге создать и привлечь больше капитала, чем интернет-компании последнего поколения.
 
Здесь мы обсудим многие связанные с токенами концепции: начнем с основ для новичков в этой области, а затем перейдем к более сложным понятиям.
 
Переведено в Alconost

Главное, что следует понимать: токены не являются акциями — они больше похожи на платные API-ключи. Тем не менее, они могут давать 1000-кратное снижение времени выхода на ликвидность и 100-кратное увеличение покупательской базы — по сравнению с традиционными средствами финансирования технологий в США (такими, как Kickstarter на самых успешных проектах). Это, в свою очередь, позволит финансировать проекты нового типа, ранее остававшиеся вне области возможностей венчурного капитала, и в их числе — протоколы с открытыми исходными кодами и проекты с потенциалом быстрого двукратного возврата.
 
Но давайте все-таки начнем с основ. Почему токены пришили именно сейчас?
 

1. Токены — результат четырехлетнего развития инфраструктуры цифровых валют


Последний раз широкая публика слышала о цифровой валюте в конце 2013 — начале 2014 года, когда цена биткойнов в последний раз коснулась тогдашнего максимума в 1242 долл. США. С тех пор кое-что произошло:
 

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



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

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


В первую очередь следует сказать, что токен — это цифровой актив, который можно передавать (не просто копировать) между двумя сторонами-участниками через Интернет без согласия какой-либо третьей стороны. «Биткойн» — это самый первый токен: с возможностью передачи биткойнов и выпуском новых биткойнов, записываемых в соответствующий блокчейн. У других токенов тоже есть механизм передачи, а изменения в денежной базе записываются в их собственных блокчейнах.
 
Один из ключевых моментов состоит в том, что кодовая база токена отличается от базы данных его блокчейна. Приведем аналогию из реального мира. Представьте, что банковская инфраструктура США начала управлять австралийскими долларами: обе валюты — «доллары» и имеют общее культурное происхождение, однако у них совершенно разная денежная база. Точно так же два токена могут использовать одинаковые кодовые базы (денежные политики), но иметь разные базы данных блокчейна (денежные базы).
 
Благодаря успеху «Биткойна» появились несколько различных видов токенов:
 
  • Токены, основанные на новых «цепочках» и ответвлениях кода «Биткойна». Такими были первые токены. Некоторые из них, такие как Dogecoin, просто изменили параметры в кодовой базе «Биткойна». Другие — например, ZCash и Dash, привнесли новые решения в области защиты конфиденциальности. А были и такие (например, Litecoin), которые начинались как небольшие модификации в коде «Биткойна», но в конечном итоге стали испытательным полигоном для новых функций. Все эти токены запустили собственные блокчейны, не связанные с блокчейном «Биткойна».
  • Токены, основанные на новых «цепочках» и новом коде. Следующим шагом было создание токенов на основе полностью новых кодовых баз, и наиболее ярким их примером является «Эфириум». «Эфириум» — это основанный на принципах «Биткойна» проект, использующий собственный блокчейн и разработанный с нуля с целью расширить возможности программирования. При этом увеличивается число возможных видов атак, однако при этом расширяется функциональность.
  • Токены, основанные на ответвленных «цепочках» и ответвлениях кода. Самый важный пример — Ethereum Classic, основанный на не совместимом с оригиналом ответвлении блокчейна «Эфириум», которое произошло после обнаружения бреши в безопасности, позволившей использовать крупный смарт-контракт непредусмотренным способом. На первый взгляд, это технический вопрос, однако по своей сути это был кризис, который заставил сообщество «Эфириума» разделиться на две группы с различными денежными политиками — в соотношении 90 на 10. Пример из реального мира: представьте, что все граждане США, не согласные с Законом об экстренной стабилизации экономики 2008 года, поменяли бы свои доллары на «классические доллары» и создали бы другую ФРС.
  • Токены, выпущенные поверх блокчейна «Эфириум». Сюда можно отнести Golem и Gnosis — они основаны на ERC20-токенах, выпущенных поверх «Эфириума».

В целом, запускать совершенно новые токены на новых кодовых базах — технически сложная задача, и гораздо легче запускать новые токены посредством ответвления «Биткойна» или токенов ERC20 на основе «Эфириума».
 
Последнее заслуживает особого упоминания, поскольку «Эфириум» настолько упрощает выпуск токенов, что эта процедура идет первым примером в руководстве по «Эфириуму»! Однако легкость создания токенов на «Эфириуме» не означает, что они в принципе бесполезны. Часто эти токены представляют собой нечто вроде публичной долговой расписки, предназначенной для выкупа в новой цепочке, которая будет создана, или выкупа иного цифрового товара.
 

3. Покупатели токенов получают закрытые ключи


При создании нового токена он часто предварительно майнится и продается при запуске токена, краудсейлом или обоими способами. Здесь «предварительный майнинг» означает выделение части токенов для создателей токена и связанных с ним сторон. «Краудсейл» — похожий на Kickstarter краудфаундинг, при котором все интернет-пользователи имеют возможность купить токены.
 
Токены — цифровой товар. И фактически их покупатели приобретают закрытый ключ. В случае «Биткойна» он выглядит примерно так:
5Kb8kLf9zgWQnogidDA76MzPL6TsZZY36hWXMssSzNydYXYB9KF


В случае «Эфириума» — так:
3a1076bf45ab87712ad64ccb3b10217737f7faacbf2872e88fdd9a537d8fe266


Можно считать закрытый ключ чем-то вроде пароля. Подобно тому, как пароль дает доступ к электронной почте, хранящейся в централизованной облачной базе данных (Gmail, например), так закрытый ключ дает доступ к цифровому токену, хранящемуся в децентрализованной базе данных блокчейна — например, «Эфириума» или «Биткойна».
 
Однако есть существенное различие: в отличие от пароля, никто, в том числе и вы, не сможет восстановить утерянный закрытый ключ. Есть закрытый ключ — есть токены. Нет ключа — нет и токенов.
 

4. Токены похожи на платные API-ключи


Пожалуй, лучшая аналогия для токенов — это концепция платного API-ключа. Например, если купить за доллары API-ключ веб-сервисов Amazon, его можно будет обменять на машинное время в облаке Amazon. Так же и покупка токена — например, «эфира» (ETH), — позволяет обменять его она вычислительное время в децентрализованной сети вычислений «Эфириум».
 
Такой обмен придает токенам собственную полезность.
 
У токенов есть еще одно общее свойство с API-ключам. Если кто-то получает доступ к вашим API-ключам сервисов Amazon, он сможет выставить счет вашему аккаунту Amazon. Точно так же, если кто-то увидит закрытые ключи ваших токенов, он сможет заполучить ваши цифровые деньги. Однако, в отличие от традиционных API-ключей, токены можно передавать другим сторонам без согласия эмитента API-ключа.
 
Таким образом, у токенов есть собственная полезность. И токенами можно торговать. А значит, у токенов есть цена.


Экспоненциальный рост токенов (не относящихся к «Биткойну») до коррекции рынка. Данные — coinmarketcap.com/charts

 

5. Токены — это новая технологическая модель, а не просто стартапы


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

6. Токены — это «неразводняющая» альтернатива традиционному финансированию


Токены не являются акциями, поскольку у них есть внутренняя полезность и они не являются разводняющими в отношении таблицы капитализации компании. Продажа токенов — это скорее продажа через Kickstarter платных API-ключей, чем краудфаундинг акций.
 
Тем не менее, если рассматривать токены как альтернативу классическому финансированию посредством выпуска акций, то продажи токенов дают более чем 100-кратное увеличение доступной базы покупателей и более чем 1000-кратное снижение времени выхода на ликвидность по сравнению с традиционными методами финансирования стартапов. Этому есть три причины: 30-кратное увеличение числа покупателей в США, 20–25-кратное — за счет остальных стран и 1000-кратное снижение времени выхода на ликвидность.
 

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


Выпуск токенов отличается от продажи акций: последнее регулируется Законом США о торговле ценными бумагами 1934 года, а первое больше похоже на продажу API-ключей.
 
Акции могут продаваться в США только так называемым «аккредитованным инвесторам» (3% взрослого населения с собственным капиталом > 1 млн. долл. США), при этом продажа API-ключей в США не может быть таким же образом ограничена без ущерба для ИТ-индустрии США. Поэтому если токены (как API-ключи) могут продаваться 100% американского населения, это дает 33-кратное увеличение доступной покупательской базы в США по сравнению с традиционным финансированием посредством выпуска акций.
 
Следует, однако, заметить, что иногда токены могут выпускаться и явно рекламироваться как способ получить часть прибыли от работы компании. Например, эмитент может захотеть наделить владельцев токенов правом на корпоративные дивиденды, правом голоса, а общий акционерный капитал компании может быть выражен в этих токенах. В этих случаях речь на самом деле идет о токенизированных акциях (а именно — о выпуске ценных бумаг), что существенно отличается от примеров с «аппкойнами», которые мы обсуждали. Если вы не хотите ограничиваться аккредитованными инвесторами согласно закону США о ценных бумагах, не выпускайте токенизированные акции. Принципиальная разница заключается в том, что обычный токен является просто имеющим полезность цифровым товаром — таким, как платный API-ключ. Повторимся: сначала ознакомьтесь с этими тремя статьями, посоветуйтесь с хорошим юристом, и только потом запускайте собственные токены!
 

8. Токены могут продаваться по всему миру через Интернет (20–25-кратное увеличение числа покупателей)


Запуск токена обычно бывает международным, и цифровая валюта поступает со всего мира. Если недавно открытый банковский счет в течение нескольких минут получит тысячи переводов со всего мира на миллионы долларов, он, скорее всего, будет заморожен. А продажа токенов в цифровой валюте для компаний всегда открыта. Учитывая, что жители США составляют лишь около 4–5% мирового населения, международная продажа токенов умножает доступную покупательскую базу еще в 20–25 раз.
 

9. Токены имеют преимущество в ликвидности (более чем 1000-кратное снижение времени выхода на ликвидность)


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


10. Токены смогут децентрализовать финансирование технологий


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

11. Токены создают новую бизнес-модель: «лучше, чем бесплатно»


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

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


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

Для этого явления термина еще нет, но это можно назвать «торговыми медиа» — по аналогии с «социальными медиа» (англ. «commercial media» и «social media»).
 

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


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

14. Токены — это мгновенное обеспечение сохранности без посредников


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

15. Токены можно обобщить для каждой технологической компании как платные логины


Можно ли модель токенов расширить за пределы чистых протоколов — Bitcoin, Ethereum, ZCash и др.? Нетрудно представить продажу токенов как билетов — для доступа к логинам, поездкам на машине, будущим продуктам. Также их можно распространять как вознаграждения авторам, которые делают существенный вклад в работу социальных сетей, или водителям, которые помогают развиваться сетям совместного использования авто. В конце концов, токены можно расширить и на «железо»: когда кто-то покупает место в очереди на Model 3 от Tesla или перепродает билет, он обменивается примитивными токенами. Но сначала модель должна доказать работоспособность на протоколах, и лишь затем ее можно будет обобщить.



Заключение


Токены — явление очень недавнее, и, скорее всего, еще произойдет существенная коррекция рынка (на момент публикации перевода капитализация обсуждаемых токенов прошла глобальный максимум и колеблется на уровне, близком к уровню на момент публикации исходной статьи). Чтобы разобраться с ожидаемым изобилием токенов и работать с ними, нам понадобятся информационные сайты наподобие Coinlist, инструменты управления портфелем (например, Prism), биржи (например, GDAX), а также многие другие составные части поддерживающей токены технической и правовой инфраструктуры.
 
Но мир уже изменился. Токены в 1000 крат лучше, чем те инструменты, что есть сейчас, а такое можно наблюдать нечасто.


О переводчике

Перевод статьи выполнен в Alconost.

Alconost занимается локализацией приложений, игр и сайтов на 68 языков. Переводчики-носители языка, лингвистическое тестирование, облачная платформа с API, непрерывная локализация, менеджеры проектов 24/7, любые форматы строковых ресурсов, перевод технических текстов.

Мы также делаем рекламные и обучающие видеоролики — для сайтов, продающие, имиджевые, рекламные, обучающие, тизеры, эксплейнеры, трейлеры для Google Play и App Store.

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

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

https://habrahabr.ru/post/334852/


Повторяющиеся задачи в Redmine

Пятница, 04 Августа 2017 г. 09:00 + в цитатник


У вас есть регулярные задачи? Скажем, провести планерку по понедельникам в 10:30, сформировать отчет клиенту по четвергам в 18:00? Или клиент по вторникам накатывает обновления, и админ должен с 10:00 быть на постоянной связи? Нужно начинать рабочий день с чек-листа? 20 числа оплатить аренду?


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


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


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


Пользуйтесь на здоровье!

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

https://habrahabr.ru/post/334844/


Метки:  

Истории успеха Kubernetes в production. Часть 2: Concur и SAP

Пятница, 04 Августа 2017 г. 08:57 + в цитатник
Продолжаем рассказывать на примере известных компаний о том, что Kubernetes в production — это не только мечты и надежды. Эта статья — снова про технарей с мировым именем: SAP и её конвергентное облако на базе OpenStack и Kubernetes. Однако начнём с менее известной Concur и вот почему…



Concur


Concur Technologies — американская компания, существующая с 1993 года и насчитывающая сегодня 6800 сотрудников. Её бизнес — это SaaS для услуг в области путешествий и управления затратами для предприятий. В 2010 году ей удалось попасть в сотню лучших маленьких компаний по версии журнала Forbes, а по актуальным сведениям (2017 г.) около 70 % представителей списков Forbes 100 и Forbes 500 пользуются её услугами. В сентябре 2014 года стало известно, что SAP покупает Concur Technologies за 8,3 млрд USD, и поглощение было завершено в декабре того же года.

Статью же про SAP я решил начать с Concur, потому что эта компания, уже будучи подразделением SAP, стала прекрасным примером одних из ранних серьёзных пользователей Kubernetes в production. Первые сведения об этом появились в мае 2016 года. На проходившем тогда в Бостоне мероприятии ContainerDays 2016 ведущий инженер компании Dale Ragan дал интервью, в котором рассказал об опыте Concur.

Использовать Kubernetes в компании начали с одного фрагмента инфраструктуры — для сервиса по управлению чеками. На тот момент в Concur уже работали с Amazon Web Services и хотели запускать своё приложение как локально (on-premises), так и в облаке. Применять EC2 Container Service, который находился тогда в бета-тестировании, в Concur не захотели из-за появляющейся зависимости от одного поставщика (Amazon).

Одним из заметных препятствий при эксплуатации Kubernetes стало отсутствие поддержки AWS Availability Zones для NoSQL-хранилища etcd — проблему решили усилиями инженеров компании и обещали передать Open Source-сообществу. Результатом внедрения Kubernetes, по словам инженера Concur, стала «неизменная» инфраструктура (immutable infrastructure) — такая, что при внесении в неё изменений вместо модификации существующего кластера создаётся новый (и туда производится миграция). Это позволило им «чувствовать себя уверенными при миграциях, когда для всей инфраструктуры делается версионирование подобно тому, как деплоятся новые версии приложения». Для мониторинга производительности в компании внедрили Prometheus и Grafana, а главной проблемой проекта Kubernetes по итогам своего внедрения в Concur назвали недостаточно хорошую/подробную документацию.

Рассказывая об этом событии в своём блоге, Dale Ragan представил общую схему полученной инфраструктуры компании в AWS на базе Kubernetes:



… и пообещал рассказать подробнее об этом проекте, однако по каким-то причинам этого не произошло :-)

Несмотря на это, применение Kubernetes в Concur получило активное продолжение и развитие. Осенью того же года старший архитектор компании Dan Wilson выступил на KubeCon 2016 с докладом о масштабировании микросервисов с помощью Kubernetes, а ещё через год — на CoreOS Fest 2017 с докладом (презентация в PowerPoint) про использование Federated Cluster Selector из Kubernetes 1.7.

В последнем докладе архитектор Concur объяснил выбор Kubernetes следующими причинами:



Отдельного замечания стоит тот факт, что к 2017 году в Concur полюбили продукты CoreOS (хотя начинали с использования только «родных» компонентов Kubernetes), в том числе объясняя это «лучшей документацией для Kubernetes». Архитектура кластеров в компании получила такой вид:



В этом же докладе Dan Wilson представил и один из Open Source-проектов Concur для Kubernetes — kubegowatcher. Это шаблон плагина, который создан для запуска в контейнере внутри Kubernetes и отслеживания изменений в сервисах, подах и узлах (с возможностью добавлять свою бизнес-логику на события добавления/изменения/удаления объектов). Дополнительно отмечу, что архитектор Concur вносит свои правки и в upstream самого Kubernetes.

SAP: DevOps, микросервисы, Kubernetes (2016)


Официальных подтверждений тому, что солидный опыт с Kubernetes у Concur повлиял на инженеров SAP, нет. Однако общие идеи как минимум «витали в воздухе» — ведь ещё при покупке Concur глава SAP выражал восторг по поводу «расширения облачного портфолио SAP ведущими решениями для путешествий и управления расходами».

Так или иначе первое публичное упоминание применения Kubernetes для нужд SAP встречается летом 2016 года, когда архитектор облачной инфраструктуры компании Darren Hague выступал на DevOps Enterprise Summit 2016 (DOES16) в Лондоне с докладом «SAP’s DevOps Journey: From Building an App to Building a Cloud». К DevOps в компании пришли ещё в 2010—2013 годах (см. выступление того же автора на FlowCon San Francisco 2013), и Kubernetes стал следующим логичным шагом в её эволюции.

Представляя Kubernetes, Darren провёл заимствованную у сотрудника ЦЕРНа аналогию с домашними животными и скотом: если первые «имеют свои имена, уникальны, получают заботу с любовью и восстановление здоровья в случае проблем», то вторые — «получают номера вместо имён, практически идентичны друг другу и легко заменяются в случае болезней» (лично от себя добавлю, что совершенно не разделяю подобное отношение к животным, но это выходит далеко за рамки статьи). Так вот Kubernetes, по мнению архитектора SAP, — это возможность «обращаться с контейнерами, как со скотом, а не домашними питомцами».

Одной из особенностей применения системы Kubernetes в инфраструктуре SAP стало её использование как фундамента, поверх которого (т.е. в Docker-контейнерах которого) запускалась облачная платформа OpenStack. Уже в середине 2016 года озвучивалась задача компании по реализации такой новой платформы в 13 регионах и 18 дата-центрах с тем, чтобы её использовали одновременно «для облачных услуг SAP и для внутренних инноваций». Общение видение платформы представлялось следующим образом:



Отдельного упоминания заслуживает предпоследний пункт: инженеры компании создавали своего «агента автоматизации» под названием Arc, упоминаний в интернете о котором, к сожалению, осталось не так много. Существующий проект на Launchpad характеризует разработку как «безопасный фрейморк удалённого исполнения команд в OpenStack для настройки и запуска задач на гостевых системах в Linux и Windows», ссылаясь на ныне отсутствующий репозиторий в GitHub.

Интересной оказалась статистика по R&D создаваемой платформы: менее 10 % работы над проектом отнесены к категории «новые разработки», а более 90 % — улучшение имеющегося Open Source-кода. В частности, специалисты SAP внесли правки в upstream таких проектов, как OpenStack, Kubernetes, Docker и Grafana. (Впрочем, по данным Stackalytics, SAP не входит в сколь-нибудь значимый топ самых активных контрибьюторов ни для OpenStack в целом, ни для компонента Kubernetes в частности — проверка осуществлена для релизов OpenStack 2016—2017 годов.)

К подробностям об этой платформе мы ещё вернёмся, а пока будем следовать хронологии. В ноябре того же года на KubeCon 2016 прозвучал доклад (PDF) двух сотрудников SAP Labs о пилотном проекте по запуску в Kubernetes контейнеров с enterprise-сервисами компании. Из него можно было узнать о продолжающемся интересе инженеров SAP к переводу монолитных приложений к микросервисной архитектуре и имеющимся способам его реализации. Общую архитектуру в SAP видят так:



В примечании к этому слайду утверждается, что SAP работает и с HashiCorp, и с Mesosphere, однако выбранной реализацией контейнеров по умолчанию является Docker, а конкретный доклад посвящён их применению с Kubernetes и CoreOS. Итог же исследовательского проекта SAP Labs таков, что он на тот момент не закончен: остаётся ряд сложностей (в основном это вопросы стандартизации и интеграции различных компонентов и процессов компании), которые инженеры намерены преодолеть до того, как практики станут повсеместно адаптироваться. Отдельного упоминания в этом проекте стоит намерение SAP Labs «выпустить в ближайшем будущем Open Source-инструмент для управления Kubernetes — инструмента, который будет полезен и для разработчиков, и для команд эксплуатации».

SAP: конвергентное облако (2017)


В марте 2017 года история облачной платформы SAP на базе Kubernetes и OpenStack получила публичное продолжение: в корпоративном блоге анонсируется production-статус конвергентного облака SAP (SAP Converged Cloud, SAPCC). Заявляется, что оно предназначено только для внутреннего применения в компании, однако его масштабы всё равно впечатляют: проект объединил 23 других облачных решения, применявшихся ранее. Так много их было по разным причинам: «от быстрой инновации в разных областях бизнеса до множества приобретений, сделанных SAP за последние годы» (у таких компаний, как SuccessFactors, Ariba и, конечно, уже упомянутой Concur, были свои облака в момент их присоединения к SAP).

Как сообщается в анонсе, «OpenStack разворачивается на 100% контейнеризированным с помощью автоматизированной системы на базе Kubernetes». Некоторые подробности о технических особенностях и трудностях применения Kubernetes можно почерпнуть из доклада (кстати, это видео содержит 4-минутную демонстрацию того, как новый дата-центр может быть развёрнут в SAP Converged Cloud) архитектора компании Michael Schmidt на OpenStack Summit 2016:



Весь CI/CD pipeline в SAP (применяется Concourse) интегрирован с контейнерами из облака (применяется OpenStack Kolla), а для удобного управления инфраструктурой, разворачиваемой Kubernetes, используется пакетный менеджер Helm. В GitHub опубликованы различные Helm Charts: для разворачивания базовой IaaS на основе OpenStack, а также дополнительные, что требуются для SAP Converged Cloud.

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



На момент анонса SAP Converged Cloud в нём была доступна лишь одна availability zone в Австралии с планами добавить ещё две европейские в течение 2 последующих недель и добиться распространения облака на 19 дата-центров в 13 регионах к концу 2018 года. В GitHub проекта SAPCC можно найти и другие интересные репозитории используемых в инфраструктуре компонентов — например, операторы для управления OpenStack на Kubernetes (подробнее об операторах для Kubernetes мы писали в этой статье) или утилиту для проверки сетевых настроек кластера Kubernetes.

Напоследок отмечу, что в этом же году СУБД SAP HANA была сертифицирована для запуска на Google Cloud Platform (GCP).

Другие статьи из цикла


  1. Истории успеха Kubernetes в production. Часть 1: 4200 подов и TessMaster у eBay
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/334770/


Метки:  

Кейс: как организовать мультиканальную поддержку клиентов на примере одного хостинг провайдера

Пятница, 04 Августа 2017 г. 08:30 + в цитатник
Мультиканальность – один из главных трендов в маркетинге, ритейле и клиентском сервисе. В этой статье мы расскажем об организации многоуровневой мультиканальной системы поддержки с помощью Deskun. В качестве примера рассмотрим службу поддержки одного из наших клиентов. Название компании клиента изменено, чтобы не сочли за рекламу.



Описание проблемы

Хостинг провайдер CoolXost – сервис, предоставляющий услуги российским и зарубежным компаниям. Прием обращений в техподдержку происходит через форму обратной связи на сайте или отправкой письма на ящик поддержки (support@coolxost.com), после чего они поступают на общую корпоративную почту компании. Основная проблема – большой поток писем, который никак не структурирован. Все сообщения накапливаются в основном почтовом аккаунте компании в G Suite, где нет возможности назначить ответственного за решение проблемы, установить приоритет и отследить ход ее решения. На все поступающие вопросы отвечают с общего ящика разработчики сервиса, что, во-первых, негативно сказывается на их продуктивности, а, во-вторых, сильно влияет на удовлетворенность клиентов.
Второстепенная проблема заключается в том, что никто не ведет отдельный учет пожеланий и запросов пользователей по улучшению функционала сервиса.

Внедрение Deskun

Руководство CoolXost поставило задачу: внедрить систему обработки заявок и расширить штат службы поддержки. В качестве helpdesk-решения был выбран сервис Deskun. Основные причины выбора – интеграция с Gmail, очень низкая цена по сравнению с аналогами и возможность подключить сразу несколько каналов связи, обрабатывая все заявки в едином месте.
Для поддержки пользователей CoolXost были подключены следующие каналы:

  • Электронная почта
  • Онлайн чат на сайте
  • Facebook, Vk.com и Telegram (для последнего канала был отдельно создан бот Telegram)

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


На 1й линии поддержки специалисты обрабатывают заявки, которые поступают в онлайн чат, подключенные мессенджеры или почту, а также вручную создают тикеты в канале для учета предложений. На первую линию CoolXost наняли и обучили специальных сотрудников. Кристина и Лиза – коммуникабельные девушки с навыками слепой печати, знанием русского и английского языков, а также безупречной грамотностью; знают основы функционирования хостинг провайдера.
На 2й линии поддержки работают технические специалисты, которые также имеют доступ к общей почте. Эти сотрудники уже работали заявками в CoolXost и обладают высоким уровнем технической грамотности. Сотрудники второй линии обрабатываю те задачи, с которыми не смогли справится Кристина и Лиза.

Схема работы службы поддержки

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


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


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

Заключение

Мы показали лишь один из возможных сценариев работы мультиканальной службы поддержки клиентов.
Итак, чтобы организовать качественную поддержку клиентов, недостаточно внедрить новое ПО. Нужна продуманная структура поддержки с грамотными и квалифицированными специалистами. В данном кейсе большим преимуществом было то, что руководство CoolXost осознавало потребность в таких специалистах, не пожалело средств на их привлечение и обучение.
Благодаря внедрению сервиса Deskun, компания CoolXost решила первичную проблему – большой поток входящих обращений был структурирован. В связи с созданием первой линии поддержки удалось повысить качество клиентского сервиса. Более того, это освободило специалистов второй линии от ненужных действий, позволило им больше времени уделять разработке и улучшению сервиса.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/334822/


Метки:  

JavaScript как праздник

Пятница, 04 Августа 2017 г. 05:40 + в цитатник
Эта пятничная статья будет ответом на статью JavaScript как явление, в которой некий пользователь (видимо по случаю прошедшего дня ВДВ) решил избить JavaScript. Лично я пишу на JavaScript уже 15 лет, искренне считаю его одним из самых мощных ЯП на сегодняшний день, поэтому не позволю его обижать. В статье будет, по возможности, аргументированная позиция относительно основных тезисов критики. По правде, вышеупомянутая статья не стоит того, чтобы на неё отвечать, но у новичков действительно часто возникают проблемы с JavaScript. Вводит в заблуждение приставка Script и несерьёзный имидж языка, а не деле обнаруживается, что язык применяется от front-end и back-end до дескопных и мобильных приложений, программирования интегральных микросхем, обработки видео и в множестве других сфер. Я давно хотел раскрыть частые заблуждения про JavaScript, а тут как раз появился повод, поэтому welcome под кат.
image

На данный момент JavaScript — самый популярный ЯП на планете. И, как бы я не уважал TypeScript, Java, C#, Go, другие языки — у них нет шансов изменить статус кво. Хотя вероятно они очень хороши для своих задач. Причина по которой JavaScript стал таким популярным (кроме монополии в веб) — его демократичность. Он позволяет программировать и в процедурном стиле, и в объектно-ориентированном и в функциональном. Он накладывает минимальные ограничения на разработчика, позволяя творить любую «глупость», но ирония состоит в том, что то, что является глупостью применимо к одному классу задач, применимо к другому является более чем целесообразным. Легенда гласит, что JavaScript был создан за 2 недели. И опять ирония жизни, в таких условиях можно заложить в язык только самое главное, оставив за бортом всё лишнее, традиционное, «правильное». Первая версия языка получилась очень компактной и лаконичной. Все эти get/set, const и await появились гораздо позже. Изначальные принципы языка были настолько хороши, что 10 лет (с 1999 по 2009) язык прожил вообще без изменений. Конечно к этому были и негативные причины, политика Microsoft и Mozilla, многое другое, но, уверен, не многие из других популярных языков смогли бы пройти такое же испытание и подняться после этого. Просто представьте, что стало бы с TypeScript или Rust после 10 лет отсутствия обновлений. Причина по которой JavaScript выжил очень проста, он решает одну задачу и делает это идеально.

JavaScript не претендует быть синтаксическим сахаром или набором клёвых фич, их программист может написать/подключить и сам. JavaScript скрывает от вас аппаратную часть устройства, даёт возможность делать что угодно с логикой и просто оставляет вас с этим. Хотите eval — пожалуйста, хотите переопределить любой объект — нет проблем, хотите передать в функцию то, что «нельзя» передавать — welcome, потому что это «нельзя» только в вашей голове. Программистам на Go или C# очень сложно понять почему это хорошо. Чтобы не вызвать на себя их хейт, это прекрасные языки, просто другие. Классически в языках ставятся барьеры, не дающие программистам отстрелить себе ногу, это и проверка типов, и различные обязательные best practices, и многое другое. В JavaScript этих барьеров нет, вы в праве стрелять куда угодно, и в 0.01% случаев стрельба в ногу тоже имеет смысл. Это можно сравнить со спортивным автомобилем, у многих языков заблокирована часть функций, а в JavaScript — нет. Если вы водите плохо — возможно это для вас минус, опасности и т.п., но если вы действительно хорошо разбираетесь и в языках, и в архитектуре, и в парадигмах, и умеете всем этим пользоваться — лучше языка чем JavaScript для общих задач вам не найти. Для частных — можно, для общих, универсального — объективно нет. Многие возразят, мол в Java тоже можно создавать словари, аналог JS-объектов, Python и Ruby тоже не типизованные, много где есть и eval и duck typing, но применять это так просто, как в JavaScript не получится нигде. В Java, например, словари это только дополнение, приделанное на типизованную класс-ориентированную основу, а в JavaScript — это основа языка, и создаётся всего двумя символами "{}". Это как если бы в спортивном автомобиле форсаж вызывался не тремя кнопками и рычажком, а одной кнопкой под большим пальцем правой руки. Свобода не просто возможна, она поощряется.

Многих это вводит в ступор, потому что они привыкли, что им не дадут расшибить лоб. Это как переход с Windows на Linux. «Я ввёл sudo rm -Rf / и всё сломалось. Не система, а г… но». С такими рассуждениями путь до мастера будет очень долгим. Порог входа в JavaScript был и остаётся очень низким, это даёт повод многим новичкам ругать то, в чём они не разобрались. Причём у человека может быть 20 лет опыта в Lisp, но по JavaScript он всё равно даже документацию не читал, типа и так умный. Этого достаточно, чтобы писать простые программы, но если человек хочет понять почему true < 2 === true, и почему это правильно и логично — прочитать про преобразования типов must have, а в идеале всю документацию (или хорошую полную книгу), это не долго.

Теперь отвечу на критику по пунктам:

Вопрос 1: однопоточный рантайм


Это очень удобно, не возникает проблем с блокировками и владением объектами и других прелестей многопоточности. Зачем вам нужна многопоточность? Выполнять программу дальше пока ждёте выполнения долгой операции? Колбеки справляются с этим гораздо лучше. NodeJS на одной средней машинке может держать по 100 000 коннектов. Сколько бы их было при замене колбеков на поточный подход? На многопроцессорных машинках js прекрасно параллелится запуском локального кластера. 8 ядер — 8 процессов, 16 ядер — 16 процессов, каждый независим друг от друга и прост внутри. Это реальный пример из практики применения, как главной серверной технологии онлайн игры с 8 миллионами пользователей. Работа с ассинхронностью/потоками это не слабость, а одно из мощнейших преимуществ JavaScript. Это может требовать переучивания и изменения привычек, но поверьте, вы приобретёте очень многое.

Вопрос 2: отсутствие единой системы / стандартов реализации модулей


В JavaScript два основных варианта работы с модулями:
  • официальный, через import
  • и традиционный, через require

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

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


Сочувствую вам с коллегами, которые «творят что хотят». Или коллегам с вами. В веб-разработке есть несколько типовых структур проекта, как правило используется одна из них, но это нигде не постулировано, и каждый действительно волен писать свою программу исходя из своего взгляда на целесообразность. А что вы хотели? Это самый популярный язык на планете, а не какой-то DSL. В разных сферах применения JS разные стандарты, и это правильно. Что касается практики, я, например, прекрасно читаю даже обфусцированный код библиотек, чего и вам желаю. Нарабатывайте опыт и изучайте распространённые паттерны.

Вопрос 4: слабые типы с неявными (и порой довольно странными) преобразованиями


Странными для кого? Программистов Java, C#, PHP, Python, Lisp или Ams? Скажете asm не странный? А Lisp? Мир гораздо богаче вашего любимого языка и то, что для одних странно, для других норма. Посмотрите хотя бы на Haskell с его монадами и функторами (очень мощные штуки, кстати. В JS тоже используются, в jQuery). В институте этому не учили, правда? ООП это только малая часть мира, настолько малая и настолько заезженная, что даже скучно говорить. А типы в JavaScript не слабые, их принципиально нет (кроме примитивных). WeakMap и прочее ввели только для того, чтобы порадовать переселенцев из других языков. Перечитайте про duck typing и научитесь им пользоваться, проблем с типами у вас не возникнет.

Вопрос 5: отсутствие нормальных классов / ООП
Опять же, специально для переселенцев с других языков и для IDE уже довольно давно введены классы. Их поддерживают все основные браузеры, не говорю уже про NodeJS. ООП в JavaScript богаче, чем в большинстве других языков. Можете наследовать через классы, можете через прототипы. Во многих случаях правильного применения JavaScript прототипы оказываются быстрее, удобнее и логичнее, а программа компактнее и более читаемой. Но опять же, этому не учат в институте, а JavaScript сообщество должно потом доказывать, что так тоже можно.

Вопрос 6: отсутствие единого вменяемого и работающего статического анализатора кода (добро пожаловать в чудесный мир глупейших ошибок типа undefined is not a function)


Это общая проблема всех интерпретируемых языков с eval, и отказываться от этой мощи ради возможности ловить 5% самых глупых ошибок — сомнительная идея. А вообще, развивайте дисциплину кода, не всё время за юбкой IDE прятаться. Это не стёб, анализаторы это хорошо, но если для вас проблема такие ошибки — как-то вы не правильно программируете.

Вопрос 7: отсутствие вывода типов в самом языке или в каком-либо инструменте


Это есть, изучайте синтаксис. Один из вариантов, в зависимости от ситуации:
typeof myVar
myVar.constructor


Вопрос 8: этот чудесный контекст this (что это значит this в этом месте кода — объект? функция?)


При правильном использовании проблем с this не возникает. Если вы вызываете функцию как myObj.func(), то можете быть уверены, что this будет равен myObj. При назначении колбеков или передаче функций как параметров, информация о myObj теряется и, если необходимо, следует задавать его явно через bind. Это логично и понятно знающим JS, так как вы, например, можете сделать так myObj2.func = myObj.func, и функция будет методом сразу нескольких сущностей. Не правильно назначать this равным myObj или myObj2, так как они симметричны. Не правильным было бы и использовать лексический контекст, так как это внесёт путаницу в миксины, прототипное наследование и многое другое. Поэтому this в таких случаях равен window или undefined, в зависимости от использования strict mode. Но это не должно вас волновать, и это принципиальный момент. Это один из типичнейших примеров стрельбы себе в ногу. На что вы надеетесь, вызывая this у функции, вызванной без контекста? Явно не на что-то хорошее. Есть много таких примеров, люди складывают массивы с числами, делят получившееся на объект и жалуются, что получают странные результаты. Во-многих странных вещах есть логика, но в особо странных это может быть просто произвол. JavaScript гибкий язык и позволяет вам делать то, с чем с C++ у вас программа даже не скомпилировалась бы, в надежде на то, что вы знаете, что делаете. Не нужно пренебрегать этим доверием и творить не весть что. Если вы хотите результат, то просто используйте this правильным логически обоснованным образом, а фразы а-ля «я воткнул себе нож в горло и у меня 2 раза потекла тёмная кровь, а 2 раза светлая, почему так?» оставьте для холиваров. И не надо хвастаться тем, что вы знаете чему в данной неочевидной ситуации равно this или как складываются несуммируемые типы. Профессионально правильной позицией будет, как ни странно, не знать это и не использовать, так как в разных браузерах и в разном контексте вы можете получить разный результат. Но JavaScript всё равно позволяет вам, если вы хотите это использовать, например для того, чтобы отличить PhantomJS c поддельным User-agent от настоящего Chrome — дорога открыта.

Вопрос 9: абсолютно дурацкая реализация pattern matching ( паттерн матчишь пустой список / объект — без проблем, извлекаешь оттуда undefined, ты же именно это имел ввиду, да? ) и здесь опять привет cannot read property foo of undefined


Два совета:
  1. не делайте логических ошибок. Ваши ошибки — не вина языка
  2. если хотите сделать регулярные выражения удобнее — используйте или напишите библиотеки. Похоже на то, что ругать C# за то, что он с Facebook не интегрирован. Руки есть, голова есть, напишите что хотите, или возьмите одну из многочисленных библиотек.


Вопрос 10: отсутствие единой технологии работы с асинхронным кодом — колбэки, примисы, фьючерсы, async (если в проекте более одной зависимости из npm то гарантированно в коде появятся все из них вперемешку)


И колбеки, и промисы, и async/await — нативные, поэтому код они не утяжеляют. Не знаю, что вы называете фьючерсами, я этим не торгую. И это прекрасно, что у вас есть выбор, что использовать. Колбэки это основа всего и ни промисы ни async/await без них не будут работать, это базовый кирпичик языка. Промисы и async/await прекрасно совместимы друг с другом и вы легко можете использовать await с любой функцией, возвращающей промис. Если же вы имели ввиду популярную библиотеку async для node, то сочувствую, ваши знания JS устарели. Библиотека хорошая, но используется всё реже ввиду появления вышеуказанного функционала в ES6. Но подтянуть её в зависимости на ноде тоже не страшно, серверные зависимости не отдаются пользователю и легко бекапятся, на случай удаления с npm (на моей практике такого не было ни разу). А ещё есть Fibers, и Sync, и много классных инструментов, используемых по назначению врача. Выбирайте тот, что больше подходит под конкретные задачи, и не жалуйтесь, что их слишком много.

Вопрос 11: const ( который на самом деле НЕ const )


Не знаю, почему вы так решили. Моя простая проверка в консоли показала обратное:
const a = 5
const a = 4
VM1825:1 Uncaught SyntaxError: Identifier 'a' has already been declared
    at :1:1

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

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


Плата за свободу творчества и отсутствие премодерации. Проблема не большая, просто всегда смотрите на число скачиваний или звёзд на github. Качество топовых пакетов очень высокое. Мало популярные тоже бывают неплохие, бывают и такие, как вы нашли. Ответственность за используемые зависимости полностью на вас. Это открытое сообщество и никто вам жёванную пищу в клюв класть не будет. На мой взгляд, эта ситуация лучше, чем в решениях от одного поставщика/судьи, так как у библиотек сотни тысяч вендоров и тысячи из них очень достойные. Если хотите однообразия — посмотрите на решения, например, от Sencha. Они платные, но про них были вполне неплохие отзывы. В npm тысячи классных библиотек, но вам надо было найти плохую и выстрелить себе в ногу. Стреляйте, кто же вам запретит.

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

https://habrahabr.ru/post/334858/


Метки:  

Конец CSRF близок?

Пятница, 04 Августа 2017 г. 02:09 + в цитатник

image


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


Древний змий


Уязвимость CSRF или XSRF (это синонимы), кажется, существовала всегда. Её корнем является всем известная возможность делать запрос от одного сайта к другому. Допустим, я создам такую форму на своем сайте.



Ваш браузер загрузит мой сайт и, соответственно, мою форму. Её я могу незамедлительно отправить, используя простой javascript.


document.getElementById("stealMoney").submit(); 

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


Способы защиты от CSRF


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


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


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


accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8  
accept-encoding: gzip, deflate, br  
cache-control: max-age=0  
content-length: 166  
content-type: application/x-www-form-urlencoded  
dnt: 1  
origin: https://example.com  
referer: https://example.com /login  
upgrade-insecure-requests: 1  
user-agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36

Защитные токены


Существуют два способа использования уникальных защитных токенов, но принцип их использования един. Когда пользователь посещает страницу, скажем, страницу банка, то в форму перечисления денег вставляется скрытое поле с уникальным токеном. Если пользователь действительно находится на сайте банка, то вместе с запросом он отправит этот токен, так что можно будет проверить, совпадает ли он с тем, что вы вставили в форму. При попытке CSRF атаки атакующий никогда не сможет получить это значение. Даже в случае запроса к странице Same Origin Policy (SOP) не позволит ему прочитать страницу, где есть данный токен. Такой метод хорошо себя зарекомендовал, однако он требует от приложения логики по внедрению токенов в формы и проверки их подлинности при входящих запросах. Еще один похожий метод заключается во внедрении такого же токена в форму и передачи куки, содержащего то же значение. Когда настоящий пользователь отправляет форму, то происходит сверка значения токена в куки со значением в форме. Если они не совпадают, то такой запрос не будет принят сервером.



Так в чем проблема?


Вышеописанные методы защиты давали нам достаточно надежную защиту против CSRF на протяжении довольно долгого времени. Конечно, проверка заголовков origin и referer не на 100% надежна, так что большинство сайтов полагается на тактику с уникальными токенами. Сложность состоит в том, что оба метода защиты требуют от сайта внедрения и поддержки решения. Вы скажете, что это совсем несложно. Согласен! Никогда не возникало проблем. Но это некрасиво. По сути мы обороняемся от поведения браузера хитрым способом. А можем ли мы просто сказать браузеру перестать делать вещи, которые мы не хотим, чтобы он делал?.. Теперь можем!



По сути Same-Site куки могут свести на нет любую CSRF атаку. Насмерть. Чуть более, чем полностью. Адьёс, CSRF! Они действенно и быстро помогают решить проблему безопасности. К тому же применить их чрезвычайно просто. Возьмем для примера какую-то куку.


Set-Cookie: sess=smth123; path=/ 

А теперь просто добавьте атрибут SameSite


Set-Cookie: sess=smth123; path=/; SameSite

Всё, вы закончили. Нет, правда! Используя данный атрибут, вы как-бы говорите браузеру предоставить куки определенную защиту. Существую два режима такой защиты: Strict или Lax, в зависимости от того, насколько серьезно вы настроены. Атрибут Same-Site без указания режима будет работать в стандартном варианте т.е. Strict. Вы можете выставить режим так:


SameSite=Strict  
SameSite=Lax 

Strict


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


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


Lax


Режим Lax решает проблемы с разлогированием описанную выше, но при этом сохраняет хороший уровень защиты. В сущности он добавляет исключение, когда куки передаются при навигации высокого уровня, которая использует “безопасные” HTTP методы. Согласно https://tools.ietf.org/html/rfc7231#section-4.2.1 безопасными методами считаются GET, HEAD, OPTIONS и TRACE.


Вернемся к нашему примеру атаки в начале.



Такая атака уже не сработает в режиме Lax, так как мы обезопасили себя от POST-запросов. Конечно, злоумышленник может использовать метод GET.



Поэтому режим Lax можно назвать компромиссом между безопасностью и удобством пользователей.
SameSite куки защищают нас от CSRF атак, но нельзя забывать про другие виды уязвимостей. К примеру XSS или браузерные атаки по времени.


От автора перевода: К сожалению, пока SameSite куки поддерживают только Chrome и Opera, а также браузер для андроида. Пруф: https://caniuse.com/#feat=same-site-cookie-attribute


Оригинал: https://www.kuoll.com/the-end-of-csrf/
До этого появлялась здесь: https://scotthelme.co.uk/csrf-is-dead/

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

https://habrahabr.ru/post/334856/


Метки:  

Когда нужна локализация: почему так трудно найти хорошего переводчика

Четверг, 03 Августа 2017 г. 22:30 + в цитатник
Процесс создания переводного и оригинального контента не слишком сильно отличаются между собой: по-настоящему качественный перевод требует не только знания языка, но и творческого усилия. Если перед автором оригинального текста стоит задача четко изложить свои мысли на, как правило, родном для него языке, то переводчик в равной степени должен понимать, что хотел сказать автор — и уметь пересказать это в соответствии с нормами целевого языка так, чтобы это было приятно читать.


Типичные трудности перевода

Классический пример симбиоза знания языка и творческого начала в ходе перевода — деятельность братьев Стругацких. Кроме создания собственных произведений, они оба работали как переводчики с английского и японского под псевдонимами С. Бережков, С. Победин и С. Витин. И если вы читали советские издания Азимова «Как им было весело», Нортон «Саргассы в космосе» или Уиндема «День триффидов» — то это были переводы Стругацких.

Как организовать работу с текстом


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

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

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

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

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

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

  • подбор исполнителя;
  • проверка результата на фактические ошибки;
  • проверка результата на стилистические ошибки.

Подбор исполнителя


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

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

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

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

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

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

Проверка результата на фактические ошибки


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

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

Проверка результата на стилистические ошибки


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

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

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

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

В результате англоязычный вариант:
Regards, 
Ivan Ivanov


Превратился в:
С уважением,
Иван Иванов


Хотя нет никаких причин не писать просто:
С уважением Иван Иванов


Кальки имеют способность проникать в язык и укореняться в нем («человек-овощ» от англ. «vegetable» и глагола «to vegetate» — «прозябать», «вызовы нашего времени» от англ. «challenge» — «сложная задача», «проблема») поэтому приведем еще несколько примеров калек и буквализмов, употребление которых отличает плохого переводчика от хорошего.

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

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

Ну и очевидно, что плохого переводчика от хорошего отличает понимание и корректный перевод фразеологизмов. Справедливости ради хочется заметить, что в каждом языке есть непереводимые фразеологизмы. Например американский «Send The Elevator Back Down», который родился на Манхэтенне с его небоскребами, буквально переводится как «спустить лифт обратно вниз», а по сути означает «оказать помощь тем, кто находится ниже тебя в иерархии/в худшем положении». Или перевести «Earworm» так, чтобы он гармонично вписался в текст, если и не сложно, то уж точно бывает проблематично.

Итого


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

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

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

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

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

https://habrahabr.ru/post/334850/


Геометрия в компьютерных играх

Четверг, 03 Августа 2017 г. 21:37 + в цитатник
Всем привет! Когда-то давным-давно я делал простенькие игрушки на Flash. Например: игрушка — провести курсор мышки через лабиринт, не касаясь стен и уворачиваясь от всяких движущихся объектов. Некоторые из этих объектов двигаются по заданной траектории, некоторые гонятся за курсором, а некоторые стреляют в курсор другими движущимися объектами.

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



Задачка 1: нарисовать стены. И сразу возникает Задачка 2: определить касается ли точка стены или нет (проиграл ты или продолжать игру).

Для этого я поделил стены на фигуры: прямоугольники и многоугольники.

С прямоугольниками всё просто: Просто нарисовать:

canvas.drawRect(x1, y1, x2, y2, paint);

и просто проверить находится ли точка внутри него или нет.

public boolean isTouched(float x, float y){
    return (x>x1)&&(xy1)&&(ycode>

С многоугольником дело обстоит не так просто: нарисовать его уже немного сложнее.

Path path = new Path();
paint.setStyle(Paint.Style.FILL);
path.moveTo(x1, y1);
path.lineTo(x2, y2);
path.lineTo(x3, y3);
.....
path.lineTo(x1, y1); //замыкаем фигуру
path.close();
canvas.drawPath(path, paint);

А проверить касание с точкой ещё сложнее. Я попытался вспомнить школьный курс геометрии, потом погуглил и нашёл такое решение:

Многоугольник обязательно должен быть выпуклым.



И описывать его надо обязательно по часовой стрелке.



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

Для этого есть простая формула.

private boolean isLeftHandSituated(float dotX, float dotY, float x1, float y1, float x2, float y2){
    float d = (dotX - x1) * (y2 - y1) - (dotY - y1) * (x2 - x1);
    return d>0;
}

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

Задачка 3: жёлтый смайлик. Если точка приближается к нему на определённое расстояние, то он гонится за точкой. Вычислить это определённое расстояние (distance) можно по теореме Пифагора:

float dx = dotX - smileX;
float dy = dotY - smileY;
double distance = Math.sqrt((dx * dx + dy * dy));

Смайлик гонится за точкой. Что это значит? Это значит что через каждый определённый интервал времени (в следующем кадре) его координаты перемещаются на определённое расстояние ближе к точке. Это расстояние за кадр по сути является скоростью. Я назвал переменную speed.



Вычислить координаты смайлика в следующем кадре можно так:

private float speed=5;
double rate = speed / distance;
newSmileX = smileX + (float) (dx * rate);
newSmileY = smileY + (float) (dy * rate);

Задачка 4: пушка всё время направлена на точку. Как вычислить угол на который её надо повернуть? Очень просто. Для этого существует метод atan2.

float dx = dotX - cannonX;
float dy = dotY - cannonY;
double theta = Math.atan2(dx, dy); //получаем угол в радианах
angle = Math.toDegrees(theta); //переводим его в градусы.

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

https://habrahabr.ru/post/334848/


[Перевод] Лицензирование музыки для инди-разработчиков

Четверг, 03 Августа 2017 г. 20:49 + в цитатник
image

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

Зачем лицензировать музыку?


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

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

Поиск песен


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

Первая остановка — музыкальный онлайн-магазин, например, ITunes или CD Baby. В них продаётся множество композиций инди-исполнителей в разных стилях, а на веб-сайтах есть удобные функции поиска. Поищите и прослушайте ознакомительные фрагменты и сохраните понравившиеся. Ещё один отличный способ — поиск в видео YouTube. Многие исполнители выпускают видео и записи концертов. Также можно поискать в более специализированных онлайн-магазинах. Мне было довольно просто найти несколько индийских магазинов, продающих музыку в подходящем для Bollywood Wannabe стиле.

Ещё один хороший источник информации — специализированные веб-сайты. Ищите сайты, посвящённые понравившемуся вам стилю музыки: фан-сайты, онлайн-радио, новостные сайты, блоги и форумы. Одним из лучших источников для меня стал сайт, посвящённый музыке в стиле «бхангра» и публиковавший информацию о песнях и видео, выпущенных популярными исполнителями бхангра. Благодаря этому сайту я нашла половину песен для Bollywood Wannabe.

Поиск контактов


Мы обнаружили песню, которую хотим лицензировать. Следующий шаг — найти того, с кем нужно договориться о лицензировании. В большинстве онлайн-магазинов есть очень мало информации об авторах песен, но, по крайней мере, удаётся найти их имена и/или названия студий, которым принадлежат права. С помощью этой информации можно найти официальный сайт этого исполнителя/студии. Это может быть сложнее, чем кажется. Запросы в Гугле часто выдают ссылки на новостные статьи, интервью и видео, и только потом официальные веб-сайты, если они вообще существуют. В названиях маленьких студий часто используются обычные слова. Поиск по таким словам приводит к куче ссылок на никак не связанные с этими студиями сайты. Если вам не удаётся найти официальную страницу, то попробуйте поискать страницу на Facebook. В разделе «Информация» (About) обычно есть ссылка на официальный сайт или контактная информация.

Как с ними связаться


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

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

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

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

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

image

Подготовка договора


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

  • Ваши имя и адрес
  • Имя и адрес правообладателя
  • Эксклюзивным ли будет использование
  • Территория действия лицензии
  • Срок действия лицензии
  • Название композиции
  • Описание всех допустимых вариантов использования композиции
  • Владелец прав на композицию и условия его упоминания
  • Оплата и лицензионные отчисления
  • Подпись и даты

При написании договора не стоит забывать о следующих аспектах:

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

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

Переговоры


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

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

image

История Bollywood Wannabe


Нет ничего лучше примера из жизни, так что я расскажу о своём опыте с Bollywood Wannabe. Сначала я хотела найти композитора, который хочет писать музыку для Болливуда и готов работать за низкую оплату ради получения опыта. К сожалению, у меня не было никаких контактов в этой индустрии и я не знала, где их искать. К тому же я не жила в Индии и рядом не было индийского сообщества. Я искала форум или онлайн-сообщество композиторов, но не нашла ничего полезного. Единственные композиторы, которых я смогла найти, были профессионалами, недостижимыми для моего бюджета, или любителями с очевидными музыкальными проблемами. У меня не хватило бы денег на найм профессионала и не было контактов и знаний, чтобы найти талантливого любителя. Настало время плана Б.

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

  • Хоть раньше я и работала в игровой индустрии, это была моя первая игра в качестве инди-разработчика.
  • Я была тем самым «бедным инди-разработчиком» и у меня не было денег на большой аванс или оплату.
  • Я мало знала о Болливуде и индийской музыке в целом, поэтому не представляла, где искать индийских инди-исполнителей.
  • У меня не было контактов в мире музыки, а также опыта в лицензировании.
  • Мне нужна была аутентичная индийская музыка, предпочтительно с текстами на хинди или панджаби, но я не знала этих языков. Это было особенно проблематично, потому что мне нужны были песни, которые хотя бы условно вписывались в сюжет игры.

Поиск хороших песен был первым испытанием. Вскоре я нашла CD Baby и сайт, специализирующийся на музыке бхангра, на котором можно было искать новые релизы. Найдя несколько понравившихся песен, я столкнулась с ещё одной проблемой: мне были непонятны тексты. Хоть я и осознавала, что скорее всего не удастся найти песни, полностью описывающие сюжет игры, я хотела, чтобы текст хотя бы немного соответствовал теме уровня. К тому же мне хотелось избежать спорных текстов. Это стало проблемой, потому что большинство понравившихся песен было на панджаби, а я не знала этого языка. Иногда песни сопровождались описаниями, но у большинства их не было. Google translate тоже не помог, потому что в его списке языков не было панджаби. В итоге я нашла онлайн-словарь, с помощью которого смогла перевести достаточно слов, чтобы понять песню, по крайней мере, когда у меня был текст. Иногда у меня было только название песни и несколько слов, которые я уже могла различать. На большинство песен были сняты видео и в них частично использовались английские слова, поэтому я более-менее могла понять общий смысл.

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

Это был очень долгий процесс — чтобы найти десять песен к игре, мне понадобилось почти два года. Конечно, мои запросы были очень специфическими и много времени я в первую очередь потратила на поиск песен. Однако всё равно, лицензирование песни, начиная с первой версии договора до подписанного контракта, обычно занимало около месяца. Но в конце концов работа себя оправдала. Мне не удалось бы найти и купить музыку для Bollywood Wannabe никаким другим способом.

Выводы


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

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

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

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

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

https://habrahabr.ru/post/334802/


Метки:  

[Перевод] Как за 6 шагов узнать хороший дизайн

Четверг, 03 Августа 2017 г. 19:55 + в цитатник
Устраняем субъективность мнений.
К самому первому моему посту на Medium оставили комментарий, на который мне захотелось дать развернутый ответ. Читательница отметила, что дизайн — штука субъективная, и спрашивала, пробовал ли кто-либо формализовать принципы хорошего дизайна. Тогда я подумал: «Почему бы не попробовать?»

С этого все и началось.

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

Искусство субъективно, это игра, в которой почти нет правил. Дизайн — дело другое, сам факт, что кто-то может составить для него список принципов уже говорит о том, что в этой игре есть определенные правила. А если есть правила, значит, можно судить, применяли их или нет, следовательно, дизайн не субъективен. Но, если честно, я не могу сказать, что дизайн на 100% объективен: всегда есть вещи, которые относятся к личным предпочтениям, определяемым вашими культурой и опытом.

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

image
Знаменитая соковыжималка Juicy Salif от Филиппа Штарка (Philippe Starck)

Думаю, почти каждый согласится, что это стильный дизайн, главный вопрос — хороший ли он?

image
Неа.

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

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

Основываясь на упомянутой соковыжималке, вы уже догадываетесь, что станет первым…

1. Эффективен ли дизайн?


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

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

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

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

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

2. Правильно ли дизайн отражает тон?


Чтобы оценить, подходит тон или нет, сначала нужно понять две вещи: бренд и аудиторию.

Бренд

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

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

Аудитория

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

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

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

image

ByronHamburgers

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

image
McDonalds

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

3. Выдерживает ли дизайн проверку временем?


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

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

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

image
Итерации логотипа Старбакс за 1971, 1987, 1992, 2011 гг.

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

Соответствует ли дизайн своему жизненному циклу? Если да, продолжим. Осталось всего 3 принципа.

4. Есть ли в вашем дизайне помехи?


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

image
Тот случай, когда текст слишком мал.

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

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

«Богатство информации ведет к бедности внимания» — Marty Neumeier

Если дизайн хорош, он невидим. Люди легко находят то, что им нужно.

Если дизайн видно — он плохой.


Отлично, осталось всего 2 пункта.

5. Дизайн визуально привлекателен?


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

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

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

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

Следующий пункт будет завершающим.

6. 1+1=3?


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

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

image
Логотип FedEx (1994)

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

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

Финальные мысли


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

https://habrahabr.ru/post/334842/


Метки:  

[Из песочницы] Аналитические системы для мобильных приложений: тест и критерии выбора

Четверг, 03 Августа 2017 г. 19:20 + в цитатник
image

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

При выборе аналитической системы, Вы можете столкнуться с несколькими сложностями:

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

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

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

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

Определите свою цель


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

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

Привлечение новых игроков


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

Игроков надо не только привлечь, но и удержать в игре. Для этого вы должны быть уверены в том, что они интуитивно понимают, что им надо делать, могут быстро почувствовать удовлетворение от игры и захотят возвращаться в игру вновь и вновь. Чтобы определить, легко ли новичкам разобраться с геймплеем, затягивает ли их игра необходимо проанализировать, как игроки проходят туториал и первые уровни игры (onbording analysis), какой процент игроков возвращается в игру (Stiky factor, Retention). Также необходимо оценить качество трафика по количеству и качеству платящих игроков (Paying share, ARPU, ARPPU).

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

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

image

Увеличение прибыли


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

image

Повышение вовлеченности


Здесь вам нужно исследовать поведение пользователей внутри игры — как они играют, что им нравится или не нравится в текущем геймплее. Проводить опросы среди игроков — какой контент они хотят, каких возможностей им не хватает. Список желаний игроков поможет вам создавать новый контент и улучшить геймплей. Дальше нужно анализировать, как пользователи восприняли нововведения — что понравилось, а что нет. Так вы начнете понимать свою аудиторию и сможете повысить вовлеченность игроков. Уделите особое внимание поведению и желания платящих пользователей. Исследуете каждый тип платящих игроков в отдельности. Это вам позволит не только повысить вовлеченность, но и увеличить LTV.

image

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

С третьей трудностью, вам поможет тест «Выбор системы мобильной аналитики». Ответив на 6 вопросов, вы получите по e-mail PDF файл со списком аналитических систем, соответствующих вашим требованиям, с детальной информацией и таблицами, в которых сравниваются возможности, характеристики, преимущества и недостатки каждой аналитической системы.

Другие критерии выбора аналитической системы


По мимо цели, необходимо учитывать такие критерии выбора, как:

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

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

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

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

Разработать свою или взять готовую


Делать свою аналитическую систему полезно в двух случаях:

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

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

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

Лучший способ определить подходящую систему — выбрать несколько и потестировать. У большинства аналитических платформ есть триальный период — 2-4 недели. Этого хватит, чтобы понять, с каким сервисом вам удобно работать.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/334836/


Метки:  

[Из песочницы] ERP: с чего начать внедрение. Альтернативный взгляд со стороны клиента

Четверг, 03 Августа 2017 г. 18:14 + в цитатник
Дисклеймер: пост не претендует на объективность. Исключительно субъективное мнение на основании не слишком большого опыта внедрения ERP на стороне клиента. В статье описаны некоторые действия, которые желательно сделать до заключения контракта на внедрение ERP-системы.

Что такое «консалтинг»?


Предлагаю для начала определиться с терминологией.

Мне кажется при внедрении ERP представители бизнеса несколько по-иному понимают понятие «услуги консалтинга», чем представители компании-исполнителя. Давайте попробуем внести ясность. Определение из Википедии:

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

Так вот, цель проекта – внедрение ERP-системы. Именно это прописывается в договоре с исполнителем. В рамках проекта внедрения консультанты НЕ будут выполнять аудит и реинжиниринг бизнес-процессов как таковых.

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

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

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

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

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

Что нужно сделать ДО заключения договора с консалтинговой компанией


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

    Нужно простыми словами пояснить и бизнесу, и компании-исполнителю зачем необходима ERP–система. Ведь что-то же сподвигло рассматривать вопрос о ее внедрении? Что именно? Зачем? Необходимо сформулировать эту мысль и изложить на бумаге.

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

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

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

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

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

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

    Поэтому перечень требований к функциональности системы:

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

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

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

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

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

  4. Оценить различные варианты внедрения системы – поэтапный и «все сразу».
    При сравнении стоит обратить внимание на следующие моменты:

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

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

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

Надеюсь, что моя статья уменьшит количество вопросов «А что, и так можно было?» на чьем-либо проекте.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/334826/


Метки:  

Семейство марки с поворотом (Tag) для загружаемых семейств Autodesk Revit

Четверг, 03 Августа 2017 г. 16:15 + в цитатник
image

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

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

Подробное описание

Категория и параметры марки:

image

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

image

Вот так выглядит семейство марки. Параметр _tag_angle опосредованно управляет поворотом марки и ее частей. А непосредственно пользователь указывает угол поворота в параметре tag_angle:

image

Да Revit не любит прямых ходов ) Мне нужна дополнительная проверка от того, не ввел ли пользователь или клиентская программа для Revit угол в 360 градусов. Может вам понадобятся другие условия проверки пользовательского ввода. Параметр _tag_angle отвечает за то, что семейство будет работать с правильными данными.

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

image

Можете развернуть копию группы «Tag» вправо на 40 градусов для того что бы она расположилась ровно. А теперь пару слов как устроена группа «Tag».

image

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

image

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

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

image

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

image

Краткая инструкция

  • Открыть семейство.
  • Не редактировать уже размещенные элементы.
  • Разместить в любом месте копию группы «Tag» из диспетчера проекта и редактировать эту группу. Копию группы можно выровнять ровно для удобства. Основная группа исправиться следом.
  • В группе нижняя метка дублирует верхнюю, так положено. Когда угол меньше или равно 90 градусов и больше 270 показывается верхняя марка, нижняя — когда угол больше 90 и меньше или равно 270 и тогда марка правильно позиционируется в проекте.
  • Метки не удалять — редактировать существующие. Видимость меток нельзя изменять, не понимая как это работает.
  • Угол можно менять в проекте как угодно, но в семействе легче наблюдать изменения когда задан 40 градусам.
  • Копию группы «Tag» после редактирования удалить.

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

https://habrahabr.ru/post/334812/


Метки:  

[Из песочницы] Карта самоорганизации (Self-orginizing map) на TensorFlow

Четверг, 03 Августа 2017 г. 16:10 + в цитатник
Привет, Хабр! Недавно начал свое знакомство с библиотекой глубокого обучения (Deep Learning) от Google под названием TensorFlow. И захотелось в качестве эксперимента написать карту самоорганизации Кохонена. Поэтому решил заняться ее созданием используя стандартный функционал данной библиотеки. В статье описано что из себя представляет карта самоорганизации Кохонена и алгоритм ее обучения. А также приведен пример ее реализации и что из этого всего вышло.

image


О картах самоорганизации


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

SOM преобразует непрерывное исходное пространство $\mathbf{X}$ в дискретное выходное пространство $\mathbf{A}$.

$\Phi : \mathbf{X} \to \mathbf{A}$



Алгоритм обучения SOM


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

Шаг 1: Инициализация. Для всех векторов синаптических весов,

$\mathbf{w}_j = [w_{j1},w_{j2},...,w_{jm}]^T\:j = 1,2,...,l$

где $l$ — общее количество нейронов, $m$ — размерность входного пространства, выбирается случайное значение от -1 до 1.

Шаг 2: Подвыборка. Выбираем вектор $\mathbf{x} = [x_1,x_2,...,x_m]$ из входного пространства.

Шаг 3: Поиск победившего нейрона или процесс конкуренции. Находим наиболее подходящий (победивший нейрон) $i(\mathbf{x})$ на шаге $n$, используя критерий минимума Евклидова расстояния (что эквивалентно максимуму скалярных произведений $\mathbf{w}_j^T\mathbf{x}$):

$i(\mathbf{x}) = \arg\min_{j}\lVert\mathbf{x} - \mathbf{w}_j\rVert, j = 1,2, ..., l\hspace{35pt}(1)$


Евклидово расстояние.
Евклидово расстояние ($\ell_2 norm$) определятся как:$\lVert \mathbf{x} - \mathbf{y} \rVert_2 = \sqrt{\sum_{i=1}^n\lvert x_i - y_i \rvert^2}$

Шаг 4: Процесс кооперации. Нейрон-победитель находится в центре топологической окрестности «сотрудничающих» нейронов. Ключевой вопрос: как определить так называемую топологическую окрестность (topological neighbourhood) победившего нейрона? Для удобства обозначим ее символом: $h_{j,i}$, с центром в победившем нейроне $i$. Топологическая окрестность должна быть симметричной относительно точки максимума, определяемой при $d_{j,i}=0$, $d_{j,i}$ — это латеральное расстояние (lateral distance) между победившим $i$ и соседними нейронами $j$.
Типичным примером, удовлетворяющим условию выше, $h_{j,i}$ является функция Гаусса:

$h_{j,i}=\exp\Bigg(-\frac{d_{j,i}^2}{2\sigma^2}\Bigg)\hspace{35pt}(2)$

где $\sigma$ — эффективная ширина (effective width). Латеральное расстояние определяется как: $d_{j,i}^2=\lvert r_j-r_i\rvert^2$ в одномерном, и: $d_{j,i}^2=\lVert r_j-r_i\rVert^2$ в двумерном случае. Где $r_j$ определяет позицию возбуждаемого нейрона, а $r_i$ — позицию победившего нейрона (в случае двумерной решетки $r = (x, y)$, где $x$ и $y$ координаты нейрона в решетке).
image

График функции топологической окрестности для различных $\sigma$.

Для SOM характерно уменьшение топологической окрестности в процессе обучения. Достичь этого можно изменяя $\sigma$ по формуле:

$\sigma(n)=\sigma_0\exp\Bigg(-\frac{n}{\tau_1}\Bigg),\:n=0,1,2,...\hspace{35pt}(3)$

где $\tau_1$ — некоторая константа, $n$ — шаг обучения, $\sigma_0$ — начальное значение $\sigma$.
image

График изменением $\sigma$ в процессе обучения.

Функция $h_{j,i}$ по окончании этапа обучения должна охватывать только ближайших соседей. На рисунках ниже приведены графики функции топологической окрестности для двумерной решетки.
image

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

В конце обучения $h_{j,i}$ сужается до ближайших соседей.

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

$\Delta\mathbf{w}_j = \eta h_{j,i}(\mathbf{x}-\mathbf{w}_j)$

$\eta$ — параметр скорости обучения.
В итоге имеем формулу обновленного вектора весов в момент времени $n$:

$\mathbf{w}_j(n+1)=\mathbf{w}_j(n)+\eta(n)h_{j,i}(n)(\mathbf{x}-\mathbf{w}_j(n))\hspace{35pt}(4)$


В алгоритме обучения SOM также рекомендуется изменять параметр скорости обучения $\eta$ в зависимости от шага.

$\eta(n)=\eta_0\exp\Bigg(-\frac{n}{\tau_2}\Bigg)\:n=0,1,2,...\hspace{35pt}(5)$


где $\tau_2$ — еще одна константа алгоритма SOM.
image

График изменением $\eta$ в процессе обучения.

После обновления весов возвращаемся к шагу 2 и так далее.

Эвристики алгоритма обучения SOM


Обучения сети состоит из двух этапов:
Этап самоорганизации — может занять до 1000 итерций а может и больше.
Этап сходимости — требуется для точной подстройки карты признаков. Как правило, количесвто итераций, достаточное для этапа сходимости может превышать количество нейоронов в сети в 500 раз.
Эвристика 1. Начальное значение параметра скорости обучения лучше выбрать близким к значению: $\eta_0 = 0.1$, $\tau_2=1000$. При этом оно не должно опускаться ниже значения 0.01.
Эвристика 2. Исходное значение $\sigma_0$ следует установить примерно равной радиусу решетки, а константу $\tau_1$ опрелить как:

$\tau_1=\frac{1000}{\log\sigma_0}\hspace{35pt}(6)$

На этапе сходимости следует остановить изменение $\sigma$.

Реализация SOM с помощью Python и TensorFlow


Теперь перейдем от теории к практической реализации самоорганизующейся карты (SOM) с помощью Python и TensorFlow.

Для начала создадим класс SOMNetwork и создадим операции TensorFlow для инициализации всех констант:

import numpy as np
import tensorflow as tf

class SOMNetwork():
    def __init__(self, input_dim, dim=10, sigma=None, learning_rate=0.1, tay2=1000, dtype=tf.float32):
        #если сигма на определена устанавливаем ее равной половине размера решетки
        if not sigma:
            sigma = dim / 2
        self.dtype = dtype
        #определяем константы использующиеся при обучении
        self.dim = tf.constant(dim, dtype=tf.int64)
        self.learning_rate = tf.constant(learning_rate, dtype=dtype, name='learning_rate')
        self.sigma = tf.constant(sigma, dtype=dtype, name='sigma')
        #тау 1 (формула 6)
        self.tay1 = tf.constant(1000/np.log(sigma), dtype=dtype, name='tay1')
        #минимальное значение сигма на шаге 1000 (определяем по формуле 3)
        self.minsigma = tf.constant(sigma * np.exp(-1000/(1000/np.log(sigma))), dtype=dtype, name='min_sigma')
        self.tay2 = tf.constant(tay2, dtype=dtype, name='tay2')
        #input vector
        self.x = tf.placeholder(shape=[input_dim], dtype=dtype, name='input')
        #iteration number
        self.n = tf.placeholder(dtype=dtype, name='iteration')
        #матрица синаптических весов
        self.w = tf.Variable(tf.random_uniform([dim*dim, input_dim], minval=-1, maxval=1, dtype=dtype),
            dtype=dtype, name='weights')
        #матрица позиций всех нейронов, для определения латерального расстояния
        self.positions = tf.where(tf.fill([dim, dim], True))

Далее создадим функцию для создания операции процесса конкуренции:

   def __competition(self, info=''):
        with tf.name_scope(info+'competition') as scope:
            #вычисляем минимум евклидова расстояния для всей сетки нейронов
            distance = tf.sqrt(tf.reduce_sum(tf.square(self.x - self.w), axis=1))
        #возвращаем индекс победившего нейрона (формула 1)
        return tf.argmin(distance, axis=0)

Нам осталось создать основную операцию обучения для процессов кооперации и адаптации:

    def training_op(self):
       #определяем индекс победившего нейрона
        win_index = self.__competition('train_')
        with tf.name_scope('cooperation') as scope:
            #вычисляем латеральное расстояние d
            #для этого переводим инедкс победившего нейрона из 1d координаты в 2d координату
            coop_dist = tf.sqrt(tf.reduce_sum(tf.square(tf.cast(self.positions -
                [win_index//self.dim, win_index-win_index//self.dim*self.dim], 
                dtype=self.dtype)), axis=1))
            #корректируем сигма (используя формулу 3)
            sigma = tf.cond(self.n > 1000, lambda: self.minsigma, lambda: self.sigma * tf.exp(-self.n/self.tay1))
            #вычисляем топологическую окрестность (формула 2)
            tnh = tf.exp(-tf.square(coop_dist) / (2 * tf.square(sigma)))
        with tf.name_scope('adaptation') as scope:
            #обновляем параметр скорости обучения (формула 5)
            lr = self.learning_rate * tf.exp(-self.n/self.tay2)
            minlr = tf.constant(0.01, dtype=self.dtype, name='min_learning_rate')
            lr = tf.cond(lr <= minlr, lambda: minlr, lambda: lr)
            #вычисляем дельта весов и обновляем всю матрицу весов (формула 4)
            delta = tf.transpose(lr * tnh * tf.transpose(self.x - self.w))
            training_op = tf.assign(self.w, self.w + delta)
        return training_op

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

Граф операций TensorFlow.

Тестирование работы программы


Для тестирования работы программы, будем подавать на вход трехмерный вектор $\mathbf{x} = (x_1, x_2, x_3), \:x_i = [0, 1]$. Данный вектор можно представить как цвет из трех $(r,g,b)$ компонент.
Создадим экземпляр нашей SOM сети и массив из рандомных векторов (цветов):

    #сеть размером 20х20 нейронов
    som = SOMNetwork(input_dim=3, dim=20, dtype=tf.float64, sigma=3)
    test_data = np.random.uniform(0, 1, (250000, 3))

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

    training_op = som.training_op()
    init = tf.global_variables_initializer()
    with tf.Session() as sess:
        init.run()
        for i, color_data in enumerate(test_data):
            if i % 1000 == 0:
                print('iter:', i)
            sess.run(training_op, feed_dict={som.x: color_data, som.n:i})

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

На рисунке представлена карта весов для сети 20х20 нейронов, после 200тыс. итераций обучения:


Карта весов в начале обучения (слева) и в конце обучения (справа).

Карта весов для сети 100x100 нейронов, после 350тыс. итераций обучения.

Заключение


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

P.S.: Полный код программы можно найти тут.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/334810/


Метки:  

[Перевод] Новый V8 и скорость Node.js: техники оптимизации сегодня и завтра

Четверг, 03 Августа 2017 г. 15:50 + в цитатник
Node.js, с момента появления, зависит от JS-движка V8, который обеспечивает исполнение команд языка, который мы все знаем и любим. V8 — это виртуальная машина JavaScript, написанная Google для браузера Chrome. С самого начала V8 создавали для того, чтобы сделать JavaScript быстрым, по крайней мере — обеспечить большую скорость, чем конкурирующие движки. Для динамического языка без строгой типизации достижение высокой производительности — задача непростая. V8 и другие движки развиваются, всё лучше решая эту задачу. Однако, новый движок — это не просто «рост скорости исполнения JS». Это — и необходимость в новых подходах к оптимизации кода. Не всё то, что было сегодня самым быстрым, будет радовать нас максимальной производительностью в будущем. Не всё, что считалось медленным, останется таким.

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

Перед вами — плод совместного труда Дэвида Марка Клементса и Маттео Коллины. Материал проверили Франциска Хинкельманн и Бенедикт Мейрер из команды разработчиков V8.



Центральная часть движка V8, которая позволяет ему исполнять JavaScript на высокой скорости, это компилятор JIT (Just In Time). Это — динамический компилятор, который может оптимизировать код в процессе его выполнения. Когда V8 только был создан, компилятор JIT назвали FullCodeGen, это был (как справедливо отметил Янг Гуо) первый оптимизирующий компилятор для данной платформы. Затем команда V8 создала компилятор Crankshaft, включавший в себя множество оптимизаций производительности, которые не были реализованы в FullCodeGen.

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

В последние годы я и Маттео Коллина сосредоточились на выяснении того, как писать высокопроизводительный код для Node.js. Естественно, это подразумевает знание того, какие подходы являются быстрыми, а какие — медленными, когда наш код исполняется JS-движком V8.

Теперь пришло время пересмотреть все наши предположения о производительности, так как команда V8 написала новый JIT-компилятор: TurboFan.

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

Конечно, прежде чем оптимизировать код с учётом особенностей V8, мы сначала должны сосредоточиться на дизайне API, алгоритмах и структурах данных. Эти микробенчмарки можно рассматривать как индикаторы того, как меняется исполнение JavaScript в Node. Мы можем использовать эти индикаторы для того, чтобы изменить общий стиль нашего кода и способы, которыми мы улучшаем производительность после применения обычных оптимизаций.

Мы рассмотрим производительность микробенчмарков в версиях V8 5.1, 5.8, 5.9, 6.0, и 6.1.

Для того, чтобы было понятно, как версии V8 связаны с версиями Node, отметим следующее: движок V8 5.1 используется в Node 6, здесь применяется компилятор Crankshaft JIT, движок V8 5.8 используется в версиях Node с 8.0 по 8.2, тут применяется и Crankshaft, и TurboFan.

В настоящий момент ожидается, что в Node 8.3, или, возможно, в 8.4, будет движок V8 версии 5.9 или 6.0. Самая свежая на момент написания этого материала версия V8 — 6.1. Она интегрирована в Node в экспериментальном репозитории node-v8. Другими словами, V8 6.1, в итоге, окажется в какой-то будущей версии Node.

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

Большинство микробенчмарков выполнено на Macbook Pro 2016, 3.3 ГГц Intel Core i7, 16 ГБ 2133 МГц LPDDR3-памяти. Некоторые из них (работа с числами, удаление свойств объектов) были выполнены на MacBook Pro 2014, 3 Ггц Intel Core i7, 16 GB 1600 МГц DDR3-памяти. Замеры производительности для разных версий Node.js выполнялись на одном и том же компьютере. Мы внимательно следили за тем, чтобы на результаты испытаний не повлияли другие программы.

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

Проблема try/catch


Один из хорошо известных шаблонов деоптимизации заключается в использовании блоков try/catch.

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

  • Функция, выполняющая вычисления в блоке try/catch, расположенном в ней (sum with trу catch).

  • Функция, выполняющая вычисления без блоков try/catch (sum without try catch).

  • Вызов функции для выполнения вычислений внутри блока try (sum wrapped).

  • Вызов функции для выполнения вычислений без использования try/catch (sum function).

-> Код тестов на GitHub



Мы можем видеть, что то, что уже известно о негативном влиянии try/catch на производительность, подтверждается в Node 6 (V8 5.1), а в Node 8.0-8.2 (V8 5.8) try/catch оказывает гораздо меньшее влияние на производительность.

Также следует отметить, что вызов функции из блока try оказывается гораздо более медленным, чем вызов её за пределами try — это справедливо и для Node 6 (V8 5.1), и для Node 8.0-8.2 (V8 5.8).

Однако, в Node 8.3+ вызов функции из блока try на производительность практически не влияет.

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

Удаление свойств из объектов


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

Проблема с delete сводится к тому, как V8 обходится с динамической природой объектов JavaScript, и с цепочками прототипов (также потенциально динамическими), которые усложняют поиск свойств на низком уровне реализации движка.

Подход движка V8 к созданию высокопроизводительных объектов со свойствами заключается в создании класса на уровне C++, основываясь на «форме» объекта, то есть — на том, какие ключи и значения имеет объект (включая ключи и значения цепочки прототипов). Эти конструкции известны как «скрытые классы». Однако, этот тип оптимизации производится во время выполнения программы. Если же нет уверенности по поводу формы объекта, у V8 имеется ещё один режим поиска свойств: поиск по хэш-таблице. Такой поиск свойств гораздо медленнее.

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

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

Тут мы сравним три тестовых случая:

  • Сериализация объекта после того, как его свойство было установлено в undefined (setting to undefined).

  • Сериализация объекта после того, как для удаления его свойства была использована команда delete (delete).

  • Сериализация объекта после того, как команда delete была использована для удаления свойства, которое было добавлено позже всего (delete last property).

-> Код тестов на GitHub



В V8 6.0 и 6.1 (они ещё не используются ни в одном из релизов Node), удаление последнего свойства, добавленного к объекту, соответствует оптимизированному TurboFan пути выполнения программы, и, таким образом, выполняется даже быстрее, чем установка свойства в undefined. Это очень хорошо, так как говорит о том, что команда разработчиков V8 работает над улучшением производительности команды delete.

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

Утечка и преобразование в массив объекта arguments


Типичная проблема с неявно создаваемым объектом arguments, доступным в обычных функциях (в противовес им, стрелочные функции объекта arguments не имеют), заключается в том, что он похож на массив, но массивом не является.

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

Array.prototype.slice.call(arguments). Такая команда вызывает метод slice объекта Array, передавая объект arguments как контекст this для этого метода. Метод slice видит объект, который похож на массив, после чего делает своё дело. В результате мы получаем массив, собранный из содержимого объекта arguments, похожего на массив.

Однако, когда неявно создаваемый объект arguments передаётся чему-либо, находящемуся вне контекста функции (например, если его возвращают из функции или передают другой функции, как при вызове Array.prototype.slice.call(arguments)), обычно это вызывает падение производительности. Исследуем это утверждение.

Следующий микробенчмарк нацелен на исследование двух взаимосвязанных ситуаций в четырёх версиях V8. А именно, это цена утечки arguments и цена копирования arguments в массив, который потом передаётся за пределы функции вместо объекта arguments.

Вот наши тестовые случаи:

  • Передача объекта arguments другой функции без преобразования arguments в массив (leaky arguments).

  • Создание копии объекта arguments с использованием конструкции Array.prototype.slice (Array.prototype.slice arguments).

  • Использование цикла for и копирование каждого свойства (for-loop copy arguments)

  • Использование оператора расширения из EcmaScript 2015 для того, чтобы назначить массив входных данных функции ссылке (spread operator).

-> Код тестов на GitHub



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



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

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

Частичное применение (каррирование) и привязка контекста функций


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

Например:

function add (a, b) {
  return a + b
}
const add10 = function (n) {
  return add(10, n)
}
console.log(add10(20))

В этом примере параметр a функции add частично применён как число 10 в функции add10.

Более краткая форма частичного применения функции стала доступна начиная с EcmaScript 5 благодаря методу bind:

function add (a, b) {
  return a + b
}
const add10 = add.bind(null, 10)
console.log(add10(20))

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

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

Вот четыре тестовых случая.

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

  • Стрелочная функция, которая вызывает другую функцию с частично применённым первым аргументом (fat arrow curry).

  • Функция, созданная с помощью метода bind, который частично применяет первый аргумент другой функции (bind).

  • Непосредственный вызов функции без использования частичного применения (direct call).

-> Код тестов на GitHub



Линейная диаграмма результатов испытаний чётко показывает практически полное отсутствие различий между рассмотренными методами работы с функциями в последних версиях V8. Что интересно, частичное применение с использованием стрелочных функций значительно быстрее, чем использование обычных функций (как минимум, в наших тестах). На самом деле, оно практически совпадает с непосредственным вызовом функции. В V8 5.1 (Node 6) и 5.8 (Node 8.0-8.2) bind очень медленный, и выглядит очевидным, что использование стрелочных функций для этих целей позволяет достичь самой высокой скорости. Однако, производительность при использовании bind, начиная с V8 версии 5.9 (Node 8.3+) значительно растёт. Такой подход оказывается самым быстрым (хотя, разница в производительности тут практически неразличима) в V8 6.1 (Node будущих версий).

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

Размер кода функции


Размер функции, включая её сигнатуру, пробелы и даже комментарии, может повлиять на то, может ли V8 сделать функцию встроенной, или нет. Да, это так: добавление комментариев к функции может примерно на 10% снизить производительность. Изменится ли это в будущем?

В данном испытании мы исследуем три сценария:

  • Вызов функции маленького размера (sum small function).

  • Работа маленькой функции, дополненной комментариями, выполняемой во встроенном режиме (long all together).

  • Вызов большой функции с комментариями (sum long function).

-> Код тестов на GitHub



В V8 5.1 (Node 6) тесты sum small function и long all together показывают один и тот же результат. Это отлично иллюстрирует то, как работает встраивание. Когда мы вызываем маленькую функцию, это аналогично тому, что V8 записывает содержимое данной функции в место, откуда её вызывают. Поэтому, когда мы пишем текст функции (даже с добавлением комментариев), мы вручную встраиваем её в место вызова и производительность оказывается одной и той же. Опять же, в V8 5.1 (Node 6) можно видеть, что вызов функции, дополненной комментариями, после достижения функцией определённого размера, ведёт к значительно более медленному выполнению кода.

В Node 8.0-8.2 (V8 5.8) ситуация, в целом, остаётся такой же, за исключением того, что стоимость вызова маленькой функции заметно выросла. Это, вероятно, из-за смешивания элементов Crankshaft и TurboFan, когда одна функция может быть в Crankshaft, а другая — в TurboFan, что приводит к разладу механизмов встраивания (то есть, должен произойти переход между кластерами последовательно встроенных функций).

В V8 5.9 и выше (Node 8.3+) добавление посторонних символов, таких, как пробелы или комментарии, не влияет на производительность функций. Это происходит из-за того, что TurboFan использует для вычисления размера функции абстрактное синтаксическое дерево (AST, Abstract Syntax Tree), вместо того, чтобы как Crankshaft, считать символы. Вместо того, чтобы принимать во внимание число байтов функции, TurboFan анализирует реальные инструкции функции, поэтому начиная с V8 5.9 (Node 8.3+) пробелы, символы, из которых составлены имена переменных, сигнатуры функций и комментарии больше не влияют на то, может ли функция быть встроенной. Кроме того, нельзя не заметить то, что общая производительность функций снижается.

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

32-битные и 64-битные целые числа


Хорошо известно, что в JavaScript есть лишь один числовой тип: Number.

Однако, V8 реализован на C++, поэтому базовый тип числового значения JavaScript — это вопрос выбора.

В случае с целыми числами (то есть, тогда, когда мы задаём числа в JS без десятичной точки), V8 считает все числа 32-х битными — до тех пор, пока они перестанут таковыми являться. Это кажется вполне справедливым выбором, так как во многих случаях числа находятся в диапазоне 2147483648 -2147483647. Если JS-число (целиком) превышает 2147483647, JIT-компилятору приходится динамически менять базовый тип числового значения на тип с двойной точностью (с плавающей запятой) — это может, в потенциале, оказать определённое влияние на другие оптимизации.

В этом испытании мы рассмотрим три сценария:

  • Функция, которая работает лишь с числами, укладывающимися в 32-битный диапазон (sum small).

  • Функция, которая работает с комбинацией 32-битных чисел и чисел, для представления которых требуется тип данных двойной точности (from small to big).

  • Функция, которая оперирует лишь числами с двойной точностью (all big).

-> Код тестов на GitHub



Диаграмма позволяет говорить о том, что, идёт ли речь о Node 6 (V8 5.1), или о Node 8 (V8 5.8), или даже о будущих версиях Node, вышеописанное наблюдение остаётся справедливым. А именно, оказывается, что вычисления с использованием целых чисел, превышающих 2147483647, приводят к тому, что функции исполняются со скоростью, находящейся в районе половины или двух третей от максимальной. Поэтому, если у вас есть длинные цифровые ID — помещайте их в строки.

Кроме того, очень заметно, что операции с числами, укладывающимися в 32-битный диапазон, выполняются гораздо быстрее в Node 6 (V8 5.1), а также в Node 8.1 и 8.2 (V8 5.8), чем в Node 8.3+ (V8 5.9+). Однако, операции над числами двойной точности в Node 8.3+ (V8 5.9+) выполняются быстрее. Вероятно, это так из-за замедления в обработке 32-битных чисел, и не относится к скорости вызова функций или циклов for, которые используются в коде тестов.

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

Перебор свойств объектов


Взятие значений всех свойств объекта и выполнение с ними каких-то действий — распространённая задача. Существует множество способов её решения. Выясним, какой из способов самый быстрый в исследуемых версиях V8 и Node.

Вот четыре испытания, которым подверглись все исследуемые версии V8:

  • Использование цикла for-in с применением hasOwnProperty для определения того, является ли свойство свойством объекта (for-in).

  • Использование Object.keys и перебор ключей с использованием метода reduce объекта Array. Доступ к значениям свойств осуществляется внутри функции-итератора, переданной reduce (Object.keys functional).

  • Использование Object.keys и перебор ключей с использованием метода reduce объекта Array. Доступ к значениям свойств осуществляется внутри стрелочной функции-итератора, переданной reduce (Object.keys functional with arrow).

  • Перебор массива, возвращённого из Object.keys, в цикле for. Доступ к значениям свойств объекта осуществляется в том же цикле (Object.keys with for loop).

Кроме того, мы провели три дополнительных теста для V8 версий 5.8, 5.9, 6.0 и 6.1:

  • Использование Object.values и перебор значений свойств объекта с использованием метода reduce объекта Array (Object.values functional).

  • Использование Object.values и перебор значений с использованием метода reduce объекта Array, при этом функция-итератор, переданная методу reduce, была стрелочной функцией (Object.values functional with arrow).

  • Перебор массива, возвращённого из Object.values, в цикле for (Object.values with for loop).

Мы не проводили эти тесты в V8 5.1 (Node 6), так как эта версия не поддерживает встроенного метода EcmaScript 2017 Object.values.

-> Код тестов на GitHub



В Node 6 (V8 5.1) и Node 8.0-8.2 (V8 5.8) использование цикла for-in, без сомнения, является самым быстрым способом перебора ключей объекта, и затем — доступа к значениям его свойств. Этот способ даёт примерно 40 миллионов операций в секунду, что в 5 раз быстрее, чем при использовании ближайшего по производительности подхода, предусматривающего использование Object.keys, и дающего примерно 8 миллионов операций в секунду.

В V8 6.0 (Node 8.3) с циклом for-in что-то случилось и производительность упала до всего четвёртой части скорости, достижимой в предыдущих версиях. Однако, это подход остался самым производительным.

В V8 6.1 (то есть, в будущих версиях Node), производительность метода, использующего Object.keys, растёт, этот метод оказывается быстрее метода с циклом for-in, однако, скорость пока даже не приближается к тем результатам, которые были характерны для for-in в V8 5.1 и 5.8 (Node 6, Node 8.0-8.2).

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

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

Кроме того, для тех, кто привык пользоваться циклом for-in из-за его высокой производительности, текущее состояние дел может оказаться весьма неприятным. Значительная часть скорости теряется, а никакой доступной альтернативы нам не предлагают.

Создание объектов


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

Мы собираемся провести три набора тестов:

  • Создание объектов с использованием объектного литерала (literal).
  • Создание объектов на основе класса EcmaScript 2015 (class).
  • Создание объектов с помощью функции-конструктора (constructor).

-> Код тестов на GitHub



В Node 6 (V8 5.1) все подходы показывают примерно одинаковые результаты.

В Node 8.0-8.2 (V8 5.8), при создании объектов из классов EcmaScript 2015, производительность составляет менее половины той, которая достижима с использованием объектных литералов или функций-конструкторов. Как вы понимаете, вполне очевидно, чем стоит пользоваться в этих версиях Node.

В V8 5.9 разные способы создания объектов снова показывают одну и ту же производительность.

Затем, в V8 6.0 (надеемся, это будет Node 8.3 или 8.4) и 6.1 (пока эта версия V8 не ассоциируется ни с одним будущим релизом Node), скорость создания объектов оказывается просто сумасшедшей. Более 500 миллионов операций в секунду! Это просто потрясающе.


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

Надо сказать, что Якоб Куммертов отметил здесь, что TurboFan способен оптимизировать выделение объектов в нашем микробенчмарке. Мы планируем это исследовать и обновить результаты испытаний.

Полиморфные и мономорфные функции


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

Мы собираемся исследовать пять тестовых случаев:

  • Функции передаются и объекты, созданные с использованием литералов, и строки (polymorphic with literal).

  • Функции передаются и объекты, созданные с помощью конструктора, и строки (polymorphic with constructor).

  • Функции передаются только строки (monomorphic string).

  • Функции передаются только объекты, созданные с помощью литералов (monomorphic obj literal).

  • Функции передаются только объекты, созданные с помощью конструктора (monomorphic obj with constructor).

-> Код тестов на GitHub



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

Разрыв в производительности между мономорфными и полиморфными функциями в V8 6.1 (в движке, который получит одна из будущих версий Node) особенно велик, что усугубляет ситуацию. Однако, стоит отметить, что этот тест использует экспериментальную ветку node-v8, в которой применяется нечто вроде «ночной сборки» V8, поэтому данный результат вполне может не соответствовать реальным характеристикам V8 6.1.

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

По поводу этого испытания хотим отметить, что команда V8 сообщила нам о том, что им не удалось надёжно воспроизвести результаты этого теста, используя их внутреннюю систему исполнения, d8. Однако, эти тесты удаётся воспроизвести на Node. Результаты теста следует рассматривать, исходя из предположения, что ситуация может измениться в обновлениях Node (основываясь на том, как Node интегрируется с V8). Этот вопрос требует дополнительного анализа. Благодарим Якоба Куммертова за то, что обратил на это наше внимание.

Ключевое слово debugger


И, наконец, поговорим о ключевом слове debugger.

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

Тут мы исследовали два тестовых случая:

  • Функция, которая содержит ключевое слово debugger (with debugger).
  • Функция, которая не содержит ключевое слово debugger (without debugger).

-> Код тестов на GitHub



Говорить тут особо нечего. Все версии V8 показывают сильнейшее падение производительности при использовании ключевого слова debugger.

Тут можно обратить внимание на то, что линия графика для теста without debugger заметно идёт вниз в более свежих версиях V8.

Испытание на реальной задаче: сравнение логгеров


В дополнение к микробенчмаркам, мы можем взглянуть на то, как разные версии V8 решают практические задачи. Для этого используем несколько популярных логгеров для Node.js, которые мы с Маттео исследовали, создавая логгер Pino.

На нижеприведённой гистограмме показано время, необходимое наиболее популярным логгерам для вывода 10 тысяч строк (чем столбик ниже — тем лучше) в Node.js 6.11 (Crankshaft).


Вот — то же самое, но уже с использованием V8 6.1 (TurboFan).


В то время, как все логгеры показали примерно двукратный рост производительности, Winston извлёк максимум пользы из нового JIT-компилятора TurboFan. Похоже, в данном случае на производительность повлияли сразу несколько факторов, которые, по отдельности, проявлялись в наших микробенчмарках. Самые медленные способы работы в Crankshaft оказываются значительно быстрее в TurboFan, в то время как то, что быстрее всего работает при использовании Crankshaft, оказывается в TurboFan немного медленнее. Логгер Winston, который был самым неторопливым, вероятно, использует техники, которые являются самыми медленными в Crankshaft, но оказываются гораздо быстрее в TurboFan. В то же время, Pino оптимизирован в расчёте на максимальную производительность в Crankshaft. Он показывает сравнительно небольшой прирост производительности.

Итоги


Некоторые из тестов показывают, что то, что было медленным в V8 5.1, 5.8 и 5.9, оказывается быстрее благодаря полноценному использованию TurboFan в V8 6.0 и 6.1. В то же время, то, что было самым быстрым, теряет в производительности, нередко показывая те же результаты, что и более медленные варианты после роста их скорости.

В основном это связано со стоимостью выполнения вызовов функций в TurboFan (V8 6.0 и выше). Основная идея при работе над TurboFan заключалась в оптимизации того, что используется наиболее часто, а так же в том, чтобы существующие «убийцы производительности V8» не влияли бы слишком сильно на скорость выполнения программ. Это привело к общему росту производительности браузерного (Chrome) и серверного (Node) кода. Компромисс, похоже, заключается в падении производительности тех подходов, которые ранее были самыми быстрыми. Надеемся, это временное явление. При сравнении производительности логгеров было выяснено, что общий эффект от использования TurboFan заключается в значительном росте производительности приложений с очень разной кодовой базой (например, это касается Winston и Pino).

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

Уважаемые читатели! Какие подходы к оптимизации JavaScript используете вы?
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/334806/


Метки:  

Dagger 2. Subcomponents. Best practice

Четверг, 03 Августа 2017 г. 15:47 + в цитатник
На хабре уже было несколько хороших статей по установке и работе с Dagger 2:


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

Перед тем, как пройти под кат, следует ознакомиться с вышеуказанными статьями.
Кого заинтересовал, you are welcome!
image

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

В этот раз я поступлю точно также.

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

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

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

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

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

В нашем случае ассистент — это и есть Dagger. Врач — наш программный компонент, имеющий четкое предназначение в программе. Именно в делегировании (от врача ассистенту) создания и предоставления зависимостей (инструментов) и заключается паттерн — Dependency Injection (внедрение зависимости).

Что можно вынести из этого примера:

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

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

Практика. Вернемся к программированию.

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

  1. Listener — для событий взаимодействия с элементами списка;
  2. Возможно, контекст или LayoutInflater — для создания ViewHodler’ов;
  3. Ну и сам список данных, если, конечно, он был инициализирован заранее (иначе адаптер реализует свой метод setList()).

Но что в итоге? Получив в нашем Fragment’е (или Activity) конструкцию

Adapter adapter = new Adapter(this, getContext(), list);
recyclerView.setAdapter(adapter);

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

image


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

Минуточку, здесь может появиться вопрос:

Если инициализацию адаптера делегировать Dagger’у, откуда он возьмет Listener (объект нашего компонента, реализующего Listener)? Хранить синглтон фрагмента или активити — это больше, чем плохая идея!

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

  1. Используете один-два Component'а для всего приложения;
  2. Все зависимости храните синглтонами;
  3. И знать не хотите про Subcomponent’ы и Component dependency.

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

Большинство примеров использования Dagger’а в «интернетах» обязательно включает в себя создание так называемого AppComponent’a с его AppModule’м с корневой зависимостью Context (либо вашим классом, расширяющим Application, что по сути тоже Context).

Разберемся, почему.

«В начале было слово...»

Имея Context, мы можем получить другие зависимости, например: SharedPreferences, LayoutInflater, какой-нибудь системный сервис и т.д. Соответственно, имея SharedPreferences, мы можем получить PreferenceHelper — класс-утилита для работы с преференсами. Имея LayoutInflater, можем получить какой-нибудь ViewFactory. Из этих «более высокоуровневых» зависимостей мы также можем получить еще и еще более сложные, комплексные. И всё это разнообразие пошло из одного только объекта — контекста. В данном случае его можно назвать ядром нашего AppComponent’а.

image

И всё вышеперечисленное — это как раз те зависимости, которые должны существовать на протяжении жизни всего приложения, т.е. Singleton’ы. Именно поэтому в качестве ядра у нас выступает тот объект, что существует всё это время — объект контекста приложения.

Продолжая эту мысль, подумаем, насколько долго должен существовать наш Adapter? Очевидно, пока существует экран, с которым этот адаптер работает.

Adapter’у мы предоставим ViewHolderFactory, которая должна существовать, пока существует Adapter. Помимо Adapter’а предоставим Fragment’у некоторый ViewController, и он также должен существовать, только пока существует Fragment, и т.д.

Если разобраться, все зависимости, используемые исключительно пока «жив» данный экран, от этого экрана и зависят. Т.о. можно сказать, что наш Fragment (или Activity) будет являться ядром нашего локального Component’а — Component'а, который существует, пока существует наш экран.

image

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

Спроси меня, «как?».

Пока что забудем про приставку sub и представим, что мы реализуем просто Component. Если вам будет проще, представьте, что наш экран — это и есть всё наше приложение.

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

@Module
public class ListModule {
}

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

@Module
public class ListModule {

    private final ListFragment fragment;

    public ListModule(ListFragment fragment) {
         this.fragment = fragment;
    }
}

Основа есть, дальше творчество.

Предоставим наш адаптер:

@Provides
public Adapter provideAdapter(Context context) {
    return new Adapter(fragment, context, fragment.initList());
}

NOTE: У нас есть Context, но явно мы его не предоставляли ни в этом модуле, ни в других модулях нашего Component'а. Об этом чуть позже.

Можно даже отдельно предоставить сам список данных (это избыточно, но для примера сойдет):

@Provides
public List provideListOfModels() {
    return fragment.initList();
}

@Provides
public Adapter provideAdapter(Context context, List list) {
    return new Adapter(fragment, context, list);
}

Теперь, чтобы всё заработало как надо, немного настроек.

Дабы подсказать Dagger’у, что:

  1. Все зависимости Component'а являют собой один граф, отдельный от основного;
  2. Мы хотим не создавать каждый раз новую зависимость, а кешировать единственную;

существуют так называемые Scope-аннотации. Выглядит каждая Scope-аннотация примерно так:

@Scope
@Retention(RetentionPolicy.Runtime)
public @interface Singleton {}

Singleton — это базовая аннотация, предоставляемая Dagger’ом. Предоставляется она просто для того, чтобы вам было, от чего отталкиваться. Само «singleton-ство» не будет происходить магическим образом, если вы не сохраните свой AppComponent в классе App (классе, расширяющем Application). Т.е. Dagger гарантирует вам, что для данного экземпляра Component'а будет создан единственный экземпляр зависимости. Но за единственность экземпляра Component'а вы отвечаете сами.

Подобным образом создадим свою scope-аннотацию:

@Scope
@Retention(RetentionPolicy.Runtime)
public @interface ListScope {}

Наша аннотация ничем не уступит аннотации Singleton, вся суть в том, как мы их используем.

Scope-аннотацией мы помечаем свои provide-методы и Component, содержащий наши модули.

ВАЖНО: В одном Component’е, подписанном определенным Scope’ом могут находиться только модули, provide-методы которых подписаны тем же самым Scope’ом. Т.о. мы не пересекаем два разных графа зависимостей.

Итоговый вид нашего ListModule:

@Module
public class ListModule {

    private final ListFragment fragment;

    public ListModule(ListFragment fragment) {
        this.fragment = fragment;
    }

    @ListScope
    @Provides
    public List provideListOfModels() {
        return fragment.initList();
    }

    @ListScope
    @Provides
    public Adapter provideAdapter(Context contex, List list) {
        return new Adapter(fragment, context, list);
    }
}

И наш Component:

@ListScope
@Subcomponent(modules = ListModule.class)
public interface ListComponent {
    void inject(ListFragment fragment);
}

Ключевой здесь является аннотация @Subcomponent. Так мы сообщаем, что хотим иметь доступ ко всем зависимостям нашего родительского Component’а, но, заметьте, родителя здесь не указываем. В нашем примере родителем будет AppComponent.

* Именно из AppComponent’а мы получим Context для инициализации адаптера.

Чтобы получить свой Subcomponent, в родительском Component’е необходимо описать метод его получения, передав в аргументы все модули Subcomponent’а (в нашем случае только один модуль).

Как это выглядит:

@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {

    ListComponent listComponent(ListModule listModule);
}

Dagger позаботится о реализации этого метода.

Организуем время жизни

Как уже говорилось, AppComponent потому Singleton, что мы храним его единственный экземпляр в классе App. Создать экземпляр своего Subcomponent’а мы можем только с помощью родительского, а потому всю логику получения и хранения Subcomponent’а также вынесем в класс App, с одним важным отличием: Мы добавим возможность в любой момент создать Subcomponent, и в любой момент разрушить.

В классе App опишем следующую логику:

public class App extends Application {

    private ListComponent listComponent;

    public ListComponent initListComponent(ListFragment fragment) {
        listComponent = appComponent.listComponent(new ListModule(fragment));
        return listComponent
    }

    public ListComponent getListComponent() {
        return listComponent;
    }

    public void destroyListComponent() {
        listComponent = null;
    }
}

NOTE: На больших проектах имеет смысл выносить логику работы с Dagger’ом из класса App в класс-хэлпер, используя композицию.

Ну, и остается описать использование всего этого в нашем фрагменте:

public class ListFragment extends Fragment {

    @Inject
    Adapter adapter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        App.getInstance().initListComponent(this).inject(this);
        init();
    }

    private void init() {
        recyclerView.setAdapter(adapter);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        App.getInstance.destroyListComponent();
    }
}

Таким образом мы привязали время жизни нашего графа к жизненному циклу фрагмента.

Это может выглядеть излишним в случае с одной зависимостью (хотя даже с одной зависимостью вынос подобной логики делает ваш код более чистым и менее зацепленным). Бо’льшая часть работы заключается в создании архитектуры. А потому теперь, если вам понадобится предоставить новую зависимость, дело сведётся к реализации одного provide-метода.
image

БОНУС


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

ListFragment реализует Listener событий, связанных с ViewHolder-ами объектов нашего списка. Соответственно, чтобы доставить Listener каждому ViewHolder’у, появляется необходимость хранения ссылки на Listener в Adapter’е.

Избавимся от посредника.

image


Хорошей практикой считается вынос создания ViewHolder’ов во ViewHolderFactory. Так и поступим:

public class ListItemViewHolderFactory {

    private final Listener listener;
    private final LayoutInflater layoutInflater;

    public ListItemViewHolderFactory(LayoutInflater layoutInflater, Listener listener) {
        this.layoutInflater = layoutInflater;
        this.listener = listener;
    }

    public ListItemViewHolder createViewHolder(ViewGroup parent) {
        View view = layoutInflater.inflate(R.layout.item, parent, false);
        return new ListItemViewHolder(view, listener);
    }
}

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

@Module
public class ListModule {

    private final ListFragment fragment;

    public ListModule(ListFragment fragment) {
        this.fragment = fragment;
    }

    @ListScope
    @Provides
    public List provideListOfModels() {
        return fragment.initList();
    }

    @ListScope
    @Provides
    public Adapter provideAdapter(ListItemViewHolderFactory factory,
                                                Context context,
                                                List list) {
        return new Adapter(factory, context, list);
    }

    @ListScope
    @Provides
    public ListItemViewHolderFactory provideVhFactory(LayoutInflater layoutInflater) {
        return new ListItemViewHolderFactory (layoutInflater, fragment);
    }
}

NOTE: Не забываем предоставить LayoutInflater в AppModule.

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

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

image

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

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

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

Пример, описанный в статье, на гитхабе.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/334710/


Метки:  

Как контролировать состояние корпоративной беспроводной сети при помощи Extreme NSight

Четверг, 03 Августа 2017 г. 15:30 + в цитатник
image
Сегодня в ритейле без беспроводной локальной сети — никуда. Однако важно контролировать ее, чтобы вовремя устранять неполадки и проблемы. Поговорим о том, как делать это эффективно.

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

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

В корпоративном сегменте для этих задач используют решения компаний Cisco, Aruba Networks, Extreme Networks. Беря во внимание опыт «Пилота» по развертыванию беспроводных сетей, разберем, как эффективно контролировать их состояние в реальном времени на примере популярного программного продукта Extreme NSight для оборудования Extreme Networks. Это, по сути, программная надстройка, расширяющая функционал инфраструктуры WiNG5 с помощью дополнительных возможностей по управлению и контролю за беспроводным доменом. Итак, ключевые особенности и функционал NSight:

Мониторинг. NSight позволяет отслеживать состояние беспроводного домена предприятия. В тело программы (кастомизируемый dashboard) возможен импорт дерева сайтов корпоративной сети непосредственно из инфраструктуры WING5 (с контроллеров NX или VX, RFDM). Возможен импорт карт из Google Maps с привязкой сайтов по гео-координатам, создание и мониторинг поэтажных планов с размещенными точками доступа и картой покрытия (heat map). Информация и визуализация дерева сети структурированы: от конкретной точки или пользователя на сайте до обобщенной информации по всему беспроводному домену. Кастомизируемый Dashboard NSight — это интерактивная, многопользовательская и многооконная программа, позволяющая легко перемещаться по дереву структуры на интересующие нас уровни для анализа и траблшутинга. Есть возможность отображать оперативный статус сетевых устройств беспроводного домена, число пользователей, нагрузку сети, пропускную способность. Вся информация может быть ранжирована и предоставлена пользователям с разным уровнем доступа и ролью воздействия. Это очень удобно, если контроль над сетью носит распределенный по зонам ответственности характер.

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

Эта информация собирается в процессе мониторинга беспроводного домена и архивируется в базу данных с настраиваемым периодом хранения.

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

Траблшутинг. Интерактивный интерфейс NSight позволяет легко получить доступ к нужным нам данным для анализа и исправления проблем беспроводной сети. Нет необходимости заходить на какую-то конкретную точку доступа для получения информации, все доступно через интерфейс программы. Вместо этого мы можем создать свой dashboard и на лету собирать и отслеживать метрики данных с удаленных точек доступа и их клиентов на любом конкретном сайте или их совокупности. Есть три встроенных механизма для получения и анализа информации:
— Packet Capture;
— Wireless Debug Log access;
— Event Log Browser.

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

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

Event Log Browser организует доступ к журналу событий через интерфейс Extreme NSight для просмотра событий за определенный период времени, которые происходили с точкой доступа или мобильными беспроводными клиентами.

Состав, требования, лицензирование, модели развертывания


Extreme NSight — строки программного кода, которые включены в ядро WiNG5, являющегося частью обычного дистрибутива для контроллеров серий NX, VX и RFS. Доступно, начиная с версии WiNG5 — 5.8.2. Функционал включается только в командной строке WiNG5 буквально парой команд:

• An NSight Policy is created for the NOC controller
image
• Assign the NSight policy on the RF-Domain of the NOC controller
image
Другая группа настроек относится к клиентам NSight — инфраструктуре и базе данных.

NSight — это приложение типа Client-Server с базой данных, где в роли сервера, на котором хранится и обслуживается вся собранная информация, как правило выступает NOC контроллер (VX или NX контроллер), а в качестве клиента, который эти данные собирает на каждом сайте и предоставляет их серверу, выступает либо RFDM on AP, либо RFDM на RFS или на NX контроллерах. Соответственно для них также создаются политики, в которых будет указан ip адрес NSight сервера (или кластера серверов). Пользовательский доступ к самому приложению осуществляется через протокол https:
image

где в качестве fdqn или ip указан адрес сервера NSight (контроллера домена). А общий вид интерфейса NSight представлен ниже:
image

Подробнее о компонентах NSight.
Сервер. Это веб-приложение. Оно взаимодействует с WiNG5 и выполняет следующие функции:
— автоматически сохраняет обновления конфигурации, поступающие с модуля WiNG Management;
— периодически сохраняет обновления статистических данных со всех RFDM беспроводного домена корпорации;
— сохраняет информацию об адаптационном процессе для точек доступа, поступающую от NOC и сайт контроллеров;
— управляет и обслуживает API запросы от сторонних приложений.

Клиент. Функции клиента возложены на RFDM каждого сайта. В качестве RFDM может выступать динамически выбранная в качестве такового точка доступа или локальный контроллер сайта. Клиент собирает статистические данные со всех точек доступа данного сайта и отправляет их серверу каждые 60 секунд (по умолчанию). Отправляет следующие данные:
— AP статистика;
— client (мобильный) статистика;
— wired статистика;
— event history;
— adoption information.

База данных. NSight Server хранит базу данных обо всех беспроводных клиентах, точках доступа и контроллерах:
— все устройства идентифицируются по их уникальному MAC- адресу;
— хранится вся информация об устройстве: Mac, IP, hostname, location и др;
— информация о SMART-RF neighbor от каждой точки доступа;
— вражеские точки доступа, обнаруженные в зоне действия сети;
— статистика о клиентах и от точек доступа;
— история событий для каждого устройства.

Extreme NSight поддерживается на платформах NX 95XX, 96XX и VX9000 в двух режимах развертывания — standalone server и интегрированный режим WING5 + NSigt. Режим standalone — это когда на контроллере (NX или VX) запущен только функционал NSight, а интегрированный — когда контроллер одновременно выполняет функции WiNG management и NSight.

Ниже в таблице представлены системные требования для VX9000 appliances в зависимости от масштаба обслуживаемой сети:
image

Для передачи данных от клиента NSight к серверу NSight требуется не более 1 kbps на одну точку, принадлежащую сайту с которого идет информация на NSight сервер.

Extreme NSight — лицензируемый функционал. Лицензия включает два ключевых компонента: число устройств и срок действия.

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

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

Если мы используем интегрированную модель развертывания (WING+NSight), то требуется только одна лицензия, устанавливаемая на NOC контроллер и разделяемая всеми членами кластера (если он есть). При внедрении standalone-схемы, также требуется лишь одна лицензия, устанавливаемая на первичный replica set. Она также разделяется между всеми членами replica set топологии. Если, например, мы запустили NSight server на VX9000 в режиме standalone, то нам не потребуется лицензия на VX платформу как таковую. Только лицензия для NSight.

Что такое replica set


Создаваемая и хранимая NSight база данных должна иметь высокую степень доступности и надежности хранения данных в случае отказов каких-либо из элементов NSight топологии. Для этого была рекомендована трехузловая модель организации хранения и обслуживания базы данных. Здесь важны два аспекта:
— топология хранения базы данных должна всегда состоять из нечетного числа узлов хранения и обработки (например, 3);
— резервирование базы данных — это независимый от процесса кластеризации WING топологии процесс.

Непосредственно replica set — группа процессов (серверов) баз данных, которые поддерживают один и тот же набор данных. Наборы реплики обеспечивают резервирование, высокую доступность и являются основой для всех моделей развертываний. По сути это распределенная группа серверов, которые синхронизированы между собой, хранят и обслуживают общую базу данных, а также обеспечивают ее надежность и доступность в случае выхода из строя каких-либо узлов топологии. Full-node — это член топологии replica set с полной копией базы данных. Arbiter — это процесс (сервер), который не хранит никаких данных, а участвует в генерации синхронизирующих сигналов и в выборе первичной базы данных.
image

Некоторые модели развертывания инфраструктуры Extreme NSight:


1. Интегрированная модель WiNG5+NSight на одном контроллере в NOC-центре
image

Компоненты NSight функционируют с WiNG5 в пределах одного физического контроллера (VX, NX). NSight получает данные с RFDM (AP или контроллер) каждого отдельного сайта по websocket. А обмен данными между элементами инфраструктуры WiNG5 осуществляется с помощью протокола MINT (level2).

2. Модель standalone (NSight only)
image

В ней сервер Extreme NSight работает на автономном VX или платформе NX9XXX без каких-либо функций управления WiNG5. Модуль Extreme NSight только получает статистические данные и информацию о конфигурации из удаленных узлов. Кроме того, каждый WiNG5 контроллер NOC-центра передает информацию о структуре конфигурации дерева сайтов. Автономный сервер Nsight не взаимодействует с WING5 модулем на том же контроллере и не сообщает никакой статистики о себе в Nsight-базу. Обмен данными и сбор статистики также происходит через websocket для NSight и через MINT для WiNG5.

В обоих вышеприведенных примерах NSight развернут в пределах одного физического устройства. Если нам требуется высокая доступность и надежность работы функционала NSight и его базы данных, то тогда реализуется топология replica set, упоминаемая ранее. Схема, состоящая из трех узлов, по одному в каждом data-центре. Третий узел не обязательно требует отдельного data-центра, главное, чтобы он был размещен в отдельной локации с надежным и бесперебойным питанием и доступом к корпоративной сети. Если этот сервер выполняет роль Arbiter, то не обязательно приобретать дорогостоящий IBM (HP) сервер. Вполне достаточно обычного компьютера, способного работать с VMware.

На рисунках ниже приведены две схемы из трех узлов топологии replica set. Первая состоит из двух full-node узлов и плюс arbiter. Необходимо отметить, что full-node узлы должны размещаться на однотипных устройствах — например, VX9000-VX9000 или NX9500 — NX9500.
image

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

В обоих приведенных примерах, топология replica set применена для модели автономной (standalone) NSight инфраструктуры. Но возможны и другие варианты.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/334646/


Метки:  

[Перевод] Microsoft не изолировала Windows Defender в песочнице, так что это сделал я

Четверг, 03 Августа 2017 г. 14:53 + в цитатник
Microsoft подвергла своих пользователей немалому риску, когда выпустила Windows Defender вне песочницы. Меня это удивило. Песочница — одна из самых эффективных техник усиления безопасности. Почему Microsoft изолировала в песочнице другие высоковероятные цели атаки, вроде кода JIT в Microsoft Edge, но оставила Windows Defender без защиты?

В качестве PoC (proof-of-concept) я изолировал Windows Defender, а сейчас выкладываю свой код в открытый доступ как Flying Sandbox Monster. Основа Flying Sandbox Monster — это AppJailLauncher-rs, фреймворк на Rust для помещения ненадёжных приложений в AppContainers. Он также позволяет вынести I/O приложения за TCP-сервер, чтобы приложение в песочнице работало на полностью другой машине. Это дополнительный уровень изоляции.

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


Flying Sandbox Monster запустил Windows Defender в песочнице для сканирования бинарника WannaCry

План


Беспрепятственный доступ Windows Defender к ресурсам системы и приём любых вредоносных форматов файлов делают его идеальной мишенью для злоумышленников. Ключевой процесс программы MsMpEng работает как сервис с привилегиями SYSTEM. Сканирующий компонент MpEngine поддерживает разбор астрономического количества форматов файлов. У него в комплекте также эмуляторы систем для различных архитектур и интерпретаторы для разных языков. Всё это вместе, исполняемое на высочайшем уровне привилегий в Windows. Оп-па.

Всё это заставило меня подумать. Насколько трудно будет изолировать MpEngine, используя ту же технику, которую я использовал на соревнованиях по сэндбоксингу сообщества CTF два года назад?

Первый шаг к изолированию Windows Defender — возможность запустить AppContainers. Я бы хотел опять использовать AppJailLauncher, но здесь была проблема. Оригинальный AppJailLauncher был написан как демонстрационный пример. Если бы я тогда знал, то написал бы его на C++ Core, чтобы не мучиться с управлением памятью. За последние два года я пытался переписать его на С++, но неудачно (почему зависимости всегда такая головная боль?).

Но затем меня посетило вдохновение. Почему бы не переписать код запуска AppContainer на Rust?

Создание песочницы


Несколько месяцев спустя, после беглого изучения учебников по Rust и написания своего первого кода, у меня появилось три главные опоры для запуска AppContainers на Rust: это SimpleDacl, Profile и WinFFI.

  • SimpleDacl — это обобщённый класс, который берёт на себя добавление и удаление простых дискреционных записей контроля доступа ACE (access control entries) под Windows. Хотя SimpleDacl работает и с файлами, и с директориями, у него есть несколько недостатков. Во-первых, он полностью переписывает существующую ACL и преобразует унаследованные элементы ACE в «нормальные». Кроме того, он пренебрегает теми элементами ACE, которые не может парсить (например, всё, кроме AccessAllowedAce и AccessDeniedAce. Примечание: мы не поддерживаем обязательные и проверочные записи контроля доступа).
  • Profile реализует создание профилей и процессов AppContainer. Из профиля мы можем получить SID, который можно использовать для создания ACE для ресурсов, к которым AppContainer должен иметь доступ.
  • WinFFI даёт нам функции и структуры, которые в winapi-rs реализованы не так хорошо, как в полезных служебных классах/функциях. Я приложил много усилий, чтобы обернуть каждый исходный HANDLE и указатель в объекты Rust для управления временем их работы.

Далее нужно было понять, как установить интерфейс со сканирующим компонентом Windows Defender. Пример реализации на С и инструкции для начала сканирования MsMpEng были в репозитории loadlibrary Тэвиса Орманди. Портирование структур и прототипов функций на Rust несложно автоматизировать, хотя я поначалу забыл о полях-массивах и указателях функций, из-за чего возникло много разных проблем; однако благодаря встроенной в Rust функциональности тестирования я быстро решил все свои ошибки портирования — и вскоре у меня был минимальный тестовый вариант, который сканировал тестовый файл EICAR.


Базовая архитектура Flying Sandbox Monster

Наш пример Flying Sandbox Monster состоит из враппера песочницы и Malware Protection Engine (MpEngine). У единственного исполняемого файла два режима: родительский и дочерний процессы. Режим определяется присутствием переменных окружения, которые содержат HANDLEs для сканируемого файла, и коммуникацией между процессами. Родительский процесс устанавливает два этих значения HANDLEs перед созданием дочернего процесса AppContainer. Теперь изолированный дочерний процесс загружает библиотеку антивирусного движка и сканирует входящий файл на предмет вирусов.

Этого недостаточно для полноценной работы PoC, ибо Malware Protection Engine не хотел инициализироваться внутри AppContainer. Сначала я думал, что это проблема контроля доступа. Но после тщательной сверки отличий в ProcMon (сравнивая отличия исполнения в AppContainer и не в AppContainer), я понял, что проблема может быть в определении версии Windows. Код Тэвиса всегда отчитывался как версия Windows XP. Мой код сообщал реальную версию хостовой системы: в моём случае это Windows 10. Проверка в WinDbg доказала, что проблема инициализации действительно в этом. Нужно было соврать MpEngine о хостовой версии Windows. В С/C++ я бы использовал перехват функций с помощью Detours. К сожалению, для Rust под Windows нет эквивалентной библиотеки для перехвата функций (несколько библиотек для перехвата функций оказались гораздо «тяжеловеснее», чем мне надо). Естественно, я реализовал простую библиотеку для перехвата функций на Rust (только для 32-битной Windows PE).

Представление AppJailLauncher-rs


Поскольку я уже реализовал ключевые компоненты AppJailLauncher на Rust, почему бы не закончить работу и не обернуть это всё в сервер Rust TCP? Я это сделал, и теперь рад представить вам «вторую версию» AppJailLauncher — AppJailLauncher-rs.

AppJailLauncher был TCP-сервером, который прослушивал определённый порт и запускал процесс AppContainer для каждого принятого соединения TCP. Я не хотел изобретать велосипед, но mio, компактная I/O библиотека для Rust, просто не подходила. Во-первых, её TcpClient не обеспечивал доступа к исходным HANDLEs сокетам под Windows. Во-вторых, эти сокеты не наследовались дочерним процессом AppContainer. Из-за этого приходится представить ещё одну «опору» для поддержки appjaillauncher-rs: TcpServer.

TcpServer отвечает за асинхронный TCP-сервер и клиентский сокет, совместимый с перенаправлением STDIN/STDOUT/STDERR. Созданные вызовом socket сокеты не могут перенаправлять стандартные потоки ввода-вывода. Для правильного стандартного перенаправления ввода-вывода нужны «нативные» сокеты (как те, которые создаются через WSASocket). Чтобы разрешить перенаправление, TcpServer создаёт эти «нативные» сокеты и не запрещает явно для них наследование.

Мой опыт работы с Rust


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

Cargo. Управление зависимостями в C++ под Windows — реально утомительное и сложное дело, особенно со ссылками на сторонние библиотеки. Rust ловко решает эту проблему с помощью пакетного менеджера cargo. Там большой набор пакетов, которые решают многие типичные проблемы вроде разбора аргументов (clap-rs), Windows FFI (winapi-rs и др.) и обработки широких строк (widestring).

Встроенное тестирование. Юнит-тесты для приложений C++ требуют применения сторонней библиотеки и большой ручной работы. Вот почему их редко пишут для маленьких проектов, вроде первой версии AppJailLauncher. В Rust юнит-тестирование встроено в систему cargo, где существует вместе с основной функциональностью.

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

Отладка. Отладка Rust под Windows работает как надо. Rust генерирует WinDbg-совместимые символы отладки (файлы PDB), которые обеспечивают беспрепятственную отладку исходников.

Интерфейс внешних функций. Windows API написаны на C/С++ и подразумевается, что таким образом и надо к нему обращаться. Другие языки, как и Rust, должны использовать интерфейс внешних функций (FFI), чтобы обратиться к Windows API. Rust FFI для Windows (winapi-rs) по большей части готов. Там есть ключевые API, но не хватает некоторых не так часто используемых подсистем вроде API для изменения списка контроля доступа.

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

Borrow Checker. Концепция собственности — то, как Rust достигает безопасности памяти. Попытки понять, как работает Borrow Checker, сопровождаются загадочными, уникальными ошибками и требуют часов чтения документации и учебников. В конце концов оно того стоит: когда у меня «щёлкнуло» и я усвоил концепцию, мои навыки программирования кардинально продвинулись.

Векторы. В C++ контейнер std::vector может выставить свой поддерживающий буфер другому коду. Оригинальный вектор остаётся валидным, даже если поддерживающий буфер изменили. В случае Vec в Rust это не так. Здесь Vec требует создания нового объекта из «заготовок» старого Vec.

Типы Option и Result. Нативные типы Option и Result должны были упростить проверку ошибок, но на самом деле сделали её как будто более подробной. Можно сделать вид, что ошибок не существует, и просто вызвать unwrap, но это приведёт к сбою рантайма, когда неизбежно вылезет Error (или None).

Другие типы и слайсы. К принадлежащим типам (owned types) и сопутствующим слайсам (например, String/str, PathBuf/Path) нужно немного привыкнуть. Они идут парами с похожими именами, но ведут себя по-разному. В Rust принадлежащий тип представляет расширяемый, изменчивый объект (обычно строку). Слайс — это вид неизменяемого буфера символов (тоже обычно строка).

Будущее


Экосистема Rust для Windows ещё растёт. Можно ещё создавать новые библиотеки Rust, упрощающие разработку ПО для безопасности под Windows. Я сделал начальные версии нескольких библиотек Rust для сэндбоксинга в Windows, разбора PE и перехвата IAT. Надеюсь, они будут полезны возникающему сообществу Rust под Windows.

С помощью Rust и AppJailLauncher я изолировал в песочнице Windows Defender, флагманский антивирусный продукт Microsoft. Моё достижение одновременно и замечательное, и немного постыдное. Замечательно то, что надёжный механизм песочницы Windows доступен для стороннего софта. Постыдно то, что Microsoft сама не изолировала Defender. Microsoft купила то, что впоследствии станет Windows Defender, в 2004 году. В те времена такие баги и архитектурные просчёты были неприемлемы, но объяснимы. За прошедшие Microsoft создала отличную организацию по разработке систем безопасности, для обычного тестирования и фаззинга. Она изолировала в песочнице критические части Internet Explorer. Каким-то образом Windows Defender застрял в 2004 году. Вместо использования методов Project Zero и непрерывного указания на симптомы этого врождённого недостатка, давайте перенесём Windows Defender обратно в будущее.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/334792/


Метки:  

DataGrip 2017.2

Четверг, 03 Августа 2017 г. 14:52 + в цитатник
Привет! Продолжаем серию постов о новых версиях IDE от JetBrains. Поговорим о том, что нового в DataGrip 2017.2.

— Поддержка Amazon Redshift и Microsoft Azure
Несколько баз данных для одного источника PostgreSQL
— Контроль транзакций
— Вычисление выражений
— Разделены вкладки DDL и Data для таблиц
— Интеграция с инструментами восстановления для PostgreSQL и MySQL
— Улучшения, связанные с запуском запросов
— Улучшения, связанные с написанием кода
и другое…




Поддержка Amazon Redshift и Microsoft Azure


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



Microsoft Azure похожа на SQL Server: мы добавили драйвер, интерфейс для создания источника данных, и улучшили получение информации об объектах. Этот процесс называется «интроспекция».

Интроспекция в Amazon Redshift стала инкрементальной: после операции DataGrip обращается за информацией только об измененных объектах.

Поддержали специфические части грамматики, которых нет в PostgreSQL. Например, UNLOAD подсвечивается корректно, а запрос в строке аргумента обрабатывается, как обычный SQL, — работает автодополнение и навигация.



Ещё пример: поддержали функции, которых нет в PostgreSQL.



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

Если вы подключались к Azure и Redshift через драйвера для SQL Server и PostgreSQL, пожалуйста, переключитесь на нужный драйвер из контекстного меню.




Несколько баз данных для одного источника PostgreSQL


Эту штуку долго ждали, и мы благодарим тех, кто дождался :)

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



Источники данных с несколькими базами теперь работают в Amazon Redshift, в Microsoft Azure и в других базах, к которым вы подсоединитесь через JDBC, если это поддерживает сам драйвер.


Контроль тразакций


Контроль транзакций (Transaction Control) заменил опцию Auto-commit.

Определяйте уровень контроля транзакций для каждого источника данных. В ручном режиме (Manual) транзакции надо фиксировать, выполняя COMMIT. В автоматическом режиме (Auto) — нет.



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



В редакторе данных при ручном режиме добавили две кнопки: Commit и Rollback. Эти действия доступны и в контекстном меню.



Работает это так:

Автоматический и ручной режим.


Кнопка Submit или Ctrl/Cmd+Enter отправляет данные в базу: накатываются ваши локальные изменения, которые до этого момента были подсвечены и хранились внутри сессии DataGrip. Но эта транзакция не будет зафиксирована, если у вас выставлен ручной режим.

Revert Selected из контекстного меню или Ctrl/Cmd+Alt+Z на выделенных строках откатывает локальные изменения в этих строках. Раньше это вызывалось по Ctrl+Z, но обычно эта комбинация клавиш означает отменить, а не откатить.

Только в ручном режиме


Кнопка Commit или Shift+Ctrl+Alt+Enter фиксирует транзакцию. Если у вас висят локальные изменения, не отправленные в базу (напомню: подсвеченные), они автоматически отправятся в базу перед фиксированием.

Кнопка Rollback откатывает незафиксированную транзакцию.


Вычисление выражений


Это поможет быстро посмотреть данные без написания отдельного запроса.

Как и в других наших IDE, используйте комбинацию клавиш Ctrl+Alt+F8 для быстрого вычисления значения выражения. Под выражением в данном случае понимается значение объекта базы данных, например для таблицы — это сами данные.



Для столбца из запроса это — значения столбца в ожидаемом результате.



Если выполнить то же действие на ключевом слове в запросе (или подзапросе), его результат появится во всплывающем окне. Для этого работает и Alt+Click.



Alt+F8 вызывает отдельное окно для вычисления выражений. Как и в «быстром» варианте, для таблицы вы увидите данные.



Здесь можно вычислять выражения в классическом понимании этого.




DDL таблицы


Мы отделили данные таблиц от исходных кодов — больше нет вкладок DDL и Data.

Теперь по двойному клику на таблице открываются данные. Для просмотра DDL нажмите Edit Source на панели инструментов или Ctrl/Cmd+B на таблице.



Этот же DDL-редактор вы увидите, если нажмете Ctrl/Cmd+B на имени таблицы в SQL-скрипте. Ctrl/Cmd+click делает то же. В предыдущих версиях это действие выделяло объект в дереве баз данных. В 2017.2 для этого нажмите Alt+F1 и выберите Database view. Напишите нам, если стало неудобно: всё-таки, для такого действия раньше было одно нажатие, а теперь два.

А вот редактор данных для таблицы стало открыть легче — просто нажмите F4 в коде или в дереве.




Интеграция с инструментами восстановления для PostgreSQL и MySQL


В 2016.3 мы интегрировали в DataGrip mysqldump и pg_dump. Логично было интегрировать и инструменты восстановления для этих баз, об этом даже просили на Хабре в прошлый раз. Они появились в контекстном меню. Если в данном контексте доступен только один инструмент, например пункт меню называется ‘Restore with pg_restore’.



Если база — PostgreSQL, то использовать можно pg_dump или psql: выбирайте вверху диалога.



А так окно выглядит для MySQL:



Запуск запросов


Добавили новое действие — Attach console. Вызывается, как всегда, из поиска действий по Ctrl+Shift+A или контекстного меню файла. Цель — запустить файл в контексте конкретной консоли, которую вы к нему прикрепите.

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



Это просили: нотификация о завершении длинных запросов. Сейчас запрос, время выполнения которого больше 20 секунд, бросит такую нотификацию внутри DataGrip. Нотификацию можно выключить: имя нотификации “Database queries that took much time”.



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



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



Это поведение теперь по умолчанию — чтобы его отключить, ищите опции “Autoscroll ..” в меню настроек по иконке с шестеренкой.



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



Починили переключатель схем для read-only соединений в MySQL.




Написание кода


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



Ссылки NEW и OLD корректно обрабатываются для триггеров в PostgreSQL.



Добавили поддержку для предложений MERGE.



Поддержали последовательности в скриптах.




Остальное


Добавили:


— Объекты базы можно добавлять в закладки (Bookmarks).
— Индексирование файла можно остановить и продолжить в любой момент.
— Результаты поиска в Find in Path с одних и тех же строк объединяются в один результат.
— Поддержка ALTER FOREIGN TABLE в PostgreSQL.
— Поддержка функции ‘json_table’ в Oracle.
— Отображаются все атрибуты в сгенерированных DDL для Redshift.

Исправили:


DBE-4600, переименованная схема теперь сразу отображается в скрипте и в дереве.
DBE-1288, переименование последовательностей в PostgreSQL не ломает запрос.
DBE-4507, теперь можно создать составной первичный ключ.
DBE-4637, запросы с GROUP BY больше не сообщают об ошибке, которой нет.
— Прокрутка в редакторе данных стала быстрее.

И как всегда: скачать здесь, о багах сообщать сюда, а ещё мы отвечаем на форуме, в Твиттере и здесь, в комментариях.

Спасибо!
JetBrians.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/334800/


Метки:  

Поиск сообщений в rss_rss_hh_new
Страницы: 1437 ... 1079 1078 [1077] 1076 1075 ..
.. 1 Календарь