Quantcast
Channel: Категорія [Статьи] — DOU
Viewing all 2421 articles
Browse latest View live

Оценка трудоемкости проектов разработки. Часть 1

$
0
0

Меня зовут Александр Катруша, я работаю Senior Engineering Manager в компании Innovecs. Большую часть своей карьеры я занимался разработкой и внедрением ERP-систем, а также оценкой и управлением соответствующих проектов.
И хотя тема оценки проектов неисчерпаема, как атом, надеюсь, мой опыт пригодится многим коллегам. Особо ценны будут советы, что делать и чего не делать, как избежать типичных ошибок в оценке и ее коммуникации.

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

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

Терминология

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

  • скоуп (англ. scope) — содержание проекта, рамки проекта, объем работ;
  • assumptions — допущения, предположения;
  • contingency — риск.

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

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

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

Когда и зачем нужна оценка проектов

Неопределенность

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

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

Когда нужна оценка

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

  1. Переговоры с клиентом о новом проекте либо фазе проекта.
  2. Ответ на RFPлибо участие в тендере.
  3. Планирование бюджета и прочих ресурсов организации, например, календарное.
  4. Расчет ROIпроекта в ходе принятия принципиального решения о его запуске.

Если оценка нужна прямо сейчас

Если вы вынуждены оценивать проект в самом начале, на этапе сбора бизнес-требований или еще раньше, есть несколько путей снизить риск:

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

Цели

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

  1. Определить и ограничить рамки проекта (scope) и зафиксировать предположения (assumptions), при которых оценка актуальна.
  2. Определить цену и себестоимость проекта на основе трудозатрат.
  3. Обосновать бюджет проекта перед внешними либо внутренними спонсорами.
  4. Получить входные данные для других процессов, таких как:
    • продажа;
    • планирование;
    • наем сотрудников;
    • бюджетирование.

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

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

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

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

Эксперимент

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

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

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

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

Оценщики и исполнители

Идеальный оценщик

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

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

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

Когнитивные искажения, влияющие на оценку

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

Ошибка планирования и оптимизм

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

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

Ошибки в оценке вероятностей

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

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

Эффект привязки (якорение)

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

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

Исполнители

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

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

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

Единицы измерения

Трудоемкость vs длительность

Я предпочитаю все задачи и проекты оценивать по трудоемкости (в человеко-часах), а не по длительности (в днях или неделях) по следующим причинам:

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

Человеко-часы, -дни, -недели, -месяцы

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

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

Степени двойки

С учетом выбора человеко-часов в качестве единицы измерения представляется целесообразным использовать степени двойки для оценки конкретных задач. Они достаточно интуитивны, хорошо соответствуют рабочему времени восьмичасового рабочего дня и удобны в расчетах:
  • 0,5–1 ч —время для минимально возможной задачи;
  • 2 ч — время, которое можно комфортно провести за монитором без отвлечения внимания;
  • 4 ч — половина рабочего дня;
  • 8 ч — рабочий день;
  • 16 ч — два рабочих дня;
  • 32 ч — «почти неделя».

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

Рабочие часы vs эффективные часы

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

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

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

Структура оценки

Как мы выяснили в первой части статьи, цель оценки — не только найти трудозатраты, но и описать скоуп, риски, а также правильно преподнести их всем стейкхолдерам проекта. А потому документ «Оценка проекта» как минимум должен содержать:

  1. Скоуп.Что мы оцениваем в виде списка требований, работ и того, что в скоуп не входит.
  2. Предположения и риски.При каких условиях оценка актуальна, и что, по нашему мнению, может пойти не так.
  3. Числа.Сколько трудозатрат потребует сделать 1 при условиях 2.
  4. Упаковка. Last but not least. Правильно преподнести оценку не менее важно, чем качественно оценить, особенно в процессе продажи.

Заметьте, что собственно оценка в виде чисел только на третьем месте, поскольку качественное определение скоупа и предположений намного важнее для успеха проекта, чем точность оценки. Числа неотделимы от того, что и при каких условиях они оценивают. Ошибка в оценке индивидуальной задачи может составить 5%, 10%, пусть даже 50%, и это может быть некритичным для проекта. В то время как неправильная оценка скоупа и рисков может увеличить трудоемкость работ в несколько раз.

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

Заключение

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


Certonid - SSH центр сертификации, который работает на AWS Lambda

$
0
0

Всем привет! Меня зовут Алексей, я разработчик/девопс/подкастер, и в этой статье я хочу вам рассказать о своем проекте Certonid — серверлесс-SSH-центре сертификации (serverless SSH certificate authority). Этот инструмент может помочь решить проблему менеджмента доступа к Linux-серверам по SSH. Давайте начнем по порядку.

SSH-сертификаты

SSH вездесущ. Это де-факто стандарт для удаленного администрирования *nix-систем. Когда девопс настраивает Linux-сервер, то обычно создается пара учетных записей с паролями. Локальное управление учетными записями хорошо работает с небольшими группами серверов, но по мере роста продукта требуется создавать центральную систему аутентификации, такую как LDAP и/или Kerberos, чтобы избежать ручного управления учетными записями на каждом сервере. При дальнейшем росте девопс может прийти к выводу, что центральная система аутентификация — единственная и потенциально разрушительная точка отказа всей системы. Как только она выйдет из строя, то все потеряют доступ ко всему (если только не создать учетные записи с прямым, в обход системы аутентификации, доступом, что может быть небезопасно). Блокирование вашей собственной системы — одна из худших вещей, которые могут случиться во время инцидента. Например, если перебои в работе службы повредили вашу систему аутентификации, то вы не сможете войти и исправить ее.

В дополнение к этим рискам выбор SSH-аутентификации с открытым ключом (SSH public key authentication) для ваших разработчиков/девопсов означает необходимость управления их открытыми ключами на всех ваших серверах. Также нередко безопасность системы ставится под угрозу, если есть неизвестные открытые ключи в файлах authorized_keys (в такой файл пишутся открытые ключи, через которые по SSH можно получить доступ к системе). Кроме того, authorised_keys требует определения доверия по отдельной паре ключей, которая не масштабируется.

Для решения проблем с SSH-аутентификацией с помощью открытого ключа (SSH public key authentication) можно перейти к SSH-аутентификации с помощью сертификатов (SSH certificate authentication). Давайте посмотрим, как это работает.

Для начала создадим свой собственный CA (certificate authority, центр сертификации), который, по сути, представляет собой обычную пару ключей:

$ mkdir sshca && cd sshca
$ ssh-keygen -C CA -f ca-key
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in ca-key.
Your public key has been saved in ca-key.pub.

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

Сейчас у вас есть два файла: «ca-key» (закрытый ключ) и «ca-key.pub» (открытый ключ). Теперь надо распространить ca-key.pub по всем серверам, к которым требуется доступ по SSH через сертификаты. Поскольку вы распространяете открытый ключ, то можно не беспокоиться о безопасности его передачи: канал его распространения необязательно шифровать. Для нашего примера давайте разместим его в «/etc/ssh/ca-key.pub» на серверах.

Следующий этап заключается в конфигурации SSH-демонов на серверах, чтобы они доверяли этому ключу, путем добавления/изменения строчки в конфиге «/etc/ssh/sshd_config» (не забудьте после изменений перезагрузить SSH-демон):

TrustedUserCAKeys /etc/ssh/ca-key.pub

Теперь, когда у вас есть цепочка доверия (chain of trust), вы можете начать создавать SSH-сертификаты. В идеале ваш CA должен быть очень защищенным сервером, к которому доступ может получить только команда, которая занимается безопасностью в продукте (security team). Одна очень важная практика безопасности состоит в том, что закрытые ключи никогда не должны покидать систем, на которых они были созданы, независимо от того, насколько безопасен канал передачи данных.

Далее уже на компьютере разработчика генерируем ему SSH-ключи (если их нет или вы хотите использовать отдельные ключи):

$ ssh-keygen -t ecdsa # или “ssh-keygen -t rsa”
Generating public/private ecdsa key pair.
Enter file in which to save the key (/Users/leo/.ssh/id_ecdsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /Users/leo/.ssh/id_ecdsa.
Your public key has been saved in /Users/leo/.ssh/id_ecdsa.pub.

Теперь в «.ssh/» каталоге у нас есть файлы «id_ecdsa» (закрытый ключ) и «id_ecdsa.pub» (открытый ключ). Копируем открытый ключ на CA-сервер. Канал передачи данных неважен. Просто никуда не передавайте закрытый ключ «id_ecdsa».

Наконец, на CA-сервере создаем SSH-сертификат для открытого ключа разработчика:

$ ssh-keygen -s ca-key -I leo -n deployer -V +1w -z 1 id_ecdsa.pub 
Enter passphrase:
Signed user key id_ecdsa.pub: id "leo" serial 1 for deployer valid from 2019-11-07T00:32:00 to 2019-11-14T00:33:44

Что тут происходит? По сути, мы подписываем «id_ecdsa.pub» через ca-key. Идентификатор сертификата будет leo, и единственным principal будет deployer. Сертификат действителен в течение одной недели и имеет серийный номер 1. Теперь у вас должен быть файл id_ecdsa-cert.pub. Скопируйте его обратно на компьютер разработчика и поместите в папку .ssh/. Канал передачи данных и здесь неважен, это общедоступная информация, а сам сертификат не работает без соответствующего закрытого ключа (тот самый id_ecdsa). Поскольку мы не настроили серверы на использование определенного набора principal, стандартная конфигурация sshd позволит этому сертификату войти в систему под именем любого пользователя (который присутствует в системе). Поскольку я использовал -n deployer для создания сертификата, то могу войти в систему как deployer-юзер. Если у вас нет специальной схемы авторизации на серверах, этого для вас может быть достаточно.

Давайте глянем информацию по сертификату с помощью ssh-keygen:

$ ssh-keygen -Lf id_ecdsa-cert.pub
id_ecdsa-cert.pub:
        Type: ecdsa-sha2-nistp256-cert-v01@openssh.com user certificate
        Public key: ECDSA-CERT SHA256:Kz/8gC5dKLQaYsiAoQwnf7wAbEJLQ0R4TD4iCHwK9Bg
        Signing CA: RSA SHA256:Tk2tXG7mqDJS8Pzj8RiA3MgpqlgOUYG2i3Ju7wYN7QM
        Key ID: "leo"
        Serial: 1
        Valid: from 2019-11-07T00:32:00 to 2019-11-14T00:33:44
        Principals:
                deployer
        Critical Options: (none)
        Extensions:
                permit-X11-forwarding
                permit-agent-forwarding
                permit-port-forwarding
                permit-pty
                permit-user-rc

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

Теперь, когда у нас есть сертификат и закрытый ключ, можно подключиться как пользователь deployer на SSH-сервер, который доверяет нашему CA:

$ ssh deployer@system-which-trust-ca-key

Как только произойдет подключение к серверу, в журнале аутентификации можно будет заметить такую строчку:

Nov 6 22:55:11 example sshd[1899]: Accepted publickey for deployer from 176.14.529.36 port 56223 ssh2: ED25519-CERT ID leo (serial 1) CA RSA SHA256:...

Прекрасно видно, что даже при входе на сервер от имени deployer система может идентифицировать сертификат, используемый для аутентификации. В этом случае сертификат с идентификатором leo. Это означает, что использование правильного -I с ssh-keygen очень важно, потому что оно идентифицирует, кому принадлежит сертификат. Также рекомендуется использовать уникальный серийный номер (тут serial 1), чтобы вы могли идентифицировать каждый выданный отдельный сертификат. Кстати, уникальные серийные номера обязательны, если вы хотите использовать SSH-параметр RevokedKeys в конфиге для отзыва скомпрометированных сертификатов с закрытыми ключами.

Надеюсь, теперь вам ясно, как работают SSH-сертификаты. Хочу заметить, что это решение не какая-то новая хипстерская поделка — аутентификация с использованием сертификатов была добавлена в OpenSSH 5.4 почти десять лет назад.

Автоматизация

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

  • netflix/bless — решение от Netflix. Работает на AWS Lambda (serverless) и использует AWS IAM. Написано на Python;
  • nsheridan/cashier — решение от Intercom. Представляет собой сервер и клиент, написанный на Golang;
  • uber/pam-ussh — подключаемый модуль аутентификации (PAM) от Uber, который написан на Golang;
  • hashicorp/vault — решение от HashiCorp для хранения секретов. Содержит SSH secrets engineс поддержкой сертификатов.

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

  1. BLESS написан на Python. Сам по себе язык Python не является чем-то плохим (хороший язык), но BLESS требует сборки проекта. Поскольку там идет сборка нативных библиотек, это надо делать в Docker-контейнере. Но даже и после этого нет гарантии, что у вас все получится: зависимости могут поломаться (опять же язык тут ни при чем). В сборку заранее нужно не забыть добавить CA-ключ, самому зашифровать его пароль и сам файл. Все это не позволяет так просто использовать BLESS.
  2. Развернуть BLESS не так легко и понятно, как кажется. Особенно если вам нужно еще добавить поддержку KMSAuth. Документация не очень дружелюбная в этом плане.
  3. У BLESS нет хорошего официального клиента. Есть небольшой Python-скрипт, и на этом все. Имеются, конечно, сторонние решения, что уже делает вызов BLESS-функции удобнее. Но даже сторонние решения не решают проблему, когда ты как пользователь должен переключаться между проектами (когда у тебя один проект, например Netflix, таких проблем не ощущаешь).
  4. BLESS заточен для работы на бастион-хосте. Бастион (Bastion host) — так называют специально отведенный компьютер в сети, обычно расположенный на внешней стороне демилитаризованной зоны (ДМЗ) организации. Через него попадают уже на другие серверы, которые находятся в закрытой сети. Я выскажу непопулярное мнение, идущее вразрез с нынешними best security practices: вам, вероятнее всего, не нужен бастион, и он может принести больше вреда, чем пользы. Я могу привести в качестве доказательства много пунктов, которые покажут, что этот узел не добавляет надежности и безопасности, но статья не об этом. Единственный плюс, который я не буду оспаривать: бастион замедляют атаку, особенно автоматизированную. Это как купить очень хорошую входную дверь: невскрываемых дверей нет, но более защищенная доставит больше хлопот грабителю при вскрытии, и поэтому многие просто могут отказаться ее вскрывать. Так вот, в большинстве продуктов нет бастион-хоста, и доступ по SSH нужно получить с машины пользователя. В таком случае настройка и развертывание клиента, что будет помогать в этом, должны быть простой процедурой.

После нескольких не очень успешных попыток завести BLESS (в комплексе, а не только AWS Lambda) за несколько выходных был написан «свой велосипед». Certonid — это как раз тот же SSH Serverless CA. Написан на Golang, за счет чего сразу предоставляются собранные бинарные файлы, которые вам не требуется дополнительно подготавливать. Состоит он из двух частей — CLI и серверлесс-части. Подготовить его достаточно просто. Вам нужно скачать CLI (выбрать под вашу систему) и серверлесс-часть (только одна версия — AWS Lambda работает на Linux). Далее создать zip-файл, в который положить серверлесс serverless.linux.amd64 (лучше назвать файл serverless), ваш ca-key и certonid.yml. В конфиге нужно будет указать, как получить доступ к ca-key (сам файл можно зашифровать симметричным шифрованием или с использованием AWS KMS) и как получить пароль для ключа (Certonid работает только с закрытыми ключами, у которых есть пароль), который будет тоже зашифрован симметричным шифрованием или с использованием AWS KMS. Для упрощения этой работы у CLI есть вспомогательные функции для шифрования строк или файлов. Пример конфига:

ca:
  storage: file
  path: ca.pem
  encrypted:
    encryption: aws_kms
    region: us-east-1
  passphrase:
    encryption: aws_kms
    region: us-east-1
    content: AQICAHhBwiHijA5XW9EyanTVga4XbbwEVCmBLSUiWIxrCrxrUwGGt8JapxlfiJljay3FycLOAAAAZjBkBgkqhkiG9w0BBwagVzBVAgEAMFAGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMtZxOyGi2foFM+y9SAgEQgCOY1N4sMr5RIiyQ4/8yloRIAi6vWaK3n/jEdgPfn3bdJjrkNQ==

certificates:
  user:
    max_valid_until: 2h
    additional_principals:
      - "ubuntu"
      - "ec2-user"
    critical_options:
      - "source-address 0.0.0.0/0"
    extensions:
    - "permit-X11-forwarding"
    - "permit-agent-forwarding"
    - "permit-port-forwarding"
    - "permit-pty"
    - "permit-user-rc"

logging:
  level: info

Далее этот zip-файл загружаем в AWS Lambda. AWS Lambda Runtime — Go 1.x. AWS Lambda Handler должен быть именем файла серверлесс-компонента Certonid в zip-файле (в примере файл serverless). Не забудьте, что этой функции требуется доступ к ключам AWS KMS, если вы через него зашифровали пароли и, по желанию, сам CA-ключ.

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

REPORT RequestId: d7e99280-7860-426e-a6e1-e80d83176f83 Duration: 3223.70 ms Billed Duration: 3300 ms Memory Size: 128 MB Max Memory Used: 58 MB Init Duration: 124.16 ms

После этого нужно настроить Certonid CLI. Для вызова функции AWS Lambda используется AWS Identity and Access Management (IAM): каждому пользователю, которому требуется доступ по SSH на серверы, создается пользователь в IAM. Если человек покидает проект, его аккаунт блокируется на AWS, и он более не сможет запрашивать новые сертификаты, чтобы попадать на серверы (старые перестанут работать по истечении указанного вами времени жизни). Совет от меня: если вы уже используете AWS для проекта, то лучше для Certonid AWS Lambda и IAM-менеджмента создать отдельный AWS-аккаунт, чтобы не смешивать сущности и доступы уже самого продукта. Конфиг CLI по умолчанию хранится в $HOME/.certonid.yml. Пример конфига:

certificates:
  examplecom:
    public_key_path: ~/.ssh/id_ed25519.pub
    username: leopard
    runner: aws
    valid_until: 4h
    aws:
      profile: aws-profile
      region: us-east-1
      function_name: CertonidFunction

Секция certificates содержит разные проекты/функции с сертификатами, поэтому один CLI может работать с несколькими серверлесс-центрами сертификации.

Для настроек доступа можно в конфиге Certonid указать AWS Access Key ID и Secret Access Key через переменные окружения или (я пользуюсь таким вариантом) настроить AWS CLI профилии внести нужный профиль для Certonid в конфигурации (в примере так сделано).

После этого с помощью команды certonid gencert можем получить сертификат на наш открытый ключ:

$ certonid gencert examplecom                                 
INFO[2019-11-07T17:57:20+02:00] Signing public key                            
certificate=/Users/leo/.projects_certs/examplecom-cert.pub 
public key=/Users/leo/.ssh/id_ed25519.pub runner=aws
INFO[2019-11-07T17:57:25+02:00] Certificate generated and stored              
certificate=/Users/leo/.projects_certs/examplecom-cert.pub 
public_key=/Users/leo/.ssh/id_ed25519.pub valid until="2019-11-08 15:57:22 +0000 UTC"

Если команду запустить заново, то она проверит существующий сертификат, и если он все еще работает, то CLI просто завершит свою работу и лишний раз не будет вызывать AWS Lambda (не забываем, что эти вызовы стоят денег).

$ certonid gencert examplecom
INFO[2019-11-07T18:00:35+02:00] Current certificate still valid. Exiting...   certificate=/Users/leo/.projects_certs/examplecom-cert.pub valid until="2019-11-08 15:57:22 +0000 UTC"

Больше по командам можно узнать из certonid -h или Вики.

Интеграция с SSH

Есть одно условие для работы сертификатов: сертификат должен лежать в той же папке, что и закрытый ключ с именем файла <имя закрытого ключа>-cert.pub. В таком случае SSH agent при добавлении закрытого ключа автоматически подхватит в хранилище сертификат. Но это неудобно, если вы используете один и тот же закрытый ключ для разных проектов (нужно перезаписывать файл сертификата и потом добавлять его в SSH-агент).

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

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

Первый вариант решения проблемы заключается в создании конфигурации для вашего SSH-клиента. Допустим, нам нужно подключаться к доменам *.example.com через сертификат examplecom. В файл конфигурации ($HOME/.ssh/config) мы можем добавить:

Match Host *.example.com exec "certonid gencert examplecom"
    Port 22
    User deployer
    IdentityFile  ~/.ssh/id_ed25519
    CertificateFile ~/.projects_certs/examplecom-cert.pub
    PasswordAuthentication no

Как видите, SSH-конфиг поддерживает для сравнения exec-опцию, которая выполнит команду, и если она завершится успешно (код выхода ноль), то условие считается истинным для конфигурации. Вот в этот параметр можно добавить команду certonid gencert examplecom. Поскольку сертификат лежит в другом месте, его можно указать через параметр CertificateFile. После такой конфигурации можно просто писать в консоли и подключаться к серверам:

$ ssh web1.example.com
$ ssh web4.example.com

Но бывают случаи, когда определенный софт не умеет работать с SSH-конфигом, а на <имя закрытого ключа>-cert.pub ему может быть все равно. Если этот софт поддерживает работу с SSH-агентом, сертификат можно добавить в него. Пример команды прост:

$ certonid gencert examplecom --add-to-ssh-agent ~/.ssh/id_ed25519

Поскольку сертификат не добавить в SSH-агент без закрытого ключа, его придется указать как значение для команды —add-to-ssh-agent. Этот параметр можно добавить в yml-конфиг, но такой вариант не подойдет тем, у кого закрытые ключи зашифрованы паролем, потому что при каждом запуске с такой командой Certonid будет спрашивать тот самый пароль. После этого можно проверить сертификат в агенте:

$ ssh-add -l
4096 SHA256:... leo@Alexeys-MacBook-Air.local (RSA)
256 SHA256:... leo@Alexeys-MacBook-Air.local (ED25519)
256 SHA256:... leopard_1573142242 [Expires 2019-11-08 17:57:22 +0200 EET] (ED25519-CERT)

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

Host *.example.com
    Port 22
    User deployer
    ForwardAgent yes
    PasswordAuthentication no

В заключение

На текущий момент Certonid не содержит всего функционала, что я задумал для него:

  • нет автоматического переключения на другие serverless, если регион упал;
  • нет тестов (что немаловажно для последующей разработки);
  • хочется добавить поддержку Google Cloud и Azure (если с первым все понятно, то у второго нет поддержки Golang);
  • надо еще улучшать документацию.

Но я надеюсь, что этот продукт уже сможет вам помочь более безопасно работать с SSH.

Формат статьи не позволяет за один раз раскрыть важные аспекты работы с SSH-сертификатами и Certonid, такие как SSH-хост-сертификаты, critical options и extensions в сертификатах, настройка и работа с KMSAuth, значение настроек в конфигах Certonid и прочее. Если читателям эта тема интересна, я постараюсь продолжить рассказ в следующей статье.

Благодарю за внимание! Успехов вам с SSH-безопасностью!

DOU Ревізор в Одесі: «Кабінетна система і більярд у Sigma Software»

$
0
0

Знімальна група DOU Ревізорвже відвідала компанію Sigma Software влітку 2017 року, але тоді досліджували львівський офіс. Цього разу ревізію провели в Одесі.

Sigma Softwareпонад 17 років займається IT-консалтингом та розробкою програмного забезпечення для клієнтів в усьому світі — від Австралії до Західного узбережжя США. Компанію було засновано 2002 року в місті Харкові, а 2006 року вона доєдналася до однієї з найбільших скандинавських ІТ-корпорацій Sigma Group у Швеції.

Офіси компанії в Україні розташовані в Харкові, Одесі, Києві, Львові, Дніпрі, Сумах та Вінниці. Також є офіси та представництва у Швеції, США, Польщі та Австралії. Одеський офіс наразі налічує 76 осіб, з них 65 технічних спеціалістів. Усього Sigma Software в Україні об’єднує понад 1100 професіоналів.

В околицях і поблизу

Перший офіс Sigma Software в Одесі відкрився 2006 року. А до БЦ за адресою вул. Леха Качинського, 7 компанія переїхала лише у травні цього року. Доти команда працювала на іншому кінці міста, ближче до Аркадії.






Крім виду на море, після переїзду з’явилися й інші переваги, в тому числі набагато більше місць поблизу, де можна перекусити:

  • Кафе «Гречка» — зовсім поруч, бізнес-ланч у закладі обійдеться до 100 грн.
  • У чотирьох хвилинах пішки від БЦ розташовані кафе «Молодість», де середній чек складає 100-150 грн,та бургерна Coopers Burgers, де обід коштуватиме приблизно 150-200 грн.
  • Популярним місцем для обіду є «Міський ринок їжі» — величезний фуд-корт у стильній старій будівлі в 7 хвилинах від офісу. Там можна знайти страву до смаку від 60 грн.

Спеціалісти мають змогу зафіксувати за собою паркувальне місце. Усього для команди Sigma Software на закритому майданчику цокольного поверху БЦ виділено 13 місць для автівок та 10 для велосипедів. Паркомісце для автівки платне, компанія відшкодовує 50% його вартості. Як нам розповіли спеціалісти компанії, зазвичай залишаються вільними 1-2 слоти,крім того, додаткове місце компанія бронює для гостей, що приїжджають з інших міст.




Офісний побут

Одеський офіс Sigma Software займає два поверхи та 1477 м2. У середньому на одну особу припадає 10,33 м2 простору.

В офісі Sigma Software реалізовано пропускну систему. Загалом пропуск потрібен для того, аби зайти до БЦ та на поверх. Проте є і закриті кімнати, до яких мають доступ лише команди відповідних проектів. Також це стосується серверної кімнати та бухгалтерії.






Верхній одяг можна залишити у загальному гардеробі на третьому поверсі або у шафі своєї проектної кімнати.

До лютого в будівлі бізнес-центру триватиме ремонт. Хоча Sigma Software і має домовленості з адміністрацією БЦ щодо ремонтних робіт, час від часу будівельники їх порушують і заважають спеціалістам шумом.

Система вентиляції та обігріву в офісі централізована. У кожній кімнаті є пульт управління, за допомогою якого можна налаштувати комфортні характеристики. До цього пульту можна підключитися зі смартфону через Bluetooth, тож немає необхідності вставати зі стільця, аби змінити температуру у кімнаті. Конфліктів не виникає, зі слів членів команди: «Вентиляція комфортна, немає дитячого садка, коли хтось змінює налаштування з телефону».


Спеціально відведеного місця для куріння у компанії немає, тож доводиться спускатися на перший поверх і виходити на вулицю. У бізнес-центрі навіть діє заборона куріння на балконах, проте вейпів вона не стосується.

Кухня є як на третьому, так і на четвертому поверхах. Там завжди в наявності все необхідне: чай, кава, сиропи, мікрохвильовки і холодильники. Щопонеділка у компанії відбувається «Fruit Monday», тоді на кухнях до всього з’являються свіжі сезонні фрукти.






Опівдні до Sigma Software привозять їжу з місцевих ресторанів, за яку можна розрахуватися або залишивши готівку в «Honesty box», або через термінал. Солодощі та різноманітні батончики також можна придбати просто на четвертому поверсі.


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


Щовихідних до Sigma Software приходить флорист, який дбає про офісні рослини. У компанії є окрема стаття витрат на озеленення простору. Спеціалісти можуть залишити заявку та замовити до кімнати бажану рослину.

Для тих, хто приїжджає у відрядження, офіс-менеджери готують гостьові халати, капці та рушники у душових кімнатах. Фен є в усіх душових, а от скористатися прасувальною дошкою та праскою можна лише на третьому поверсі.





Робочий простір

Інтер’єр офісу створили з простих матеріалів: дерева, бетону та скла. У дизайн заклали філософію, яку сповідують у Sigma Software, — ла́гом. Це шведське поняття, що означає розумне ставлення до життя: коли в тебе всього не багато і не мало, а саме стільки, скільки треба.

У компанії давно відмовилися від формату опенспейсів — їх немає в жодному з офісів Sigma Software. Простір організовано за кабінетною системою, в кожній робочій кімнаті в середньому від 6 до 12 осіб. Є одна велика кімната на 14 столів, але на постійній основі там працює лише один фахівець. У ній також розміщуються спеціалісти, що приїхали у відрядження з іншого міста. Одеський офіс користується найбільшою популярністю влітку.






За потреби членам команди надають підставки для роботи стоячи або столи, в яких можна відрегулювати висоту. У компанії виділена роль «People partner». Запити до нього надходять різні: він відповідає за процес адаптації та соціалізації новачків, а також виступає першим контактом, від якого можна отримати будь-яку інформацію. Один people-партнер може відповідати за команду до 80 осіб.

Табличку «Clean me, please» спеціалісти компанії залишають, аби «подати сигнал» прибрати на їхньому робочому столі. Знак призначено офісним прибиральницям.


У Sigma Software намагаються розрахувати майбутнє оновлення техніки. Щороку у компанії бюджетують певну кількість комп’ютерів залежно від спеціальності. При виборі техніки орієнтуються на потреби проектів та стандарти конфігурації, які оновлюються щороку. Аби отримати покращений або новий комп’ютер, спеціаліст звертається безпосередньо до свого менеджера. Планово у компанії замінюють техніку, що досягла трирічного віку. Працюють як на стаціонарних комп’ютерах, так і на ноутбуках, дизайнери переважно працюють на Apple-комп’ютерах.






Усього у компанії вісім переговорних кімнат: п’ять на третьому поверсі та три на четвертому. Забронювати їх можна за допомогою Outlook-календаря або просто у кілька кліків на планшетах, що розташовані біля кожної переговорки. Для цього спеціалісти Sigma Software написали невеликий додаток.


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






Офіційний графік — з 10 до 19, але насправді він залежить від проекту та його географії. Якщо команда працює з замовником зі Сполучених Штатів, то починають свій день пізніше. Також спеціалісти компанії можуть працювати віддалено з дому або з будь-якого офісу — вони, до речі, відчинені 24/7.

Відпочинок і натхнення

Біля кухні третього поверху є кімната для відпочинку із столами для більярду, настільного тенісу та кікеру.

Більярдний стіл з ігровим полем у 10 футів — справжня родзинка офісу. Члени команди часто грають між собою та запрошують професійних тренерів, аби покращити свої вміння. Оскільки кімната з більярдним столом знаходиться подалі від робочих зон, немає обмежень та заборон на гру в якийсь конкретний час.





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





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

Заняття з йоги проходять із зовнішнім тренером зранку щосереди та щоп’ятниці. Також двічі на тиждень увечері заняття проводить одна з членів команди Sigma Software.





Коли планували, як організувати простір нового офісу, провели опитування. Виявилося, що ігрова приставка не викликає ажіотажу серед членів команди, тож вирішили обійтися без неї. Але на практиці зрозуміли, що попит є, тому на четвертому поверсі з’явилася невелика ігрова зона з PlayStation 4. Наразі вона знаходиться в коридорі.


Спеціалісти мають змогу відвідати 10 безкоштовних сеансів масажу щопівроку. Аби далеко не ходити, в офісі облаштували окрему масажну кімнату.





Зайнятися чимось новим спеціалісти компанії можуть у «R&D лабі». Наприклад, створити робота, що самостійно знаходить вихід з лабіринту. В Одесі є окремі змагання, коли організатори надсилають схему лабіринту учасникам, а вони запускають робота та фіксують час, за який машина змогла впоратись із завданням. Наразі у лабі знаходиться синтезатор, проте планують розмістити зону з музичними інструментами в окремому місці.






Уроки англійської мови проходять двічі на тиждень для кожного рівня. Спеціалісти можуть займатися з трьома різними викладачами, з них двоє — носії мови. У компанії регулярно проводять тематичні короткі курси, наприклад про те, як правильно листуватися англійською або вести переговори. Усіма тренінговими активностями та навчанням спеціалістів займається окремий тренінг-департамент.

З першого дня роботи спеціалісти отримують доступ до корпоративної програми IT assistant. Вона має і медичний напрям: можна викликати лікаря, здати аналізи та пройти обстеження. У межах програми спеціалісти отримують знижки на усі кафе та ресторани, що підтримують IT assistant. Також можна скористатися напрямом IT Care, щоб знайти спеціалістів, які вирішать побутові питання або допоможуть налаштувати сервіси. Програма передбачає і юридичну підтримку: спеціалісти можуть отримати консультацію в IT Legal.

DOU Ревізор запитує

Ми провели анонімне опитування членів команди Sigma Software, у якому взяли участь 46 спеціалістів компанії, тобто 60% команди одеського офісу. Ми поцікавилися, як же їм живеться в офісі, і попросили оцінити за п’ятибальною шкалою деякі характеристики: розміщення, графік, робоче місце й офісний простір.

Усі опитані спеціалісти оцінили графік, можливість працювати віддалено та розміри особистого простору у 4 та вище бали. Найменш задовільні оцінки отримала якість периферійних пристроїв: 30% опитаних залишили відмітку 3 й нижче. Третина респондентів вважає розташування у центрі однією з найбільших переваг офісу, однак середня оцінка характеристики — усього 4,17 з 5 балів.

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

Серед побажань від спеціалістів — замінити крісла на більш ергономічні, додати окрему музичну кімнату та організувати більше місць, де можна відпочити наодинці. При цьому третина опитаних зазначає, що в офісі їх все влаштовує та вони нічого б не хотіли змінити або покращити.

Ми також особисто поспілкувалися зі спеціалістами компанії й поставили два нескладні запитання: що їм найбільше подобається в офісі та що хотілося б поліпшити або змінити.

Олексій, Back-end Developer, 4 роки з компанією

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

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

Вадим, .NET Software Developer, 2 роки з компанією

Мені дуже подобається дизайн, особливо комбінація «лофт плюс скло». Круто, що ще під час ремонту продумали кондиціонування приміщень. А ще дуже зручно, що у нас майже все дублюється і не потрібно бігати між поверхами.

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

Роботу з дому мені зараз складно назвати перевагою. За два роки в компанії це стало так звично, що дивно, якщо такої опції немає. У нас це надзвичайно легко вирішується та реалізується.

Анна, Product Manager, 7 років з компанією

Свій шлях у компанії я розпочинала як тестувальниця. Встигла опанувати багато різних ролей та попрацювати з різними проектами. У компанії підтримують твій розвиток — немає обмежень у напрямку. Я вважаю, що це дуже велика перевага.

Попередній офіс теж був непоганий, проте цей — просто чудовий. Я багато часу провожу на роботі, тож приємно, коли офіс знаходиться в центрі міста. Ти можеш вийти випити кави на балкон з видом на старе місто та порт. Мені подобається, що є можливість розпоряджатися власним графіком — ніхто не вимагає приходити за секундоміром. Особисто я працюю зі Штатами, тож опівдні тільки приходжу на роботу.

Чотири роки тому ми шукали якусь активність, що була б цікавою для дівчат у компанії. Бо хлопці займалися і футболом, і баскетболом, а от дівчата не мали чогось для себе. Тоді я відвідувала заняття з йоги. Шлях до зали був незручним, проте мені неймовірно подобалась тренерка. Тож вона почала проводити тренування в офісі лише для дівчат, але зараз на заняттях більше половини хлопців.

Щодо мінусів, то мені іноді не вистачає мітинг-румів. Маленьких, де можеш зачинитися сам або провести невелику спонтанну зустріч. Проте у нас досить багато комфортних зон, де можна перепочити. Наприклад, на диванчику у більярдній. Це, звісно, не капсули для сну... Проте якусь підзарядку можна легко отримати.


Ну що, ми рушаємо далі... А якщо ви хочете, аби DOU Ревізор завітав до вас, пишіть: revisor@dou.ua

Ми катаємося по Україні в пошуках найкреативніших та нестандартних офісів ІТ-компаній. Разом з нами ви зможете зазирнути за лаштунки офісного життя. Але вирішувати, гарний це офіс чи ні, будете тільки ви!

Стежте за нами у Facebook.

Підписуйтесь на відеоканал DOU Ревізора на YouTube.


Фотограф: Леся Коверега

На що звернути увагу ІТ-спеціалісту під час підписання договору із замовником. Поради юриста

$
0
0

Договори без звички читати складно. Їх написано формалізованою мовою, вони довгі й часто містять фрактальні уточнення та купу посилань на інші пункти... У них легко заплутатися. Окрім того, якщо ваша робота не пов’язана з договорами, легко прогледіти щось важливе й не завжди можна тверезо оцінити, чому якісь із пунктів дійсно істотно впливають на процес роботи з контрагентом, а якісь уписано лише для залякування чи формальності. Проте в ІТ-сфері більшість роботи все-таки пов’язана з угодами, і людям з далекою від права професією часто хочеться поліпшити свої навички читати юридичні тексти й оцінювати наслідки їхніх положень. Дехто навіть пише собі шпаргалки: на що звернути увагу? Що перевірити насамперед?

Я юрист і переважно працюю з контрактами, GDPR/ССРА (тобто персональними даними) й інтелектуальною власністю. У цій статті поговоримо про укладення договорів на розробку програмного забезпечення. Ми пройдемо по ключових, типових та страшних пунктах і розберемося, що це все означатиме для розробника. Стаття буде корисна девелоперам, які укладають договори з ІТ-компаніями на постійній основі чи у проектному режимі.

FAQ

Перш ніж розпочати екскурс у договори, ми швидко пройдемося найчастішими запитаннями й дамо на них відповіді.

Чому одні договори двомовні, а інші одномовні?

Тому що під час укладання договорів у межах України (наприклад, якщо замовник і виконавець — українські компанії, ФОПи чи громадяни) договори все-таки ліпше укладати українською. Тоді не буде складнощів у роботі з державними органами чи банками, які надають перевагу державній мові й під час проведення платежів за договором регіональною мовою можуть вимагати (завірений) переклад.

Якщо одна зі сторін іноземна (тобто договір укладено між, наприклад, українським ФОПом та американською компанією), то звичною діловою практикою стало вкладання двомовного договору (зазвичай українсько- й англомовною версією): так державні органи й банки відразу матимуть погоджений переклад українською мовою. Багато банків також приймають російськомовні тексти, але, щоб запобігти затримкам, найбезпечнішим буде вписати паралельний український переклад.

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

Чим надання послуг відрізняється від виконання робіт?

Послуга, у більшості випадків, споживається у процесі її надання. Наприклад, консультування — це послуга, бо інформацію надають у процесі виконання договору.

Але робота має певний утілений у матерії результат: якщо підрядник має виконати якісь дії для створення об’єкта, і замовник потім має результат роботи оглянути й прийняти, то в більшості випадків це вважатимуть роботою.

Що дійсно важливо знати, так це те, що акти після виконання договору ліпше підписувати як під час надання послуг, так і під час виконання робіт.

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

Яким завтовшки має бути договір за стандартом?

ДСТУ щодо кількості сторінок у договорах немає. Вони можуть бути великі й докладні, а можуть бути стислі та небагатослівні: усе визначають природа послуг чи робіт і роль кожної сторони. Однак договір — це правила гри: що докладніша інструкція, то менше запитань у процесі співпраці щодо невиправданих сподівань.

Вимог щодо розміру шрифту немає. Тут скоріше діє логіка: кожен пункт в договорі має бути читабельним з точки зору розміру шрифту.

Яка різниця між ФОПом і працівником? Чи є ці слова синонімами?

Ні. Працівників захищають права (і вони несуть обов’язки) не лише відповідно до трудового договору або контракту, а й згідно з трудовим законодавством (славнозвісним КЗпП). Вони мають право на відпустки, лікарняні й оплату за роботу понад установлений робочий день чи у вихідні та святкові дні.

Абсолютна більшість ІТ-індустрії в Україні пропонує розробникам надавати послуги через формат співпраці з ФОП. ФОП — суб’єкт господарювання, що укладає господарський договір, і тому в такому договорі можна писати все, що можна писати в межах свободи договору, і такі пункти будуть діяти. Наприклад, досить проблемним є одностороннє розірвання договору з боку розробника, якщо це прямо заборонено договором, і за це є штраф.

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

У нормі ФОП сплачує єдиний податок у 5% (або ж 3% + ще ПДВ). У багатьох ІТ-компаніях, що наймають працівників, із зарплати зі свого боку утримують ПДФО (18%) і військовий збір (1,5%). Водночас не зникає потреба платити ЄСВ: у ФОПа він не має бути меншим за 22% від мінімальної заробітної плати, а під час працевлаштування компанія нараховуватиме ЄСВ на заробітну плату працівника.

Але вигідним може бути не лише оподаткування: у випадку з договорами на розробку й авторськими договорами отримувач послуг має зручніший інструмент впливу на підрядників, ніж на працівників за трудовими: наприклад, може розірвати договір з підрядником у найкоротші строки з мінімальними формальностями (звісно, якщо це прописано в договорі) чи навіть притягти його до відповідальності за неотриманий прибуток (якщо зможе довести в суді причинно-наслідковий зв’язок між поведінкою підрядника та неотриманим прибутком і надати переконливі аргументи щодо існування таких можливостей та завданих компанії збитків). Інакше кажучи, за наявності по суті умов відносин працевлаштування той, хто бажає отримати певні послуги, може перебувати в привілейованому становищі з погляду законодавства про працю. Тому держава намагається відстежувати приховані трудові відносини.

Якщо в мене договір з іноземною компанією, то закони якої країни застосовуються?

Це треба точно перевірити в договорі: зазвичай там є розділ, де вказано право держави однієї зі сторін або навіть третьої держави (наприклад, якщо це договір про розподіл акцій між українським інвестором і кіпрською компанією, то там часто можна знайти посилання на англійське право). В ідеалі слід консультуватися з юристом, перш ніж підписувати договір, що його складали відповідно до незнайомого правопорядку.

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

Ілюстрації: Каталіна Маєвська

Non-disclosure

Страшно, коли тебе зв’язує NDA: ніколи не знаєш, як багато можеш розповісти друзям у барі після важкого тижня. Запитання «Як справи? Що на роботі?» й сухе «NDA» у відповідь можуть згубити чудову дружбу! (А скільки ж запитань чують юристи, коли ввечері святкують у барі прийнятий другом офер!)

Випереджаю запитання: так, NDA дійсно в окремих випадках загрожують неприємностями. Однак не слід плутати Non-disclosure agreement (NDA) з Non-compete agreement (NCA). У наступному пункті ми зупинимося на цьому докладніше, але поки що:

NDA = NCA

NDA (non-disclosure agreement) традиційно перекладають українською як договір про нерозголошення конфіденційної інформації. Це може бути окремий договір або ж розділ в іншому, загальнішому договорі (наприклад, договорі про надання послуг (чи виконання робіт) з розробки програмного забезпечення). Інколи трапляється, що треба спочатку погодитися із цим пунктом, відтак підписати договір, а потім ще й у журналі компанії-замовника розписатися! Тому перевіряти, що перед вами NDA, ліпше не за формою, а за змістом.

У договорі про конфіденційність одна сторона (зазвичай замовник, або конфідент, Discloser, Disclosing Party) розкриває, а інша (виконавець, конфіденціал, Recipient, Receiving Party) дістає доступ до певної інформації й зобов’язується не розголошувати та не використовувати її поза межами виконання договору з першою стороною.

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

Текстова частина: NDA потребує обережного формулювання. Ліпше ні угоду, ні пункт контракту не брати з Інтернету чи іншого договору. Поганою ідеєю є також скористатися автоматичним перекладом іншого (хай навіть англомовного та підготованого найліпшими британськими юристами) договору. NDA — річ тонка, і в хорошому пункті чітко зазначать, зокрема:

  • яка інформація вважається конфіденційною (завершені й незавершені комп’ютерні програми, програмний код чи об’єктний модуль, сценарії, алгоритми,
  • об’єкти дизайну, бази даних, ноу-хау, плани майбутніх програм, застосунків, ціни, технології виробництва тощо — деталізація не завадить!);
  • від яких дій треба утриматися (тобто способи розголошення: усно, письмово, через пошту чи поштових голубів, через операції зі своїм акаунтом у хмарі чи флешносіями тощо);
  • які дії для захисту даних треба виконувати (дотримуватися політик безпеки даних, що застосовуються в компанії, не виносити техніку чи не приносити свою й не користуватися незахищеними мережами);
  • відповідальність (умисні дії або витік даних через грубу необережність, штраф або обов’язок відшкодувати вартість утраченої інформації).

Водночас усі ці деталі припасують до конкретної домовленості. Наприклад, у сейлза й розробника буде доступ до різної інформації: оскільки конфіденційності зазвичай найліпше відповідає принцип need-to-know як передумова доступу до інформації, то для різних ролей підрядників і посад працівників ліпше скласти окремі редакції NDA (і вносити туди лише ті види інформації, способи захисту та санкції, які відповідають конкретним завданням підрядника або посадовій інструкції працівника).

Організаційна частина:окрім власне NDA, замовникові треба буде подбати про налагодження процесів і процедур, які сприяли б реальному захисту інформації. Інакше кажучи, просто задекларувати наявність конфіденційної інформації недосить: слід підтвердити, що вона дійсно цінна, і її охороняє замовник.

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

Однак на практиці NDA можуть принести несподівані радощі ні в чому не винному підрядникові чи працівникові. У ситуації, якщо, скажімо, дизайнер підпише договір, який підпорядковано праву США, то саме замовник буде зобов’язаний доводити витік даних і зв’язок між злитими в канали Telegram скринами редизайну гри й виною саме цього українського дизайнера. Схожі моменти існують і з працевлаштуванням: хоча в багатьох юрисдикціях підписання NDA є нормальною практикою (у тих самих Штатах), в Україні спробу роботодавця через суд виконати положення договору про конфіденційність можуть сприймати як порушення КЗпП (стаття 9 якого забороняє вкладати з працівниками договори, умови яких погіршують становище працівників, як порівняти із чинним законодавством), і суди переважно відмовляються визнавати такі NDA дійсними.

Ще один плюс роботи з підрядниками в такому разі: до працівників не можна застосувати відповідальність, яку передбачає стаття 24 Закону України «Про захист від недобросовісної конкуренції»: цей закон поширюється тільки на суб’єктів господарювання (зокрема компанії й ФОПів). Тобто в разі, якщо конфіденційність порушив працівник, то позов можна засновувати на загальних засадах, передбачених Цивільним кодексом, але не Господарським кодексом чи законодавством про захист конкуренції.

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

  • відповідача ознайомили з положенням підприємства про інформацію, що належить до конфіденційної;
  • позивач не надав доказів розкриття конфіденційної інформації;
  • позивач не надав будь-яких обґрунтувань суми неотриманого прибутку (тобто чи дійсно позивач отримав би цей дохід і в заявленому позивачем розмірі);
  • позивач не надав доказів причинно-наслідкового зв’язку (тобто що саме відповідач своїми діями чи бездіяльністю спричинив розкриття інформації і що таке розкриття дійсно завдало шкоди позивачеві);
  • договір був безстроковий або укладений на нераціональний (з огляду на цінність самої інформації, спосіб її обробки або технічний прогрес) строк (що досить поширено в судових органах країн, де NDA широковживаний) тощо.

Але є й успішні кейси. Наприклад, якщо колишній працівник позивача міг завдяки своєму службовому становищу дістати доступ до конфіденційної інформації про клієнтів позивача й скористався нею, перейшовши до іншої компанії (щоб переманити клієнтів), то позивач має всі шанси стягти з відповідача вартість неукладених з колишніми клієнтами контрактів, які він інакше зміг би укласти.

Попри це, ліпше відразу оцінити свої шанси поповнити вітчизняну судову практику власним прикладом, перш ніж (1) підписувати NDA і (2) розголошувати конфіденційну інформацію. З питаннями збереження конфіденційності також інколи пов’язують захист ділової репутації, і часто репутація може бути куди ціннішим ресурсом для потенційного відповідача, аніж прибуток від частково проданої клієнтської бази попереднього замовника послуг.

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

Non-compete/Non-solicit

Non-compete (NCA), або договір про неконкуренцію, частіше вживають для опису домовленості між замовником і працівником/підрядником про те, що колишній працівник або підрядник не конкуруватиме зі своїм замовником або роботодавцем, зокрема в тій самій сфері або на тій самій території, протягом певного часу — кількох місяців або навіть років. Non-solicitatiton (NSA) зі свого боку стосується й (не)переманювання працівників і підрядників одна в одної, і заборони впливати на клієнтів іншої компанії з умовляннями відмовитися від послуг конкурента. Обидві використовують зазвичай для досягнення таких цілей:

  1. Виграти час, протягом якого колишній працівник чи підрядник утратить кваліфікацію або актуальність інформації чи навичок, які здобув за час співпраці.
  2. Здобути виключні права на виробництво певного товару чи надання послуг протягом кількох років (і не зміцнювати конкуренцію кількістю своїх підрядників та колишніх працівників).
  3. Запобігти витоку конфіденційної таємниці.
  4. Утримати талановитих підрядників і працівників біля себе.

Тут усе просто: суди в Україні тепер не визнають ніяких NCA чи NSA, які вклали відповідно до українського законодавства. То чи можна підписувати їх без жодної задньої думки? Спойлер: ліпше не треба.

Традиційно українські суди вважають NCA й NSA формою обмеження права на працю, яке гарантує Конституція, і погіршенням становища працівника, що забороняє КЗпП. Однак у разі, якщо NCA або NSA укладено відповідно до іноземного закону, то вони можуть бути дійсними, оскільки є легальними і їх застосовують у правовій системі, праву якої належить цей договір. Наприклад, французькі працівники будуть зв’язаними NSA/NCA, якщо їх передбачено в колективній угоді.

Заразом не слід скидати з терезів також інші особливості:

  • Територію, на яку поширено вимогу неконкуренції (перевага надається території населеного пункту або його частини, але водночас не слід плутати договір про неконкуренцію з дистриб’юторськими договорами, які теж часто містять обмеження території).
  • Період часу, протягом якого слід утримуватися від конкуренції або переманювання (американські суди в низці штатів зазвичай допускають період від кількох місяців до року або двох, водночас наполягаючи на додаткових обмеженнях заборони).
  • Оплата або відшкодування наданих послуг чи виконаних робіт, які отримував підрядник або працівник за час співпраці (деякі юрисдикції у Європі й Штатах мають нижню межу оплати праці або послуг: якщо заробітна плата або сукупний дохід були меншими за цей поріг, то вкладати з нею NCA/NSA законодавство або судова практика не заохочують).
  • Право ініціювати розрив угоди про неконкуренцію або непереманювання.
  • Право перевідступу договору про NCA (оскільки продавець, наприклад, не може перевідступати право покупцю компанії, якщо працівник не надав на це окремої згоди) тощо.

Тому ліпше ознайомитися з текстом. А якщо договір іноземний, пошукати інформацію про стан судової практики у відповідній державі.

Оплата

У працівників зарплата щомісяця (зазвичай), а в підрядника може бути по-різному. Зазвичай форми оплат діляться на категорії time-and-material, fixed price та екзотичні форми.

За умови оплати time-and-material підрядник (сейлз, дизайнер, розробник, тестер тощо) отримує оплату не як фіксовану щомісячну суму, а за результатами наданих послуг. Наприклад, її можна вимірювати в ефективних годинах: якщо на новий дизайн або цикл тестування підрядник витратив у сумі орієнтовно двісті годин, то йому оплатять кількість цих годин (помножену на погодинну ставку). Тобто оплачують не вартість проекту, а певну кількість витраченого на надання послуг часу (а також витрати на купівлю матеріалів: програмного забезпечення й техніки, послуги хмарного зберігання тощо). Їх можна розбивати на оплату кількості годин, які витратили за певний період. Водночас слід уважно відстежувати, чи несе відповідальність, наприклад, компанія-аутстафер за результати послуг, чи ж просто надає послугу: години послуг своїх працівників або підрядників. Тоді як для підрядника-аутстафера важливо з’ясувати:

  • чи оплачуватимуть йому простій (бенч), у якому розмірі й хто — компанія-аустафер чи замовник;
  • чи діє на нього умова про buyout (так званий викуп), якщо підрядник захоче працювати не з компанією-аутстафером, а з клієнтом напряму (buyout також зацікавить, наприклад, сейлзів з уже напрацьованою базою: він дасть можливість залишити свої контакти й перейти з ними до іншої компанії, продовжуючи співпрацю без порушення договорів про неконкуренцію, непереманювання або конфіденційність);
  • які потрібні знання, досвід, кваліфікація й рівень володіння фреймворками (оскільки до них часто прив’язують гарантії щодо якості фінального продукту: такий підхід поширений, наприклад, у Штатах, де від розробника, системного адміністратора або тестувальника конкретного рівня залежать сподівання щодо результату наданих ним послуг або реальність виконання ним implied warranties компанії щодо фінального продукту);
  • кому належать розроблені права інтелектуальної власності (програми, винаходи тощо) і якої миті ці права переходять до замовника — відразу після створення (що вигідно замовникові) чи оплати (що вигідно підрядникові).

Інша умова — fixed price: увесь проект оцінюють у єдину суму, водночас оплату здійснюють не за кількість залучених спеціалістів або витрачених на роботу годин, а за виконання конкретного завдання й передавання результатів замовникові. Зазвичай у такому разі підрядник несе відповідальність не за кількість витраченого часу (окрім, звісно, дедлайну проекту), а за кінцевий результат послуг (щоб він відповідав наданому замовником ТЗ).

Водночас найбільше суперечок під час обговорення умов співпраці зазвичай виникає через:

  • дедлайни (звісно ж);
  • оплату частинами (milestone schedule — попри те, що фінальну вартість уже узгоджено, сторони поділяють її на кілька платежів, які прив’язано до часових інтервалів або інтервалів передавання замовникові вже готових результатів);
  • передавання інтелектуальної власності (як і в попередньому абзаці);
  • додаткові послуги й прив’язку до ТЗ (оскільки зазвичай завдання, як-от кількість user stories абощо, узгоджують у повному переліку й оцінюють у певний кост;
  • якщо в процесі треба додати нові послуги або прибрати частину з них, сторони можуть домовлятися про переоцінку проекту з огляду на те, що його вартість падає або зростає);
  • порядок прийняття-передання результатів робіт і послуг.

Однак є й інші способи. Є абонентські тарифи (коли передбачено стандартне навантаження за певну вартість, і платежі за такої умови є щомісячними, щоквартальними тощо) і капи (тобто як буде досягнуто певну вартість або кількість годин, сторони можуть укласти новий договір, просто передати вже розроблені до цієї миті об’єкти й розійтися або узгодити інші умови чи встановити новий ліміт годин). Можна використовувати будь-яку систему оплати послуг, головне переконатися, що вона охоплює передавання об’єктів інтелектуальної власності (а якщо ні, то скільки підрядник або працівник отримуватимуть додатково за кожну програму, малюнок чи модуль?).

Права інтелектуальної власності

Пул запитань виникає відразу:

Кому належать права інтелектуальної власності (авторові, замовникові, роботодавцеві, клієнтові чи всім порівну?)

Це питання ліпше прописувати в договорі чітко: автор може опинитися в незручній ситуації, коли він як підрядник створить у вільний час на бенчі програму, а потім виявиться, що оскільки він використовував обладнання замовника, то останньому й належать усі майнові права на цей твір. Або ж навпаки: замовник вважатиме, що йому перейшли всі права на створений бренд-бук, а насправді підрядник-дизайнер не прописав чітко цей пункт і права їм належать у рівних частинах (50 на 50%). Якщо ж цей малюнок, програму чи інший матеріал створив працівник у межах службових обов’язків, то ці результати, найімовірніше, належатимуть роботодавцеві.

Що передають у межах цього договору?

Українське право не дозволяє забрати в автора його немайнові права (наприклад, право бути згаданим як автор цього зображення). Водночас право на створення похідних творів, на переклад або використання не тільки в бренд-буку, а й на сайті та в літературних творах можна монетизувати (тобто воно є майновим правом) і передавати. У такому разі в договорі з підрядником слід чітко описати, які саме права передають, наприклад: виготовлення копій програмного забезпечення, публічна демонстрація дизайну, модифікація й переробка об’єктів, розповсюдження (тобто продаж і безплатне передання конкретних екземплярів ліцензій), здавання в найм, ліцензування тощо.

Ці об’єкти оплачують окремо чи разом з іншими послугами?

За загальним правилом, передавання прав інтелектуальної власності підлягає оплаті. Щоб уникнути цього, якщо об’єкти розробили під час надання інших послуг (або виконання суміжних робочих обов’язків, які в нормі не передбачають створення об’єктів інтелектуальної власності), договори передбачають формулювання на кшталт «винагорода за цим договором охоплює також вартість розроблених у межах надання послуг об’єктів інтелектуальної власності». Якщо це не передбачено, то можуть укладатися окремі цивільно-правові угоди про передання об’єктів інтелектуальної власності (ліцензії або угоди купівлі-продажу). Якщо ж ці програми або зображення створили в межах авторського договору, то ситуація інша: такий договір саме й передбачає створення об’єкта інтелектуальної власності і його передавання замовникові.

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

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

Якщо договір описано з урахуванням усіх тонкощів, то сторона, що складала договір, може мати перевагу в суді: просто тому, що договори складають з метою якщо не уникнути судового розгляду, то принаймні зробити його мінімально витратним і складним для сторони, що складала договір. І якщо підрядник або працівник не намагатиметься зменшити кількість зв’язків між розробленим ним сайд-продуктом і його замовником чи одним із замовників (через використання власної техніки й особистих облікових записів у SaaS-софті, у час, вільний від надання послуг, без оплати замовником витратних матеріалів чи потрібних даних та без використання інтелектуальної власності замовника), то цілком імовірно, що в разі успіху йому доведеться позмагатися в суді з озброєним логами, чеками й виписками колишнім замовником.

Дедлайни і строк надання послуг

Цілком логічно боятися ексклюзивності: може статися, що замовник наполягатиме, щоб ви відмовилися працювати з його прямими конкурентами або займатися іншими проектами під час дії договору. Це може бути обмеженням свободи торгівлі й практикою порушення конкуренції, але завжди є ризик того, що договір підлягатиме правопорядку, де таке обмеження є цілком законним.

Важливо переконатися, що цей договір не завадить потім вашому кар’єрному зростанню чи розширенню бізнесу. До речі, чи встигнете ви напевне надати послуги в строк? Чи охоплює дедлайн припущення, що строк подовжать у разі виявлення дефектів ПЗ чи артефактів коду або з причин, що не залежать від сторони? А якщо виникне потреба наново зібрати команду (бо клієнт попрохав усунути одного з мідлів, а за договором послуги має надавати команда в повному складі) і це займе час?

Ліпше передбачити ці ризики й залишити собі можливість відкласти дедлайн.

Порядок розірвання договору

Зауважте, що безстрокові договори з іноземними партнерами викликають (часто обґрунтовану, з огляду на досвід) підозру вітчизняних податківців і банків. Тому виникає потреба встановити ліміт часу надання послуг: наприклад, стандартом часто встановлюють рік і пролонгацію (продовження договору) за умови виконання певних формальних умов. Інший спосіб — укладати генеральний рамковий договір і погоджувати його продовження додатковими угодами до нього (які, наприклад, фіксують конкретний проект і склад команди).

Інколи життєво важливо прописати порядок виходу з договору:

  • строк і спосіб повідомлення про бажання припинити угоду;
  • порядок оплати вже виконаної роботи або наданих послуг;
  • порядок погодження та прийняття в роботу завдань (tasks) і чіткі критерії їхнього завершення;
  • порядок вирішення суперечок і виправлення дефектів у раніше наданих послугах чи виконаних роботах;
  • ідеально — фіксування переходу всіх оплат за допомогою актів передання результатів робіт чи робіт, де вказано, що сторони не мають претензій одна до одної.

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

Продуктивність

Якщо це дійсно важливо, ліпше все звести до певної цифри. Чи то буде кількість ідей для рекламного ролика в межах однієї комерційної пропозиції, чи кількість рядків коду, чи кількість модулів, чи кількість зображень у концепті персонажа, чи кількість способів розміщення реклами на огорожі футбольного поля в комп’ютерній грі, чи варіантів малюнка для реєстрації як знака для товарів і послуг...

Також ліпше чітко передбачити відповідальність, скажімо, хто має надавати ідеї: замовник (а підрядник — шляхи реалізації) чи підрядник? Чи повинен потім підрядник створювати прототипи, чи відразу готовий об’єкт? Як довго може тривати погодження ідеї в компанії замовника (і хто з його боку відповідає за погодження результатів послуг)? До якого етапу реалізації замовник може вносити чи пропонувати зміни?

А головне: хто оплачує брак креативності чи спад продуктивності? Що робити, якщо агентство створило прототипи чітко за ТЗ замовника, але не отримало обґрунтованої відмови: покинути неуспішний проект, надати інвойс за фактично надані послуги й сконцентруватися на пошуку нових замовлень чи працювати на гонорар успіху без сподівань будь-коли відшкодувати хоча б витрачений час і матеріали? А що як перспективний замовник узяв розроблену схему чи архітектуру проекту й замовив реалізацію іншим підрядникам?

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

На десерт: відповідальність

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

Головне не панікувати і вчасно оцінити свої можливості. І звісно, внести правки в люб’язно наданий замовником договір.

По-перше, уникайте використання штрафів як карних функцій: багато правопорядків забороняє використовувати їх для покарання контрагента. Ліпше розглядати штраф як зручний інструмент стягнення збитків. Тобто ліпше вибирати щось одне: або відшкодування збитків (тоді в постраждалого з’являється ще завдання не лише оцінити збитки, а й довести, що вони виникли з вини підрядника), або (розумний) штраф.

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

По-друге, не беріть на себе відверто несправедливий обов’язок компенсувати чужі помилки: якщо потім інші програмісти змінюватимуть частину розроблених об’єктів або інхауз-маркетологи підтримуватимуть чи переналаштовуватимуть маркетингові кампанії, то ліпше відразу обговорити відмову від відповідальності в разі, якщо вони припинять діяти або порушуватимуть права й інтереси (чи законодавство загалом) іншої країни. Кому хочеться нести відповідальність за рекламу (чи пропагування) алкоголю й контенту для дорослих у країнах, де вони під забороною, оскільки внаслідок цього підготований для реалізації на цій території тираж ігор залишився незапитаним або його конфіскували на митниці?

По-третє, приймаючи офер, не підписуйте ніяких боргових розписок! Адвокати чудово дають раду з такими ситуаціями, але ліпше заощадити собі нерви й кошти та просто запобігти несподіваному запрошенню відвідати судове засідання.

По-четверте, оберіть спосіб вирішення суперечок: переговори, альтернативні способи вирішення спорів (наприклад медіацію), третейський суд чи державний суд (а якщо договір має іноземний елемент, то в якій країні і який саме суд в ієрархії судів, якщо це дозволяють міжнародні угоди). Тут може знадобитися порада юриста, але загальне правило — тверезо зважити свої знання місцевих законів і можливість винести певну частину питань на розгляд вітчизняного суду (а також схильність замовника погодитися з вибором українського суду).

Звісно, це не звільняє від потреби читати договір повністю (а ще ліпше з олівцем). Але ліпше відразу оцінити баланс витрат і доходів, можливість вийти з договору (особливо якщо стосунки зіпсуються) та наслідки для репутації. Можливо, ліпше витратити більше часу на відшліфовування комфортних умов співпраці?

Підсумки

Однак це не применшує важливість і тих положень, про які ми говорили раніше. Отже, чеклистом на сьогодні може бути:

  1. Переконатися, чи впливають NDA й NCA на можливість приймати інші, потенційно цікавіші офери та замовлення.
  2. Передбачити, яку частину оплати й до якої дати слід чекати та чим погрожує затримка оплати послуг чи праці.
  3. Подбати про свою інтелектуальну власність: робити пет-проекти на власній техніці, поза офісом роботодавця або замовника й у позаробочий час.
  4. Скласти собі графік дедлайнів і підготувати шлях виходу з договору, що став забирати забагато часу.
  5. Пам’ятати, що кожен запис у логах і кожна авторизація може бути чудовим аргументом замовника/роботодавця проти вас у суді.

Останній пункт здається особливо страшним. Але не варто хвилюватися: Європейський суд з прав людини вказав, що кожен може цілком законно використовувати техніку й електронну пошту на веб-сервері роботодавця для реалізації свого права на особисте життя та таємницю кореспонденції і кілька особистих імейлів (без зловживання) з корпоративної пошти не можуть слугувати причиною для звільнення чи вибачати надмірне втручання працедавця в особисте життя працівника (наприклад, публікувати зміст листів для загального ознайомлення). Водночас ознайомтеся з хенд-буком або документацією замовника чи роботодавця, що стосуються інформаційної безпеки (а ще ліпше — проконсультуйтеся з місцевим юристом): цілком імовірно, що право держави дозволяє йому вводити моніторинг поведінки працівників, збирати їхні біометричні дані й проводити бекграунд-чеки (навіть якщо це стосується лише деяких посад в особливо важливих для держави підприємствах чи службах).

GeoZilla — приложение и геотрекер для безопасности и комфорта семьи

$
0
0

В рубрике DOU Проекторспециалисты рассказывают о том, как создавали свой продукт (как стартап, так и ламповый pet-проект).

Всем привет! Я Илья Казанский, CTO стартапа GeoZilla. Наша команда разрабатывает семейное мобильное приложение, с помощью которого можно быть в курсе точной геолокации ваших детей, пожилых родственников и домашних животных. В отличие от других проектов, связанных с GPS-технологией, мы взяли на себя задачу благодаря Big Data Processing и Machine Learning определять аномалии в геоповедении пользователей и заранее оповещать их о том, что может произойти с ними или с их близкими. В этом месяце наш продукт получил бейдж Product of the Dayна популярной площадке для стартапов Product Hunt. Но обо всем по порядку.

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

За четыре года существования стартапа мы смогли привлечь в iOS- и Android-приложения более 1 миллиона активных пользователей. Большую популярность приложение получило в США, Китае, Бразилии и Мексике.

Интерфейс онбординга приложения GeoZilla

Как все начиналось

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

Спустя четыре года часть нашего офиса переехала в Сан-Франциско. Но большая часть команды (38 человек, две трети из которых — технические специалисты) базируется в Киеве, где и ведется основная техническая разработка проекта. В команде сейчас специалисты по Data Science, Objective C, Cloud Architecture, PHP, Java и QA Automation. Мне кажется, что до сих пор в нашей компании ярко проявляется дух современного стартапа, что позволило создать распределенную команду. В ней есть ребята, которые живут в Швеции, Англии, Китае. Также сотрудники часто путешествуют, заезжая в один из офисов GeoZilla.

Киевская команда проекта

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

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

Релиз продукта состоялся в апреле 2015 года. Сперва мы запустили iOS-версию, а приложение в Google Play вышло через шесть месяцев. На разработку проекта и поиск команды ушло полгода. Все начиналось с личных инвестиций. Сейчас же стартап находится на стадии growth: проект привлек 2,1 миллиона от частных инвесторов.

Особенности

В отличие от других социальных платформ и мессенджеров, GeoZilla использует различные сенсоры на смартфоне и IoT-устройствах. У нас много алгоритмов, которые ежемесячно обрабатывают миллиарды сигналов с разных девайсов пользователей. Функционал распознает аномалии в привычных сценариях и сигнализирует о них. Используется, например, шагомер, высотомер, гироскоп, акселерометр, компас, пульсометр. Мы применяем ML powered decision trees, чтобы предсказать пользовательский путь и вовремя сообщить близким о том, что может произойти. Например, такая технология помогает предупредить маму о том, что ребенок очень долго идет из школы или проводит много времени в незнакомом месте.

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

Как мы обеспечиваем безопасность пользовательских данных? Есть концепция «privacy by design» — сама архитектура построена с учетом максимальной приватности, это приоритет приложения. У нас нет данных, которые можно связать с конкретным человеком. Сведения по геолокации есть — но это не личная информация: у нас нет имен, адресов. Даже если предположить, что данные куда-то «утекут», их все равно нельзя будет сопоставить с определенной личностью. Из внешнего мира никто не может получить доступ к информации, сеть целиком закрыта.

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

Как работает приложение

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

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

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

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

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

Дополнительная функция приложения — Driving Protection. Она дает возможность проследить поведение пользователя за рулем или в пути: используется ли телефон, превышается ли скорость, есть ли аварийные ситуации. Это может помочь начинающим и пожилым водителям контролировать свое поведение за рулем.

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

Технологии

Приложение построено на Java и Objective C, бэкенд-компоненты состоят из микса Java и PHP. У нас есть тщательно спроектированная инфраструктура, которая может справиться с Load Distribution и Autoscaling, чтобы мы были более cost effective и могли справиться со значительной нагрузкой. Мы используем сочетание Relational и NoSQL Databases для решения определенного типа задач и в настоящее время переносим их в облако.

Большая часть инноваций в продукте сформулирована на основе ML-алгоритмовпрогнозирования, обнаружения и рекомендаций. Мы используем как клиентские возможности, такие как CoreML, так и серверные, например Spark.

Поскольку мы сосредоточены на том, чтобы сделать продукт лучше и привлечь больше пользователей, которые могут получить пользу, то вкладываем свои силы в Business Intelligence. Наши сервисы генерируют миллиарды non-personal data points каждый месяц. Мы используем такие продукты, как Google Big Query и Data Studio, для решения бизнес-задач.

Так как сейчас мы находимся на пороге совершенно нового времени, то видим, как активно распространяется 5G и какие возможности это открывает для IoT-стартапов.

В чем уникальность

Во-первых, это единственное приложение на рынке, которое объединило в одном интерфейсе не только мобильные телефоны ваших близких, но и другие их девайсы. Например, вы можете синхронизировать продукт с Apple Watch или GPS-трекером от GeoZilla. Последний можно приобрести вместе с подпиской на премиум-версию приложения. Это формула Phone to Phone & Phone to Device.

GPS-трекер

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

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

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

О развитии команды

Одна из самых важных проблем на данный момент — то, что за этот год у нас очень выросла команда. Мы увеличили штат почти в два с половиной раза, и сейчас в команде 38 человек: специалисты в области R&D, Marketing, QA, BI, Business Development, User Acquisition, Research, Design. И для того, чтобы дальше создавать полезный продукт с постоянным перфомансом, нам нужно научиться быть классной командой, достаточно быстро сплотиться.

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

Как мы строили BI-отдел и как теперь работаем с Big Data

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

Иногда стартапы используют уже готовые решения: например, Firebase, Mixpanel, Amplitude, Flurry, Localytics, Google Analytics. Мы тоже начинали так. Но нужно успеть вовремя перестроиться и начать нанимать своих Data Engineers и специалистов по Data Analytics. Их задача — своевременно передавать данные маркетологу, product-менеджеру или CEO.

С самого старта работы в GeoZilla я начал строить BI-отдел, чтобы создать свою кастомную аналитику. Нашему стартапу помог перестроиться Google Cloud Storage. Мы отправляем данные в хранилище, где можем достаточно быстро проанализировать их. Также мы использовали Google BigQuery. Этот инструментарий позволяет команде аналитиков работать с SQL, чтобы делать запросы на таблицу в 13 петабайт. Также советую обратить внимание на Google Data Studio. Этому инструменту чуть больше полугода. Он позволяет на основе запросов строить красивые визуализации, графики, дашборды, которые будут автоматически обновляться.

Масштабирование инфраструктуры стартапа

Есть разные этапы развития стартапа. Первый — когда все только начинается, пока работаешь на выживание, и второй — когда ты смог доказать рынку, что твоя идея валидна, и ты уже встал на ноги. Все просто: start, growth, scale.

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

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

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

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

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

Усовершенствование процессов

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

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

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

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

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

С чем у нас возникла проблема? Мы очень долго работали в формате Agile Scrum на 20 инженеров. С ростом компании и команды очень важно своевременно вносить изменения в девелопмент-процессы. Наилучшее сочетание — когда в одной команде Agile Scrum будет 6-7 человек.Тогда это будут разные, независимые команды, отвечающие за не связанные между собой разделы продукта.

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

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

Какие планы

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

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

Кроме того, мы постоянно проводим продуктовые A/B-тестирования нашего приложения, добавляя таким образом новые функции. Некоторые из них доступны только по премиум-подписке. Сейчас стоимость квартальной подписки составляет $39,99.

Надеюсь, наш стартап смог вас заинтересовать. Всегда будем рады новым пользователям нашего семейного приложения. А еще — классным специалистам и профессионалам, которые готовы присоединиться к нашей команде! Свежие вакансии мы размещаем на сайте GeoZilla, а также на странице DOU.

Здоров'я ІТ-спеціаліста: сон, харчування, фізична активність

$
0
0

Хотілось би, щоб ця стаття стала мотивацією стежити за власним здоров’ям: мити руки з милом, їсти фрукти, носити шапку. А враховуючи специфіку роботи в ІТ — перевіряти зір, займатись спортом або хоча б влаштовувати піші прогулянки, відвідувати масажний кабінет, вимикати всі девайси за годину до сну тощо. Це якщо стисло. А якщо детальніше — читайте далі.

Ця стаття є першою з серії матеріалів на DOU, присвяченої здоров’ю. Тут ви знайдете загальні поради від сімейного лікаря, тренера та дієтолога, а також кейси від ІТ-спеціалістів та HR. Наступні статті будуть більш профільними: розглянемо проблеми з зором, спиною, неврологію та психічне здоров’я.

Нагадуємо: самолікування може зашкодити, тому у будь-якому разі радимо звертатись до лікарів. Також важливо пам’ятати, що універсальних порад не існує, тож не варто сприймати текст як абсолютну істину. Все індивідуально.

Найпоширеніші професійні захворювання

Особливості роботи у будь-якій сфері можуть впливати на здоров’я її представників. ІТ-сферу ця проблема також не оминула. Михайло Цюрак, сімейний лікар,розповідає, з якими проблемами зі здоров’ями найбільш імовірно зіткнуться програмісти.

Робота за комп’ютером є фізично легкою, але може виснажувати в психологічному сенсі. Також не варто забувати про ненормований робочий графік програмістів: багато з них працюють як фрилансери та часто виконують свою роботу вночі. Комбінація цих факторів може призводити до хронічного головного болю та безсоння. Зазвичай у працівників сфери IT виникає головний біль напруги. Він характеризується відчуттям стискаючого обруча навколо голови, з’являється під кінець робочого дня.

Синдром сухого ока — ще один неприємний стан, який може виникати у працівника, що проводить тривалий час за комп’ютером. Коли людина напружено працює за монітором, вона «забуває» кліпати. Через це рогівка ока не отримує достатнього зволоження. Це спричиняє відчуття сухості, піску в очах (звідси й назва синдрому). Також тривала робота очей на близькій відстані може викликати спазм акомодації — напруження м’яза, який відповідає за зміну кривизни кришталика. Це може призводити до порушення зору на далеку відстань.

Робота за комп’ютером передбачає працю сидячи.ІТ-працівники, на жаль, не завжди роблять регулярні перерви та розминку. Це може викликати болі в спині, а також застій в тазових органах. Для чоловіків такий застій загрожує, в першу чергу, розвитком геморою та простатиту, для жінок — хронічним запаленням яєчників та маткових труб.

Синдром зап’ястного каналу — одне із захворювань, які можуть виникнути у набирачів тексту за комп’ютером. Воно характеризується затерпанням у кисті та пальцях рук. З прогресуванням синдрому виникає біль, який може ускладнювати виконання звичайної щоденної роботи.

Тривала напружена робота за комп’ютером в офісі часто призводить до того, що людина припиняє харчуватися регулярно.На зміну звичайній формулі сніданок-обід-вечеря приходять випадкові перекуси фаст-фудом та літри кави. Таке харчування негативно позначається на системі травлення. Може виникати гастрит, панкреатит, холецистит, синдром подразненого кишечника. Першими сигналами розвитку цих захворювань зазвичай є наступні симптоми: важкість після прийому їжі, печія, біль в животі ниючого характеру.

Малорухомий спосіб життяцілком характерний для ІТ-спеціалістів. У поєднанні з неправильним харчуванням це часто призводить до надлишкової маси тіла та ожиріння. Причому воно є не лише косметичною проблемою, а й фактором ризику розвитку цукрового діабету — небезпечного захворювання, що супроводжується високим рівнем цукру в крові, а за відсутності адекватного лікування — ураженням головного мозку, нирок та судин кінцівок.

Якщо у вас з’явилися якісь скарги на здоров’я, то не відкладайте візит до лікаря. ІТ-спеціалістам варто щороку перевіряти зір, вимірювати артеріальний тиск, індекс маси тіла. Не зайвими будуть аналізи на цукор крові та холестерин.

І, насамкінець, не забувайте про здоровий регулярний сон. Дорослим людям рекомендують спати принаймні 8 годин на добу. Перед сном, за 1 годину, варто вимкнути всі ґаджети.

Порушення режиму сну та безсоння

Майже кожному з нас вкрай складно змусити себе заснути принаймні раз на місяць. Трапляються ситуації, коли й декілька разів пізньої ночі доводиться просиджувати зі смартфоном або з книжкою в очікуванні сонливості.

Марина Марчук, провідний лікар національної мережі центрів фізичної терапії та масажу «Амбулаторія спини», що надає консультації при безсонні, зазначає: найчастіше порушення сну можна спостерігати у представників професій, робота яких пов’язана з дедлайнами, потребує активної мозкової діяльності, пам’яті, високої концентрації, точних розрахунків, значної відповідальності.

Причин порушення сну та безсоння безліч, і при дослідженнях нелегко визначити, що саме в житті особи впливає на її режим сну. Зазвичай такі впливи вже глибоко вкоренилися в щоденний графік, і людина може навіть не фіксувати дискомфорт, вважаючи його нормою.

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

Симптоми порушення режиму сну:

  • важко заснути, а ще важче прокинутися зранку;
  • у голові повно думок, що заважають спати;
  • під час засинання відчувається тривога або страх;
  • засинаєте вчасно, але пробудження відбувається в певний час серед ночі;
  • пробудження і засинання відбувається декілька разів за ніч (сон неглибокий);
  • прокидаєтесь раніше, ніж потрібно;
  • не вдається зручно влаштуватися в ліжку;
  • відчуваєте нервовість, не можете утриматися лежачи.

Такі симптоми можуть бути пов’язані як з психічним, так і з фізичним станом людини.

Ілюстрації: Дарина Скульська

Коли порушення сну стають хронічними — погіршується розумова діяльність, постійно відчувається сонливість, складно бути уважним та зосередженим, запам’ятовувати нове. Згодом посилення симптомів призводить до проявів депресивного стану, при цьому часто буває складно визначити, депресія є першопричиною безсоння, чи власне порушення режиму сну спровокувало появу депресії.

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

Зверніть увагу: при цьому період порушень має бути тимчасовим, нехай інколи і дещо тривалим. Але якщо ви живете звичайним життям, а сон від вас тікає майже щоночі — час переглянути режим активності та відпочинку. Можливо, доведеться позбутися певних шкідливих звичок та дещо вплинути на режим харчування. Хоча якщо «нічне життя» та бурхливі вечірки для вас є нормою, владнати питання з режимом буде нелегко.

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

Формула сну та денної активностідостатньо зрозуміла: 24 години = 14-16годин денної активності + 8-10годин сну

Відмовляючи собі в зайвих хвилинах «сидіння» в смартфоні чи за комп’ютером, ви вже почнете збалансовувати режим. Зрештою контроль сну зводиться до самоконтролю вчасно лягати.

Формула рухудля кожної людини може бути особистою, пов’язаною з генетичними особливостями, але близькою до загальних параметрів: 14-16годин денної активності = 25-40%«в русі» + 60-75%«відпочиваючи»

«В русі» — означає рухову активність, в якій задіяні всі групи м’язів при звичайних навантаженнях (відповідно до ваших рухових звичок) — працюємо ногами, працюємо руками, працюємо шиєю і торсом, використовуючи здорову амплітуду та мобільність суглобів.

«Відпочиваючи» — означає тимчасовий відпочинок для м’язів, які використовувались «в русі».

На жаль, формула рухової поведінки більшості офісних працівників значно дисбалансована враховуючи відсутність можливості достатньо рухатися в офісному кріслі. Тож варто почати з 10-15хвилин суглобової та м’язової розминки на день з використанням прикладних елементів — купіть маленьку гантель або тонкий еспандер, які можна залишити в ящику вашого стола або поруч зі стільцем. Станьте хорошим прикладом для власних колег.

Фізична активність

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

Біль у попереку, дискомфорт у грудному та шийному відділі хребта є найчастішими скаргами з боку працівників інтелектуальної сфери, що більшість часу проводять за комп’ютером. До цього призводить слабкість глибоких м’язів спини, внаслідок чого порушується живлення хребта, його м’язового та зв’язкового апарату, — переконаний експерт з фітнесу та спеціаліст з фізичної реабілітації Дмитро Марушевський, що має вісім років тренерського досвіду.

Вкрай негативний вплив на здоров’я чинить надлишкова вага, яка є безпосереднім наслідком незбалансованого харчування та низької фізичної активності. На щастя, навіть помірні заняття спортом здатні компенсувати згубні прояви малорухомого способу життя і значно покращити здоров’я.

Будь-яка фізична активність, незалежно від інтенсивності, сприятливо діє на опорно-рухову, серцево-судинну та інші системи організму. Головним є те, чи здатні ви дотримуватися рухового режиму протягом тривалого часу (тобто все життя). Тож обирайте те, що вам до вподоби.

Загальноприйнятим вирішенням проблеми малорухомого способу життя є відвідування фітнес-клубу. Це справді має свої переваги: під одним дахом ви отримуєте повний спектр послуг — від тренажерів та басейну до масажних кабінетів і SPA. Якщо ви початківець і раніше спортом не займались, скористайтесь послугами фахівців. Обирайте спеціаліста з профільною освітою та досвідом роботи. Тренуйтесь два-три рази на тиждень впродовж 45-90 хв.Показниками того, що ви все робите правильно, мають бути гарний настрій після заняття та поступові кроки до поставленої мети.

Найкращі результати дає поєднання тренувань різної спрямованості. Комбінуйте силові та аеробні заняття із вправами для розвитку гнучкості. Не слід розпочинати здоровий спосіб життя з пробіжок, особливо якщо початківець має суттєву надлишкову вагу, проблеми з боку опорно-рухового апарату та непідготовані м’язи ніг. Безпечним рішенням у цьому разі стануть тривалі прогулянки — від 30 до 90 хв на день.

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

Три корисні звички на щодень:

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

За словами Ярослава Сойнікова, співзасновника мережі фітнес-студій hiitworks, малорухливий спосіб життя позначається не лише на зовнішньому вигляді (що часто і приводить людей до спортзалу), а й на розумових здібностях, а також репродуктивних та метаболічних показниках. Сила-силенна параметрів, що визначають якість життя, залежать від активності людини.

Так, активний спосіб життя наразі досить популярний тренд. Проте зважаючи на те, що більшість людей проводять свій день, сидячи за робочим столом, фізична активність їм просто необхідна. Існує велика кількість видів фізичної активності, і кожна країна має свої власні фітнес-тренди, які формуються залежно від середнього віку людей у цій країні, а також від клімату.

Говорячи про Україну, то дуже популярними є різні бігові напрямки. Це найдешевший і легкодоступний вид фізичної активності. Але, тим не менше, біг не замінить комплексну фітнес-програму, необхідну для підтримання та поліпшення якості життя. Існують й інші тренди, наприклад крос-фіт. Суть крос-фіта — змагання, челендж, постійне випробовування себе на міцність. Але травматизм у крос-фіті досить значний, практично такий самий, як і в професійному спорті.

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

Ще одним з яскравих фітнес-трендів у світі є сайкл. Особливо це стосується США. Сайклінг — це драйвовий, простий і дуже безпечний спосіб виконати певний об’єм інтенсивної роботи. Втім, такий вид спорту має і недоліки. Наприклад, особа, яка просиділа весь день в офісі, в автівці, де завгодно — на сайклінгу, як і до цього, сидить. Тож сайклінг — це гарне тренування для серцево-судинної системи, для катаболізму. Але не таке вже й гарне для тіла загалом, для опорно-рухового апарату. Тому сайклінг не варто розглядати як єдиний спосіб фізичної активності.

У переліку трендів останніх п’яти років — йога. Також не рекомендовано зациклюватися на ній як на самостійному напрямку. Але будь-яку програму фізичної активності може бути успішно доповнено йогою.

Протягом останніх 10 років HIIT-тренування входять до п’ятірки трендових. HIIT — це тренування, в якому чергуються етапи високої інтенсивності з етапами відновлення. Переваги таких тренувань — вони вимагають мало часу і дозволяють потужно і швидко впливати на стан ендокринної системи, на метаболізм. Крім того завдяки hiit-тренуванням ви спалюєте жир не тільки під час заняття, але і 48 годин після. Таким чином, є можливість позбавитися від зайвої ваги і швидше прийти у форму, витративши мінімум часу. Мінімум часу — максимум результату.

Силовий тренінг також залишається трендом. Вправи з додатковою вагою рекомендують виконувати не рідше двох разів на тиждень. Для будь-якої людини, старшої за 18 років, силові тренування необхідні для того, аби збільшувати та підтримувати здорову кількість м’язової маси, здоров’я суглобів і поставу.

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

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

Що стосується норми рухової активності, рекомендований об’єм — від 150 хвилин на тиждень помірної інтенсивності. Тобто це мінімум три легких тренування на тиждень або три півгодинних високоінтенсивних тренування. Також не слід оминати звичайну ходьбу — 8-10тисяч кроків вдень.

Харчування

Відомо, що важливим фактором гарного самопочуття є харчування: режим, раціон, звички. Порадами щодо харчування ділиться нутриціолог Іванна Лук’янчук.

Перекусам в офісі вона радить сказати «ні». Коли ми постійно чимось перекушуємо, ми змушуємо підшлункову безперервно працювати, виділяти інсулін, тим самим виснажуючи її, що в подальшому може призвести до ожиріння, інсулінорезистентності та цукрового діабету. Це стосується снеків, печива, піци, батончиків (навіть якщо вказано, що вони цільнозернові — це перш за все маркетинговий хід, і додаючи їх до свого раціону, ви додаєте високу дозу цукрів).

Оптимально їсти тричі на день — цього достатньо, аби потім не відчувати голоду. Що стосується фруктів, то їх рекомендовано вживати окремо від основної їжі, найкраще — через 2-2,5 год.

Чи важливо дотримуватися погодинного режиму харчування? Для початку визначимо, що таке режим харчування.Це кількість прийомів їжі, час та інтервали між ними, розподіл раціону за хімічним складом, калорійністю, набір продуктів та їхня маса, а також поведінка під час прийому їжі.

«Я рекомендую вживати їжу тоді, коли ви відчуваєте голод, але важливо не переплутати голод і апетит. Голод вказує на потребу в енергії, апетит — на необхідність задоволення. Дуже просто сплутати відчуття голоду з такими станами: „підводить“ шлунок, „смокче“ під ложечкою, виникають спазми. Все це вказує на розвантаженість органу після переповнення, на потреби шлунку та харчового центру апетиту (це низка структур головного мозку, що координують вибір, споживання їжі та початкові стадії травлення). Правильним імпульсом до споживання їжі має бути саме голод, оскільки оманливість апетиту може призвести до набору надлишкової ваги», — каже Іванна Лук’янчук.

Оптимальними інтервалами за правильного режиму харчування вважаються проміжки від чотирьох до шести годин, вони забезпечують нормальну роботу системи травлення. Як варіант — розподіляти свій раціон у відсотковому співвідношенні калорій орієнтовно так: сніданок — 30%, перекус — 7-9%,обід — 35%, вечеря — 25%. Не варто відмовлятися від сніданку, обіду чи вечері, адже це може призвести до переїдання під час наступного прийому їжі.

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

Ваш раціон має містити:

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

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

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

Рекомендації щодо вживання кави

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

Що стосується кави, то вона є прекрасним антиоксидантом та позитивно впливає на кишкову мікрофлору. В ній наявні важливі для правильного функціонування та здоров’я організму сполуки: кофеїн, хлорогенова кислота, тригонелін, дітерпени, що мають протизапальну дію. Але слід пам’ятати, що кава — це діуретик, тобто чим більше ви її п’єте, тим частіше бігаєте до вбиральні. Із сечею організм втрачає важливі мінерали — кальцій, магній, калій, а це, своєю чергою, може призвести до порушення балансу електролітів. Тож візьміть за правило: перед чашкою кави випиваємо стакан води. Кофеїн стимулює перистальтику кишечника, тож ви встигаєте засвоїти менше поживних речовин із того, що з’їли. З часом це може викликати хронічне відчуття втоми, дратівливість, порушення сну тощо.

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

Ваше здоров’я — у ваших руках

Хто має піклуватися про ваше здоров’я, як не ви самі? Звісно, було б чудово, якби працедавці, окрім медичного страхування, ще й докладали зусиль, аби мінімізувати професійні захворювання своїх працівників, як це, наприклад, роблять ІТ-компанії у Люксембурзі: «Під час влаштування до ІТ-компанії проходиш медичний огляд. Перевіряють зір, слух, спину тощо — стандартний набір. Якщо раптом протягом роботи стан здоров’я погіршується (виникають проблеми із зором чи хребтом), компанія виплатить компенсацію та профінансує все лікування. Саме тому в компаніях дуже уважно ставляться до здоров’я співробітників: забезпечують щонайменше зручні стільці і якісні монітори».

За словами кар’єрного консультанта Юлії Шишенко, що має досвід в HR, в Україні і за кордоном вона не зустрічала кейсів у своїй практиці, де б роботодавці безпосередньо системно і спеціально займалися здоров’ям співробітників. Здебільшого вони мають якісь загальні процеси, що стосуються всіх співробітників у компанії, — пропонують фрукти, освітлення, зони відпочинку, їдальні, лікаря в офісі тощо. Чи скористається співробітник цим благом — залежить від його бажання. Компанії це пропонують радше як бенефіти, аніж піклування про здоров’я співробітників, і спеціально не нав’язують.

«Від кандидатів, що працюють за кордоном, я чула, що вони здебільшого невдоволені системою охорони здоров’я, особливо якщо в Україні мали корпоративне медичне страхування VIP-рівня. Бо в багатьох країнах важко потрапити до лікарів, робочий день яких такий самий, як у всіх офісних працівників. Складно записатися чи отримати якусь вузьку консультацію чи обстеження. Страховий поліс багато чого не покриває, а оплачувати рахунки самостійно (наприклад, стоматологію) дуже дорого. Тож багато кандидатів, яких я знаю, їдуть лікуватися до України.

Хоча у компанії, де я раніше працювала у HR-відділі, ми разом з колегами зробили цілий захід на декілька днів, який так і назвали: „Дні здоров’я“. Суть була в тому, що ми домовилися зі страховою компанією, що лікарі клініки „Медіком“ приїдуть прямо до нашого офісу і всі охочі співробітники зможуть безкоштовно пройти профілактичний медичний огляд. Приїхали лікар з мобільним апаратом УЗД, окуліст, гастроентеролог, кардіолог та терапевт. Лікарі приймали у закритих переговорних кімнатах. Ми з колегами з HR-відділу чергували біля кабінетів та записували співробітників у спеціальні форми, щоб не відволікати їх від роботи, а викликати у зазначений час по черзі. Самі надягли білі халати та шапочки і поставили таблички з назвами наших „нових професій“. Керівник HR-відділу став головним лікарем. Рекрутер — старшою медсестрою, а я — начмедом. Був величезний ажіотаж та декілька цікавих і живих днів у офісі. Це було весело і корисно одночасно. Співробітники були надзвичайно задоволені нашою ініціативою. Але це був більше одноразовий захід, ніж система. Наскільки я знаю, такі кампанії більше в офісі не організовували», — розповідає Юлія.

В Україні ІТ-компанії пропонують приблизно схожий «пакет»: медичне страхування, відшкодування вартості абонементу до фітнес-центру, фрукти в офісі. Проте цим не обмежуються.

В ELEKS упродовж останніх двох років регулярно відбуваються мітапи із різноманітними спеціалістами з медичної сфери. Уже виступали імунолог, невропатолог, дієтолог та багато інших. Проводять зустрічі з психотерапевтами, аби говорити не лише про фізичне здоров’я, а й про ментальне, зокрема про асертивність, стрес-менеджмент, про світ емоцій тощо. Схожа практика існує в компанії SimCorp: запрошують лікарів з лекціями про корисний сон, аюрведу, корисне харчування в офісі. Також компанія проводить вакцинацію співробітників (за бажання). А працівників Forte Group відвідував стоматолог, який розповідав, як правильно чистити зуби та доглядати за ротовою порожниною, масажист з лекцією про те, які м’язи пошкоджуються при неправильній поставі та сидячій роботі, які види спорту є корисними для покращення здоров’я. А у MGID реагують на виклики часу: наприклад, проводять лекції про небезпеку дифтерії та розповідають, як захистити себе (у результаті — проводять вакцинацію охочих). Більшість компаній також проводять вакцинацію спіробітників.

У Netcracker проводять лекції на тему здорового способу життя: «школи здоров’я», де колег навчають інтерактивним вправам для зняття напруги в м’язах, показують як роити гімнастику для очей, розповідають про «тунельний синдром» та «комп’ютерний синдром», методи їх попередження.

Intellias, MGID, AB Soft, Netcracker організовують медичні тренінги з першої домедичної допомоги для спеціалістів компанії. На тренінгах навчають, як укомплектувати аптечку, як надати першу допомогу та врятувати життя в критичній ситуації. Тренінги минають у форматі практикумів з використанням сучасного обладнання та манекенів.

Компанії також підтримують цікавість працівників до спорту: наприклад, SoftServe проводить корпоративні змагання SoftServe Olympics. Теплої пори року в AB Soft відбуваються масові спортивні челенджі. Свої заняття спортом учасники фіксували за допомогою фото- і відеозйомки, а також трекерів. Ті, хто мінімум тричі на тиждень приділяв увагу фізичним навантаженням, автоматично потрапляли до переліку претендентів на головні призи челенджу — грошові та спортивні подарунки. Спортивний челендж включав не лише індивідуальні заняття спортом, а й масштабні групові активності: співробітники позаймалися з кращими тренерами Одеси, відвідали корпоративні кросфіт-тренування, потрапили на бігове тренування до ультрамарафонця Дениса Соколова. Netcracker заохочує командні види спорту: футбол назбирав найбільше прихильників. Компанія оплачує для ігор футболістів взимку зал, а влітку відкритий майданчик. Раз в рік відбуваються міжофісні змагання з футболу, куди з’їжджаються команди з трьох українських офісів. Також компанія бере участь у марафонах та забігах.

З цікавого: Luxoft двічі на рік проводить День донора в компанії.









Ми задали українським ІТ-спеціалістам запитання щодо того, з якими професійними захворюваннями вони стикались і що роблять, аби покращити свій стан.

Антон Чередниченко, Lead Backend Developer в Genesis

Работаю в Genesis уже больше четырех лет. Когда пришел в компанию, имел немного лишнего веса и практически не занимался физической активностью (сидячая работа + хорошее питание = второй подбородок и «спасательный круг»).

В компании уже тогда были тренировки по бегу, и, проработав полгода, я решился попробовать, тем более коллега из команды стабильно ходил на них. Сходил — и умирал все 8 км тренировки, так как тогда бежал хуже всех. Тренер, по сути, провел мне «персональную» тренировку, без передышек и остановок. Кстати, это один из лучших триатлетов Украины, Саша Хадыко. Он умеет мотивировать, а главное — он действующий спортсмен. В итоге тренировки меня зацепили, бег — самый простой вид спорта, все что нужно — хорошие кроссовки и немного времени. В итоге перестала побаливать спина и шея от вечного сидения — хватало пары тренировок в неделю. Когда уже набегал определенную форму, начал интересоваться забегами. Кроме того, они очень мотивируют, когда тебя легко обгоняют старички или люди «в теле», и ты начинаешь понимать, что тренил мало и слабо. В то время как раз появилась Race Nation, или «Гонка нации» — такой бег с препятствиями, и наша фирма оплачивала участие — в итоге пробежал уже 13 таких забегов. Само собой, бегал все возможные вариации забегов в Киеве: начинал с 5 км, потом 10, потом 21, уже пробежал марафон и планирую еще пару раз пробежать 42 км, но уже на определенный результат/время. Особенно круто выходить на пробежку где-нибудь в поездке в новом месте/городе — лучшие экскурсии, как по мне! Еще лучше — покупать участие на спортивный ивент за границей — едешь на три-четыре дня, а эмоций и воспоминаний потом...

Когда бег наскучил, появился велосипед, и как оказалось, в Киеве полно любителей, которые организовывают неплохие покатушки как в Украине, так и в Европе. В итоге — ищу себе шоссейник из карбона... Принимал участие и в заплывах, но у меня явно проблема с техникой. Когда-нибудь найду время, тренера и бассейн — и научусь нормально плавать. Около года-полутора ходил на кроссфит и планирую опять возобновить тренировки — это лучший вид тренинга в зале, как мне кажется. Когда погода нормальная, особенно когда готовлюсь к стартам, расписание имею примерно такое: 2-3тренировки по бегу в неделю, от 8 до 25 км, по времени — от часа до двух; велосипед — одна длительная, 80-120 км,около четырех часов, если повезет со временем — еще пара небольших; турник почти каждый будний день. На зиму планирую переключиться на зал — кроссфит, бассейн и велостанок на балконе.

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

Андрій Лозінський, веб-розробник

Маю проблеми, пов’язані з сидячою роботою. Стикнувся з початковою фазою розширення вен на ногах, закидом жовчі чи то кислоти в шлунок від неправильного сидіння (так-так, сидіти теж можна неправильно, наприклад, коли після їжі відкидаєшся на спинку крісла і сидиш в такій напівлежачій позі).

Фізкультура — наше все. Зробив турніки під будинком і регулярно (2-3рази на тиждень) займаюся на них. Обов’язково чергую вправи на турніках (бруси, перекладина), які навантажують в основному руки, із вправами, що навантажують ноги (присідання і таке інше), 1-2рази на тиждень намагаюся бігати, а влітку плавати. Плавання при варикозі — це найбільш вдалий спосіб навантажень. Також придбав собі «стій-стіл», що дозволяє працювати стоячи, а після їжі або виходжу прогулятись, або працюю стоячи. Таким чином поборов закиди жовчі/кислоти в шлунок.

Ще одна значна проблема при сидячому способі життя — це надмірна вага. Вирішення одне: споживати калорій менше, ніж спалюєш, тобто багато рухатись і менше їсти. Я намагаюся контролювати вагу таким чином, що їм лише тричі на день, а останній прийом їжі маю до 18:00. Раз на тиждень пропускаю два прийоми їжі — роблю такий собі розвантажувальний день.

Євгеній Андрєєв, Front-end Developer в Innovecs

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

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

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

Первые попытки показали, насколько у меня все плохо с растяжкой. Но я продолжал усердно повторять за инструктором все асаны (позы). И магия случилась через месяц, когда ушли боли в спине. Да-да, я уже мог часами сидеть за столом — и никаких болей, магия! (Нет, на самом деле — только тренировки и четко поставленная цель.) Очень воодушевляло, что выполнять асаны получалось все лучше, и можно было пробовать более сложные штуки. Вот несколько популярных каналов, которых будет достаточно для начала: Yoga With Adriene, chilelavida. Когда вернулся в Украину, стал ходить на вечерние занятия в студию «Истоки» (к сожалению, сейчас они закрылись). Посещал занятия в Украинской федерации йоги (УФЙ).

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

Питание — холиварная тема по дефолту, есть много разных мнений и исследований. Поэтому делюсь сугубо личным опытом и взглядами. Много лет назад перестал класть сахар в чай и кофе. Первые недели было сложно, потом привык к новому вкусу. И это было замечательным решением! В ежедневном рационе у меня превалируют овощи и фрукты, зелень, каши, бобовые, орехи и яйца. Из мяса — нежирное; птица отварная или на пару; рыба. Сейчас стараюсь ограничить количество кисломолочных продуктов. Постепенно отказываюсь от молока, перехожу на растительное. В качестве легкого перекуса в офисе запариваю овсянку с семенами, орехами и изюмом/финиками. Быстро, вкусно и полезно! Отказавшись от ежедневного употребления сладкого и мучного, я смог улучшить работу ЖКТ, состояние кожи и общее самочувствие. Появилось больше энергии.

Я — за здравый смысл и баланс во всем: могу с удовольствием слопать бургер или пиццу с друзьями, но не чаще 1-2раз в месяц. Многие IT-компании обеспечивают своих сотрудников фруктами. Это помогает закрыть вопрос с легким перекусом. В компании, где я сейчас работаю, есть в том числе и безлактозное молоко. Переосмыслил некоторые вещи после книги «Китайское исследование».

У меня есть друзья, которые пользуются услугами компаний по доставке здорового питания. Суть такова: выбираешь программу и меню, тебе каждый день привозят 3-5-разовое питание. Такие услуги дорогие, но это очень удобно и зачастую полезно. Один знакомый сбросил пару десятков кило благодаря такой программе. Могу порекомендоватькомпанию, а классные ланч-бэги можно купить тут.

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

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

May the Force be with you!

Идем воевать с Java-боттлнеками

$
0
0

Меня зовут Игорь Колосов, я Automation/Performance Architect, Consultant в GlobalLogic, Харьков. В сфере IT уже около 10 лет. В 2011 году увлекся автоматизацией и всем, что связано с производительностью ПО, что и определило мой дальнейший карьерный вектор развития. Являюсь активным участником и спикером нескольких сообществ по тестированию программного обеспечения. В моем портфолио более 20 проектов, а повседневные задачи покрывают целый спектр различных компетенций — от архитектуры тестовых решений и старта новых проектов до создания тестового окружения и инфраструктуры.

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

Большинство приложений имеют аналогичную цель и создаются разработчиками, имеющими сходное мышление; существуют и распространенные ловушки, в которые могут попасть многие разработчики. К счастью, такие ловушки можно обнаружить и «вылечить», если знать, как искать и где искать. Сегодня я постараюсь немного помочь тем, кто раньше не боролся с проблемами производительности Java-приложений, и поделюсь материалом по мотивам своего доклада на GlobalLogic Java Conference 2019.

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

На основании современной статистики можно выделить следующий топ групп проблем с производительностью Java-приложений:

  • базы данных;
  • облака и виртуализация;
  • программирование;
  • ОС, платформа, стороннее ПО;
  • кеширование;
  • CPU;
  • сеть;
  • память;
  • дисковая подсистема;
  • специфическое железо.

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

Базы данных.Одна из самых часто встречающихся — это группа проблем, связанных со слоями данных (с базами данных, с различными хранилищами и т. д.). Для осознания масштабов будет нелишним привести цитату из одной книги по производительности — «Look elsewhere. The database is always the bottleneck». Хорошим примером подобных боттлнеков могут служить конфликты при записи, неэффективные запросы, тяжеловесные Join.

Для наглядности вспомним об индексировании. Часто программистам рекомендуют иметь индекс для каждого foreign key в таблице, но всегда стоит помнить, какие именно запросы выполняются. Не все индексы будут использоваться. Неиспользуемые индексы займут место на диске, а база данных будет обновлять индексы каждый раз, когда происходит вставка/удаление записей. Это замедлит общую обработку запросов.

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

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

Рассмотрим пример с Java-сервлетом для наглядности. Смешивание вызовов между output stream сервлета и записью форматированного вывода через PrintWriter приведет к частой очистке сетевых буферов. Частая очистка буферов очень дорога с точки зрения производительности: дороже, чем перекодирование данных. Кодирование большого блока данных обычно ненамного дороже, чем кодирование небольшого блока данных (в этом случае вызов encoder будет наиболее ресурсоемкой операцией). Следовательно, частые вызовы encoder для небольших фрагментов динамических данных, чередующихся с вызовами для отправки предварительно шифрованных массивов байтов, могут замедлить работу приложения: выполнение частых вызовов encoder займет больше времени, чем один вызов для шифрования всего (включая статические данные). Неопытные программисты довольно часто совершают подобные ошибки.

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

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

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

На этом скриншоте мы наглядно можем увидеть пример CPU bottleneck при визуализации средствами Amazon CloudWatch.

Специфическое железо.Не стоит забывать и о зоне риска, связанной с каким-то специфическим или специализированным hardware, особенно с учетом высокой популярности использования Java в сегменте IoT-решений.

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

А что же с самим приложением?

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

  • проблемы с архитектурой;
  • неправильный выбор технологий;
  • неэффективная garbage collection;
  • неэффективная конфигурация heap;
  • неправильный размер потокового стека;
  • проблемы многопоточности (deadlocks, starvation, live locks, race conditions и т. д.);
  • неэффективные алгоритмы;
  • некорректный выбор дизайн-паттернов;
  • неподходящие структуры данных.

Проблемы с архитектурой.Любая реализация системы начинается с архитектуры. Если на старте архитектор не задумывался о производительности решения, это может привести к плачевным и дорогим последствиям. Архитектура — очень важная отправная точка, для которой работает принцип «чем позже, тем дороже». К сожалению, в жизни мы часто сталкиваемся с ситуацией, когда за неделю перед релизом в production запускаются первые performance-тесты и как гром среди ясного неба звучит призыв аврально тюнить продукт. О производительности часто забывают и задумываются о ней в последний момент. Архитектор, имея нефункциональные требования к производительности на входе, может принять ряд ключевых решений, которые облегчат жизнедеятельность проекта и улучшат итоговый результат, по сути, понизив трудозатраты и стоимость выведения ПО на нужный уровень качества.

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

Неправильный выбор технологий.Вторая по дороговизне группа проблем с производительностью Java-приложений — неправильный выбор технологий. Мы не пишем приложение в вакууме. Мы используем сторонние библиотеки, различные 3rd-party-компоненты, связываем наш продукт с какими-то сторонними сервисами, добавляем различные технологии для увеличения удобства написания и хорошей поддержки кода и т. д. На выходе может получиться огромная сборная солянка с проблемами во внутренних взаимодействиях, причем какие-то из внедренных технологий сами по себе могут обладать низкой производительностью. Неправильный анализ и выбор инструментария может проявить себя уже в момент performance-тестов либо, еще хуже, уже в live-режиме, когда с системой будут работать реальные люди. В такой ситуации «лепить подорожник» и тюнить систему или выкорчевывать плотно проросшие технические решения будет очень дорого.

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

Конфигурация JVM.Думаю, все прекрасно помнят, что Java-код запускается на такой штуке, как JVM (Java Virtual Machine). Поэтому когда мы говорим о проблемах с производительностью Java, нельзя не упомянуть целую группу проблем с производительностью, связанных с самой платформой, с Java-машиной.

Чаще всего это будут некие проблемы с конфигурацией JVM, например конфигурация сборки мусора. Java позволяет достаточно гибко конфигурировать garbage collection. Всегда стоит помнить о грамотном планировании capacity вашего окружения и не забывать настроить размер кучи (параметры -Xms и -Xmx) с учетом ожидаемого железа в production. Довольно важная настройка — размер стека потоков (-Xss). Используя эти ключевые настройки бездумно, вы рискуете столкнуться с общим замедлением приложения.

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

Некорректное программирование.Практически каждый программист проходит через стадию «руки-клешни» и набивает свои шишки. Очень много боттлнеков проявляются в связи с самим кодом и решениями во время программирования. Часто можно встретить проблемы с потоками, такие как deadlocks, starvation, live locks, race conditions. Если программист неаккуратно использует потоки и прерывания, очень высока вероятность того, что у вас возникнут проблемы при мультипоточной работе в асинхронных приложениях.

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

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

Примеры боттлнеков в трехслойной архитектуре

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

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

Пример трехслойной архитектуры:

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

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

Коммуникация

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

Слой Web-server

  • Битые ссылки.
  • Некорректный дизайн транзакций.
  • Перегруженная безопасность.
  • Недостаточная аппаратная емкость.
  • Web-server плохо сконфигурирован.
  • Неэффективная балансировка нагрузки.
  • Неэффективное использование ресурсов ОС.
  • Недостаточная пропускная способность.

Слой App-server

  • Утечки памяти.
  • Бесполезная/неэффективная сборка мусора.
  • Плохая конфигурация соединений с БД.
  • Бесполезные/неэффективные транзакции.
  • Сложности масштабирования из-за неоптимальных stateful-сессий.
  • App-server плохо сконфигурирован.
  • Неэффективное использование аппаратных ресурсов.
  • Неэффективная модель доступа к объектам.
  • Проблемная модель безопасности.
  • Неэффективное использование ресурсов ОС.

Слой данных

  • Неэффективные SQL statements.
  • Маленький query plan cache.
  • Неэффективная модель SQA queryl.
  • Некорректная конфигурация БД.
  • Недостаточное кеширование данных.
  • Избыточные соединения с БД.
  • Избыточный процессинг строк в единицу времени.
  • Отсутствующее/неэффективное индексирование.
  • Проблемы с распараллеливанием.
  • Неэффективный подход к масштабированию.
  • Переусложнение архитектуры БД.
  • Deadlocks.

Интеграция сторонних сервисов (3rd-party)

  • Увеличение трафика.
  • Сторонние сервисы потребляют пропускную способность.
  • Неэффективный код.
  • Недостаточное время отклика стороннего сервиса.

Идем на войну с bottlenecks

Дам ряд советов стратегического характера со стороны подходов:

  1. Задумывайтесь на этапе планирования архитектуры о своей производительности. Если вы делаете highload, делайте highload со старта и донесите эту мысль до всех участников процесса. И заложите соответствующие архитектурные решения.
  2. Аккуратно и взвешенно проводите решения по техническому стеку, допустим по 3rd-party-компонентам или библиотекам.
  3. Проводите код-ревью с учетом производительности. Такие код-ревью хороши всегда, но полезнее их проводить ближе к продакшен-стадии.
  4. Performance-тестировщики — полезные ребята. Не забывайте о них. Если у вас нет в команде специально выделенных людей, почитайте о перформанс-тестировании и хотя бы в минимальном объеме тестируйте производительность сами. Нагрузите свой сервер, посмотрите, как он работает под нагрузкой, проведите трейсинг производительности клиента, посмотрите общий user experience.
  5. Профайлеры рулят. Это очень важный элемент, который позволяет нам отлаживать и оптимизировать свой код, бороться с проблемами производительности. Хорошими представителями этого сегмента инструментария будут такие профайлеры, как JProfiler (наверное, топ-1 сейчас), VisualVM, YourKit.
  6. Не забывайте о прозрачности. В этом нам поможет мониторинг утилизации ресурсов и, если финансы позволяют, Application Performance Monitoring (APM). Такие инструменты мониторинга, как Zabbix, Prometheus, Nagios, не потребуют больших инвестиций. Поэтому мониторинг утилизации ресурсов практически всегда можно получить в относительно короткие сроки. Если у вас есть DevOps в команде, он обычно сам предложит варианты и сам проведет имплементацию. Если же нет, то поднимите этот вопрос со своей стороны. Есть бюджет на APM — вы уже на передовой борьбы с боттлнеками. Идеальным вариантом будут мощные APM-системы Dynatrace, AppDynamics, New Relic или Stackify Retrace как недорогая альтернатива.

Советы для самых юных

  1. Разберитесь с тем, как Java-машина работает с памятью. Я был удивлен, но многие девелоперы, даже достаточно опытные, не знают, что такое heap, eden space, generations и т. д. Разберитесь, как работает сборка мусора, в каком случае и что будет более эффективным решением.
  2. Разберитесь с работой JIT-компиляции. Да, она тоже может тормозить.
  3. Знайте свой environment. Разберитесь с тем, в каком окружении будет работать ваша система. Здесь имеет смысл говорить об окружении как software, так и hardware.
  4. Помните о нефункциональных требованиях. Если вы их держите в голове, то будете задумываться о том, как их достичь.
  5. Не забывайте о ваших объектах сессий.
  6. Не забывайте о пулах соединений.
  7. «Потом доконфигурируем» часто забывается.
  8. Используйте кеширование.
  9. Не оптимизируйте то, что нет смысла сейчас оптимизировать. Premature-оптимизация вредна.
  10. Читайте хорошие книги. Прочесть 1–2книги по производительности будет полезно практически каждому Java-разработчику.

Что почитать

Удачи в борьбе!

Вывод реализаций интерфейсов в Scala c библиотекой Shapeless

$
0
0

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

Мотивация

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

class Foo {
 private var bar: Int
 private var baz: Double
 private var qux: String

 override def equals(that: Foo): Boolean  = {
   this.bar == that.bar && this.baz == that.baz && this.qux == that.qux
 }
}

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

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

Хотелось бы иметь магический метод Compare(a,b), который бы работал для большого количества типов и в то же время был легко настраиваемым.

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

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

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

Семейства запечатанных трейтов в Scala (sealed trait family)

В Scala конструкции, состоящие из некоторого количества «интерфейсов», доступных к расширению в рамках одного файла (sealed trait), и классов, содержащих только неизменяемые данные (case classи case object), их наследующих, называются ограниченной иерархией кейс-классов. Эта конструкция довольно неплохо справляется с моделированием замкнутых ADT (Algebraic Data Type).

Пара примеров:

sealed trait Color

sealed trait PredefColor extends Color
case object Red extends PredefColor
case object Green extends PredefColor
case object Blue extends PredefColor

case class RGB(r: Byte, g: Byte, b: Byte) extends Color
case class RGBA(r: Byte, g: Byte, b: Byte, a: Byte) extends Color
case class HSV(h: Byte, s: Byte, v: Byte) extends Color

Или

case class Id(text: Id)
sealed trait WithId{ def id: Id }
sealed trait UserData{
 def login: String
 def email: String
}
sealed trait AdminPriviledges {def privileges: Set[String]}
sealed trait User
case object Unregistered extends User
case class New(id: Id) extends WithId
case class LoggedUsser(id: Id, login: String, email: String) extends WithId with UserData
case class Admin(id: Id, login: String, email: String, priviledges: Set[String]) extends WithId 
  with UserData with AdminPriviledges

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

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

Имплиситы и тайпклассы в Scala

Тайпкласс, как гласит Википедия, это конструкт для ad-hoc полиморфизма. Иными словами, способ для выбора конкретной реализации полиморфной функции по типу аргумента.

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

Во-первых, существуют неявные значения, они помечаются ключевым словом implicit, например:

implicit val foo: Int =5
implicit val 

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

def functionWithImplicitParameters( regularParam: String
                                 )(implicit
                                   implicitParam1: String,
                                   implicitParam2: Int
): (String, String, Int)= (regularParam, implicitParam1, implicitParam2)

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

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

type T1
type T2
type T3

implicit def foo(implicit t1: T1): T2
implicit def bar(implicit t2: T2): T3

implicit val t1: T1 = ???

val res = bar

В данном случае вызов

bar 

развернется до

bar(foo(t1))

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

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

type Bar[T]
def foo[F](implicit b: Bar[F]): Unit

в

def foo[F : Bar]:Unit

При условии, что тип Barимеет место для одного параметра.

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

Например:

sealed trait Color

sealed trait PredefColor extends Color
case object Red extends PredefColor
case object Green extends PredefColor
case object Blue extends PredefColor

case class RGB(r: Int, g: Int, b: Int) extends Color

implicit class ToRgbOps(val color: PredefColor) extends AnyVal {
 def toRgb: RGB = {
   case Red => RGB(255 byteValue, 0, 0)
   case Green => RGB(0, 255 byteValue, 0)
   case Blue => RGB(0, 0, 255 byteValue )
 }
}

И тогда мы сможем писать Red.toRgb или Green.toRgb.

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

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

Например:

trait Show[A] {
 def show(a: A): String
}

Второй компонент — это companion object этого трейта, который даст возможность использовать определенный синтаксис.

object Show {
 def apply[A](a: A)(implicit show: Show[A]): String = show.show(a)
}

А сам синтаксис использования будет выглядеть так:

Show[A](a)

Третий компонент — это набор реализаций: implicit val showString: Show[String] = {s => s} /*синтаксический сахар для анонимных классов c одним методом был создан, потому что писать new Foo {override def baz}каждый раз слишком громоздко*/

implicit val showString: Show[String] = {s: String => s} /* синтаксический сахар для анонимных классов c одним методом, был создан, потому что писать new Foo {override def baz} каждый раз слишком громоздко*/

implicit val showInt: Show[Int] = {i: Int => i.toString}
implicit def showList[T : Show]: Show[List[T]] = {list: List[T] =>
 list.map{Show[T].apply _}.mkString("List(", ",", ")")
}

Четвертый, не обязательный, но крайне желательный компонент — это «синтаксис» тайпкласса, который позволит вызывать этот метод через точку:

implicit class ShowSyntax[T](val t: T) extends AnyVal {
 def show(implicit instance: Show[T]): String = instance.show(t)
}

А вызов будет выглядеть вот так:

println(List(1,2,3,4,5,6).show)

Деконструкция sealed trait family

Теперь мы попробуем построить sealed trait family из набора «примитивных» типов. Для этого нам потребуются следующие компоненты: набор идентификаторов Id, набор примитивных типов PTи несколько операций. Строить будем некоторое множество типов T. Во-первых, любой примитивный тип является и типом Т. Нам понадобится операция связывания идентификатора с типом, будем обозначать ее символом @. То есть, если id — идентификатор и t — тип, то lt := t @ id — тип с идентификатором. Далее, введем операцию конструирования на типах с идентификаторами: если t1, …, tn — типы из Ти id1, …, idn — идентификаторы, то t := (t1 @ id1, t2 @ id2, …, tn @ idn) — тип из Т. Далее, вводим операцию «или» на типах: если t1, …, tn — типы из Т, то t := t1 | t2 | … | tn — тип из Т. Такая модель упрощенно показывает структуру ADT.

В нашем случае примитивными типами выступают, собственно, встроенные типы данных из разряда Int, Byte, Long, String, Double, Boolean и, кроме этого, различные типы, которые не являются частью ADT, такие как, например, java.time.Instant.

Операция конструирования моделирует введение нового типа при помощи кейс-классов или кейс-обджектов, например, из типов Int, String, String, идентификаторов foo, bar, baz мы можем построить новый тип Qux case class Qux(foo: Int, bar: String, baz: String), который в нашей модели будет представлен как Qux := (Int @ foo, String @ bar, String @ baz).

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

Операция «или» моделирует sealed trait. Ограниченность sealed trait рамками одного файла позволяет гарантировать, что перечень типов, которые наследуются от данного sealed trait, полон и известен на этапе компиляции.

sealed trait PredefColor
case object Red extends PredefColor
case object Green extends PredefColor
case object Blue extends PredefColor

То есть в этом случае мы можем смоделировать PredefColor := Red|Green|Blue.

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

Остается вопрос о параметрических типах вроде List[T]и т. д., но пока на этом останавливаться и вводить дополнительный формализм не будем: большинство вопросов, связанных с высшими каиндами, уже решено в механизме поиска имплиситов в компиляторе Scala.

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

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

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

Для операции «или», с учетом объектов ob1, ob2,...,obnтипов t1|...|tn, понятно, что настоящие типы этих объектов будут t_iи t_jдля некоторых i,jиз 1,...,n. Тогда если i == j, мы возвращаем результат сравнения внутренностей объектов, а если i != j, возвращаем несовпадение действительных типов.

Инструментарий

Нам понадобятся абстракции для представления операций @, (_,...,_)и “|”. К счастью, библиотека Shapeless предоставляет таковые.

Для операции @существует отдельный тип FieldType[Identifier, T], который представляет абстракцию для поля класса, названного некоторым именем. О его использовании — ниже.

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

Дело в том, что сам тип HList — это надтип для очень широкого семейства типов, но конструктора у конкретных типов всего два: HNil — пустой список и ::[+Head, +Tail <: HList]. Благодаря синтаксическому сахару для типов с двумя параметрами конструкции вроде ::[String, ::[Int, HNil]] выглядят как String :: Int :: HNil.

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

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

Далее, операцию «или» представляет тип Coproduct. Он подобен HList в том, что имеет структуру, похожую на цепь, но на этот раз у него есть несколько конструкторов. Общий тип Coproductнаселен типами T1 :+: T2 :+: … :+: TN :+: CNil, для N= 1,2,3,.... Каждый тип для фиксированного N= N0состоит из элементов Inl(t1: T1), Inr(Inl(t2: T2), … , Inr(Inr(,, Inl(tn0: TN0))). Где в H :+: T при T <: Coproduct Inr обозначает, что конкретный объект типа H, а Inl обозначает, что тип конкретного объекта находится в T. Тип CNilсуществует для терминирования последовательности CNil, и ни для чего более.

Рекурсивное прохождение по всем возможным вариантам принадлежности конкретного объекта к типу будет очень похоже на такое у гетерогенного списка.

Теперь нам необходимо связующее звено, которое выведет тип представления конкретного объекта через описанные выше три типа данных и предоставит механизм для превращения из конкретного объекта в обобщенное представление. В Shapeless существует тайпкласс LabelledGeneric, экземпляры которого генерируются неявным макросом (как и большинство экземпляров тайпклассов в этой библиотеке, так что открытие портала в измерение неявных макросов и призыв реализаций — это вполне обыкновенный способ взаимодействия с ней) на этапе компиляции. Чтобы «призвать» LabelledGenericдля типа T в скоупе, в котором объявлен, достаточно написать:

import shapeless._
val v = LabelledGeneric[T]

Для того чтобы призвать экземпляр тайпкласса для параметра типа T, необходимо потребовать implicit параметр lgen: LabelledGeneric.Aux[T, Repr], и ввести дополнительный параметр, который будет нести тип представления Repr.

Из чего будет состоять тип Repr? Этот тип будет действовать именно по описанной выше модели. Для кейс-классов он будет выдавать HListиз FieldType[FieldName, TypeName], тегированный специальным образом, для sealed trait — coproduct.

Следует отметить, что у IDE возникают определенные сложности с определением типов репрезентации labelled generic. Например, для класса

case class Foo(s: String, i: Int, b: Boolean)

...мы получим тип LabelledGeneric[Foo], который, естественно, соответствовать настоящему не будет, но даст нам некоторое представление о том, как это выглядит в реальности.

LabelledGeneric.Aux[
 Foo,
 FieldType[String with KeyTag[Symbol with Tagged[{type s}], String], String] ::
 FieldType[Int with KeyTag[Symbol with Tagged[{type i}], Int], Int] ::
 FieldType[Boolean with KeyTag[Symbol with Tagged[{type b}], Boolean], Boolean] ::
 HNil
]

Здесь страшные типы вроде String with KeyTag[Symbol with Tagged[{type s}], String] — это способ библиотеки Shapeless генерировать уникальные теги на уровне типов для полей классов.

Для иерархии

sealed trait All
case class Foo(s: String, i: Int, b: Boolean) extends All
case class Bar(l: Long, f: Foo) extends All
case class Baz(foos: List[Foo], bars: List[Bar]) extends All

Мы получим выражение:

LabelledGeneric.Aux[
   All,
   Bar with KeyTag[Symbol with Tagged[Symbol with Tagged[{type Bar}]], Bar] :+:
   Baz with KeyTag[Symbol with Tagged[Symbol with Tagged[{type Baz}]], Baz] :+:
   Foo with KeyTag[Symbol with Tagged[Symbol with Tagged[{type Foo}]], Foo] :+:
   CNil
 ]

И снова, приписки with KeyTag[_, _]относятся к техническому аспекту shapeless выдавать уникальные типы на каждый класс. (Подробнее — Singleton types)

Естественно, работать с этими типами вручную не нужно — с ними нужно работать при помощи рекурсии, и это мы рассмотрим чуть ниже.

Решение

Итак, объявим интерфейс и несколько вспомогательных классов. ComparisonResultдля результата сравнения в виде Successи Failure. FailEntry[T]для представления различий. Pathдля определения местонахождения сравниваемого элемента.

package object genericComparators {

 sealed trait ComparisonResult {
   def append(fe: FailEntry[_]): ComparisonResult

   def &&(that: ComparisonResult): ComparisonResult

   def fails: Chain[FailEntry[_]]

 }

 object ComparisonResult {

   case object Success extends ComparisonResult {
     override def append(fe: FailEntry[_]): ComparisonResult = Failure(Chain(fe))

     override def &&(that: ComparisonResult): ComparisonResult = that

     override def fails: Chain[FailEntry[_]] = Chain.empty[FailEntry[_]]

   }

   case class Failure(fails: Chain[FailEntry[_]]) extends ComparisonResult {
     override def append(fe: FailEntry[_]): ComparisonResult = Failure(fails :+ fe)

     override def &&(that: ComparisonResult): ComparisonResult = Failure(this.fails ++ that.fails)

   }

 }

 case class FailEntry[T](path: AdtPath, left: T, right: T)

 object AdtPath {
   val root = AdtPath(Chain.empty[PathElement])
 }

 sealed trait PathElement

 case object Root extends PathElement

 case class DownGeneric(generic: String) extends PathElement
 case class DownField(field: Symbol) extends PathElement
 case class DownCoproductElement(coproductType: Symbol) extends PathElement
 case class Primitive(field: String) extends PathElement
 case class DownIterable(index: Long) extends PathElement
 case class DownManual(tag: String) extends PathElement

 case class AdtPath(steps: Chain[PathElement], last: PathElement = Root) {
   def downHlist(fieldName: Symbol): AdtPath =
     last match {
       case DownField(_) => AdtPath(steps, DownField(fieldName))
       case Primitive(_) => throw new RuntimeException(s"should not never happen")
       case _ => AdtPath(steps :+ last, DownField(fieldName))
     }

   def downCoproduct(element: Symbol): AdtPath =
     last match {
       case DownCoproductElement(_) => AdtPath(steps, DownCoproductElement(element))
       case Primitive(_) => throw new RuntimeException(s"should not never happen")
       case _ => AdtPath(steps :+ last, DownCoproductElement(element))
     }

   def downGeneric(className: String): AdtPath =
     last match {
       case Primitive(_) => throw new RuntimeException(s"should not never happen")
       case _ => AdtPath(steps :+ last, DownGeneric(className))
     }

   def downIterable(index: Long): AdtPath = last match {
     case DownIterable(_) => AdtPath(steps, DownIterable(index))
     case Primitive(_) =>throw new RuntimeException(s"should not never happen")
     case _ => AdtPath(steps :+ last, DownIterable(index))
   }

   def downManual(manual: String): AdtPath = AdtPath( steps :+ last, DownManual(manual))

   def primitive(primitiveTag: String): AdtPath = AdtPath( steps :+ last, Primitive(primitiveTag))
 }
}

Далее, определяем интерфейс нашего тайпкласса и несколько простых реализаций:

object GenericComparer {
 def compare[T](first: T, second: T)(implicit
                                     compare: GenericComparer[T]
 ): ComparisonResult =
   compare.apply(first, second)(AdtPath.root, ComparisonResult.Success)

 def instance[U](f: (U, U) => Boolean)(tag: String = ""): GenericComparer[U] = new GenericComparer[U] {
   override def apply(t1: U, t2: U)(implicit path: AdtPath, result: ComparisonResult): ComparisonResult =
     if (f(t1, t2)) result
     else result.append(FailEntry(path, t1, t2))
 }
}

trait GenericComparer[T] {
 def apply(t1: T, t2: T)(implicit path: AdtPath, result: ComparisonResult): ComparisonResult
}

Неявный параметр pathнужен для возможности «записывать» пройденный путь по структуре класса при рекурсивном применении этой функции. Неявный параметр resultявляется аккумулятором в рекурсии.

В компанион обджекте создан метод def compare[T](first: T, second: T)(implicit compare: GenericComparer[T]): ComparisonResult, который предоставляет интерфейс для использования тайпкласса как GenericComparer.compare(a,b).

Там же функция для создания реализации из функции сравнения instance.

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

implicit val scompare: GenericComparer[String] = GenericComparer.instance[String] { _ == _ } {"string"}
implicit val icompare: GenericComparer[Int] = GenericComparer.instance[Int] { _ == _ } {"int"}
implicit val lcompare: GenericComparer[Long] = GenericComparer.instance[Long] { _ == _ } {"long"}
implicit val bcompare: GenericComparer[Byte] = GenericComparer.instance[Byte] { _ == _ } {"byte"}
implicit val boolcompare: GenericComparer[Boolean] = GenericComparer.instance[Boolean] { _ == _ } {"bool"}
implicit val ccompare: GenericComparer[Char] = GenericComparer.instance[Char] { _ == _ } {"char"}
implicit val shortcompare: GenericComparer[Short] = GenericComparer.instance[Short] { _ == _ } {"short"}
implicit val bicompare: GenericComparer[BigInt] = GenericComparer.instance[BigInt] { _ == _ } {"bigInt"}
implicit val dcompare: GenericComparer[Double] = GenericComparer.instance[Double] { _ == _ } {"double"}

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

//decompose sealed trait family
implicit def lgenCompare[T, Repr](
 implicit
 ctag: ClassTag[T],
 lgen: LabelledGeneric.Aux[T, Repr],
 reprCompare: Lazy[GenericComparer[Repr]]): GenericComparer[T] = new GenericComparer[T] {
 override def apply(t1: T, t2: T)(implicit path: AdtPath, result: ComparisonResult): ComparisonResult = {
   reprCompare.value.apply(
     lgen.to(t1),
     lgen.to(t2))(
     path.downGeneric(ctag.runtimeClass.getSimpleName),
     result
   )
 }
}

Эта реализация функции тайпкласса пытается «призвать» LabelledGeneric с каким-либо типом представления и вывести реализацию для обобщенного представления. Но сама по себе эта реализация бесполезна без реализаций для примитивов, случая с HListи Coproduct. Обратите внимание на то, что операция сравнения для обобщенного представления Reprобернута в Lazy, для того чтобы избежать ошибки diverging implicit expansion.

Итак, сначала случай HList.

Терминальная точка для рекурсии:

implicit val hnilCompare: GenericComparer[HNil] =
 GenericComparer.instance[HNil] { (_, _) => true }{"hnil"}

И сама рекурсия, метод который выводит операцию сравнения для непустого списка Head :: Tail:

implicit def hconsCompareKeyed[Key <: Symbol, Head, Tail <: HList](
 implicit key: Witness.Aux[Key],
 compareHeads: GenericComparer[Head],
 compareTails: Lazy[GenericComparer[Tail]]
): GenericComparer[FieldType[Key, Head] :: Tail] =
 new GenericComparer[FieldType[Key, Head] :: Tail] {
   override def apply(
     t1: FieldType[Key, Head] :: Tail,
     t2: FieldType[Key, Head] :: Tail)(
     implicit path: AdtPath, result: ComparisonResult
   ): ComparisonResult = {
     val newPath = path.downHlist(key.value)

     compareHeads.apply(t1.head, t2.head)(newPath, result) &&
       compareTails.value.apply(t1.tail, t2.tail)(newPath, result)
   }
 }

Откуда такой набор типов и такая сигнатура? Во-первых, нам необходимо имя поля, его достаем при помощи типа Key, который является символом. Для «вызова» значения имени поля используем неявный параметр key: Witness.Aux[Key], который и вызовет то значение, которое кодируют страшные типы из главы выше. Это и есть тот обещанный способ не работать напрямую с типом тега, который тегирует конкретное поле в классе — введя его как параметр функции, компилятор попытается его вывести автоматически.

Далее, Head — это тип тегируемого при помощи Keyполя в классе, нам необходимо иметь для него операцию сравнения, поэтому мы заявляем это как еще один неявный параметр — compareHeads: GenericComparer[Head].

И наконец, чтобы сделать рекурсивный вызов, мы вводим параметр типа хвоста списка Tail, который снова должен быть гетерогенным списком, и просим вывести для хвоста реализацию при помощи заявления еще одного неявного параметра: compareTails: Lazy[GenericComparer[Tail]].

Почему это будет рекурсивным вызовом? Потому что под тип GenericComparer[Tail]подпадает эта же реализация, или же терминальная точка рекурсии hnilCompare. При этом мы избавились от необходимости рассматривать все типы списка сразу, а рассматриваем их только по одному за вызов, что позволяет обрабатывать списки произвольной длины.

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

Теперь рассмотрим случай Coproduct. Терминирование рекурсии будем производить при помощи:

implicit val cnilCompare: GenericComparer[CNil] =
 GenericComparer.instance[CNil] { (a, b) => a.impossible
}{"neverhappen"}

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

implicit def cconsCompareKeyed[Key <: Symbol, Head, Tail <: Coproduct](
 implicit key: Witness.Aux[Key],
 compareHeads: GenericComparer[Head],
 compareTails: Lazy[GenericComparer[Tail]]
): GenericComparer[FieldType[Key, Head] :+: Tail] =
 new GenericComparer[FieldType[Key, Head] :+: Tail] {
   override def apply(
     t1: FieldType[Key, Head] :+: Tail,
     t2: FieldType[Key, Head] :+: Tail)(
     implicit path: AdtPath, result: ComparisonResult): ComparisonResult = {
     val newPath = path.downCoproduct(key.value)
     (t1, t2) match {
       case (Inl(a), Inl(b)) =>
         compareHeads.apply(a, b)(newPath, result)
       case (Inl(_), Inr(_)) | (Inr(_), Inl(_)) =>
         result.append(FailEntry(newPath, Coproduct.unsafeGet(t1), Coproduct.unsafeGet(t2)))
       case (Inr(tail1), Inr(tail2)) =>
         compareTails.value.apply(tail1, tail2)
     }
   }
 }

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

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

def compareIterables[T: GenericComparer]: GenericComparer[Iterable[T]] =
 new GenericComparer[Iterable[T]] {
   override def apply(t1: Iterable[T], t2: Iterable[T])(implicit path: AdtPath, result: ComparisonResult)
   : ComparisonResult = {
     if (t1.size == t2.size) {
       (t1 zip t2).foldLeft((result, 0)) { case ((res, i), (el1, el2)) =>
         (implicitly[GenericComparer[T]].apply(el1, el2)(path.downIterable(i), res), i + 1)
       }._1
     }
     else result.append(FailEntry(path.downIterable(-1), t1, t2))
   }
 }

Объединение

Теперь необходимо соединить все в единую структуру, пригодную к использованию. Нам бы хотелось при всем том, что умеет эта библиотека, уметь заменять генерацию операции своей реализацией, иначе бы от такой библиотеки пользы было мало. Достичь этого можно при помощи механизма затенения неявных значений (implicit shadowing). Для этого нужно положить реализацию для Labelled generic, HListи Coproduct в трейт GenericComparatorsLowestPriority. Затем от него наследовать трейт AllComparators со всеми реализациями для примитивов. Далее — в любой точке применения наследовать AllComparatorsсвоим классом/обджектом/трейтом.

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

Готовый результат можно посмотреть в репозитории на GitHub.

Наиболее простой способ запустить этот код локально — установить intellij IDEA Community edition и Scala plugin к ней, далее просто открыть проект и импортировать — плагин и IDE сделают все сами.

Преимущества и недостатки

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

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

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

Послесловие

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


Как я работаю: Степан Митиш, Head of EPAM в Киеве и Виннице

$
0
0

[В рубрике «Как я работаю»мы приглашаем гостя рассказать о своей работе, организации воркспейса, полезных инструментах и лайфхаках]

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

Степан — фанат UFC, бокса и «Формулы-1». Увлекается кроссфитом, путешествиями, машинами, а также книгами о лидерстве и психологии успеха.

О себе

В 1985-мгоду наша семья переехала в Болгарию: моего отца пригласили заниматься пуском и наладкой АЭС. Там мне и подарили первый компьютер — «Правец 8D». В комплекте с компьютером шла документация к языку Basic. По ней я научился вводить команды и, например, проигрывать примитивные мелодии. Меня это очень заинтересовало, и с того времени компьютеры стали частью моей жизни.

В конце 90-х —на тот момент мы уже вернулись в Украину — мне нужно было определиться с будущей специальностью. Я выбирал между экономикой и программированием. Страсть к компьютерам победила — я поступил в КПИ. Во время учебы жил в общежитии. Денег, которые выделяли родители, хватало не всегда, а потому уже на втором курсе стал искать парт-тайм подработку.

Меня взяли на позицию программиста в букмекерскую компанию. Мы писали два приложения на Delphi и PHP: back-end для сайта и front-end для кассиров. Считаю, мне очень повезло с первой работой: я смог применить на практике полученные в вузе знания. И, к тому же, встретил ментора, который помог мне развиваться как программисту.

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

После этого мы с коллегой решили поработать «на себя» и занялись разработкой ПО для печатных изданий. Это был колоссальный опыт: мы прошли все RUP-этапы от Inception до Construction и Transition. Бизнес просуществовал год — у нас были сложности с поиском новых клиентов.

В 2006-мгоду один из бывших коллег по Softline пригласил меня попробовать силы в EPAM. Я согласился — и задержался тут на 13 лет.

Роль и обязанности

Начиная работать программистом, я не думал, что когда-нибудь стану менеджером. Мне было интереснее творить самому, а не руководить. Мне казалось, что менеджеры — это какие-то бездельники :)

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

В EPAM я пришел на роль проектного менеджера, хотя по факту первое время выполнял обязанности техлида. Затем были позиции Software Engineering Manager, Senior Software Engineering Manager и Software Engineering Director. В этих должностях я отвечал за Delivery крупного финтех-аккаунта, развитие Microsoft-направления и позже портфолио финансовых проектов в Украине. Полгода назад занял должность Head of EPAM в Киеве и Виннице.

Это тоже Delivery роль, но существенно большего масштаба. У меня есть две основные задачи. Во-первых, я слежу, чтобы Delivery было зеленым, а клиенты — счастливыми. Это невозможно без сильной команды и правильных людей на правильных местах. Во-вторых, вместе с моей командой обеспечиваю компании постоянный рост выручки на 20-25%в год. Для этого нужно заводить новых клиентов и расширять существующие проекты.

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

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

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

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




Типичный рабочий день

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

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

10:30.Начинается время митингов. Во вторник, среду и четверг у меня много встреч по операционной работе — они занимают около 40-60%всего рабочего времени. Помимо этого, есть митинги по каким-то неразрешенным вопросам, а также встречи с текущими и потенциальными клиентами.

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

В перерывах между встречами я стараюсь выделять по 5-10минут на спортивную разминку. У нас в офисе есть небольшой спортзал, а у меня в кабинете — своя гиря :) Я разделяю мысль, что в здоровом теле — здоровый дух. К тому же спорт помогает отвлечься и переключиться между задачами.

17:00.Вечером уделяю время рутинным задачам — смотрю и подготавливаю отчеты, планирую следующий день. Также провожу звонки с коллегами и клиентами из США.

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

Инструменты и продуктивность

На мое отношение к тайм-менеджменту повлияло две книги: «Съешьте лягушку! 21 способ научиться успевать»Брайана Трейси и «Тайм-менеджмент. Искусство планирования и управления своим временем и своей жизнью»Джулии Моргенстерн. Вот что я из них вынес.

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

Я где-то читал, что в США провели опрос топ-менеджеров крупных компаний, и оказалось, что только 3% тратят больше 10% времени на решение стратегических задач. Остальные утопают в рутине и не успевают думать о развитии на три-пять лет вперед. Мне не хотелось бы повторять эти ошибки. Стараюсь, чтобы у меня хватало времени не только на операционную текучку.

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

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

Также недавно мы на уровне всей компании начали использовать Microsoft Teams — это более удобная замена Skype For Business. Там можно создавать группы по области ответственности, и в рамках них — каналы и чаты. Также в Microsoft Teams есть модули для мессенджеринга и видеоконференций.

Аудиокниги слушаю через приложение Audible от Amazon.




Книги и самообразование

Я давно увлекаюсь бизнес-книгами: все началось с попсовой «Первый миллион. 21 способ его заработать»Брайана Трейси, которую мне порекомендовали знакомые. Лет 15 назад прочитал «21 неопровержимый закон лидерства»Джона Максвелла. Это книга позволила мне эффективно поработать над своим характером и подходами к работе.

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

  • «Exponential Organizations» by Salim Ismail, Michael S. Malone — о том, как технологии меняют компании и способы ведения бизнеса. Идеи авторов как раз отлично согласуются с тем, что мы пытаемся строить в EPAM.
  • «Never Split the Difference» by Chris Voss, Tahl Raz — о том, как грамотно вести переговоры. Среди ее авторов — бывший агент ФБР, который занимался освобождением заложников. Например, одна из типичных ошибок — пытаться в лоб доказать, что собеседник не прав. Автор советует, наоборот, подвести собеседника к тому, чтобы он сам усомнился в своей правоте и самостоятельно пришел к этому заключению.

Сейчас слушаю одновременно две книги: «Принципы. Жизнь и работа»Рея Далио и «The Hard Thing About Hard Things» by Ben Horowitz. Первая — биографический рассказ о принципах в жизни и работе, основанных на культуре радикальной прозрачности. Вторая — история бизнесмена, инвестора, предпринимателя и одного из топ-менеджеров первого коммерческого браузера Netscape о взлетах и падениях компаний, которыми он руководил, и принципах принятия сложных решений.

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

В прошлом году я делал на DOU подборку пяти книг о лидерстве — советую посмотреть.

Ретроспектива и планы на будущее

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

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

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

Оценка трудоемкости проектов разработки. Часть 2

$
0
0

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

Метод оценки

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

Шаг 1. Подготовка (Prerequisites)

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

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

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

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

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

Шаг 2. Опишите требования и рамки проекта (scope)

Четыре категории требований по степени известности

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

  1. Known knowns. Заявленное в явном виде, понятное и достаточное для точной оценки. Что с этим делать? Оценить.
  2. Unknown knowns. Косвенное заявленное либо не заявленное, но легко доступное. Не ленитесь прочитать требования и спецификации, «прокликать» гиперссылки в них, зайти на сайт клиента, спросить SME. Это не требует больших трудозатрат, но позволяет намного лучше понять требования и выявить скрытые риски. Что с этим делать? Найти, прочитать, спросить, прояснить, перевести в Known knowns, оценить.
  3. Known unknowns. Недостаточные требования, неготовая документация и тому подобное. Например, заказчик знает, что будет интеграция с другими системами, но не знает протоколов, форматов и объемов обмена данными.

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

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

Действия по подготовке требований к оценке

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

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

FeatureEstimate
Login page24mh— оцениваем
Single sign-onNOT ESTIMATED— оценим позже, когда будет понятнее
Sign-up linkOut of scope— не собираемся оценивать и делать

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

  1. Идентифицируйте рискованные требования. Под рискованными я подразумеваю такие требования, как «сайт должен работать в любой точке мира и поддерживать все языки». Они часто формулируются одной строчкой, но могут увеличить трудозатраты вашего проекта на порядок. Как правило, заказчик не осознает всей сложности их реализации и ему не нужны «все языки». К сожалению, для выявления таких требований приходится внимательно перечитывать всю доступную документацию, поскольку эти «сокровища» могут быть раскиданы на сотнях страниц текста.
  2. Соберите нефункциональные требования. Мало кто думает в начале проекта о них, потому стоит по крайней мере поставить вопрос, выбить из заказчика хотя бы приблизительные оценки количества данных, пользователей, доступности системы и внести их в предположения. Многие из этих параметров могут критически повлиять на ваши архитектурные решения, а следовательно, и на трудозатраты проекта.
  3. Тщательно проанализируйте унаследованные артефакты (legacy). С началом проекта все они, к сожалению, могут стать вашими. Это касается не только кода, но и документации, данных, контрактов, сторонних библиотек и прочих вещей, составляющих проект. Часто проще переписать код, чем пытаться исправить его после предыдущих «специалистов», и лучше об этом знать заранее. Помимо технического долга, вам могут перейти прочие виды долгов, такие как зависимости от внешних компонент, контрактные обязательства, плохая документация, нецелостные данные и так далее.

«Сделайте так же, но лучше»

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

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

Шаг 3. Создайте ИСР на базе требований

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

  1. ИСР, основанная на декомпозиции по продукту (noun-oriented), проще для оценки по этому методу, чем основанная на разбиении по другим критериям.
  2. Уровень детализации ИСР. Строки нижнего уровня не должны занимать более 40, максимум 80 часов.
  3. Вопреки общепринятым рекомендациям покрывать 100% работ, наша ИСР может не содержать некоторые виды работ вроде встреч и менеджмента. Ниже будет понятно почему.

Например, для простейшей системы обработки заказов ИСР может выглядеть так:

  1. Login page
    • 1.1. UI
    • 1.2. Login
    • 1.3. Logout
  2. Order page
    • 2.1. UI
    • 2.2. Create order
    • 2.3. Confirm order
    • 2.4 Cancel order
    • 2.5. Search and filtering
  3. Integration with payment
    • 3.1. Outbound
    • 3.2. Inbound

Шаг 4. Зафиксируйте предположения (Assumptions)

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

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

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

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

  • Definition of Doneдля задач и всего проекта. Фиксирует общее понимание критериев сдачи задач либо проекта.
  • «Срок годности» оценки. Все находится в постоянном изменении: рынок, бизнес, люди, технологии и наше представления о них. Если ваш клиент захочет вернуться к уже сделанной оценке через полгода, хорошо бы ее пересмотреть на предмет актуальности.
  • Версии. Для каких версий языков, браузеров, операционных систем, компонент, железа, фреймворков, других продуктов верны ваши оценки.
  • Доступ к внешним ресурсам. Если вы работали с большими корпорациями, то вам могут быть знакомы мучения с получением доступа к их серверам, системам и прочим ресурсам, которые могут повлиять на качество оценки.
  • При использовании, особенно первом, внешних компонент, API стоит внести предположение о том, что они будут работать так, как указано в документации, а их поставщик будет оперативно отвечать на ваши запросы.
  • Требования к железу и производительности. Стоит указать, на каком железе ваше система сможет показывать плановую производительность. Даже производительность сред разработки и сетевого соединения между ними, базой и рабочими станциями членов команды может серьезно повлиять на время разработки.
  • Если вы знаете, что оцениваете brownfield-проект, не имея доступа ко всем старым артефактам, напишите это в предположениях: «При получении доступа к старому коду оценка может быть пересмотрена».
  • Лицензирование, прочие ресурсы и расходы. Хорошо бы согласовать, что вам нужно будет для оценки, если это предоставляется клиентом либо третьей стороной.
  • Ожидаемый объем данных. Большие базы данных и файлы могут серьезно увеличить время любых операций с ними. Одно только копирование терабайтной базы на локальный компьютер может занять несколько дней или недель при плохом сетевом соединении.
  • Любые комментарии, сомнения, противоречия. На одном из проектов мы делали технический апгрейд систем на новую версию фреймворка. Нашей задачей было пройти стандартные шаги апгрейда, убедиться, что код компилируется и запускается и что целостность данных не нарушена. Клиент при этом ожидал полностью протестированную и функционирующую систему. Этот проект шел долго и трудно и в конце концов был закрыт с большими убытками.

Шаг 5. Оцените каждую задачу и проект в целом

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

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

1. Договоритесь о том, что есть разработка

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

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

Далее, действия 2–5выполняются для каждой строки ИСР, если соответствующий тип работ необходим.

2. Оцените время разработки

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

Если различные виды разработки оцениваются отдельно в рамках одной задачи, например front-end и back-end, то их оценки необходимо сложить.

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

Если ваша команда сформирована и сработана, хорошие оценки может дать Planning poker, хотя это и относительно дорогая техника.

3. Добавьте время на работу с требованиями и дизайнами

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

4. Добавьте время на обеспечение качества

Добавьте время на работы по тестированию (написание тестовой документации и непосредственно ручное тестирование, включая интеграционное) — 50% от времени разработки. Если вы собираетесь использовать автоматизированное тестирование, отдельно добавьте время и на него.

5. Добавьте время на риски

Оцените степень риска (Contingency) по задаче. Это субъективный показатель того, насколько разработчик уверен в оценке и понимании задачи по следующей шкале:

  • +5% — полностью уверен, низкий риск;
  • +15% — средний риск;
  • +30% — риск высокий.
Выше 30% — слишком высокий риск, задача требует дополнительного исследования либо разбиения на подзадачи. Хотя на ранних стадиях проекта, в условиях высокой неопределенности, коэффициент риска может быть выше.

Степень риска затем умножается на полное время выполнения задачи (BA + DEV + TST).

6. Добавьте время на общепроектные задачи

Для всего проекта добавьте:

  • Время на встречи — 20% от времени разработки. Гибкие методологии могут потребовать и больше времени на встречи.
  • Время на менеджмент — 15% времени разработки. Включает в себя время тимлида на управление командой.
  • Время на управление инфраструктурой (DevOps) — 5–10%времени разработки.
  • Время на прочие работы вашего проекта (например, автоматизированное тестирование или командировки).
  • Проектный буфер — от 5 до 15% от суммарного времени, в зависимости от рисков, размера проекта, сложности предметной области и требований, степени взаимосвязи разных задач.

7. Сведите все вместе

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

BA & UI — Business analysis and UX/UI design
DEV — Development
TST — Test
Cont — Contingency

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

Округляйте оценку до целых часов, десятков, сотен, в зависимости от конечного результата. Число 1574,56 может создать у читателя ложное ощущение точности, в отличие от 1580 или 1600.

Заметьте, что трудоемкость всего проекта в три раза выше трудоемкости непосредственно разработки: 971 человеко-час против 312. Интересно, что это соотношение совпадает с выводом в классической книге Ф. Брукса по управлению проектами «Мифический человеко-месяц», написанной аж в 1975 году. Оно также может служить грубой проверкой полноты оценки.

Шаг 6. Оформите оценку

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

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

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

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

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

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

Чек-листы

Настойчиво рекомендую создавать, использовать и пропагандировать контрольные списки (чек-листы). Неважно, сколько вы проектов оценили в своей жизни, всегда есть шанс что-то упустить. Отличная книга по этой теме — The Checklist Manifesto: How to Get Things Right, в которой ее автор, Атул Гаванде, описывает, как чек-листы спасают здоровье и жизни в авиации и медицине. Этот дешевый и простой инструмент может однажды спасти и ваш проект.

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

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

Немного математики

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

Случайные величины

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

Эмпирически мы знаем, что плотность распределения времени выполнения задачи можно смоделировать так, как показано на рисунке ниже, с длинным правым «хвостом» (своего рода следствие законов Паркинсонаи Мерфи), поскольку количество негативных рисков, по сути, не ограничено. В отличие от позитивных рисков.

Источник

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

Критика метода трех точек

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

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

Заметьте, что даже в общепринятых описаниях метода нет четких определений и различия между самым вероятным (most likely) и реалистичным. Также не каждый разработчик знает и понимает, что такое математическое ожидание.

Представим, что мы дали одну и ту же задачу 25 разработчикам примерно одинаковой квалификации. И получили фактические значения потраченного времени, как на диаграмме ниже. Математическое ожидание в таком случае будет равно 6,16, а наиболее вероятное время выполнения — 5. То есть при неправильной коммуникации реалистичной оценки можно «промазать» на 20–25%.

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

  1. Придумывать три величины для каждой задачи достаточно трудоемко. На практике оптимистические и пессимистические оценки могут проставляться «от фонаря», особенно если задач десятки или сотни.
  2. Неточность в определениях, что есть a, m, b, вносит неточность и в оценку.
  3. «Риск задачи», на мой взгляд, намного более интуитивная категория, чем «три точки».
При этом метод трех точек можно порекомендовать для отдельных больших и рискованных задач. А также для борьбы с излишней оптимистичностью оценщика и корректировки реалистичной оценки.

Центральная предельная теорема

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

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

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

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

Источник

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

Увеличиваем доверительный интервал

Итак, подойдет ли нам сумма оценок всех задач в качестве финальной оценки? Только в случае, если нас удовлетворит 50-процентнаявероятность попадания в бюджет... Чтобы быть более уверенным в завершении проекта в срок и в рамках бюджета, необходимо добавить еще некоторую величину. При использовании трехточечного метода для всех задач ее возможно вычислить достаточно строго, например +3 сигмы для доверительного интервала в 99,7%.

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

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

Таким образом, наш метод оценки получает некое нестрогое математическое обоснование.

Заключение

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

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

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

$
0
0

Пропрацювавши близько трьох років тестувальницею і досить довго не змінюючи проектів, я помітила за собою деякі зміни, порівняно з початком моєї кар’єри. Зрозуміла, що залежу від розробника набагато більше, ніж сподівалася, і підсвідомо можу вирішувати, послуговуючись певним інтуїтивним алгоритмом. До, здавалося б, аналогічних завдань я можу бути прискіпливішою в одній ситуації й менш скрупульозною в іншій. Можу повернути назад у роботу одне завдання й пропустити інше, керуючись своїм загальним враженням, а не об’єктивними причинами, тому що ці аналогічні завдання виконували різні розробники.

Працюючи в команді, ми налагоджуємо зв’язки й починаємо працювати організованіше. З погляду менеджменту, спрацьованість команди — прекрасна річ, бо створює ефект синергії. Проте чи впевнені ми, що командна робота має лише позитивні аспекти? Давайте подивимось.

Ілюстрації автора

Упередження, що впливають на роботу

Коли людина тільки починає працювати тестувальником, вона сповнена ентузіазму й запалу, відповідально ставиться до своїх завдань. Цього зазвичай досить, щоб наважитися подужати «Силлабус ISTQB»і, можливо, навіть скласти сертифікацію. Після 2–3місяців запал вщухає, і «Силлабус» обертається на завжди відкриту вкладку в браузері, яку ніколи не проглядають. Але дуже важливо те, що до першого розділу «Силлабусу» обов’язково дійдуть усі, хто наважився на крок підвищити свою професійність.

Перший розділ дає нам розуміння деяких важливих речей: основ і головних принципів тестування. Зокрема, підрозділ 1.5 The Psychology of Testing (ISTQB Foundation Level Syllabus 2018) розповість про всі структурні особливості аджайл-команд: хто яку роль грає і яка роль у тестувальника. Як тестувальник має доносити до розробника або менеджера результати своєї роботи й на яку реакцію він може сподіватися. Тобто спеціальність, яка спочатку здавалася винятково технічною, виявилася значно складнішою з психологічного погляду, і це навіть підкреслили в збірнику для сертифікації. Це природно, що всі ми, працюючи разом, комунікуємо, а отже, впливаємо одне на одного.

Коли тестувальник не знайомий з розробниками, його підхід до тестування сталий: є тест-план, чек-лист, тест-кейс — певна процедура. Процедура, за якою відбувається тестування, і воно якнайоб’єктивніше, бо йде за планом. Але з часом робота стає цікавішою і, хоч як дивно, простішою. І ось уже розробник, якого тиждень тому ми вперше побачили, стає вам знайомішим. Ми вже знаємо, що він п’є каву без молока, а в розрахунках завжди робить помилки в десятих, але ніколи не нехтує піксельною точністю. Ще через деякий час розуміємо, що парадокс пестициду (ISTQB Foundation Level Syllabus 2018, розділ 1.3) уже працює на нас, що ми вже, як штучний інтелект, працюємо з прецедентами й вибудовуємо алгоритм у підсвідомості. Ми розуміємо, що залежно від того, хто виконував завдання, по-різному тестуватимемо.

Уявімо собі, що беремо в роботу завдання від інтерна. Перш за все ми подумаємо, що людина без досвіду, і помилок має бути багато. Через деякий час бачимо, що працівник ретельно перевіряє свою роботу й віддає в тестування лише попередньо протестовані завдання та, як наслідок, ми не знайдемо багато помилок у цьому коді. Ми перестанемо так ретельно перевіряти роботу цього розробника, бо підсвідомо довіряємо програмістові. Водночас до нас у роботу надходять завдання від іншого розробника (не вказуватиму тут рівень програміста, оскільки це неважливо). І ось раз у раз ми бачимо, що людина припускається якихось дрібних помилок, але кожне завдання з ними: десь, у титулці, літеру пропустив, десь колір переплутав, десь — мінус з плюсом. І щоразу щось незначне, але трапляється. Звичайно, ми намагатимемося бути якнайуважнішими з завданнями від цього розробника й витратимо більше часу на пошук дрібного багу. У третій ситуації нам надійдуть завдання, які, ймовірно, можуть бути недороблені. Наприклад, в описі завдання 5 пунктів, а людина виконала тільки 4. Відволіклась і забула про той 5-йпункт. Але перші 4 ідеальні. І таке трапляється приблизно в 30% завдань. У такому разі ми уважніше читатимемо опис й Acceptance criteria. Отже, для кожного спеціаліста в нас буде свій алгоритм роботи. Випадків безліч, і до кожного ми так чи інакше адаптуємося.

З одного боку, це упереджене ставлення, що для тестувальника погана характеристика, але, з іншого, є група методів тестування (ISTQB Foundation Level Syllabus 2018, розділ 4.4), які базуються на досвіді, тести створюють на основі вміння, інтуїції й досвіду тестувальника. Тобто виходить, що наша підсвідомість дає саме нам цей інструмент тестування. Цікаво те, що коли розробник, якого ми аналізуємо, не розвиватиметься, ми звикнемо до нього і, так би мовити, зафіксуємо модель як сталу. Пряма залежність — розробник розвивається, і ми також. Але ж головне, щоб ми це вчасно помітили. Саме тут може спрацювати упередженість. Ми тестимо код джуніор смарта, а він уже рік як сеньйор мерседес.

З психологічного погляду, такий феномен називають когнітивним упередженням — відхилення в судженнях, яке супроводжується можливою нелогічністю у висновках про інших людей і ситуації. Людина створює свою «суб’єктивну соціальну реальність» на основі власного сприйняття даних зовнішнього світу. Когнітивних упереджень, спотворень безліч (~65), і всі вони в нас є.

Серед тих, які я помітила за собою, хочу виділити такі:

Фреймінг — це відмова від альтернатив. Наш зір замилюється, і все, що ми бачимо, — це те, до чого вже звикли, тож ми просто не намагаємося змінювати своїх кроків. За півроку тестування одного продукту вивчити його можна від «а» до «я». Кнопки вже натискаються автоматично, логін уводиться сам, і подекуди тільки за 15 хвилин тестування усвідомлюєш, що ти просто зловив ґаву та тестив на автоматі. Це може призвести до того, що ми не розвиватимемося як тестувальники, а обернемося на автоматизований тест. Просто тест, що ходить за одним алгоритмом. Привіт, парадоксе пестициду.

Ретроспективне упередження — це спроба підтвердити думку, яка вже є в наших думках (експеримент Форера). Усе просто: якщо ти не «любиш» того «гівнюка», то знайдеш баги в його коді (навіть якщо їх там немає — нічо’, будуть). Проблема в тому, що, намагаючись підтягнути реальність до наших сподівань, ми можемо побачити те, чого немає. Наприклад, розмір кнопки, відтінок, швидкість кліку. Якщо все це, наприклад, чітко не прописано в Acceptance criteria, то підстав для дискусії багато, і треба керуватися здоровим глуздом, а він у кожного свій. І витрачати час на баг через колір відтінку кнопки під час натискання просто нераціонально.

Ефект прилучення до більшості — ми більш схильні погоджуватися з думками більшості, ніж відстоювати або навіть генерувати власні. Особливо якщо ми знайомі з цими людьми чи вони для нас авторитети (експеримент Соломона Аша). Якщо я в чомусь не впевнена, то піду по пораду до інших людей і послухаю їх. Головне — так чоловіка не вибирати. Звичайно, прислухатися до думок решти варто, але вирішувати треба самостійно. Як мама казала: «А якщо всі з мосту підуть стрибати, ти теж підеш?» Не треба з мосту за всіма — є й інші джерела інформації, коли з’являється спірне питання. Перш за все — документація. Якщо її немає, а немає її часто, то варто звернутися до Product Owner — він на проекті, щоб розв’язувати проблеми (хоча це теж спірне питання). Наприклад, нам дали нове завдання: протестувати інтеграцію з іншою програмою. Ми знайшли спірний баг, але дослідили питання й з’ясували, що аналогічна проблема траплялася на інших проектах, де використовували цю програму. Колеги ж дотримуються думки, що проблема наша. І в такому разі, з ними погодившись, ми не зробимо краще. У ситуації, коли наше рішення безпідставне, ліпше прислухатися до тих, хто краще тямить саме в цьому питанні. На мій погляд, якщо ви знаєте, що потім пошкодуєте, як не висловите свою думку, то треба її відстоювати.

Сліпота неуважностізумовлена фреймінгом. Це прояв класичної неуважності, якщо ми зосереджені на чомусь одному, то на інше подекуди просто не звертаємо уваги. Нове завдання може бути цікавішим і пріоритетнішим, ніж старий функціонал. Унаслідок цього те, у чому ми, здавалося, були впевнені, може підкласти свиню у вигляді критичного багу. Тому що туди просто ніхто давно не лазив і не тиснув ту кнопку.

Ефект негативу — скептичне ставлення до всього. Така собі «Баба-Яга проти». В окремих ситуаціях це непогано (негативне тестування). Але коли ти бачиш усюди зраду, то потрібно до лікаря. Зацикленість може бути проявом маніакальних схильностей :) Цей випадок — прекрасний приклад важливості пріоритизації та серйозності (Priority/Severity).

Утрачена вартість. Те, у що ми вклали час, сили, гроші, будь-які ресурси, має цінність. І ми це розуміємо, але не усвідомлюємо, що як з вкладеними ресурсами результату немає, то цінності також немає. Якщо ми витратили тиждень на роботу, а в кінці тижня зрозуміли, що припустилися помилки, і завдання виконане неправильно, ми докладемо ще більше зусиль, щоб довести собі та іншим, що все окей. Навіть коли знаємо, що це не так. Знаю, що стаття не ідеальна, але я вже другий тиждень над нею сиджу.

Варто також зазначити, що не лише тестувальники підлаштовуються під розробників, у зворотному напрямку працює так само. Залежно від тестувальника, розробники також по-різному працюють — знаючи, що людина відповідальна, можна перекласти всю роботу на тестувальника й узагалі не перевіряти свій результат. Якщо ж «коп» поганий, і розробник боїться дістати на горіхи, то й попрацює перед тим, як віддати код на тестування.

Для мене це явище цікаве не в негативному розумінні, адже там воно, безумовно, має значний вплив, а в позитивному. Наскільки корисною може бути ця особливість людського мозку? Адже ми насправді заощаджуємо час, не перевіряючи там, де це не потрібно, адже ймовірність зустріти баг невисока, і докладаємо більше зусиль там, де, найпевніше, це буде виправдано. За моїми спостереженнями, з часом продуктивність роботи тестувальника знижується — набридає проект, він втрачає концентрацію, доводить навички до автоматизму. Метрик для визначення ефективності роботи тестувальників досить багато: вимоги до розроблюваного ПЗ; якість розроблюваного продукту; можливості й ефективність команди QA; якість роботи команди тестування; зворотний зв’язок та задоволеність користувачів.

З одного боку, зменшувати показники буде когнітивним спотворенням, але з іншого, наша схильність до оптимізації роботи через визначення слабких і сильних сторін розробника компенсує втрати продуктивності. Зазвичай такі метрики збирають раз на квартал. Середній термін роботи інженерав одній компанії — від 1 до 2 років. За такий термін з моніторингом раз на 3 місяці простежити динаміку змін досить складно. Будьмо оптимістами й візьмімо середній термін у 2,5 року. За цей час маємо 10 точок спостереження. Можна їх усі проаналізувати й побачити, коли упередження почали впливати на людину. Але так ми втратимо час. А от з правильним плануванням й аналізом упереджень, а також застосуванням кроків на усунення наслідків ефективність роботи не тільки не знизиться, а й зросте.

Поради

У більшості випадків усім схожим спотворенням можна запобігати так:

  1. Знати, що когнітивне спотворення є й закладати це як ризики, плануючи проект.
  2. Досконалості немає — усі роблять помилки, їх треба лише помітити.
  3. Треба вміти пріоритизувати — не всі помилки для тестувальника важливі, треба вміти вчасно зупинитись і подивитися на баг об’єктивно.
  4. У всіх є емоції, хтось сильно керований ними, хтось мало, але вони є у всіх, і наші думки від них залежать.
  5. Треба бути уважними — насамперед до себе.
  6. Не довіряйте собі — усі брешуть, і ви — також.
  7. Самі собі менеджер — подивіться на себе з боку. Якщо ви відчуваєте, що ваш ККД впав нижче за допустиму межу, змінюйте проект або усвідомте, що ви маєте бути більш бюрократичним, ніж раніше.
  8. Процедури — це корисно, хоча б для того, щоб бути завжди готовими до співбесіди.
  9. Автоматизуйте дурну роботу — не засмічуйте мозок.
  10. Фіксуйте під час кожного спринту якість тестування вимірювальними показниками: знайдено помилок з першого разу, з другого. Знайдено помилок після релізу. Оптимально налаштовуйте такі показники в системі керування проектами, щоб можна було завжди формувати звіти на основі зібраних даних.
  11. Створюйте додаткові точки перевірки роботи команди, наприклад раз на два місяці. Якщо кількість помилок, що їх виявив тестувальник, знижується на 10/20/30%, то варто перевірити дві гіпотези: або розробник працює ліпше, або тестувальник гірше. Як варіант, можна залучити тестувальника зі стороннього проекту: якщо він виявить більш як на 20% помилок, ніж «свій» тестувальник, саме час «струснути» команду.
  12. Постійно стежте за кількістю помилок, виявлених після релізу. Якщо їх кількість зростає, очевидно, знижується якість внутрішнього тестування.

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

Замість висновку

Пишучи цю статтю, я витратила багато часу й сил, але, перечитавши її, зрозуміла, що текст мене не влаштовує. І тут спрацювала упередженість. Я витратила купу часу, проаналізувала багато інформації, знайшла цікаві факти й напрямки, у яких можна розвивати статтю. Мені було дуже цікаво поділитися ними, показати масштабність і важливість цього питання. Але зупинившись і оцінивши написане, я вирішила викинути кілька абзаців, частину тексту переписати, у деяких напрямках зупинити пошуки — не тому, що це нецікаво, а тому, що в цій статті це непотрібно, не входить у контекст. І хоча ця написання статті захоплює мене, я розумію, що саме ця робота — найяскравіший приклад, як упередженість може негативно позначитися на роботі. Для мене когнітивне упередження — це реальність, з якою я зустрічаюся щодня.

Сборка домашнего 3D-принтера своими руками: рекомендации из личного опыта

$
0
0

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

Зачем нужен 3D-принтер? Сценарии использования

Впервые с идеей 3D-печати я столкнулся в далеких 90-х,когда смотрел сериал Star Trek. Помню, как меня впечатлил момент, когда герои культового сериала печатали необходимые им во время путешествия вещи прямо на борту своего звездолета. Печатали они все что угодно: от обуви до инструментов. Я думал, что было бы здорово когда-нибудь тоже иметь такую штуку. Тогда это все казалось чем-то невероятным. За окном — хмурые 90-е,а «нокиа» с монохромным экраном была вершиной прогресса, доступной лишь избранным.

Годы шли, все менялось. Примерно с 2010 в продаже начали появляться первые рабочие модели 3D-принтеров. Вчерашняя фантастика стала реальностью. Однако стоимость таких решений, мягко говоря, обескураживала. Но IT-индустрия не была бы собой без любознательного комьюнити, где происходит активный обмен знаниями и опытом и которому только дай покопаться в мозгах и потрохах новых железок и ПО. Так, чертежи и схемы принтеров стали все чаще всплывать в Сети. Сегодня самым содержательным и объемным ресурсом по теме сборки 3D-принтеров является RepRap — это огромная база знаний, которая содержит детальные гайды по созданию самых разных моделей этих машин.

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

Согласитесь, лучше разместить свое устройство на основе Raspberry Pi или Arduino в эстетически приятном «кузове», который не стыдно поставить в квартире или взять в офис, чем организовывать компоненты, например, в пластиковом судочке для еды. И да, можно печатать детали для сборки других принтеров :)

Сценариев применения 3D-принтеров огромное множество. Думаю, каждый сможет найти что-то свое.

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

Готовое решение vs своя сборка

Когда технология обкатана, ее стоимость на рынке заметно снижается. То же произошло и в мире 3D-принтеров. Если раньше готовое решение стоило просто заоблачных денег, то сегодня обзавестись такой машиной — дело более гуманное для кошелька, но тем не менее не самое доступное для энтузиаста. На рынке присутствует ряд уже собранных и готовых к домашнему использованию решений, их ценовой диапазон колеблется от $500-700 (не самые лучшие варианты) и до бесконечности (адекватные решения стартуют с ценника около $1000). Да, есть варианты и за $150, но на них мы, по понятным, надеюсь, причинам, останавливаться не будем.

Если коротко, рассматривать готовую сборку стоит в трех случаях:

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

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

Основной минус сборки — необходимость большого количества времени. На свою первую сборку я потратил около 150 часов.

Что нужно, чтобы собрать принтер самому

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

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

  • Экструдер — элемент, который непосредственно отвечает за печать, печатная головка. На рынке есть множество вариантов, но для бюджетной сборки я рекомендую модель MK8. Из минусов: не получится печатать пластиками, которые требуют высокой температуры, есть заметный перегрев во время интенсивной работы, который может вывести элемент из строя. Если бюджет позволяет, то можно посмотреть на MK10 — там все минусы учтены.
  • Процессорная плата.Хорошо подойдет знакомая многим Arduino Mega. Я не заметил минусов у этого решения, но можно потратить на пару долларов больше и приобрести что-то более мощное, с заделом на будущее.
  • Плата управления.Я использую RAMPS 1.4, которая прекрасно работает в связке с Arduino Mega. Более дорогая, но более надежная плата — Shield, которая уже совмещает в себе процессорную плату и плату управления. В современных реалиях рекомендую обратить внимание именно на нее. В довесок к ней нужно приобрести минимум 5 микрошаговых контроллеров шаговых двигателей, например — А4988. И лучше иметь пару таких в запасе для замены.
  • Стол с подогревом. Это часть, на которой будет находиться печатаемый элемент. Подогрев необходим из-за того, что большинство пластиков не будут держаться на холодной поверхности. Например, для печати PLA пластиком необходимая температура поверхности стола составляет 60-80°C, для ABS — 110-130°C, а для поликарбоната она будет еще выше
    В выборе стола тоже есть два варианта — подешевле и подороже. Дешевые варианты, по сути, представляют собой печатные платы с проложенной разогреваемой проводкой. Для эксплуатации на стол такого типа потребуется класть боросиликатное стекло, которое будет царапаться и трескаться в процессе эксплуатации. Поэтому лучшее решение — стол из алюминия.
  • Шаговые двигатели.Для большинства моделей, включая i2 и i3, используются двигатели типового размера NEMA 17: два для оси Z и по одному для осей X и Y. Готовые экструдеры обычно идут со своим шаговым двигателем в комплекте. Двигатели лучше брать мощные с током в обмотке двигателя от 1А и более, чтобы мощности хватило для подъема экструдера и печати без пропуска шагов на высокой скорости.
  • Базовый комплект пластиковых креплений.
  • Ремень и шестеренки для его привода.

Примеры внешнего вида элементов: 1) экструдер MK8; 2) процессорная плата Arduino; 3) плата управления RAMPS; 4) контроллеры двигателей; 5) алюминиевый стол с подогревом; 6) шаговый двигатель NEMA 17; 7) набор пластиковых креплений; 8) шестерни привода; 9) ремень привода

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

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

Трапециевидная шпилька м8 для оси Z, использование которой сэкономит вам кучу времени и нервов. Доступна для заказа на всех крупных онлайн-площадках

Также необходимо приобрести адаптированные пластиковые детали для оси X, например, этииз комплекта модификации MendelMax.

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

Что сколько стоит

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

ДетальКоличество, ед.Средяя стоимость, USD
Экструдер МК8117
Экструдер МК10145
Стол с подогревом111
Плата Arduino110
Плата RAMPS 1.4 с драйверами110
Двигатель NEMA 1747
END-стопы (концевики)31
Набор пластиковых креплений130
Приводной ремень G221
Шестеренки для валов двигателей21
Шпильки м8210
Шестеренки для валов двигателей21
Катушка пластика для печати112
Итого с МК8135
Итого с МК10163

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

Выбор платформы

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

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

Собственно, иллюстрация платформ: 1) платформа i2; 2) платформа i3

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

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

Лично я начинал свои опыты в сборке принтеров с платформы i2. О ней и пойдет речь дальше.

Этапы сборки, сложности и улучшения

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

Общая схема всех основных компонентов выглядит примерно так. Чего-то особо сложного здесь нет:

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

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

Собираем раму

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




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

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

Координатный станок

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





Из важного — вам потребуется приобрести (или же самостоятельно изготовить) каретку для передвижения экструдера и крепление для приводного ремня. Приводной ремень я рекомендую GT2.

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

Калибровка и настройка

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

Настраиваем станок

Я рекомендую проводить калибровку станка при помощи электронного штангенциркуля. Не поскупитесь на его приобретение — вы сэкономите много времени и нервов в процессе.

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

Константы для прошивки Marlin

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

Калибруем экструдер

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

Если подача недостаточная, то напечатанный тестовый предмет будет с заметными пробелами, как тестовый кубик 1. И наоборот, результат будет выглядеть раздутым при чрезмерной подаче пластика (кубик 2)

Приступаем к печати

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

Интерфейс Slicer

В качестве сырья для печати я рекомендую начать с обычного ABS-пластика — он довольно крепкий, изделия из него долговечны, а для работы с ним не требуется высоких температур. Для комфортной печати ABS-пластиком стол нужно разогреть до температуры 110-130°С, а сопло экструдера — в пределах 230-260°С.

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

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

Альтернативный вариант, который я использую вместо скотча — нанесение нескольких слоев обычного светлого пива с последующим нагревом стола до 80-100°С до полного высыхания поверхности и повторного нанесения 7-12 слоев.Наносить жидкость необходимо при помощи тряпочки, смоченной напитком. Из преимуществ такого решения: ABS-пластик самостоятельно отделяется от стола при остывании примерно до 50 °С и снимается без усилий, стол не придется отдраивать, а одной бутылки пива вам хватит на несколько месяцев (если использовать напиток только в технических целях :)).

После того как мы все собрали и настроили, можно приступать к печати. Если у вас есть ЖК-экран, то файл можно передать на печать при помощи обычной SD-карты.

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

Рекомендации, которые смогут упростить жизнь (а иногда — сэкономить деньги)

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

  • Не экспериментируйте с форсунками.Если вы планируете сразу печатать из материалов, которые требуют высоких температур, то лучше сразу возьмите экструдер МК10. На МК8 можно «навесить» специальные форсунки, поддерживающие высокотемпературные режимы. Но такие модификации часто вызывают сложности и требуют особого опыта. Лучше избежать этой возни еще «на берегу», просто поставив подходящий для вас экструдер.
  • Добавьте реле стартера для стола с подогревом.Усовершенствование системы питания этой важной для печати детали при помощи реле стартера поможет решить известную проблему RAMP 1.4 — перегрев транзисторов, управляющих питанием стола, который может привести к выходу платы из строя. Я сделал такой апгрейд после того, как пришлось выбросить несколько RAMPS 1.4.
  • Выберите правильный диаметр пластика для печати.Рекомендую брать пластик диаметром 1,75 мм для MK8 и MK10. Если взять пластик, например, в 3 мм, то экструдеру просто не хватит сил, чтобы проталкивать его с приемлемой скоростью — печататься все будет значительно дольше, а качество упадет. Для MK8 идеально подходит ABS-пластик, MK10 сможет производить изделия из поликарбоната.
  • Используйте только новые и точные направляющие по осям X и Y. Это влияет на качество печати. Сложно рассчитывать на хорошее качество при гнутых или деформированных направляющих по осям.
  • Позаботьтесь об охлаждении.В ходе моих экспериментов с различными экструдерами лучшие результаты показал МК10 — он печатает довольно точно и быстро. Также МК10 может печатать пластики, требующие более высокой температуры печати, чем ABS, например поликарбонат. Хоть он и не так сильно подвержен перегреву, как его младший брат МК8, все же я рекомендую позаботиться о его охлаждении, добавив в вашу конструкцию кулер. Он должен быть постоянно включен, эту опцию можно настроить в Slicer. Также можно добавить кулеры для поддержания приемлемой температуры шаговых моторов, однако следите, чтобы их потоки воздуха не попадали на печатаемую деталь, так как это может привести к ее деформации из-за слишком быстрого охлаждения.
  • Предусмотрите сохранение тепла.Да, с одной стороны, мы боремся с перегревом элементов. С другой — равномерная температура вокруг принтера будет способствовать качественной печати (пластик будет более податливым). Для достижения равномерной температуры можно поставить наш принтер, например, в картонную коробку. Главное — перед этим подключить и настроить кулеры, о чем написано выше.
  • Подумайте о термоизоляции стола.Стол с подогревом нагревается до больших температур. И если часть этого тепла уходит с толком, подогревая печатаемую деталь, то вторая часть (снизу) — просто уходит вниз. Чтобы сконцентрировать тепло от стола на детали, можно провести операцию по его термоизоляции. Для этого я просто креплю к его нижней части пробковый коврик для мыши при помощи канцелярских зажимов.

Выводы

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

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

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

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

Буду рад ответить на комментарии, замечания и вопросы.

Что почитать/посмотреть

5 ошибок при внедрении OKR

$
0
0

Меня зовут Константин Коптелов, и я Business Development and Strategy Manager в Eazzy. Уже лет пять в меру своих сил я помогаю компаниям налаживать процессы и коммуникации, чтобы они могли пережить масштабирование. Более трех лет внедряю OKR, провожу по нему лекции, стратегические сессии. Сегодня хотел бы сделать краткий экскурс для вас о том, что же такое OKR и какие есть ошибки при его внедрении. Если статья окажется полезной, буду рад поделиться с вами накопленным опытом в этой теме. Поехали!

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

Понимание рождает практику. Компании ищут фреймворк для того, чтобы измерять и управлять. И находят два подхода: традиционный KPI и более гибкий OKR.

Сейчас стало модно выбирать второй, но обычно у бизнеса нет времени разбираться в отличиях. В итоге внедряется Scrum, в котором есть жесткие сроки и диаграмма Ганта. То есть мы просто берем и в коробку от iPhone кладем Nokia 1100. Инструмент хороший, проверенный, но время требует несколько других решений, технологий и подходов.

Что такое OKR

Objective and Key Results — гибкий способ управления компанией по целям. Если попытаться кратко описать разницу между KPI и OKR, то она аналогична отличию классического управления проектами (Waterfall) от гибкого.

Источник

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

Типичный OKR состоит из двух частей:

  1. Цель (objective), которая эмоциональна, мотивирует, вдохновляет и дает драйв.
  2. Координаты (key results), с помощью которых мы отслеживаем дорогу к цели. Успеваем? Нужно поднажать или все же стоит менять цель? Туда ли мы идем или запутались в изменениях и творческих порывах и пошли вообще в другом направлении?

Принципы OKR

Важен не только формат, но и принципы, которые закладываются в OKR:

  1. Публичность и доступность — все могут видеть цели и координаты всех.
  2. Амбициозность — некоторые, но не все из целей в 5–10раз больше обычной планки, чтобы стимулировать сотрудников искать новые подходы и нестандартные решения.
  3. Не привязаны напрямую к системе оценки и оплаты труда, чтобы сотрудники не боялись ставить себе достаточно амбициозные цели и при этом не появлялось лишнее желание «поиграть в цифры», «взломать систему».
  4. Регулярность сверки — синхронизация по OKR должна происходить не реже чем раз в две недели. Иначе система не сможет вовремя подсказать, что нам нужно корректировать курс.
  5. Как можно меньше целей и метрик, чтобы мы могли сфокусироваться, как лазер, и сделать прорыв, вместо того чтобы просто «понадкусывать» несколько направлений.
  6. 30/70 или 60/40. OKR не спускаются полностью сверху вниз, как это часто происходит с KPI. На 30–40процентов цели и координаты даются руководством, на 60–70 ихсоздают сотрудники. Получается процесс совместного творчества, способствующий тому, что подходы, стратегия и тактика будут больше соответствовать реальному положению дел.
  7. Квартальность. Цели и координаты ставятся на квартал четко, а на год ориентировочно, размыто и карандашом. Это дает сочетание гибкости за счет способности быстро реагировать на изменения рынка и четкости за счет планирования хоть все же и на небольшой промежуток времени.
  8. Показатели — это координаты. Иногда компании используют показатели как ориентир или способ стимулирования. В OKR мы их используем как координаты в GPS-трекере. Они помогают нам придерживаться пути, регулировать скорость, вовремя менять тактику. И что очень важно в любом бизнесе, сообщают окружающим о том, где мы и куда идем. Это важно для того, чтобы вся компания работала как слаженный, но гибкий и адаптирующийся организм.

Источник

Где начинаются сложности

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

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

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

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

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

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

Ошибка 1. С ходу набросать себе 5 целей и по 5 метрик в каждой

Такая история часто возникает в компаниях, в которых до этого почти не было никакого планирования. Прочли книжку «OKR для начинающих»Джона Доэра. Поняли, что должно быть не больше 5 целей и не больше 5 метрик для каждой цели. «Нет времени объяснять, начальство сказало ставить цели, вперед!» А задач-то и целей много, столько всего не сделано! И сколько еще предстоит не сделать!

Иногда действительно команда останавливается на отметке в 5 целей по 5 метрик. Я сталкивался со случаями, где 5 целей и 7 метрик в каждой. Максимальное число, которое попадалось за три года консалтинга в этой теме, 12 целей и метрики в каждой из них.

Это слишком много. По опыту скажу, что на уровне компании максимум 3 цели, на уровне департамента — 2, на уровне отдела — 1. А в идеале еще меньше. На уровне компании 1 цель — вообще превосходно. Почему? Сила фокуса.

Ко мне однажды пришла компания, в которой у каждого топа было по 3 цели и по 4-5метрик у каждой. Моя рекомендация заключалась в том, чтобы оставить по одной. Команда ТОПов приняла решения взять на себя повышенные обязательства и оставить как есть. Они молодцы, что делали регулярную сверку. В итоге через полтора месяца количество целей на ТОПа сократилось до двух, а еще через три недели до одной. К сожалению, эта одна, в большинстве случаев, не была достигнута тоже.

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

Помните про силу фокуса!

Ошибка 2. Взять просто KPI и сделать более амбициозные

Ошибка в том, чтобы просто взять KPI, которые были, увеличить их в 5 раз, добавить сверху вдохновляющий заголовок и сказать: «Ребята, у нас OKR!» Но так это не работает! Люди не чувствуют связи с цифрами или просто красивыми названиями.

Это часто приводит к другой распространенной ошибке. Сотрудники, один раз услышав, что можно амбициозные цели выполнять на 60–70%,у себя в душе получают индульгенцию на то, чтобы не доделывать, не дожимать. И потом, когда у них спрашивают: «Ну как, эта цель сделана?», — они говорят: — «Ну, на 60% сделали». И дальше идут.

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

У меня был клиент, который гордился тем, что у него в компании OKR. Он попросил меня проконсультировать по одному из багов, который обнаружил: все цели достигаются максимум на 50-55%.Я пообщался с сотрудниками и в их речи услышал, «так это цель на 60%». Сотрудникам не точно донесли зачем нужны амбициозные цели. У них выработалась такая логика: любую цель можно выполнить на 60% и это ОК. А поскольку человек, который метит в 60%, часто не добегает до финиша, то и в среднем цели выполнялись наполовину. Это очень сильно подрывало веру в этот подход. Очень быстро сотрудники решили, что OKR — это просто очередной «бзик» руководства. «Ну, хочет он цели и цифры, нарисуем, нам не сложно». Потребовался полный перезапуск OKR в этой компании.

Ошибка 3. Не измерять движение по мере

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

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

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

Установите конкретный день недели и делайте в этот день сверки еженедельно без исключений.

Ошибка 4. Использовать показатели, которые непонятно, как считать

Мне однажды прислали на ревью «Увеличить NPS (Net Promoter Score) в 3 раза». Амбициозно. Я смотрю и понимаю: «Классно, вдохновляет. А сейчас какой показатель?» Мне отвечают: «Не знаем».

Как же вы тогда по такой метрике будете отслеживать продвижение к цели?

В случае NPS это не заново что-то пересчитывать, это надо прямо инструмент внедрить. То есть создать возможность голосовать, вставить ее в сайт, внедрить в письма и т. д. То есть у вас из трех месяцев квартала, которые вы выделили на повышение NPS, в лучшем случае 1–2месяца уйдет на внедрение самого NPS. И когда вы будете раз в две недели делать срез, у вас будут спрашивать: «Что по этому OKR?» Все, что вы сможете ответить: «Да нет, еще и нечего считать». Это будут цифры ради цифр, неживой KR. Поэтому лучше поставить KR «внедрить систему NPS», где в скобках указать: это проект, в котором 54 задачи. И отслеживать прогресс по этой метрике на основании сгорания этих 54 задач.

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

Ошибка 5. Излишняя амбициозность и торги по целям и метрикам

Есть цели амбициозные и недостижимые, а есть нереальные. Недостижимые — это когда ты знаешь, что надо сделать что-то out of box, только приблизительно понимая, как этого достичь. Под недостижимостью мы понимаем недостижимость в конкретный промежуток времени. За квартал недостижимы, но за год, в принципе, мы могли бы.

А есть нереальные, которые вообще никак не достичь в этой компании. «Увеличить конверсию посадочной страницы до 100%». «Увеличить NPS до 100%». Нереальные цели не надо ставить. Лучше себе ставить спокойные операционные цели, амбициозные, но достижимые земными людьми, например: «Увеличить до 60%». Потому что люди смотрят на нереальные цели и серьезно их не воспринимают. Они видят: «Сделать конверсию посадочной страницы до 100%» — и думают: — «Я займусь пока другими, так как это явно неконкретная цель, непонятно, что с ней делать. Как ни трудись, достичь ее невозможно». Стоит такого избегать.

Вместо итогов

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

Убедитесь, что все ваши цели соответствуют критериям:

  • установлены на квартал;
  • KR-измеримы (как минимум, «выполнено/не выполнено»; подходит, но такого варианта лучше избегать);
  • цель — лишь заголовок ЧЕГО мы хотим достичь;
  • цель помогает достичь целей более высокого уровня или в нее могут сделать вклад другие команды;
  • у вас не более 3-5 целей,а в идеале — всего одна;

Убедитесь, что все ваши ключевые результаты соответствуют критериям:

  • 70% и более целей установлено «снизу вверх»;
  • цели четко и однозначно измеримы;
  • прогресс проверяется минимум раз в две недели (в идеале — раз в неделю);
  • цели разделены на операционные и амбициозные;

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

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

5 книжок про роботу мозку від Олексія Молчановського, керівника магістратури з Data Science в УКУ

$
0
0

Від редакції: у рубриці DOU Booksспеціалісти розповідають про 5 своїх улюблених книжок — ті, які змінюють світогляд та корисні читачам-колегам.

[Про автора: Олексій Молчановський — керівник магістерської програми Data Science Українського Католицького Університету, співзасновник Prometheus]

The Tipping Point: How Little Things Can Make a Big Difference by Malcolm Gladwell

Українською — Малколм Гладуелл «Поворотний момент: як дрібні зміни спричиняють великі зрушення»

За рівнем вражень та захоплення ставлю книгу в один ряд з працею Канемана «Мислення швидке і повільне». Книга про те, які закони керують поширенням соціальних явищ (епідемій). Вона так добре мені «лягла», бо, напевно, останнім часом я сильно захопився мережевим підходом: я бачу мережі майже скрізь :) Хоча в самій книжці автор слово «мережі» використовує, мабуть, менше п’яти разів. Але мова йде про ті самі процеси, які описуються в Network Science.

У моїй бібліотеці є кілька інших книжок, які різними словами говорять про одне й те саме: як події, думки, ідеї захоплюють нас, людей; і про те, яким чином це можна не тільки спостерігати та аналізувати, але й намагатися самим провокувати. Ось ці книжки:

The Book of Why by Judea Pearl and Dana MacKenzie

Усі, хто вивчали колись статистику та теорію ймовірностей, мають пам’ятати золоте правило: «Correlation is not causation». Статистика від самого свого зародження уникає розмов про причини та наслідки. Натомість звертається лише до асоціативності або одномоментності певних подій. З іншого боку, для нашого мозку природними є постійні спроби виводити закономірності — знаходити причини та наслідки подій і явищ. Але як це описати математично (і чи взагалі можливо)?

Judea Pearl є засновником одного з методів штучного інтелекту — баєсових мереж (які, в свою чергу, ґрунтуються на одному з основних правил теорії ймовірностей — правилі Баєса). Ці дослідження завели його далі і він запропонував інструмент — каузальні діаграми, які дозволяють математично поєднати статистику та причинно-наслідкові зв’язки. Зрештою, в деяких колах прийнято говорити про «каузальну революцію», яка відбувається останні двадцять років: повернення уваги фахівців зі статистики, математики та комп’ютерних наук до каузальності.

На самому початку автор описує свою «філософію»: рівні причинності (the ladder of causation). Їх три і вони досить добре пов’язуються з питаннями: «що? як? чому?» Статистичний апарат (та поточний стан моделей ШІ) знаходиться на першому рівні та відповідає на питання «що?», описуючи явища та намагаючись побудувати їх екстраполяцію, але не пояснюючи, як щось сталося та чому воно стається. Це перевага людей, яку ми здобуваємо з малого віку. Метод каузальних діаграм дозволяє прорвати це зачароване коло та вийти на рівні «як?» та «чому?».

Ця трійка рівнів мені нагада іншу книжку — Start With Why by Simon Sinek, в якій зовсім з іншого боку також описується ієрархія цих трьох питань. І «чому?» є найважливішим з них.

On Intelligence by Jeff Hawkins

Російською — Джефф Хокинс «Об интеллекте»

Цікавий шлях автора книги. Jeff Hawkins — засновник компанії Palm Computing, яка випускала одні з перших кишенькових комп’ютерів та комунікаторів. Маючи давнє захоплення нейронауками, Джеф, вже будучи успішним бізнесменом, заснував центр з нейронаук Redwood Neuroscience Institute, який з 2005 року став частиною Університету Берклі, Каліфорнія.

Дослідження в цьому центрі Джеф спрямував на розгадування загадки мозку і побудови його моделі. Щоб у фінальному результаті можна було створити «справжній штучний інтелект» (те, що прийнято називати Artificial general intelligence).

Фахівці з сучасних методів ШІ не сприймають Джефа та його підходи з особливим захопленням. Основна критика стосується того, що моделі, які він пропонує, не здатні відтворити ті результати, які зараз з успіхом демонструють підходи на основі Deep Learning (штучних глибоких нейронних мереж).

Але мені ця книжка сподобалася доступністю викладу матеріалу. Я виніс з неї одну просту ідею, яку тепер постійно використовую: наш мозок спроектований таким чином, щоби виявляти, запам’ятовувати та конструювати послідовності. Послідовності чого завгодно: чисел, звуків, зображень тощо. Мозок (і, відповідно, ми самі) спроектовані Богом або матінкою Природою (кому як краще) так, щоби скрізь бачити послідовності. І коли ти це усвідомлюєш, то по-іншому починаєш дивитися на речі та, особливо, на поведінку людей. Наше прагнення (часто — несвідоме) всьому дати пояснення, описати у вигляді причинно-наслідкових зв’язків — це абсолютно з тієї самої «опери» (бо причини і наслідки — це ще один вид послідовностей). Вишукувати шаблони — улюблена справа нашого мозку, те, що йому вдається найкраще (ось чому, зокрема, «теорії змови» мають таку популярність, або чому ви бачите закономірності у випадкових кодах підтвердження від Приват24).

Я не знаю, чи коли-небудь погляди Джефа будуть реалізовані у вигляді моделей для ефективного ШІ (знаю, що деякі інвестори готові за це давати живі гроші), але його книжка дала мені достатньо важливий ключ для розуміння нашого світу і нас в ньому.

Why We Sleep: The New Science of Sleep and Dreams by Matthew Walker

Російською — Мэттью Уолкер «Зачем мы спим. Новая наука о сне и сновидениях»

Автор книги заснував і очолює Центр дослідження сну в Університеті Берклі, Каліфорнія.

Я давно захоплююся всім, що пов’язано зі сном. Колись на одному випробуванні, коли я ще був у 10-мукласі школи, мене запитали, що мені більше подобається: сон чи їжа. Тоді я відповів, що сон — і мотивацією були сни: бачити їх, мандрувати ними. Пізніше я познайомився з глибинною психологією Юнга і почав більш прискіпливо ставитися до своїх снів — намагатися через них почути і зрозуміти своє глибинне «Я». Тож сон для мене завжди був важливим.

Крім того, колись я багато експериментував зі сном. Був період, коли я спав по чотири години на день протягом двох тижнів чи більше — за методикою «Леонардо» (тепер я підозрюю, що да Вінчі навряд чи таким займався).

Так ось, ця книга вчить вас цінувати сон. У сучасному суспільстві прийнято зневажати сон і навіть змагатися, хто менше буде спати. Якщо людина спить 5-6 годин,то це ознака її працездатності. Сон навіть може асоціюватися з лінощами. Людство дивиться на сон, в більшості своїй, як на атавізм. Але це неправильно.

Протягом останніх двадцяти років було проведено багато досліджень, які демонструють позитивний вплив здорового сну (8-9 годин)та негативний вплив обмеженого сну (5-6 годин)на:

  • фізичне здоров’я: збільшення ризику серцево-судинних захворювань, збільшення ризику виникнення раку (деякі країни — у книжці згадується Данія — внесли професії, які включають нічні зміни, до таких, що можуть призводити до раку), зменшення репродуктивних функцій, навіть зміни на рівні ДНК;
  • ментальне здоров’я: здоровий сон критичний для того, щоби ми добре запам’ятовували та опрацьовували нову інформацію; так само фаза REM-сну (найбільша частка якої припадає на кінець 8-годинногоперіоду сну) є ключовою для креативності;
  • психічне здоров’я.

Важливі факти з досліджень, які наводяться в книжці, можна продовжувати довго. Але наведу ще один. Алкоголь руйнує якість сну. Фактично після вжитого алкоголю ми не занурюємося в глибоку фазу сну достатньо глибоко, а в цій фазі відбувається перенесення нової інформації з короткотермінової пам’яті до довготермінової. Що цікаво, цей ефект може впливати на інформацію, яка була отримана кілька днів тому, а не тільки напередодні. Тож це ще одне пояснення, чому студенти, які здали сесію, забувають багато вивченого матеріалу («здав — забув»), адже бурхливе святкування сесії з великою кількістю алкоголю якраз так і діє на наші мізки.

P. S. Нещодавно з’явився виступ Меттью на TED, де він також розповідає про важливість сну. Можна переглянути перед тим, як братися за книжку.

Сергій Плохій «Брама Європи»

Ця книжка про українську історію. Мені вона ніколи не давалася під час навчання в школі, тому, можливо, зараз я компенсую ті прогалини та втрати. Не скажу, що я читаю багато книжок з історії, але часом трапляється. «Брама Європи» Сергія Плохія, який очолює Український науковий інститут в Гарварді стала для мене хітом (я її «з’їв» за два-три дні). Після того захоплення дружина подарувала мені іншу його книжку — «Козацький міф: Історія та націєтворення в епоху імперій», над якою автор працював багато років.

Це було абсолютне відкриття для мене. Я взагалі вперше почув про такий твір, як «Історія Русів» — артефакт, про історію якого розповідає «Козацький міф». Але основне — мене вразила абсолютно детективна (і до кінця так і не відкрита) історія його творення.

Напевно, найбільше мене захоплюють нетривіальні причинно-наслідкові зв’язки. Коли ти дізнаєшся, що те, що є для тебе звичним, типовим, є наслідком якоїсь абсолютно дивної історії. «Історія Русів» — якраз про те. Твір, створений нащадками козацької старшини у Північно-Східній Україні (Північ Чернігівщини), який вони видали за давній літопис, створений Могилевським єпископом, з метою переконати імператорське правління Росії, що вони мають давні права і їхній родовід тягнеться від київських князів. Містифікацію достатньо швидко (за тим часом) розгадали, але цього вистачило, щоби нею захопилися «молоді українські націоналісти», серед яких був Тарас Шевченко. І під цим впливом він почав писати відомі поеми на козацьку тематику.

Сьогодні українську націю без цих козацьких (та інших історичних) поем Кобзаря, як і без архетипів козаків, неможливо уявити. Але той факт, що Шевченко не написав би (або написав, але не так промовисто) ті твори, які потім вплинули на всю націю і якими надихалися так багато наших провідників, без історичної підробки, яку вигадали кілька людей на початку ХІХ сторіччя на території, яка вже навіть не належить Україні, — це просто mind blowing для мене.

Тож якщо ви цінуєте захопливу історичну літературу та/або закручені історії, дуже раджу.

Пишемо свої Gradle плагіни для автоматизації тестування

$
0
0

Я займаю позицію Lead Software Engineer in Test в EPAM. У цій статті розглянемо, як писати свої Gradle плагіни і які проблеми цим інструментом можна вирішити. У галузі автоматизації тестування, як, напевно, і в розробці загалом, часто зустрічаються рутинні задачі, які спочатку виконуються вручну, а потім люди втомлюються і якось їх автоматизують. Для цього зазвичай у хід ідуть скриптові мови програмування, які є в арсеналі у виконавця: Python, Bash, Excel VBA — кого вже як життя покидало.

Переважно ці рішення є ефективними, але але якщо у вас тести написані на Java і проект збирається за допомогою Gradle, то для деяких таких задач варто розглянути варіант написання свого Gradle плагіна, а саме для тих, які логічно було би прив’язати до компіляції проекту. У цій статті я наведу приклади такого рішення, які застосовую у власній практиці.

Наведені приклади також можна застосувати і до збірок Maven — там теж є плагіни, тільки Maven плагіни мають бути обов’язково окремими проектами, тоді як у Gradle є можливість їх реалізувати прямо в проекті з тестами, помістивши до магічної директорії buildSrc. Це, щоправда, має сенс, якщо плагіни тісно пов’язані з даним Gradle проектом і не будуть використовуватись в інших. Так ми уникаємо проблем із версіонністю і потребою в додаткових збірках на CI.

Контекст

Отже, уявімо, що ми маємо System Under Test у вигляді простого веб-застосунку за назвою Reminders. Там можна додавати, редагувати і видаляти нагадування. Кожне нагадування має три атрибути: текст, час і прапорець, чи виконано. Також ми маємо і UI тести, написані на Java з використанням TestNG і Selenide.

Код тестів і самого застосунку у фінальному вигляді можна подивитися тут.

Тепер розглянемо два Gradle плагіни, які могли би бути корисні для тестів.

Test Format Check Plugin

Такий вигляд у нас має тест зі створення нагадування:

@Test(description = "Create reminder",
        dataProvider = "createReminderData",
        groups = {Groups.SMOKE, Teams.ALPHA, Sprints._1})
@TestCase("REM-132")
public void createReminder(Reminder reminder) {
    NavigationSteps.openRemindersApp();
    ReminderSteps.addReminder(reminder);
    ReminderSteps.checkLastReminder(reminder);
}

Абстрагуймося від деталей реалізації і звернімо увагу на мета-дані тесту — список груп (зокрема, приналежність до команди і спринта), а також анотацію @TestCase, яка містить ідентифікатор задачі в якійсь трекінг-системі, наприклад JIRA. Схожий список атрибутів має переважна більшість фреймворків у тому чи іншому вигляді, і що більший проект (а точніше, що більше автоматизаторів одночасно працюють над ним), то гостріше стоїть потреба у перевірці наявності цих атрибутів і відповідності певному формату. Це нам дасть упевненість у завтрашньому днівибірках за цими атрибутами як зараз, так і через кілька років, коли ми вже фізично не зможемо руками перевірити всі тести.

Таку перевірку можна робити вручну на code review, можна написати окремий скрипт, а можна включити просто до процесу збірки проекту, наприклад, наступним етапом після компіляції. Тоді кожен автоматизатор отримає найшвидший зворотний зв’язок про стан мета-даних своїх тестів, просто зібравши проект локально після своїх змін. Для цього нам і знадобиться Gradle плагін.

Спочатку робимо в корені проекту директорію buildSrc, в якій створюємо Gradle модуль, тобто свій build.gradle (build.gradle.kts) файл і директорію src, куди покладемо сам код плагіна. В нашому випадку це один клас, написаний на Kotlin. Власне, тут ви якраз можете потренуватись в будь-якій мові, яка компілюється в JVM bytecode, що я і зробив.

Директорія buildSrc у проекті:

Файл build.gradle.kts має такий вигляд:

plugins {
    kotlin("jvm") version "1.3.50"
    `java-gradle-plugin`
}

gradlePlugin {
    plugins {
        create("testFormatCheck") {
            id = "reminder-test-format-checker"
            implementationClass = "com.example.plugins.TestFormatCheckPlugin"
        }
    }
}

repositories {
    jcenter()
}

dependencies {
    compile("com.github.javaparser:javaparser-core:3.14.7")
}

Єдиною бібліотекою, потрібною для нашого плагіна, є javaparser. Вона вміє парсити Java код в абстрактне дерево, а також генерувати його, але ця функціональність у нашому випадку не потрібна. В блоці gradlePlugin ми даємо плагіну унікальний id і вказуємо клас імплементації, який має реалізувати інтерфейс org.gradle.api.Plugin.

І ось так виглядатиме наш клас TestFormatCheckPlugin:

package com.example.plugins

import com.github.javaparser.ast.body.MethodDeclaration
import com.github.javaparser.ast.expr.AnnotationExpr
import com.github.javaparser.ast.expr.MemberValuePair
import com.github.javaparser.ast.expr.NormalAnnotationExpr
import com.github.javaparser.ast.expr.SingleMemberAnnotationExpr
import com.github.javaparser.utils.SourceRoot
import org.gradle.api.Plugin
import org.gradle.api.Project
import java.io.File

class TestFormatCheckPlugin : Plugin<Project> {
    override fun apply(project: Project) {
        project.task("checkTestFormat") { task ->
            task.doLast {
                val errors = arrayListOf<String>()
                val packagePath = File("${project.projectDir}/src/test/java/com/example/tests").toPath()
                SourceRoot(packagePath)
                        .tryToParse("")
                        .filter { it.isSuccessful }
                        .map { it.result.get() }
                        .forEach { compilationUnit ->
                            compilationUnit.findAll(MethodDeclaration::class.java).forEach { method ->
                                if (method.isTest()) {
                                    errors.addAll(findErrorsWithTestCase(method))
                                    errors.addAll(findErrorsWithMandatoryTestProperties(method))
                                }
                            }
                        }
                if (errors.isEmpty()) {
                    println("Checking tests format passed")
                } else {
                    println("===================================================")
                    println("Errors in tests format:")
                    errors.forEach { println("> $it") }
                    println("===================================================")
                    throw RuntimeException("Checking tests format failed. See errors in log.")
                }
            }
        }
    }

private fun MethodDeclaration.isTest(): Boolean =
            this.findFirst(AnnotationExpr::class.java) { it.nameAsString == "Test" }.isPresent

    /**
     * TestCase annotation should be present and match certain format
     */
    private fun findErrorsWithTestCase(method: MethodDeclaration): List<String> {
        val result = arrayListOf<String>()
        val testCase = method.findFirst(SingleMemberAnnotationExpr::class.java) { it.nameAsString == "TestCase" }
        if (testCase.isPresent) {
            val testCaseValue = testCase.get().memberValue.asStringLiteralExpr().value
            if (!testCaseValue.matches(Regex("REM-\\d+"))) {
                result.add("@TestCase annotation does not match format 'REM-1234' for test " +
                        "${method.nameAsString}. Actual value: '$testCaseValue'")
            }
        } else {
            result.add("No @TestCase annotation found for test ${method.nameAsString}")
        }
        return result
    }

    /**
     * Mandatory attributes are description, team and sprint
     */
    private fun findErrorsWithMandatoryTestProperties(method: MethodDeclaration): List<String> {
        val result = arrayListOf<String>()
        val test = method.findFirst(NormalAnnotationExpr::class.java) { it.nameAsString == "Test" }.get()
        if (!test.findFirst(MemberValuePair::class.java) { it.nameAsString == "description" }.isPresent) {
            result.add("Description not found in @Test for method ${method.nameAsString}")
        }
        val groups = test.findFirst(MemberValuePair::class.java) { it.nameAsString == "groups" }
        if (groups.isPresent) {
            if (!groups.get().value.toString().contains("Teams.")) {
                result.add("No Team found for test method ${method.nameAsString}")
            }
            if (!groups.get().value.toString().contains("Sprints.")) {
                result.add("No Sprint found for test method ${method.nameAsString}")
            }
        } else {
            result.add("Groups not found in @Test for method ${method.nameAsString}")
        }
        return result
    }
}

Розглянемо, що тут взагалі відбувається. Реалізовуючи інтерфейс Plugin, ми маємо реалізувати метод apply(Project), де можемо розширити логіку проекту, як нам заманеться. А саме, ми створюємо task під назвою «checkTestFormat» і пишемо його конфігурацію. Зокрема, нам потрібно просто виконати якийсь блок коду, для цього використовуємо властивість doLast {...} і описуємо в ній ту логіку, яка має відпрацювати, коли буде викликана задача checkTestFormat.

Логіка ж задачі така: використовуючи javaparser,ми перебираємо всі Java файли з тестами, фільтруємо методи за анотацією @Test, потім збираємо список невідповідностей атрибутів (наприклад, наявність команди в групах тесту), і якщо список помилок не порожній, то виводимо його в консоль і валимо збірку викиданням RuntimeException.

Залишилося кілька штрихів. Застосовуємо плагін у нашому проекті: для цього в нашому основному build.gradle.kts файлі в блоці plugins додаємо id нашого плагіна:

plugins {
   java
   `reminder-test-format-checker`
}

Тепер ми можемо його викликати напряму в командному рядку:

$ gradlew checkTestFormat

Але так нецікаво. Краще додати його в обов’язковому порядку після компіляції. Тоді при запуску тестів навіть локально ця перевірка не дасть пропустити жоден обов’язковий атрибут тесту. Для цього додаємо таке в основний build.gradle.kts файл:

tasks.compileTestJava {
   finalizedBy("checkTestFormat")
}

Тепер в консолі будемо бачити таке повідомлення, якщо з атрибутами наших тестів все гаразд:

> Task :checkTestFormat
Checking tests format passed

BUILD SUCCESSFUL in 2s

І наприклад таке, якщо щось пішло не так:

> Task :checkTestFormat FAILED
===================================================
Errors in tests format:
> No Team found for test method createReminder
> No @TestCase annotation found for test updateReminder
> No Sprint found for test method updateReminder
> @TestCase annotation does not match format ’REM-1234′ for test deleteReminder. Actual value: ’REM-’
===================================================

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ’:checkTestFormat’.
> Checking tests format failed. See errors in log.

* Try:
Run with —stacktrace option to get the stack trace. Run with —info or —debug option to get more log output. Run with —scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 2s

Звичайно, подібний плагін також можна застосувати і до тестів у форматі BDD. Там навіть жодної бібліотеки не треба підключати: можна просто читати текстові файли з тестами і перевіряти відповідні атрибути за допомогою RegEx або іншим способом.

Swagger Codegen Plugin

У нас UI тести, але добре було б мати можливість викликати API напряму, щоб, наприклад, приготувати певні передумови для тесту, або і взагалі писати API тести. Отож, ми вирішуємо, що нам це потрібно, але як це правильно зробити? Напевно, перше, що спадає на думку, — підключити Rest-Assured, і вперед. На щастя, людство винайшло Swagger, тож якщо девелопери зробили вам таке щастя і підключили його, то ви будь-якої миті можете подивитись API специфікацію у читабельному вигляді і, відповідно, написати тести на потрібні вам точки доступу.

Але виявляється, що існує ще більш просунутий варіант. Людство не зупинилось на досягнутому і винайшло також Swagger Codegen — інструмент, який дозволяє згенерувати код API клієнта (точки доступу і сутності) на основі API специфікації, яку генерує Swagger. Він підтримує різні мови і бібліотеки для API клієнтів, але нас, зокрема, цікавлять Java і Rest-Assured. Існує command-line інструмент, але оскільки він написаний на Java, то нам зручніше викликати його програмно, підключивши як бібліотеку. Аби зрозуміти, де найкраще викликати цю генерацію, поміркуймо, які саме переваги вона нам дає. Крім того, що цей код не треба писати самому, Swagger Codegen дає можливість постійно перегенеровувати API клієнт, тож якщо ми будемо це робити щоразу безпосередньо перед компіляцією проекту, і в нас змінились сутності або точки доступу, які ми смикаємо в тестах, то компіляція впаде, і ми одразу будемо змушені виправити невідповідність. Знову ж таки, отримуємо швидший фідбек, і нам не треба дізнаватись про зміни в API, розбираючи тести, що впали — вони навіть не запустяться.

Отже, дописуємо ще один плагін. Для цього у файлі buildSrc/build.gradle.kts додаємо інформацію про нього і його залежності:

gradlePlugin {
    plugins {
        ...
        create("codegen") {
            id = "reminder-codegen"
            implementationClass = "com.example.plugins.SwaggerCodeGenPlugin"
        }
    }
}

dependencies {
    ...
    compile("io.swagger:swagger-codegen:2.4.7")
}

Тепер пишемо клас реалізації:

package com.example.plugins

import io.swagger.codegen.DefaultGenerator
import io.swagger.codegen.config.CodegenConfigurator
import org.gradle.api.Plugin
import org.gradle.api.Project
import java.io.File

const val SWAGGER_JSON_URL = "http://localhost:8080/v2/api-docs"
const val INVOKER_PACKAGE = "com.example.services.api.client"
const val API_PACKAGE = "com.example.services.api.controllers"
const val MODEL_PACKAGE = "com.example.entities.generated"

class SwaggerCodeGenPlugin : Plugin<Project> {
    override fun apply(project: Project) {
        project.task("generateApi") { task ->
            task.doLast {
                // Clean up temp dir and existing API client packages
                File("${project.projectDir}/temp").deleteRecursively()
                deletePackageDirectories("${project.projectDir}",
                        listOf(INVOKER_PACKAGE, API_PACKAGE, MODEL_PACKAGE))

                // Configure and run code generation
                val config = CodegenConfigurator()
                config.inputSpec = SWAGGER_JSON_URL
                config.outputDir = "${project.projectDir}/temp"
                config.lang = "java"
                config.library = "rest-assured"
                config.additionalProperties = mapOf(
                        "invokerPackage" to INVOKER_PACKAGE,
                        "apiPackage" to API_PACKAGE,
                        "modelPackage" to MODEL_PACKAGE,
                        "dateLibrary" to "java8",
                        "hideGenerationTimestamp" to "true"
                )
                DefaultGenerator().opts(config.toClientOptInput()).generate()

                // Copy generated files to the corresponding directory in sources
                File("${project.projectDir}/temp/src/main/java")
                        .copyRecursively(File("${project.projectDir}/src/test/java"))

                // Clean up temp directory
                File("${project.projectDir}/temp").deleteRecursively()
            }
        }
    }
}

fun deletePackageDirectories(projectPath: String, packages: List<String>) {
    packages.forEach { pack ->
        File("$projectPath/src/test/java/${pack.replace(".", "/")}").deleteRecursively()
    }
}

Додамо плагін до блока plugins в нашому основному build.gradle.kts файлі:

plugins {
    ...
    `reminder-codegen`
}

У нас з’явився таск generateApi, і ми можемо його викликати:

$ gradlew generateApi

Він нам згенерує файли моделі (в нашому випадку це тільки Reminder), API клієнта і наших точок доступу (в нашому випадку ReminderControllerApi):

Непоганий результат, але ми ще не можемо смикати API в тестах, треба трохи допиляти напилкомдописати код. Створюємо клас «степів» у пакеті steps.api:

package com.example.steps.api;

import com.example.entities.generated.Reminder;
import io.restassured.response.ResponseBody;

public class RemindersApiSteps extends BaseApiSteps {
    public static void addReminder(Reminder reminder) {
        apiClient
                .reminderController()
                .createUpdateUsingPUT()
                .body(reminder)
                .execute(ResponseBody::prettyPrint);
    }
}

У свою чергу абстрактний клас BaseApiSteps міститиме конфігурацію apiClient:

package com.example.steps.api;

import com.example.services.api.client.ApiClient;
import io.restassured.builder.RequestSpecBuilder;
import io.restassured.filter.log.ErrorLoggingFilter;

import static com.example.services.api.client.ApiClient.Config.apiConfig;
import static com.example.services.api.client.ApiClient.api;
import static io.restassured.config.RestAssuredConfig.config;

public abstract class BaseApiSteps {

    protected static ApiClient apiClient = api(apiConfig().reqSpecSupplier(
            () -> new RequestSpecBuilder()
                    .setConfig(config())
                    .addFilter(new ErrorLoggingFilter())
                    .setBaseUri("http://localhost:8080")
    ));
}

Тепер ми можемо використати додавання reminder-а через API як передумову для тесту з видалення, який виглядатиме приблизно так:

@Test(description = "Delete reminder",
        dataProvider = "deleteReminderData",
        groups = {Teams.GAMMA, Sprints._1})
@TestCase("REM-171")
public void deleteReminder(Reminder reminder) {
    RemindersApiSteps.addReminder(reminder);
    NavigationSteps.openRemindersApp();
    ReminderSteps.deleteLastReminder();
    CommonUiSteps.refreshPage();
    ReminderSteps.checkReminderIsAbsent(reminder);
}

Ще лишилося вирішити, де саме викликати генерацію класів API клієнта. В даному випадку я би все ж не включав її як обов’язкову перед стадією компіляції, адже якщо, наприклад, наш System Under Test зараз недоступний, то ламати в цей час збірку проекту у когось на комп’ютері не виглядає справедливим. В даному випадку доцільніше викликати генерацію явно:

$ gradlew generateApi test

Таку конфігурацію варто застосувати на CI після кожного коміта в Back-end: або генерація + компіляція тестів, або генерація + smoke API тести.

Висновок

Наведені приклади Gradle плагінів, як, напевно, і майже всі Gradle плагіни, можна було би замінити якимось скриптом, який лежить за межами проекту. Але коли в такій задачі з’являється потреба прив’язати її до якоїсь стадії збирання проекту, варто замислитись над перенесенням скрипта до плагіна.

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


Team Performance Dashboard, или Как измерить реальную продуктивность сотрудников

$
0
0

Я работаю в компании Devart на позиции Senior Technical Project Manager в отделе, состоящим из 4 команд. Общая численность отдела — около 50 сотрудников, занимающимися 35 проектами. Помимо нашего есть и много других небольших отделов.

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

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

Team Performance Dashboard — инструмент, предназначенный для определения эффективности работы как команд, так и отдельных сотрудников. Оценка, которую можно получить, используя Team Performance Dashboard, будет полезна в первую очередь менеджерам проектов, тимлидам, HR-ам, PP-ам, и, конечно же, CTO. В статье я расскажу о том, как мы в компании сами разработали, внедрили и как сейчас используем этот инструмент.

С чего все началось

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

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

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

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

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

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

Вот чем оказалась полезна эта система для меня как для PMа, для тимлидов команд и для топ-менеджеров в целом:

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

Но это мы забежали немного наперед...

Как создавали комплекс оценивания

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

Далее перечислены пройденные этапы:

  • определены уровни градаций для следующих типов сотрудников: Dev, QA, TW;
  • описаны требования для перехода сотрудника на следующий уровень (например от junior до strong junior);
  • разработана система оценивания issue по сложностям (для Feature, Task, SubTask, Bug и др.);
  • введен учет количества переоткрытий задач сотрудником и командой;
  • сформирован процесс определения общего балла сотрудника, составленный с учетом как динамических, так и статических критериев оценки сотрудников;
  • составлен список критериев, по которым будет выполняться оценка Dev, QA, TW;
  • определен период и частота оценивания сотрудников;
  • сформированы виды оценок, применяющиеся при формировании общего балла (рейтинга сотрудников).

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

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

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

Пример формирования статических критериев и рейтинг сотрудников (на примере QA) можно увидеть на рисунке ниже:

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

Практическое применение системы в реальных условиях

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

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

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

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

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

В оранжевом прямоугольнике можно увидеть, что бывший сеньор уже «смирился» с тем, что он в первую очередь тимлид команды, а только потом девелопер. Сильный спад продуктивности, почти до «нуля» — он был в отпуске :) А дальше следуют равномерные колебания в зависимости от релизов, джунов и так далее.

Из приведенного примера видно, что если продолжать оценивать лида как senior девелопера, то он несомненно будет «проигрывать» в такой оценке.

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

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

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

Запрос на пересмотр оплаты труда

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

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

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

Определение оптимальных сотрудников для завершения релиза

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

Дополнительный функционал для People Partners и HR компании

Для HR отдела добавлен функционал «личная карточка сотрудника», которая содержит следующую информацию:

  • список всех сотрудников компании, сгруппированных по командам и по должностям (Dev, QA, TW и т. д.);
  • дата приема сотрудника в компанию, общий стаж работы на аналогичной позиции, фото сотрудника, дата его рождения, текущий уровень квалификации (junior, middle и т. д.) и его контактная информация (email, skype, cell-phone и др.);
  • проекты, в которых принимал участие сотрудник, и какие технологии использовал в них, сколько задач было сделано по проектам и сколько времени на это было затрачено (суммарное значение);
  • результаты проведения one-to-one митингов с сотрудником и сделанные выводы по ним.

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

  • Сотрудник.Этот уровень позволяет просматривать текущий рейтинг, как статической, так и динамической оценки сотрудника (только своей). Также контактную информацию о сотруднике с возможностью ее редактирования.
  • Team Lead.Предназначен для тимлидов команд и позволяет просматривать как свою оценку и контактную информацию, так и всех сотрудников своей команды. Кроме этого, он может посмотреть, как работала команда за выбранный период времени.
  • HR/PP компании.Этот уровень позволяет просматривать «личную карточку сотрудника» и модифицировать её, а также динамическую оценку выбранного сотрудника за выбранный период.
  • Менеджмент.Этот уровень аналогичен уровню «администратора» и имеет доступ ко всей информации системы.

Подведем черту

Для компании использование этой системы оказалось весьма полезным. Почему? Да все просто:

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

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

Горизонтальное масштабирование для SQL Server баз данных: как это сделать

$
0
0

Если вы или ваша компания ищете возможность горизонтального масштабирования для SQL Server баз данных, тогда эта статья для вас.

Устоявшиеся привычки, дороговизна адаптации новых решений, обязывающий стек технологий — это далеко не полный список причин, по которым многие проекты продолжают работать с реляционными базами, адаптируя их под требования больших данных. В этой статье я поделюсь собственным опытом реализации и внедрения scale-out масштабирования при помощи Elastic Database Tools.

Кратко обо мне. Я Lead Developer в компании Sitecore с опытом работы в IT более 12 лет. Ex-leader Dnipropetrovsk MongoDB User Group in Dnipro, Leader Dnepr SQL User Group, докладчик на различных конференциях (SqlSaturday, MyWebTech, SitecoreSaturday). С базами данных веду плотную дружбу вот уже 7 лет.

Кратко о главном

Долгое время базы данных классифицировали по двум типам SQL и NoSQL (реляционные и нереляционные). Модные докладчики больших конференций и авторы статей использовали ‘NoSQL’ как buzzword для привлечения внимания.

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

Реляционные базы данных — это гигант и прародитель всех существующих и всех будущих вариаций хранения данных. SQL-хранилища позволяют хранить данные в структурированном, нормализованном виде с поддержкой комплексных транзакций и сложных JOIN-операций. Этот тип хранения отлично справляется с задачами, где консистентность данных очень важна. Дабы не быть многословной, приведу пример с банковским переводом в миниатюрном изложении. Когда денежный перевод осуществляется от клиента А клиенту Б, очень важно убедиться, что средства, списанные со счёта отправителя, успешно зачислились на счёт получателя. В данном случае на помощь приходят транзакции.

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

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

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

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

  • Complex Transaction;
  • JOIN;
  • Static Schema.

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

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

  • Key-value;
  • Column Family;
  • Graph;
  • Document-oriented.

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

Одним из последних трендов развития баз данных являются NewSQL хранилища со своей спецификой, объединяющей сильные стороны как SQL, так и NoSQL хранилищ, но это тема для отдельной статьи.

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

Немного истории

Тем, кто любит переходить сразу к сути, предлагаю пропустить раздел «когда мы были молодыми» и читать следующий раздел.

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

Затем произошел естественный переход на реляционные хранилища (SQL Server, Oracle), которые долгое время служили верой и правдой до того, как понадобилось хранить большие объёмы данных. На тот момент решение было очевидным: переписать всё и перейти на NoSQL базы данных, в частности на MongoDB.

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

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

Microsoft продолжала инвестировать средства в поиски решений проблемы горизонтального масштабирования для SQL баз данных. Спустя время были анонсированы Elastic Database Tools — набор библиотек и Azure-сервисов для возможностей горизонтального масштабирования в SQL Azure.

Теперь самое интересное, погнали...

Elastic Database Tools

Набор Elastic Database Tools состоит из следующих фичей и сервисов:

  • Elastic Database Client Library;
  • Elastic Database Jobs;
  • Elastic Database Query;
  • Elastic Database Transactions;
  • Split-Merge Tool.

Несмотря на то, что этот набор фичей изначально был рассчитан на работу с SQL Azure, часть из библиотек и подходов мы смогли успешно внедрить и в On-Premise решения.

Elastic Database Client Library

Для работы с распределенными данными, как On-Premise, так и SQL Azure, мы использовали библиотеку Elastic Database Client Library. При помощи этой библиотеки был написан инструмент для создания и конфигурации sharded cluster, провайдера для работы с данными в шардах, а также, в более поздних версиях, добавили возможность горизонтального масштабирования (scale-in/scale-out).

В отличие от MongoDB, где вся работа с кластером, балансирование данных, отказоустойчивость являются встроенными фичами, не требующими ни одной строчки кода, работа с Elastic Database Tools предполагает несколько больше усилий, так как она предоставляет инструменты и библиотеки, внедрение которых не является бесплатным.

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

Table Types

Elastics Database Client Library поддерживает два типа таблиц: sharded tables и reference tables.

Sharded Tables

Sharded Tables — это тип таблиц, которые хранят данные, распределенные по инстансам кластера по определенному ключу, его ещё называют shard key.

Мы определяем колонку таблицы, которая будет нашим ключом распределения (shard key) между шардами, определяем диапазон уникальных ключей для каждого из шардов и работаем с кластером как с единой логической базой данных. Вся мета-информация по конфигурации шардов хранится в каталоге, в самой ключевой базе данных — Shard Map Manager, но о ней чуть позже.

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

Reference Tables

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

Shard Key

При проектировании распределённой базы данных ключевым моментом является анализ запросов к базе данных для определения правильного shard key для каждой из таблиц.

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

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

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

Shard Map

В Elastic Client Library существует концепция Shard Map. По сути, это карта соответствия ключ-шард. При помощи Shard Map вы определяете, к каким шардам относятся какие ключи, сохраняете эту информацию в Shard Map Manager, а Elastic Client Library API умеет с этой мета-информацией работать (к примеру, открывать соединение к нужному шарду по ключу в предикате запроса).

Существует два типа shard map: List Shard Mapи Range Shard Map. Из названия можно определить, что List определяет соответствие точечных ключей к шардам, а Range — диапазоны ключей к шардам.

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

Elastic Scale — Key Elements

Ключевые элементы Elastic Scale:

  • Shard Map Manager;
  • Data-Dependent Routing;
  • Multi-Shard Query.

Shard Map Manager

Я уже упоминала об этой базе данных — по сути, она хранит мета-информацию по распределению данных. Эта база хранит данные по зарегистрированным шардам в кластере, зарегистрированным Shard Map, хранит схему shard key для возможностей scale-in и scale-out масштабирования. Shard Map Manager является одним из ключевых элементов системы.

Data-Dependent Routing

Механизм Data-Dependent Routing (DDR) позволяет направлять запрос на определенный шард, используя предикат запроса, в котором применяется shard key колонка.

DDR работает через Elastic Scale Client Library API. Другими словами, DDR выполняет роутинг запроса на определенный шард, используя мета-информацию распределения из Shard Map Manager.

Запросы, в предикате которых присутствует ключ распределения, являются очень эффективными. Стоит минимизировать запросы, в предикате которых нет shard key, так как они будут направлены на все шарды кластера и являются Multi-Shard Query запросами.

Multi-Shard Query

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

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

Data Modeling

Хотелось бы ещё раз обратить ваше внимание на моделирование схемы базы. Связанные данные должны находиться в рамках одного шарда. К связанным данным можно отнести таблицы, которые связаны по Foreign Keys.

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

Replication

Репликация является одним из ключевых элементов High Availability. При использовании Elastic Scale для On-Premise решений удобным будет использование AlwaysOn Availability Groups и концепции AG Listeners.

При конфигурации Availability Group необходимо создавать AG Listener, который выполняет лишь функцию перенаправления запроса на Primary Replica. Приложение, работающее с базой данных, в качестве строки соединения к базе данных принимает конфигурацию Listener, что даёт возможность автоматически переключать систему на живую базу при отказе Primary Replica.

Shard Map Manager хранит всю конфигурацию shard cluster, включая имя сервера для каждого зарегистрированного инстанса/shard. При настройке репликации необходимо заменить имя сервера для каждого из шардов на AG Listener созданного для каждой из AG.

При выходе из строя одного из инстансов Listener автоматически перенаправит соединение к Secondary Replica, сконфигурированной в Availability Group.

Rebalancing, Split/Merge Service

Возможность горизонтального масштабирования — одно из основных требований любой Elastic системы. Для этих целей был разработан Split/Merge Service, который является одним из компонентов Elastic Database Tools. К сожалению, Split/Merge Service умеет работать лишь с SQL Azure базами.

Split/Merge — это cloud service, в обязанности которого входит перемещение данных из одного шарда в другой с использованием диапазона ключей.

Split/Merge service предоставляет веб-страницу, на которой вы можете указать source и target инстанс, выбрать диапазон ключей для перемещения и запустить механизм перемещения данных. Также есть возможность запустить перемещение данных при помощи PowerShell скриптов. В большинстве случаев веб-страницы вполне достаточно.

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

При необходимости сократить количество шардов в кластере Split/Merge Service позволяет склеить/переместить данные из шарда, который мы намерены удалить, в другой или другие шарды, тем самым мы можем сократить расходы на содержание shard cluster, когда в этом нет необходимости.

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

Заключение

Горизонтальное масштабирование для SQL баз данных — не миф, а вполне реально работающая фича, хотя процесс внедрения scale-out не является тривиальным и требует пересмотра схемы базы, а также внедрения Elastic Database Tools.

При реализации этого подхода в нашем проекте мы полностью пересмотрели схему базы данных, переписали уровень доступа к данным, используя Elastic Database Client Library, и внедрили возможность scale-in/scale-out масштабирования для SQL Azure при помощи Split/Merge Cloud Service.

Советы сеньоров: как прокачать знания junior security specialist

$
0
0

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

Вадим Чакрян, Lead of Information Security Team в DataArt

10+ лет в области InfoSec

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

Я бы советовал сперва определиться с тем, в какой команде вы хотите быть — атакующих (offense) или защищающих (defense). Те, кто находятся в команде атакующих, думают о том, как проникнуть в систему, как атаковать элементы инфраструктуры, физические ресурсы и людей (я имею в виду социальную инженерию). Те же, кто находится в команде защищающихся, больше думают о том, какие механизмы безопасности внедрить, как их внедрить, и занимаются непосредственным внедрением.

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

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

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

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

Для веб-пентеста:

  • Разобраться с тем, что такое OWASP.
  • Прочесть книгу Web Application Hacker’s Handbook 2nd edition.
  • Скачать и запустить локально Web for pentesters I и II, а также OWASP WebGoat. Начать с ними практиковаться.
  • Также попрактиковаться на juice-shop.herokuapp.com, а еще тут hackthebox.euи root-me.org.
  • Разобраться в OWASP Testing Guide, OWASP Top Ten, OWASP ASVS.
  • Освоить Burp Suite, OWASP ZAP, nmap, и другие тулы для веб-пентеста в Kali Linux.

Для сетевого пентеста:

  • Как минимум пройти курсы по сетям (например: Cisco CCNA или CompTIA Network+ и т. п.).
  • Прочесть книгу Network Security Assessment 3rd Edition.
  • Установить локально Metasploitable 2 и 3. Практиковаться на них.
  • Научиться работать с Wireshark, nmap, Ettercap, Yersinia, Metasploit и другими тулами для сетевых атак в Kali Linux. Можно еще с Shodan и Censys разобраться.
  • Также советую найти поучаствовать в онлайн-соревнованиях по сетевому хакингу, по типу lab.pentestit.ru.

Другие области рассматривать не будем, но думаю, смысл понятен. Можете найти мою презентацию о том, «С чего начать свой путь этичного хакера?» (YouTube, слайды), там есть другие полезные книги и материалы для тренировок. Чтобы найти больше лабораторных стендов для практики — исследуйте VulnHub. Есть вероятность, что в чем-то вам поможет SecurityTube.

Также, когда вы уже будете слегка матёрым и порешаете все задачи на тренажерах — начните играть в Capture the Flag (CTF) игры. Вы можете найти ближайшие и будущие CTF игры по всему миру на сайте ctftime.org (что такое CTF, рассказывать не буду — почитайте тут). Если же захотите подзаработать немного деньжат и попробовать силы в реальных проектах — то попробуйте поучаствовать в BugBounty программах, например на HackerOneили BugCrowd (но это уже когда будете совсем матёрые).

В плане сертификаций я бы посмотрел в сторону Pentest+, CEH, OSCP.

В направлении защищающихся есть очень много областей:

  • Инженеры безопасности (занимаются внедрением механизмов безопасности в рамках компании).
  • SecOps-специалисты и расследователи инцидентов (эти ребята реагируют на угрозы безопасности и расследуют их, чтобы предотвратить атаку, устранить последствия и восстановить нормальный ход бизнеса).
  • Цифровые криминалисты (эти люди очень хорошо знают, как правильно собрать и хранить цифровые улики таким образом, чтобы они были признаны легитимными в суде).
  • Аналитики вредоносного ПО (они очень хорошо разбираются в Assembler и умеют восстановить принцип работы программы без ее исходного кода. Помогают создавать противоядие против зловредов).
  • Compliance-специалисты (не знаю, как это кратко и верно перевести на русский язык, но, в общем, эти товарищи следят за соблюдением требований государственных законов, а также мировых и отраслевых стандартов в области безопасности, применимых к компании/предприятию).
  • Аудиторы (проводят аудиты безопасности в компании, часто совмещается с Compliance).
  • Специалисты по обеспечению физической безопасности (обеспечивают физическую безопасность рабочего пространства компании — начиная от системы защиты на входе в офис до системы пожаротушения в серверных комнатах).

Проблема defense-направления состоит в том, что получить достаточный опыт вы сможете только в боевых условиях. В качестве обучения я бы посоветовал всем освоить базу. Для этого подойдут материалы для сертификации CompTIA Security+. Дальше смотрите по сертификационным направлениям: CompTIA, (ISC)2, SANS, Ec-Council. Да, там все платно и иногда очень даже платно, но как минимум нужно разобраться, какого уровня какая сертификация, чтобы понимать с чего начать. Затем найти описание их содержания — так вы получите информацию о том, что нужно выучить, и сможете составить для себя дорожную карту развития.

В качестве образовательных площадок воспользуйтесь: Cybrary (тут много бесплатного), Udemy (тут не дорого и бывают распродажи, когда все по $10), CBTNuggets (тут далеко не все по безопасности и платно, но они делают просто офигенный контент).

Я бы посоветовал увеличивать свою сеть знакомых в этой области. Ходите на конференции, в Украине их много появилось: BSides и OWASP в разных городах, UISGCON / NoNameCon / HackIT в Киеве и многие другие. Обязательно знакомьтесь со спикерами и с участниками. Вообще, это должно быть вашей главной задачей, приобретение знаний — второстепенной. Попросите добавить вас в чаты безопасниковлокальных сообществ, там можно будет задавать вопросы, и всегда найдутся люди, которые помогут найти ответ. Хоть и трудно, но очень полезно организовывать свои мероприятия — контакты появятся волей не волей, но это путь тернистый и не для каждого, так что уговаривать не буду.

Михайло Кропива, Associate InfoSec Director у SoftServe

15 років досвіду у галузі

Зазвичай у початківців, які планують розвиватися у напрямку інформаційної та кібербезпеки, є розуміння функціоналу декількох програм — виявлення вразливостей, мережевих сканерів, антивірусних продуктів. У більш «прокачаних» є навички етичного хакінгу (Metasploit, OWASP framework). Ступор наступає, коли доходимо до питання, чи усього цього достатньо компанії, щоб почуватися в безпеці. Висновок — необхідне комплексне розуміння векторів загроз і вразливостей, способів їх зниження (по-простому — заходи безпеки/security controls) та усвідомлення своєї ролі у всій цій екосистемі.

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

1. Оцінка та управління ризиками (GRC)

Зазвичай нудна і незрозуміла частина для «технарів», проте саме на цій функції базується більшість процесів інформаційної безпеки та ІТ-організації загалом. Підґрунтям більшості підходів до оцінки ризиків є ISO27001 чи NIST. Також однією з функцій відділу GRC (зазвичай долучається також юридичний відділ) є процеси, пов’язані з обробкою персональних даних в компанії. Для цієї функції підходять люди, котрі мотивовані більше процесом, ніж швидким досягненням результату. І це в більшості не Junior Security Engineer :)

Рекомендовані ресурси та сертифікації:

2. Оператор (частина SecOps чи Blue Team)

Перше, з чим необхідно розібратися кожному початківцю — що таке інформаційна безпека і кібербезпека, і в чому принципова різниця між ними. Адже це базове питання, котре в подальшому вам будуть ставити на співбесідах, якщо ви тільки починаєте свою кар’єру. Кібербезпека — це складник інформаційної безпеки, що має на меті захист інформації в цифровому світі. В той же час інформаційна безпека — це комплексне поняття, що включає в себе і цифровий захист, і фізичний (сейфи, турнікети, камери відеонагляду), тощо, а також відповідні стандарти.

Ймовірно, що першою сходинкою у вашій кар’єрі буде позиція оператора операційного центру/команди з кібербезпеки. Його завдання полягає в роботі з інструментами інформаційної безпеки та людьми, а метою є виявлення загроз, підозрілої активності, а також аналіз аномалій та їх дослідження. То що повинен знати той, хто бачить себе саме в такій ролі?

  • Перш за все, потрібно розібратися з поняттям логування (журналювання). Які є типи логів та яку інформацію вони містять.
  • Далі доведеться розібратися із мережевим стеком і основними протоколами.
  • Ніяк не обійтися без розуміння базових речей, які забезпечують взаємодію з «диким» світом (інтернет). Тобто вам мають бути знайомі такі слова, як Active Directory, DNS, DHCP, IIS і так далі.
  • Також корисним буде розуміння принципів роботи різних операційних систем (Kali Linux, CentOS Windows Server, etc).
  • Розуміння базових принципів криптографії.
  • А найголовніше — вміння думати та концентруватися на поставленому завданні.

Можна навести таку алегорію: уявіть, що ви сапер і в полі знайшли міну. Що ви маєте робити? Як вийти із ситуації? Як захисти себе і всіх навколо? Ви маєте володіти навиками та інструментами для того, щоб знайти, класифікувати, ізолювати та знешкодити міну. Отже, якщо вам цікаве спостереження, дослідження та аналіз — тоді операційна частина кібербезпеки — саме для вас.

3. Аналітик з кібербезпеки

Наступним кроком у вашій кар’єрі буде позиція аналітика. Ці люди відповідальні за налаштування та постійне покращення інструментів кібербезпеки (частина SecOps чи Blue Team), а також сюди відносяться фахівці, що займаються тестуванням на проникнення (penetration testing або Red Team). Також окремо можна зазначити інженерів, завдання котрих полягає у створенні і підтримці інфраструктури для аналітиків та операторів. Зазвичай роль інженерів виконують системні адміністратори чи девопси.

Аналітик повинен знати все те, що й оператор, але додатково:

  • Володіє знаннями та навиками адміністрування систем захисту. До переліку цих інструментів слід віднести системи виявлення та попередження вторгнень (IDS/IPS), системи збору і аналізу логів (SIEM), антивіруси, сканери вразливостей, фаєрволи, тощо.
  • Створює кореляційні правила для виявлення підозрілої активності, що дозволяє співставити події з різних систем, що відбулися протягом одного часового проміжку.
  • Застосовує різноманітні техніки і методології для виявлення слабких ланок та використання вразливостей в інфраструктурі, мережі чи програмному забезпеченні.

Повернімося до нашого сапера :) На відміну від першої ситуації з оператором, аналітик тонко налаштовує інструменти та будує алгоритми виявлення мін та мінних полів. Для побудови міцного захисту ви повинні розуміти, як себе поводить мінер, які інструменти він використовує, які сліди залишає та за якими ознаками можна виявити загрозу. Додатково час від часу залучаєте команду із навчальними мінами (penetration testing) для тестування вищезгаданих інструментів та алгоритмів виявлення мін.

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

Основні задачі сyberforensics-аналітика:

  • провести аналіз кінцевої точки (лог-файлів, реєстру Windows, мережевих пакетів і т. д.), збирати і аналізувати артефакти вторгнення (наприклад: вихідний код, шкідливе ПЗ і конфігурацію системи);
  • провести відновлених даних для отримання інформації, яка має відношення до інциденту;
  • вставити першопричину виникнення інциденту;
  • забезпечити правову хронологічну документацію, яка фіксує послідовність розслідування, аналіз і т. д. (chain of custody документ);
  • описати порядок дій, котрі необхідно виконати для зменшення негативного впливу від інциденту і запобігти повторенню.

Рекомендовані ресурси:

Рекомендовані сертифікації:

CompTIA Security+ — для тих, хто входить в ІБ, для початківців, що вже у сфері, теоретична (не важливо, чи defense, чи offense).

CEH — середній рівень, теоретична (більше для offense, ніж для defense).

OSCP/OSCE — важкий і найбільш цінується в індустрії, так як здача базується на практичних уміннях (для offense).

CISSP — важкий, але теоретичний, в більшості для керівних посад: VP, C-level, etc.

ISC2 SSCP — це як CISSP, тільки для технічного спеціаліста.

CCNA Sec — якщо працюєш з CISCO (але в цілому і для мережі).

CIA — для аудиторів.

Пропонована градація на три групи є відносною і в деяких компаніях ролі можуть суміщатися, для прикладу Blue Team та Read Team чи GRC. Прокладаючи свій кар’єрний вектор, варто враховувати не лише технічні навички для різних ролей, але і мотиваційну складову та навіть особливості характеру людей, котрі виконують чи залучені до цих різних команд інформаційної безпеки. Розвивайтесь постійно, цікавтесь, чим живуть суміжні департаменти ІТ і шукайте свою нішу у світі інформаційної безпеки, яка дозволить вам розкрити власні таланти наповну!

Евгений Пилянкевич, CTO в Cossack Labs

Более 20 лет опыта в ИБ

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

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

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

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

First things first: то, что отличает рост хорошего джуниора от плохого, — знание азов:

  • Computer science 101. Вам нужен набор базовых знаний об устройстве компьютера, операционных систем и сетей, владение азами программирования. Чем азы лучше и чем ближе от 101 к Pro, тем легче будет учиться.
  • Security-кругозор — одно из основных слабых мест всех entry-level специалистов в ИБ. Легкий способ систематизировать азы и пройти обзорный курс базовых понятий ИБ — учебные программы для начинающих с экзаменами вроде CompTIA Security+, ISC2 SSCP, GIAC Security essentials.
  • Security-навыки: теоретические и практические курсы. Для многих пользующихся спросом специальностей уже есть готовые курсы разной степени глубины. И если в OSCP для red team-специалиста можно вместить многое из того, что нужно знать для работы, то для blue team-инженера с уклоном в криптографию без пары специальных курсов в институте будет сложновато.

Во-вторых, нужно определиться с целью, «куда именно расти». С одной стороны, это про узкий набор технологий, с другой — про ориентацию defensive/offensive. Любая специализация в ИБ в какой-то пропорции содержит работу двух видов — защищать (blue team) и нападать (red team):

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

Skills and credentials

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

  • [100% skill] Practice lab:вне зависимости от blue/red специализации, вам понадобится playground для экспериментов. Начиная от пары виртуалок за $5 и заканчивая мини-датацентром в кладовке. Возможность строить и ломать, не привлекая внимания санитаров леса, — следующий после базовых навыков по важности ресурс, телепорт из теоретиков в практики.
  • [100% skill, ??% credentials (sometimes)] CTF and public playgrounds: capture-the-flag конкурсы и онлайн-плейграунды вроде HackTheBoxдля сетевых задач или Cryptopalsдля криптографов, спроектированные специалистами для отработки навыков поиска и использования уязвимостей. У некоторых из них есть публичные доски почета, которые могут использоваться как credentials при найме.
  • [??% skill, 100% credentials] Сертификации:поскольку в заметной части собеседований с вами будут разговаривать люди, которые в предметной области разбираются хуже вашего, индустрия придумала набор сертификаций, подтверждающих вашу квалификацию. Не берусь оценивать качество экзаменов, но замечу, что это важный инструмент в общении с внешним миром для любой замкнутой профессии.

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

  • В Украине проходит ряд отраслевых конференций для людей разного уровня развития — неформальные митапы DC8044, OWASP Ukraine, небольшие конференции Security BSides, большие конференции вроде NoNameConи монстры отечественной индустрии, вроде UISGCON.
  • Практически в каждой профессии существует список эталонных книг и «главных блогов», его несложно найти. Cложнее понять, что вся профессия information security на самом деле про людей и то, как они принимают решения, и что стоит читать книги про психологию, поведение в кризисных ситуациях, инженерную надежность, риск-менеджмент и пр. Остальное вам коллеги посоветуют и так.
  • Подкасты: украинские No Name Podcast, международные — Defensive Security, Risky Business, Security weekly.

Александр Адамов, руководитель NioGuard Security Lab, преподаватель в ХНУРЭ и Blekinge Institute of Technology, Швеция

15 лет в кибербезопасности

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

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

Операционисты vs Аналитики

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

  1. Операционисты (Security Operations L1-2, SecDevOps, инженеры кибербезопасности, большая часть тестировщиков), которые выполняют алгоритмизируемые задачи, используя инструменты автоматизации.
  2. Аналитики (Security Operations L3, аналитики, консультанты, меньшая часть тестировщиков, криптографы) решают задачи, для которых нет инструкций и готовых решений.

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

Также есть деление специалистов на Defensive Security — те, кто защищает (Blue Team), и Offensive — те, кто атакует (Red Team). Однако такое деление условно, так как существует, например, Purple Team, в задачи которой входит как тестирование на проникновение, так и последующая защита выявленных брешей в безопасности.

Рассмотрим более многочисленную первую группу ‒ операционистов. На данный момент существует высокий спрос со стороны индустрии, удовлетворяемый за счет выпускников технических вузов, которые зачастую проходят стажировку в компаниях после или даже во время обучения в университете. Там они и получают практические («hands-on») знания предметной области.

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

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

Для примера возьмем Security Operations — мониторинг и реагирование на инциденты кибербезопасности. На смену классическим агрегаторам событий безопасности (SIEM — Security Information and Event Management), приходят системы с аналитикой, которые с помощью ИИ позволяют находить аномалии, связывать данные (bird’s-eye view), выявлять инциденты и приоритизировать их согласно системе оценки рисков (risk scoring system), облегчая тем самым работу SecOps. Более того, новое поколение SOAR (Security Orchestration, Automation and Response) систем также позволяет автоматически реагировать на большинство обнаруженных инцидентов без участия человека. Справедливости ради стоит заметить, что эти системы пока что нуждаются в обучении человеком — экспертом в данной области, то есть аналитиком.

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

Рассмотрим несколько примеров из моей практики. Шифровальщик MoneroPay использовал оригинальную технику социальной инженерии для того, чтобы убедить пользователя загрузить и запустить троянца у себя на компьютере под видом майнера для якобы новой криптовалюты SpriteCoin, информация о которой была опубликована на форуме bitcointalk.org 6 января 2018 года. Еще одним примером креативности хакеров является атака всем известного псевдо-вымогателя NotPetya, который был доставлен 27 июня 2017 года и запущен на компьютерах жертв — через бэкдор, добавленный в обновление ПО М.E.Doc. А уже в начале текущего года прошла успешная атака криптолокера LockerGoga на ряд промышленных гигантов, когда троянец использовал валидный цифровой сертификат, выпущенный на подставную компанию, для того, чтобы обойти системы киберзащиты.

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

Слоеный пирог из знаний

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

  1. Фундаментальный слой‒ включает базовые знания из университетской программы. Сюда могут входить (список курсов и образовательные слои открыты для обсуждения в комментариях):
    • высшая математика с матанализом и линейной алгеброй;
    • численные методы и матстатистика;
    • дискретная математика;
    • нечеткая логика и нейронные сети;
    • теория цифровых автоматов;
    • микроконтроллеры и архитектура ЭВМ;
    • теория информации;
    • сети;
    • операционные системы;
    • системное программирование и не только.
  2. Профильный слой‒ специализированные знания в области кибербезопасности, такие как:
    • криптография;
    • информационная безопасность;
    • технологии детектирования кибератак;
    • анализ вредоносных программ и реверс-инжиниринг;
    • веб-безопасность и Ethical Hacking;
    • цифровая криминалистика;
    • сетевая и облачная безопасность;
    • разработка безопасного ПО и ПО для безопасности;
    • безопасность беспроводных сетей;
    • децентрализованные системы и блокчейн.
  3. Междисциплинарный слой‒ знания в смежных IT—областях для расширения кругозора аналитика:
    • ИИ с машинным обучением и интеллектуальным анализом данных (AI / ML / DM);
    • Cloud-технологии;
    • Big Data;
    • IoT;
    • Automotive;
    • Industrial Control Systems.

К сожалению, не все из перечисленных профильных курсов доступны в технических вузах Украины, где есть соответствующие специальности. К слову, мы с коллегами из ХНУРЭ, Львовской политехники, ГУТ, НТУ «КПИ» внесли свою лепту в разработку европейской магистерской программы по кибербезопасности в рамках EU TEMPUS проекта ENGENSEC, которая включает большую часть из названных выше курсов по кибербезопасности, и постепенно внедряем их в учебные программы своих университетов.

Где учиться

Если говорить об университетском образовании, то здесь есть ряд подводных камней. Во первых, профильные курсы не обязательно будут локализованы на специальности 125 «Кібербезпека». Например, я читаю курс по выбору «Методы детектирования и анализа компьютерных угроз» на специальности «Специализированные компьютерные системы». Во вторых, содержание и качество подачи материала будет отличаться у разных преподавателей в разных вузах. В третьих, ведение небольших курсов (80-120 часов)зачастую растянуто на целый семестр так, что иногда у студентов выходит одна лекция раз в две недели, и они к следующему занятию успевают забыть, что было на предыдущем :)

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

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

Источником экспертных знаний могут также стать, как это ни странно звучит, YouTube-каналы популярных конференций по кибербезопасности. К счастью, уже не надо лететь через океан и покупать билет за $3000 долларов (да, именно столько стоит билет на топ-конференцию), а можно просто подождать день, неделю, месяц и посмотреть видеозапись, сидя дома на диване и попивая чаек с печеньем или пригласить друга, девушку/парня и посмотреть вместе :) К тому же на больших конференциях доклады обычно разбиты на два и более потоков, поэтому, даже присутствуя там физически, невозможно посетить все выступления.

Что посмотреть

Мои подписки на YouTube-каналы:

Комьюнити

Еще одна возможность получить новые знания — посещение локальных конференций, воркшопов, мастер-классов, Security Day, общение с представителями комьюнити, подкасты, некоторые из них также доступны на YouTube:

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

Участие в научных исследованиях в университете или компании может оказаться очень полезным для прокачивания аналитических навыков. Для поиска релевантных научных исследований рекомендую Google Scholar.

Книги не даю, так как все направления покрыть нереально. Гугл в помощь!

В заключение, я бы порекомендовал, независимо от текущего уровня профессионализма, продолжать учиться, используя все возможности. Такая концепция получила название «Lifelong Learning» и становится все более популярной в современном быстро развивающемся мире. И помни: ИИ уже следит за тобой и однажды займет твое место <DEVIL>

Павел Кривко, DevOps Security Engineer в ЕРАМ Ukraine

6 лет в ІТ

Кибербезопасность — огромная отрасль. Она объединяет много направлений, которые могут существенно отличаться друг от друга, поэтому в первую очередь стоит уделять внимание получению базовых знаний и уже после углубляться в выбранную специализацию, будь то Application Security, Cloud Security, Penetration Testing или что-то еще. Однако мои общие рекомендации таковы:

  • Учите английский. Думаю, нет смысла подробно комментировать. Хороший уровень владения иностранным языком открывает много возможностей в IT-индустрии.
  • Прокачивайте навык программирования. Он один из самых важных, потому что позволит решать много повседневных задач. Стандартом отрасли считается С и Python. Из книг могу порекомендовать Head First: Python, Head First: C.
  • Разберитесь, как работают операционные системы и их основные службы. Linux отлично подходит как для изучения, так и в качестве основной ОС, знакомство с ней можно начать с How Linux Works.
  • Уделите время ознакомлению с сетями и сетевыми протоколами, прочитайте Computer Networking. Для вас не должно быть загадкой, в чем разница между ICMP, UDP и HTTP.
  • Хотя бы поверхностно разберитесь в криптографических примитивах и протоколах. Без этого сложно представить современную кибербезопасность. Советую прочитать Crypto 101.
  • Начните прокачивать профильные знания, например, с изучения практик и инструментов, которые применяют в контексте Secure SDLC. Это даст вам понимание процесса разработки ПО и контроля безопасности на всех этапах жизненного цикла продукта, а также опыт работы с SAST, DAST, SCA и другими инструментами.
  • Чтобы развивать профильные практические навыки, хорошо подходят всевозможные [Hack|Crack|Exploit]Me челенджи и CTF. Из того, что стоит посмотреть в первую очередь, — это Hack The Boxи CTFTime.
  • Задумайтесь о прохождении сертификаций и курсов. Наличие у вас профильных и признанных в отрасли сертификатов — это хорошо, хотя и не обязательно. Примерный список таких сертификаций можно посмотреть в Cyber Career Map. Из курсов стоит взглянуть на Linux Academyи Pentester Academy.
  • Немаловажное место занимают ивенты и конференции. Если хотите посетить конференцию, но не знаете, какую выбрать, можно начать поиск на сайте infosec-conferences.

Думаю, для старта будет достаточно. Успехов :)

Разработка highload-системы на .NET Core: задачи и их решения

$
0
0

Меня зовут Андрей Губский. На данный момент я являюсь Software Architect в компании Video Intelligence, где занимаюсь проектом vi stories. Также я — CTO проекта Торф ТВ и создатель //devdigest. Коммерческой разработкой занимаюсь примерно с 2008 года. Окончил КПИ, кандидат технических наук. Являюсь Microsoft MVP в номинации Developer Technologies.

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

Немного про наш продукт: vi stories

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

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

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

Что такое высоконагруженная система

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

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

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

Задача № 0. Как из джавистов сделать дотнетчиков так, чтобы они этого не заметили

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

Существовал, правда, небольшой нюанс: тот проект был на Java, и, соответственно, основными инструментами коллег были Ubuntu, macOS и IntelliJ IDEA. К счастью для ребят, часть проекта уже была переведена на .NET Core и им не пришлось изучать нюансы установки Windows через Boot Camp. Поскольку IntelliJ IDEA от Rider на расстоянии больше метра вряд ли кто сможет отличить, а C# один в один похож на Java, какой она будет примерно в 2045 году — новые члены нашей команды почти не почувствовали подмены.

Интересно, что в какой-то момент в нашей команде использовались практически все существующие IDE для работы с .NET: Visual Studio, Rider, Visual Studio Code и Visual Studio for Mac.

Что касается миграции на .NET Core, проект мы переводили постепенно. Сначала в .NET Standard мы сконвертировали проекты, которые отвечали за описание базовых классов предметной области и всю ту часть, которая могла быть покрыта юнит-тестами. Затем постепенно стали переводиться отдельные сервисы. Из проектов типа Windows Services получились очень компактные и удобные консольные приложения, которые затем были аккуратно перенесены на Linux.

Итоги и выводы

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

Задача № 1. Выбор стека и определение приоритетов разработки

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

Оригинальный стек выглядел примерно так:

  • Windows Server;
  • Microsoft .NET 4.6.2;
  • Couchbase;
  • IIS;
  • MSMQ;
  • MySQL;
  • Elasticsearch;
  • хостинг — Amazon EC 2.

Это довольно серьезно отличается от того, с чем мы работаем сейчас:

  • Linux;
  • .NET Core 2.2;
  • Redis;
  • nginx;
  • Rabbit MQ;
  • MariaDB;
  • Elasticsearch;
  • развернуто почти все в Kubernеtes.

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

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

Что мы получили, переехав в K8S?

  • Независимость от облачного провайдера. Сейчас практически любой из крупных провайдеров предлагает Kubernetes as a service: Azure, AWS, Digital Ocean, Google Cloud.
  • Возможность быстрого деплоя. Так как все построено на докер-контейнерах, то откатить версию или развернуть на время какую-то специфическую версию — дело нескольких секунд.
  • Вся инфраструктура описана в скриптах.Эти описания могут храниться в системе контроля версий.

Условный минус — практически всем участникам команды пришлось изучить основы того, как работает Kubernetes, узнать, что такое Helm и Terraform.

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

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

  • Отказались от ручного администрирования Elasticsearch, перейдя на сервис от AWS. Стабильность и возможности масштабирования Amazon Elasticsearch Service полностью нас устраивали, поэтому мы смогли освободить команду от необходимости ручного управления и обслуживания кластера.
  • Мы также отказались от ручного обслуживания кластера Couchbase, перейдя на Amazon ElastiCache, с которым работаем по Redis-совместимому протоколу.
  • Убрали in-house библиотеку для логирования, которая была разработана в компании и использовалась до этого в ряде проектов. Ее заменили NLog.
  • Отказались от различных реализаций (как собственных, так и сторонних) библиотек для периодического выполнения задач, полностью переложив эти задачи на cron. Чем также сделали архитектуру многих сервисов проще. А чем проще решение, тем меньше в нем потенциальных точек нестабильности.

Итоги и выводы

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

Задача № 2. Минимизировать побочные эффекты при работе над проектом (почему иммутабельность — это хорошо)

Итак, почему? Вот несколько основных причин:

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

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

В .NET Core (да и .NET Framework) уже есть набор иммутабельных коллекций из коробки:

  • ImmutableArray
  • ImmutableArray<T>
  • ImmutableDictionary
  • ImmutableDictionary<TKey,TValue>
  • ImmutableHashSet
  • ImmutableHashSet<T>
  • ImmutableList
  • ImmutableList<T>
  • ImmutableQueue
  • ImmutableQueue<T>
  • ImmutableSortedDictionary
  • ImmutableSortedDictionary<TKey,TValue>
  • ImmutableSortedSet
  • ImmutableSortedSet<T>
  • ImmutableStack
  • ImmutableStack<T>

Чтобы использовать эти коллекции, достаточно подключить NuGet-пакет System.Collections.Immutable.

Итоги и выводы

На данный момент при работе со списками практически все методы в нашей системе возвращают и принимают иммутабельные объекты. Тип возвращаемого объекты обычно IReadOnlyCollection<T>. Это позволило значительно упростить понимание работы и взаимодействия модулей системы между собой. Разработчики всегда понимают, какие данные в каком состоянии.

Задача № 3. Работа с пиковыми нагрузками

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

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

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

  • Probe — отвечает за проверку состояния одного из показателей системы.
  • Spectator — опрашивает один или несколько датчиков. Изменяет свое состояние в зависимости от текущих показаний датчиков.
  • State calculator — на основе журнала метрик вычисляет текущее состояние.
  • State journal — набор показателей каждого из датчиков с указанием времени опроса.

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

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

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

Итоги и выводы

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

Задача № 4. Отладка и логирование

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

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

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

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

Итоги и выводы

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

Если в своем проекте вы используете или рассматриваете вариант использования Serilog, обратите внимание на этот раздел документации. Также будет интересен этот проект.

Задача № 5. Минимизация технического долга

Технический долг — одна из самых типичных проблем любого проекта. К сожалению, вред от него не всегда очевиден. В большинстве случаев его рассматривают только в разрезе устаревших технологий и необходимости тратить время на их поддержку. Но у технического долга есть и еще одна сторона, как ни странно, техническая. Это зависимость от устаревших пакетов и сторонних ресурсов. Да, большинство современных репозиториев пакетов (таких как NuGet в .NET, NPM в Node.js и других) обещают вам, что будут хранить все версии всех пакетов, которые когда-либо туда попали. Однако бывают и исключения. Кроме того, в скриптах сборки некоторых пакетов могут быть зависимости на внешние хранилища, которые и вовсе не гарантируют «вечную» сохранность файлов.

Итоги и выводы

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

В завершение

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

.NET Core удалось сохранить все преимущества классического .NET Framework и при этом обзавестись всеми плюсами кросс-платформенности. Думаю, это один из самых удачных примеров экспансии от Microsoft в новый для себя сегмент разработки. За короткое время платформа смогла пройти все болезни роста и сейчас надежно закрепилась на рынке.

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

«Полювання» на пам’ять. Практичні рекомендації щодо уникнення memory leaks на прикладі Node.js

$
0
0

За часів, коли комп’ютери були великі, а обсяги пам’яті незначні, розробники «боролися» за кожний біт на дорогоцінних мікросхемах. Мови програмування тоді буквально вимагали від авторів програм детального ознайомлення з низькорівневими особливостями конкретної архітектури й відповідно мегаакуратного ставлення до виокремлення та вивільнення й без того обмежених ресурсів.

Проте минуло небагато часу відтоді, як обсяги пам’яті вимірювали числами з дев’ятьма й більше нулями, інструменти абстрагувалися від особливостей архітектур, обросли допоміжним функціоналом, фреймворками, методиками. І в цьому є чимале раціональне зерно, адже нині розробник може ліпше зосередитися на предметній частині проблеми, яку розв’язує його код, замість того щоб гаяти час на вивчення тонкощів конкретної апаратної архітектури. На жаль, неможливо сповна абстрагувати всю апаратну частину, і одним з яскравих прикладів цього є наявність помилок типу виходу за межі доступної для процесу пам’яті (Out Of Memory Error / OOM) у значній більшості, а можливо, й у всіх сучасних мовах програмування.

Особисто для мене перше серйозне знайомство з особливостями ручного керування пам’яттю відбулося після написання перших програм мовою С і це мало приблизно такий вигляд:

Концепція роботи з покажчиками неможлива без знань того, як адресувати й виокремлювати пам’ять, що й примусило опановувати зен. Потім були Java, Python та Node.js, які вже не змушували прискіпливо досліджувати код на наявність викликів free після кожного malloc і набагато зменшили кількість SIGSEGV через зосередження на блоках пам’яті, яких немає.

Останні п’ять років як хобі я беру участь у роботі над проектом з відкритим кодом Appium в якості Core Maintainer’а. Це фреймворк, серверна частина якого написана на Node.js і яка імплементує REST API, сумісне з протоколом Selenium WebDriver для автоматизації функційного тестування. Appium зазвичай асоціюють з мобільним тестуванням, але він через концепцію драйверів підтримує значну кількість різноманітних платформ, зокрема Windows, Mac OS, Raspberry Pi тощо. Саме в цьому проекті ми стикалися (і далі стикаємося) з цікавими, на мою думку, проблемами, практичними рецептами, про розв’язання яких хотілося б розповісти. Також під час роботи над проектом і як результат опрацювання помилок я виробив для себе кілька правил, зокрема щодо роботи з обмеженими ресурсами, які, сподіваюся, будуть корисні не лише в контексті розробки для Node.js.

Трохи нудної теорії

Node.js використовує сміттєзбірник (Garbage collector) для очищення пам’яті, що була раніше зайнята об’єктами. Ділянка пам’яті, яку V8 (JavaScript engine, розроблений для Chrome та Chromium) використовує для розміщення джаваскриптових сутностей, називається купою (V8 managed heap). Після запуску інтерпретатора для купи виокремлюєтсься ділянка пам’яті, максимальний розмір якої обмежений. У ранніх версіях Node.js це обмеження зумовлено архітектурними причинами й залежно від розрядності інтерпретатора могло мати розмір до 1,5 Гбайт (1400 Мбайт для х64 та 700 Мбайт для х86). У нещодавніх версіях за бажанням максимальний розмір можна збільшити за допомогою параметрів командної стрічки (див. --max-old-space-size).

Реалізація сміттєзбірника в Node.js досить просунута. Вона виявляє потенційні циклічні посилання, розбирається із замиканнями (closures), але безсила перед класичними проблемами вивільнення об’єктів з боку розробника (тобто браку такого вивільнення). Щоб не вдаватися у глибокі «нетрі», треба знати, що новостворений об’єкт будуть вважати «живим» і він не зможе бути переданим процедурі збору сміття доти, доки на нього посилається хоча б одна сутність з активного простору імен. Якщо таких «живих» об’єктів накопичиться досить, щоб їхній загальний розмір досяг максимального розміру купи, V8 не зможе виокремити пам’ять для наступної нової сутності, і це призведе до «краху» всього процесу (FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed).

Досліджуємо проблему

Для діагностики проблем з використанням пам’яті в Node.js в Appium використовуємо Chrome Inspector / Remote Debugger. В Інтернеті є досить інформації про те, як користуватися цим інструментом. Відлагоджування можна здійснювати в реальному часі або за допомогою дослідження знімків стану купи (Heap Snapshots). На мою думку, останній метод ефективніший, особливо якщо є проблема на комп’ютері користувача, до якого немає фізичного доступу. У Node.js до версії 12 треба під’єднати модуль Heap Dumpі надіслати процесу SIGUSR2, щоб Node.js створив знімок купи в активному каталозі процесу (не впевнений, що це працює у Windows, оскільки сигналів там немає). Після релізу версії 12 цю функційність внесено в основну кодову базу Node.js, тому під’єднувати цей модуль більше не треба. Знімок купи можна потім завантажити в той самий інспектор для дослідження. Якщо знімок зроблено у правильному відрізку часу, то в інспекторі можна буде побачити, які сутності займають найбільше місце в купі і стек викликів під час їхнього створення, чого в багатьох випадках досить для локалізації помилки в коді. Внісши потрібні виправлення, процедуру слід повторити й переконатися в тому, що проблеми немає й не відбувся регрес.

На жаль, такі проблеми майже неможливо розв’язати без знімків або хоча б досить детального описання кроків для їхнього відтворення. Останній варіант досить непевний, бо інколи для розв’язання проблеми треба буде відтворити й усе оточення. Також, залежно від характеру помилки, відтворення може потребувати тривалого часу (інколи йдеться про години, навіть дні).

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

Запис журналу подій (logs) є звичною практикою для всіх більш-менш серйозних застосунків. Журнали можуть інколи бути єдиною ниточкою, яка дасть змогу розплутати клубок загадкової поведінки застосунку в конкретному середовищі (читайте на комп’ютері користувача).

Але в нашому випадкусаме журналювання «виїдало» доступну пам’ять й зумовило OOM.

Appium для журналювання використовує тонку обгортку над модулем npmlog. Аналіз вищезазначених знімків зі звіту засвідчив, що значну кількість пам’яті в купі займають стрічки (strings), а якщо точніше, то стрічки, що були записані в журнал. Крім того, виявилося, що більшість з них займають по кілька мегабайтів (!), хоча файл журналу мав розмір менше як 1 Мбайт.

Надалі аналіз модуля npmlog засвідчив, що в ньому є внутрішній циклічний буфер, у якому зберігають N недавніх записів у журнал. Стандартно N становить 10 000. Якщо припустити, що середній розмір 1 стрічки — 1 Мбайт (а там були й набагато довші), це дасть загальний розмір журналу мінімум 10 000 Мбайт або 10 Гбайт, що вже далеко за межами доступної пам’яті. Тому спочатку ми встановили максимальний розмір буфера рівним 3000. Це дало певне поліпшення, однак проблему все одно не розв’язало — у буфер потрапляли дуже довгі стрічки, яких не було в журналі (тобто вони були, але обрізані максимум до 300 символів від початку), і ми спершу не могли зрозуміти причину такої поведінки. Подорож «нутрощами» реалізації Node.js, що тривала кілька вечорів, нарешті, допомогла знайти відповідь — інтернування стрічок (strings interning) та відповідний баг на цю тему.

Виявляється, виклики substring, trim, split і схожих методів для «поділу» стрічок не зберігає нову копію оригінальної стрічки, а зберігає покажчик на її зріз (slice). Зберігши такий покажчик у масиві, збільшуємо кількість посилань на оригінальну (довгу) стрічку, що потім не дає змогу сміттєзбірнику стерти її з пам’яті. Розв’язання цієї проблеми недосконале, але ліпшого поки що знайти не вдалося. Ідея тут проста — примусити інтерпретатор зберігати копію скороченої стрічки під час збереження її в буфер журналу, замість того щоб зберігати посилання на оригінал.

Висновки

  • Не покладайтеся сповна на релізацію модулів, отриманих від третіх сторін, заздалегідь не вивчивши їхні API та особливості роботи.
  • Не бійтеся заглянути «всередину» цих модулів, якщо невпевнені в їхній функційності.
  • Учіться на око визначати приблизний максимальний розмір структур даних з динамічним розміром під час написання коду — списків, хешів, дерев. Особливу увагу треба зосереджувати на структурах, які будуть доступні протягом життєвого циклу застосунку або більшої його частини (в ідеалі таких структур має бути якнайменше). Якщо приблизний максимальний розмір структури досягає хоча б десятої частини розміру всієї доступної пам’яті, варто задуматися про обмеження кількості елементів у ній та/або про обмеження розміру цих елементів.
  • Вникайте в особливості реалізації вашої мови програмування — це хоч і потребує додаткових зусиль, зате допоможе в майбутньому уникнути проблем, які складно діагностувати.
  • Реальною причиною втрат пам’яті в чималих проектах може бути майже кожна стрічка коду — намагатися навздогад знайти її і розв’язати проблему, не маючи відповідних матеріалів для детального дослідження, буде марним гаянням часу.

Давши Promise — тримайся, не давши — кріпися

Ще один цікавий випадок можна знайти тут.

Згідно зі знімком, купа була сповнена стрічок, але незрозуміло, як вони там опиняються й чому залишаються. Ланцюжок викликів стеку (Stack Trace) демонстрував, що стрічки утримуються всередині Bluebird-промісів. Але чому ці проміси акуратно накопичуються в пам’яті й надалі не стираються звідти, не міг сказати ніхто. Після кількох «підходів» стало зрозуміло, що без радикального рішення обійтися буде складно. Один з методів, сигнатура якого розміщена вище по стеку, мав таку хитромудру реалізацію черги, що саме описання цієї реалізації займало більше місця, ніж її імплементація. Та ще й до того це все було «підживлене» хаками, що дають змогу скасувати проміси. Заміна реалізації черги з використанням асинхронних локів (async lock) дала змогу уникнути втрат пам’яті, а також зробила непотрібними наявні хаки.

Висновки

  • Якщо ви не можете розібратися в певній частині коду або код має такий вигляд, що лише за допомогою багатогодинної медитації можна відкрити його сакральні таємниці, та ще й до того ж у виконанні коду є проблеми, то це може означати, що його треба переписати. Звичайно, таке рішення слід ухвалювати командою, але наявність хитрих хаків, коментарів TODO та FIXME неодмінно буде прекрасним індикатором того, що ви на правильному шляху.
  • Завжди спочатку намагайтеся зреалізувати функційність за допомогою стандартного документованого інструментарію. Удавайтеся до застосування хаків лише тоді, коли інші стандартні рішення «не працюють». Зазвичай використання прихованих API — найпростіший спосіб «прострелити собі ногу», особливо, якщо ви не впевнені в тому, що робите.

Де просто, там живуть років 100

Третій і останній випадоку цьому огляді.

Проблема все в тих самих промісах, що (незрозуміло як) залишаються в пам’яті. Була застосована стратегія з попереднього випадку, і ще один хитрий хак переписано з використанням «усталеніших» методів. Але це не допомогло, і пам’ять все одно втрачали. Зате у знімку стек був набагато простішим, і тепер знайти «винуватця урочистості» більше не було суперскладною проблемою.

Висновки

  • Згодом будь-який проект збільшується до розмірів, коли ніхто не здатен засвоїти сповна його архітектуру. Спрощення й локалізація проблемних областей — це завжди прекрасні «друзі» для розв’язання таких проблем.
  • Думайте про керування пам’яттю безпосередньо під час написання коду й переглядів комітів ваших колег. Наявність сміттєзбірника (Garbage collector), хоч яким просунутим він був, не позбавляє код можливих проблем з втратами пам’яті.
  • Додавайте моніторинг стану пам’яті у процес неперервної інтеграції. Є інструменти, що можуть автоматично генерувати попередження, якщо використання пам’яті застосунком набагато «відхиляється» від медіани.
  • Користуйтеся статичними аналізаторами коду.

Що більше знаєш, то більше сумніваєшся

На мою думку, проблеми з втратою пам’яті належать до найскладніших для розв’язання програмних проблем. Вони непомітні для компіляторів та інтерпретаторів, а також можуть за певних умов або не проявлятися взагалі або дуже рідко, через значні відрізки часу. Виникнення такої проблеми на системному рівні вважають критичною помилкою і призводить до «краху» всього процесу. Це робить memory leaks одночасно і небезпечними, і цікавими (challenging) з погляду розробника.

Viewing all 2421 articles
Browse latest View live