На место героя рубрики «10 вопросов программисту» Виктор Яблоков подходит как нельзя лучше, хотя, по его собственному признанию, давно не кодит — за вычетом SQL-запросов и скриптов для автоматизации работы с продуктовой аналитикой, зато в своё время писал 3D-игры под наладонники и занимался антивирусным движком под Symbian. Чуть забегая вперёд, дополним портрет: первым местом работы Виктора был Cybiko (стартап Давида Яна), а дальше — 14 лет в «Лаборатории Касперского», где сегодня он руководит управлением разработки мобильных решений.
Мы расспросили Виктора о том, чем ему помог в IT математический аппарат, как мобильная разработка встраивается в структуру компании, с какими угрозами имеет дело его команда, какие у «Лаборатории Касперского» патенты, почему в мобильной разработке продуктовые релизы делаются по Канбану, как работает ферма автотестирования, — и о массе других технических и мировоззренческих вещей. Предупреждаем: много, много букв по делу.
— Как у тебя складывалась жизнь до IT и как ты влился в индустрию?
— С моей точки зрения, жизнь постоянно даёт тебе шансы и бросает вызовы. Либо ты их принимаешь, либо уклоняешься. Я вызовы стараюсь принимать, так что всю свою жизнь вижу как последовательность вызовов — когда более, когда менее значимых.
Предпосылок к тому, чтобы стать айтишником, ни в детстве, ни в ранней юности у меня не было. Семья жила довольно скромно, компьютера дома не было. В школе я учился неплохо, но скучал. Как теперь понимаю, как раз-таки за отсутствием вызовов. Однажды преподаватель по математике предложил мне поучаствовать в олимпиаде. До неё оставалось две-три недели. Я поставил перед собой цель — не опозорить родную школу. Выиграть не удалось, но вполне достойное третье место по городу занял. У меня прорезался интерес к теоретической математике. Вскоре у нас в Вологде открылся физико-математический лицей. Вот и следующий вызов: почему бы не попробовать поступить туда? Сумел. Такими шагами я и дошёл до университета — поступил на мехмат МГУ.
Учился я на кафедре дифференциальных уравнений, занимался уравнениями математической физики в очень неоднородных средах. Коротко говоря, это когда в периодических средах с малыми ячейками протекает физический процесс и встаёт вопрос, что будет с ним при уменьшении ячейки. Далековато от прагматики, но только на первый взгляд. Например, вообразим, что вместо стандартного спутника мы запускаем в космос объект с определённым образом расположенными отверстиями в поверхности, чтобы он весил меньше обычного, но по своим физическим характеристикам мало отличался от обычного. Меня грела надежда на то, что мои изыскания найдут применение в науке. Кстати, кандидатскую диссертацию на мехмате МГУ я в итоге защитил, причем писал ее в метро по дороге на работу и домой.
Программировать начал на первом курсе, на языке КуМир — полностью русскоязычном. Уже тогда усвоил: не важно, на чём программировать, важно уметь оперировать алгоритмами. Кодил в университете вечерами. Пристрастился решать задачи для товарищей. Понравилась девушка (в будущем она стала моей женой) — стал помогать ей, а в её группе с программированием всё было серьёзнее, так что купил книжку, чтобы не подкачать.
В «кризисном» августе 1998 года я наконец обзавёлся компьютером. Когда рубль обвалился, отец получил долги по зарплате. Мы с другом носились по Москве, по отдельности покупая комплектующие. На монитор денег не хватило — выпросил у приятелей в общежитии чёрно-белый. С тех пор писал программы не только вечерами, но и ночами.
На пятом курсе остро встал вопрос, куда двигаться дальше. К тому моменту я убедился в том, что, останься я в науке, мои достижения в теории получили бы практическое развитие разве что у будущих поколений. А мне хотелось, чтобы моя работа приносила пользу сейчас. Тогда же я решил остаться в России, хотя многие с нашего курса уехали за границу. Были такие предложения и у меня.
В 2000 году устроился к Давиду Яну в Cybiko. Сначала приходящим тестировщиком, потом меня взяли в штат. Постепенно компания расширялась, и я захотел перейти в программисты. Тогда они ориентировались на то, чтобы выпускать по приложению в день. А программистов было 15–20 человек. Так что мне надо было делать два приложения в месяц. Попутно мне представилась возможность совмещать все роли. Я и дизайнером чуть-чуть был, и черновые варианты текста писал, и тестировал. Эдакий full-stack специалист в квадрате. Но за полтора-два месяца приноровился.
В какой-то момент я начал отвечать за 3D-игрушки для наладонников. И один из первых моих патентов был связан с движком для создания 3D-игр — чего-то наподобие Wolfenstein. Именно такого типа технологии меня издавна заинтересовали — не GUI, а «потроха».
В геймдеве мне нравилось. Ещё бы — при таких-то вызовах.
— Как ты попал в «Лабораторию Касперского», с чего начинал свой путь в ней и как далеко зашёл?
— Покидать геймдев меня не тянуло. Но я делал продукт не для себя, а под ТЗ заказчика. Захотелось попробовать свои силы в компании, которая занималась in-house разработкой. Вакансия «Лаборатории Касперского» мне подвернулась случайно. Им требовался разработчик антивирусного решения под Symbian.
К лету 2004 года я уже задумывался о мобильной безопасности. В геймдеве тогда основным способом монетизации были SMS. Я представлял себе, как гипотетический злоумышленник мог бы использовать его для наживы, и хотел узнать про это больше. Это было одним из поводов сходить на собеседование. Обнаружилось, что опыт работы с мобильными платформами у меня был неплохой. На той встрече я много говорил — выдвигал гипотезы о том, какие угрозы могут ждать нас в ближайшем будущем. А ведь в то время вредоносных программ под мобильные платформы были единицы — вроде Cabir, Skulls и Commwarrior. В основном черви, распространявшиеся по Bluetooth или MMS.
Через две недели я начал работать в «Лаборатории Касперского». Точнее, в её внутреннем стартапе. Формально — разработчиком, но, такой вот изгиб карьеры, в департаменте продаж. Сразу со старта меня бросили на разработку антивируса под Symbian. Я совмещал все мыслимые роли: и тестировал, и отвечал за дизайн, был и проектным менеджером, и аналитиком. Мне доводилось и самому разбирать код вредоносных программ под мобильные платформы, если использовать внутрилабораторный сленг, я попробовал себя в роли «дятла».
Дятел — антивирусный аналитик. «Дятлы» непрерывно обрабатывают всё возрастающий поток вирусов, червей и прочих угроз. Иными словами, день и ночь «долбят» новых «зловредов» (или по клавиатуре). В «Лаборатории Касперского» «дятел» — не обидное прозвище, а очень даже почётное.
Кстати, спустя всего год после того, как пришел в компанию, я получил первый приз из рук Евгения Валентиновича — за перспективные разработки.
Переход к управлению у меня происходил постепенно. В 2004-м я пришел на позицию разработчика, потом стал стал старшим разработчиком, в 2008-м — ведущим, а в 2009 уже получил должность руководителя направления разработки под мобильные устройства. Это обычная история: получая опыт работы в новых областях, ты пробуешь его применять и уходишь от разработки. Долгое время, подобно многим тимлидам, пытался совмещать. Но в какой-то момент всегда встаёт вопрос: либо ты технический специалист, либо менеджер. Пока приоритетными для компании платформами оставались Symbian и Windows Mobile, ещё удавалось сидеть на двух стульях. А потом темп изменений стал нарастать, и пришлось выбирать.
— Чем сложна киберзащита мобильных устройств и какие цифровые угрозы сегодня самые острые?
— По большому счёту, угрозы для мобильных устройств в своём развитии проходили те же этапы, что и угрозы для ПК, только куда быстрее: несколько лет против десятилетий. Поначалу главная проблема заключалась в том, насколько слабо люди были осведомлены об опасностях, которые им грозили. Уже вспыхивали массовые заражения на мобильных платформах, а пользователи не верили, что такое возможно. Не сталкиваясь с угрозами сами, они и не испытывали потребности в защите своих телефонов и наладонников.
Но по-настоящему взрывной рост вредоносных программ совпал с резким ростом популярности Android. Первый зловред под него мы засекли в августе 2010 года.
На самом деле сегодня угрозы для платформы Android крайне многообразны: начиная от относительно безобидных рекламных приложений, которые буквально заваливают пользователя рекламными банерами, заканчивая сложными APT-угрозами, возможности которых порой безграничны, один только Skygofree чего стоит!
Безусловно для пользователя самыми значимыми угрозами являются те, которые несут прямой урон его финансовому состоянию, например, мобильные банковские троянцы, которые выуживают банковские учетные данные. В них часто предусмотрены хитрые сценарии увода данных. Например, они подсовывают пользователям мобильных приложений банков фишинговые окна, требующие ввести информацию с кредитной карты, как это было в случае с Asacub. При этом такой троянец может маскироваться под что угодно — приложения для работы с MMS или клиент популярного сервиса бесплатных объявлений и т.д.
А еще есть троянцы-шпионы, которые, например, сливают интимные фото на сервера злоумышлеников, а также троянцы-вымогатели, которые блокируют работу устройства.
При этом количество таких угроз постоянно растёт. На текущий момент нам известно более 34 миллионов угроз различных классов.
При этом количество таких угроз постоянно растёт. На текущий момент нам известно более 34 миллионов угроз различных классов.
В наши дни наиболее серьёзные сложности с киберзащитой мобильных платформ — это закрытость ОС, их фрагментация, а также ограничения, которые создатели самих платформ порой искусственно создают для разработчиков security-софта, наконец, сама модель распространения приложений.
Что касается магазина приложений, он может быть абсолютно надёжно защищён (чего, правда, в действительности всё-таки не бывает, ведь ни одна система не может быть на 100% надежной), однако существуют сценарии, по которым программы попадают на устройство из других источников. В случае с iOS это, например, подписанные enterprise-сертификатами приложения, а также корпоративные iOS MDM профили. Да что там, в сам AppStore периодически, по нашим наблюдениям, проникают вредоносные программы. Например, настоящее шпионское ПО Pegasus.
При этом вредоносными программами спектр угроз не ограничивается, их множество, в том числе риски утечки данных, например, через фишинговые страницы или при потере устройства.
Вообще в работе мы постоянно сталкиваемся с различными вызовами. Например, как добиться того, чтобы приложение автостартовало и не выгружалось из памяти, как в условиях песочницы Android научиться фильтровать контент в браузере Chrome, фильтровать нежелательные звонки, защитить сторонние приложения, как в реальном времени перехватить и предотвратить установку вредоносного ПО.
Фрагментация — тоже головная боль. В случае с Android все производители устройств на базе этой ОС пытаются выделиться на фоне конкурентов. Начинают бороться за заряд аккумулятора и производительность аппарата, вырезать из системы «лишние» компоненты или добавлять свои, запрещать программам, включая защитные решения, запускаться самим и работать в бэграунде. Зачастую приходится затачивать решения под конкретного производителя или даже под конкретную модель. Это трудно, но решаемо. Мы организовали у себя процессы разработки так, чтобы отлавливать такие проблемы на ранних этапах (например, мы мониторим корректность работы наших продуктов на обновлениях прошивок популярных вендоров) и затачивать свои решения, чтобы они функционировали на максимальном количестве моделей гаджетов.
Кстати, поддержка старых версий ОС с точки зрения фрагментации, количества и масштаба тех проблем, что вносит сам производитель, — не такая уж и проблема, а вот с поддержкой новых версий OС дела обстоят чуть сложнее — приходится поработать. Что до вывода той или иной версии ОС из поддержки, мы лояльны по отношению к пользователю: обычно мы их поддерживаем даже дольше, чем сами производители устройств, и дольше, чем рекомендуют производители операционных систем.
— Кто работает в подразделении мобильной разработки и как оно выглядит структурно?
— Мы в «Лаборатории Касперского» — центр экспертизы по мобайлу. За исключением непосредственного исследования киберугроз всё, что в нашей компании разрабатывается по линии продуктов для мобильных устройств, делается у нас в подразделении. При этом всё, что мы создаём в мобильной разработке, расходится по двум веткам — b2c и b2b.
Это и полноценные защитные решения, такие как Kaspersky Internet Security для Android или Kaspersky Security для мобильных устройств. Первое — для домашних пользователей, а второе — для бизнеса. А также различные приложения, например, Kaspersky Password Manager, который помогает генерить и хранить надежные пароли, Kaspersky Secure Connection — решение для защиты трафика, в частности во время использования ненадежного Wi-Fi.
Помимо этого, мы разрабатываем утилиты — решаем узкую пользовательскую проблему приложениями под конкретные платформы. Например, наш продукт Kasperksy QR Scanner работает как полноценный QR-сканер, но при этом до загрузки проверяет, куда ведёт считанный им код. А тот может вести, например, на фишинговый сайт, и переход на такой ресурс сканер блокирует. А Kasperksy Battery Life помогает продлить время работы батареи на Android. В общем, рассказывать о наших продуктах я могу бесконечно.
С организационной стороны, в фундамент нашего подхода — и с точки зрения процессов, и с точки зрения общей организации — заложена идея re-use и максимального шаринга общих практик.
Можно было бы сформировать команды по сервисам и сделать так, чтобы в каждую входили люди, которые отвечали бы за мобайл-составляющую. Мы пошли другим путём — открыли центр, отвечающий за мобильную разработку от и до. В нашем случае это несёт наибольшую выгоду. Все продукты сложные и зависят от специфики вендоров и особенностей версий ОС, и, если бы команды работали отдельно друг от друга, они наступали бы на одни и те же грабли. Мы же из решения каждой проблемы извлекаем уроки и масштабируем наработки на все свои проектные команды.
Организован отдел — в народе «мобильный штаб» — следующим образом. Опирается всё на core-команду: она занимается фреймворком, так называемым SDK, который объединяет все или почти все технологии подразделения. Это субстрат, на котором «растут» продукты. Продуктовые команды берут наши общие мобильные компоненты и на их базе — с доработкой бизнес-логики, UI и пр. — выпускают продукты.
Далее, наряду с технологической командой, у нас имеется два крупных продуктовых отдела. Первый называется «отдел разработки защитных решений» и отвечает за всё, что связано с ними (уже упомянутые Kaspersky Internet Security for Android или Kaspersky Security for Mobile). Второй — за неантивирусные приложения (их объединяет то, что они входят в кроссплатформенные решения и взаимодействуют с нашим порталом My Kaspersky), например, Kasperksy Password Manager или Kaspersky Safe Kids.
В управлении есть выделенный архитектор, который отвечает за общие практики разработки и re-use. Android и iOS команды выделены в два близких друг другу направления, и широко делятся практиками. В каждом из отделов трудятся проджекты.
В управлении есть отдел контроля качества, через который проходят все релизы мобильных продуктов. Отдельная команда занимается сопровождением автоматизации, а в саму автоматизацию вовлечены разработчики и тестировщики всех проектных команд.
С одной стороны, во избежание дублирования функций мы стараемся использовать общие с другими подразделениями R&D централизованно поддерживаемые процессы и инструменты, а с другой — учитывать мобильную специфику и, когда это объективно нужно, адаптировать инструментарий под мобильную специфику.
Проекты у нас разных масштабов: есть экспериментальные, которыми занимается один разработчик, а есть проекты с командой из менеджера, тим-лида, архитектора, разработчиков, аналитиков, дизайнеров, инженеров по документации и локализации, а также тестировщиков.
Параллельно с практикой re-use внутри нашего подразделения, мы «реюзаем» то, что делают в других уголках компании. Есть масса компонентов, которые мы получаем из Core Technologies, «Антивирусной лаборатории» и т. д. Мы живём не в вакууме.
— Кого вы берёте к себе в отдел и каких специалистов ты сам хочешь видеть под своим началом?
— Охотно берём молодых специалистов и выпускников вузов. Когда-то, лет десять назад, я в «Лаборатории Касперского» был одним из первых, кто взял за правило целенаправленно привлекать к себе в отдел стажёров. Я очень верю в молодых людей с горящими глазами. Для таких у нас созданы все условия, чтобы они выросли в классных спецов. Многие из тех, кто занимает серьёзные позиции в компании, включая руководителей групп, тимлидов и senior-разработчиков, в своё время присоединились к компании в качестве стажёров. Вообще, наверное, сейчас треть мобильного отдела — бывшие стажёры. Кстати, для тех, кто хочет попробовать свои силы, у нас есть специальная программа SafeBoard.
А вот что у нового сотрудника точно должно быть изначально, так это желание спасать мир. Потому что ровно этим мы в «Лаборатории Касперского» и занимаемся изо дня в день.
Важно ещё одно качество, для которого у нас правда нет строгого термина. Специфика нашей работы в том, что мы делаем решения для защиты миллионов пользователей. Наши ошибки могут повлечь за собой серьёзные последствия — как для пользователей, так и для нас самих. Поэтому у нас налажена многоступенчатая система защиты от ошибок. Мы всеми силами стремимся её укреплять. У нас в ходу присказка: «К пуговицам претензий нет». Это когда я карманчик пришил, ты рукав, он пуговицы, каждый элемент хороший, а костюмчик получился так себе. Так вот, искомое качество — это не просто ответственность, это желание и готовность выходить за рамки своих непосредственных обязанностей, мыслишь шире, не категориями карманов и пуговиц, заботиться о том, чтобы хорошим был целый костюм, а не составные его части.
Поделюсь болью: девять из десяти разработчиков мобильных приложений на рынке не всегда думают о безопасности. У нас — думают. И работают как единая команда, отдавая себе отчёт в том, что делают коллеги со смежными ролями. Это важная часть защиты от ошибок.
Ну а относительно технологического стека я не скажу, что у нас какая-то ни на что не похожая мобильная разработка. Мы используем те же подходы и инструменты, что и многие другие компании. Допустим, человек, занимавшийся раньше мобильными играми, может прийти к нам, и, если он достойный профи и разделяет наши ценности, ему найдётся участок работы. Да что говорить — я сам в 2004 году оказался таким человеком.
Правда, уровень разработчиков у нас ощутимо выше, чем в среднем по индустрии. Это не бахвальство — факт: к нам регулярно «стучатся» люди с опытом работы тимлидами в крупных компаниях и не проходят у нас технического собеседования. Причём, хотя порог входа у нас высокий, мы не спрашиваем ничего из ряда вон выходящего.
Благодаря тому, что вся мобильная разработка сконцентрирована в одном подразделении, мы в состоянии давать человеку проекты, которые, с одной стороны, будут привлекательны именно в его глазах, с другой — позволят ему принести максимум пользы компании.
Смена проекта по желанию сотрудника в порядке вещей. Обсуждаем с ним детали, договариваемся о переходном периоде, и в течение месяца-двух он переходит в другой проект. Перебраться из мобильной разработки в инфраструктурную или в десктопную тоже возможно. И наоборот, к нам в мобильный отдел перекочёвывали специалисты из других подразделений и становились, например, лидами. Мягкая ротация происходит постоянно.
Вот, с моей точки зрения, три главные причины, почему мобильными решениями у нас заниматься действительно круто.
- Вдохновляет то, что ты делаешь нечто действительно полезное — востребованные продукты, которыми пользуются миллионы людей по всему миру. И да, ты чувствуешь, что твое детище помогает защищать мир от киберпреступности.
- Это продукты — твои. Ты делаешь их не по заказу клиента, о котором через полгода забудешь. Как и все члены команды, ты вправе привносить в них свои идеи, это приветствуется. Поработав какое-то время, в продуктах ты начинаешь различать частичку себя.
- Ты начинаешь глубже разбираться в технологической части. Ребята у нас начинают копаться в исходниках Android. Они неплохо разбираются в том, как эта ОС работает. Благодаря чему кто-то из них оказывается способен сделать то, что многим кажется невозможным. Kaspersky Safe Kids, Kaspersky Battery Life, Kaspersky Password Manager, — сплошь такие решения, что, спроси среднего мобильного разработчика со стороны, сумеет ли он такое реализовать, и он может удивиться — «как так, Android ведь — песочница». То же с iOS. У нас всё располагает к тому, чтобы с уровня человека, программирующего по тем API, которые ему дали, со временем погружаться все глубже и глубже и начинать хорошо понимать тонкости операционных систем.
— Насколько, чем и как автоматизирована работа в мобильном отделе?
— Мы уже несколько лет как построили Continuous Integration на Jenkins. Для контроля версий используем Git. Всё по-взрослому: на каждом pull request проходят проверки — code review и статический анализ кода. Потом сборка продукта. При сборке — юнит-тесты. После сборки — smoke-тесты. Дальше билд попадает на ферму автотестирования. Не каждый, конечно. Потому что возникают классические проблемы: тестов очень много, нельзя останавливать сборку, нельзя останавливать передачу в тестирование. Поэтому не всё сразу. Есть тесты, которые запускаются на каждый pull request, есть те, которые запускаются ночью.
Ферма автотестирования состоит из реальных устройств. Также в нашем распоряжении серверные мощности, на которых развёрнуты эмуляторы, и если специфика самого девайса на физическом уровне не принципиальна, сборку гоняем на них.
Нам хочется доверять автоматизации настолько, чтобы ручное тестирование сводилось к исследовательскому тестированию, анализу поведения приложения с точки зрения пользователя. Пока на ручное тестирование мы тратим, по-моему, слишком много времени. Continuous Integration есть, билд проверяется и доставляется, а дальше? Пока у нас налажена воронка. Сначала раскатываем билд команде тестирования, потом раскатываем в IRO — сотрудникам компании. Если всё о'кей, то выпускаем в «бассейн» — так у нас называют сообщество внешних бета-тестеров. С их помощью проверяем сборку в первую очередь на краши и ANRs. Порядок? Выкатываем в продакшен уже на всех пользователей. Точнее, поэтапно, что возможно и на Android, и на iOS: доставляем релиз части пользователей и постепенно раскатываем его шире.
Мы хотим прийти к тому, чтобы все эти процессы выполнялись с минимальным участием человека. Сейчас у нас автоматизировано большинство действий вплоть до момента раскатки в бета-канал. Мы фокусируемся на самых узких местах и планируем справиться прежде всего с ними.
— Какие методологии разработки вы «исповедуете» у себя в отделе?
— Над выпуском новых версий продуктов наши проектные команды работают почти исключительно по Канбану. У нас больше нет фиксированных спринтов (несколько лет назад были): из-за динамичности разработки мы пошли дальше. Попросту из-за динамичности разработки. У нас множество заказчиков внутри компании, мы входим в различные бандлы, которые зачастую поставляются конкретному партнёру «Лаборатории Касперского». Так что изменения в нашем приоритизированном бэклоге случаются очень часто. В такой ситуации закладываться на спринты фиксированной длины было бы неправильно. «Немобильно». Если релиз нужно выпустить завтра, он состоится завтра. Такое случается почти на каждой неделе. Поэтому — Канбан, с планированием задачами, а не итерациями.
Что касается разработки технологий вне жизненного цикла релизов продуктов, здесь мы задействуем разные подходы, вплоть до итеративного waterfall, который используется, например, при разработке сложных движков.
— А разрабатываете ли вы и ваш отдел инновационные технологии? Если да, то дают ли патенты на мобильную разработку ощутимые преимущества компании и сочетается ли практика патентования с темпами современного рынка?
— Мобильная команда получает несколько патентов в год. Патентование безусловно необходимо. При этом из примерно 700 патентов, около 10% связано с мобильными технологиями (сам я являюсь соавтором где-то двух десятков патентов), и мы стремимся увеличить это число следуя трендам развития отрасли!
Мы не патентуем решение, если не уверены, что оно будет использоваться. Только если точно или с высокой долей вероятности ему найдётся у нас применение. В конце концов, удовольствие это не бесплатное. Мы стараемся получать патенты с широким объемом прав, выходя за рамки нашей области цифровой безопасности и пытаясь «заглянуть» в возможное будущее развития технологий.
При этом патентование никак не противоречит сокращению time-to-market. Это параллельные процессы. Да, оно требует финансовых затрат, иногда занимает годы. Правда, в последнее время мы получаем патенты сравнительно быстро — многому научились, в частности правильно оформлять их.
Это не стопорит выход продукта с использованием соответствующего ноу-хау. А выпуск решения с публикацией информации о наличии в нём такой фичи или технологии в открытых источниках лишь приветствуется. Мы стараемся подавать патентные заявки еще на стадии проработки решений, когда еще только готов лишь Proof-of-concept, для того, чтобы к моменту выхода продукта (или технологии) на рынок технология либо уже была бы запатентована (patented), либо была в статусе патентной заявки (patent-pending).
Три–четыре года назад в патентовании мы удерживали фокус на b2b: выводили на рынок решения для защиты информации, разделения персональных и корпоративных данных, контейнеризации, запуска кода в безопасных средах. Последние патенты, которые мы получили, касаются способов перехвата контента на Android — того, каким образом в условиях песочницы, с ограниченным доступом к различной информации, всё-таки получать и фильтровать её.
— Масштабы «Лаборатории Касперского», если откровенно, не замедляют работу отдела, хотя бы необходимостью согласований?
— Да, согласования с другими департаментами и командами требуются, и часто. Это может увеличивать time-to-market. С другой стороны, есть способы сокращать его — тем же MVP-подходом. Не надо сразу бросаться строить подводную лодку, особенно если речь идет о переправке через реку и задачу можно решить с помощью плота. Незачем инвестировать сразу много: надо валидировать гипотезу, понять, будет ли фича востребована, а потом уже решать, вкладываться или нет. Так что критически важных замедлений процессов из-за масштабов всего бизнеса я не вижу.
Мы в мобайле сфокусированы на предельно быстрой обработке поступающих к нам требований, на удовлетворении потребностей пользователей и клиентов. Менеджер продукта эти потребности ранжирует по приоритетности, и мы их последовательно закрываем.
Нельзя делать всё и сразу. Но если идея валидирована, мы готовы сесть и оперативно сделать MVP. Пример — утилита IoT-сканер. После того, как эта задумка пришла на ум нашему коллеге, прототип мы соорудили за неделю.
— Твоё самое большое достижение и самый большой фейл за годы работы в «Лаборатории Касперского»?
— Фейл связан с легендарной «железной комнатой». Вернее, не совсем фейл. Некоторое время назад, еще в эпоху Symbian, нам требовалось тестировать свои решения на реальных угрозах. Тогда вредоносные программы мало на что были способны, разве только на отправку MMS/SMS. Вытащил симку — червь ничего не сделает. Единственное, ещё по Bluetooth мог попросить соседа об установке на его телефон. Но всех соседей по офису мы знали, от начальства сидели далеко. Всех вокруг предупредили, чтобы не принимали запрос от червя. Так и работали какое-то время. И вполне себе спокойно, пока однажды сотрудник не прошёл мимо меня с Symbian-устройством и к нему не сунулся в телефон Cabir. Босс — сразу к Евгению Валентиновичу [Касперскому] с расспросами. Я перепугался: думал, уволят. И Евгений Валентинович постановил: «Вот этих с Cabir — в „железную комнату"». И действительно, в офисе была оснащена специально изолированная, «железная комната», в которой не ловилась сотовая связь и Wi-Fi. Чуть что требовалось проверить, я брал ноутбук и нёсся со своего рабочего места туда, через два этажа, чтобы не заразить случайно устройства коллег. Это был мой фейл? Абсолютно точно. Но в итоге он нежданно-негаданно имел важные для компании последствия.
Вообще, никогда не бывает одного виновного в провале. За ним всегда кроется комплекс причин. Фейлы случаются каждую неделю. Главное — учиться на них. Если ты не проводишь Root Cause Analysis, не понимаешь, из-за чего всё пошло наперекосяк, и не принимаешь никаких мер к тому, чтобы минимизировать вероятность повторения ошибки в будущем, дело плохо. Я очень ревностно отношусь к промахам и провалам и воспринимаю каждый как свой личный. Если что-то в компании по мобильному направлению не слава богу, это моя вина.
А мой главный успех — становление мобильного направления в «Лаборатории Касперского» как такового. То, как из разрозненных проектов и задач мы вместе создали, по-моему, сильное и технически, и с точки зрения подходов к работе подразделение. Одной из наших побед было то, что в какой-то момент, лет семь назад, мы не побоялись из двух продуктов — Kaspersky Internet Security для Android и Kaspersky Endpoint Security для Android — выделить наши общие технологии в SDK. Это сильно повлияло на наше будущее. Мы создали нашу компонентную SDK-разработку сами в достаточно короткие сроки. Подозреваю, не прими мы это решение, мобильное направление постепенно стало бы неэффективным.
Мобильной разработке нужно больше программистов. Подробное описание вакансий есть на карьерном портале «Лаборатории Касперского». Но у тех, кто дочитал до конца, есть возможность попасть на собеседование, минуя техническое интервью. Решите наши задачи и присылайте ответы в специальной форме — мы проверим и свяжемся с сильнейшими.
Android + Java & Kotlin
Задача №1
Есть код
getSupportFragmentManager()
.beginTransaction()
.add(R.id.activity_main_frame, messageFragment)
.add(R.id.activity_main_frame, messageFragment2)
.add(R.id.activity_main_frame, messageFragment3)
.show(messageFragment2)
.commit();
Какой фрагмент в результате транзакции будет виден пользователю в итоге?
Конечно, вы проверите и увидите третий фрагмент. Но почему так?
Как все-таки добиться того, чтобы, не меняя порядок «add», увидеть в результате транзакции второй фрагмент?
Как после этого вернуть в топ именно третий фрагмент, не трогая сами фрагменты (то есть не удаляя и добавляя их заново во FragmentManager )?
Конечно, вы проверите и увидите третий фрагмент. Но почему так?
Как все-таки добиться того, чтобы, не меняя порядок «add», увидеть в результате транзакции второй фрагмент?
Как после этого вернуть в топ именно третий фрагмент, не трогая сами фрагменты (то есть не удаляя и добавляя их заново во FragmentManager )?
Задача 2
Есть такая Rx-цепочка:
Observable.range(0, Integer.MAX_VALUE - 1)
.take(10)
// something else
.subscribe();
Что уже плохого вы здесь видите?
На первый взгляд, нам нужно только 10 элементов, а в коде используется Observable.range(0, Integer.MAX_VALUE — 1). Получается, что перебор будет происходить до самого конца, хотя нужна только часть. Так ли это?
Опишите, что вообще происходит внутри Observable.range, и как он будет работать в данной цепочке от начала до конца с кодом из исходников.
На первый взгляд, нам нужно только 10 элементов, а в коде используется Observable.range(0, Integer.MAX_VALUE — 1). Получается, что перебор будет происходить до самого конца, хотя нужна только часть. Так ли это?
Опишите, что вообще происходит внутри Observable.range, и как он будет работать в данной цепочке от начала до конца с кодом из исходников.
Задача 3
Даны 3 интерфейса:
public interface Request {
// некоторый контент
};
public interface Producer {
// возвращает null, если объект stopSignal указывает на необходимость остановки,
// либо новый запрос в противном случае
Request GetRequest(Stopper stopSignal);
}
public interface Consumer {
// обрабатывает запрос, завершает обработку досрочно, если
// объект stopSignal указывает на необходимость остановки
void ProcessRequest(Request request, Stopper stopSignal);
}
Используя только средства классической Java SE и Android (без подключения внешних зависимостей) написать Android-приложение. Приложение выкладывайте в файлообменник, в ответе достаточно оставить ссылку.
- В приложении необходимо организовать генерацию, приём и обработку запросом. Для этого необходимо класть в одну очередь задания, возвращаемые функцией GetRequest.
- Запустить несколько обрабатывающих запросы потоков (переменное число, но не менее двух), которые должны обрабатывать поступающие из очереди задания с помощью ProcessRequest.
- Поработать в течение 30 секунд.
- Корректно остановить все потоки. Если остались необработанные задания, не обрабатывать их и корректно удалить.
- Завершить программу.
Дополнительные условия:
- Все настройки приложения должны быть выведены в UI.
- Тип Stopper должен быть определён вами и должен представлять собой механизм досрочной остановки выполняемого действия (предполагается, что GetRequest и ProcessRequest будут его корректно использовать).
- Вызов GetRequest может не сразу возвращать задания.
- Вызов ProcessRequest может не мгновенно обрабатывать задание
Задача 4
Android + Kotlin:
fun main(args: Array<String>) {
val list = ArrayList<String>()
list.add("hello")
list.add("habr")
list.forEach {
if (it.length < 5) return
print(it)
}
print("end")
}
Что выведет данный код и почему?
Задачи под iOS
Задача №1
Что будет выведено в консоль?
Есть ли проблемы в данном коде?
Если есть, то какие?
Есть ли проблемы в данном коде?
Если есть, то какие?
final class User: NSObject {
@objc var nickname = "Foo"
}
func main() {
let user = User()
let observer = user.observe(\User.nickname) { user, _ in
print("nickname: \(user.nickname)")
}
user.nickname += "Bar"
observer.invalidate()
}
Вопрос 2
Что будет выведено в консоль? Поясните свой ответ.
func closureTask() {
func first() {
print("----- first -----")
var num = 42
var str = "foo"
var arr = [1]
let closure = {
print("num: \(num)")
print("str: \(str)")
print("arr: \(arr)")
}
num = 10
str = "bar"
arr = [1, 2]
closure()
}
func second() {
print("----- second -----")
var num = 42
var str = "foo" as NSMutableString
var arr = [1] as NSMutableArray
let closure = { [num, str, arr] in
print("num: \(num)")
print("str: \(str)")
print("arr: \(arr)")
}
num = 10
str = "bar"
arr = [1, 2] as NSMutableArray
closure()
}
func third() {
print("----- third -----")
var num = 42
var str = "foo" as NSMutableString
var arr = [1] as NSMutableArray
let closure = { [num, str, arr] in
print("num: \(num)")
print("str: \(str)")
print("arr: \(arr)")
}
num += 10
str.append("bar")
arr.add(2)
closure()
}
first()
second()
third()
}
func main() {
closureTask()
}
Вопрос 3
Что будет выведено в консоль при исполнении следующего кода? Объясните своё решение.
func main() {
let foundationString = "abcdefg_123456"
let part1String = String(foundationString.split(separator: "_")[0])
let part2String = String(foundationString.split(separator: "_")[1])
let cPart1 = part1String.utf8CString.reversed()
let cPart2 = part2String.utf8CString.reversed()
let cString = Array(cPart1) + Array(cPart2)
let representationPointer = cString.withUnsafeBufferPointer { $0 }
let reversedFoundationString = String(cString: representationPointer.baseAddress!)
print(contains(character: stringToChar("1"), inCString: representationPointer))
print(contains(character: 0, inCString: representationPointer))
print(reversedFoundationString.contains("1"))
print(reversedFoundationString.contains(Character.init(Unicode.Scalar(0))))
print(representationPointer.count == foundationString.count)
}
func stringToChar(_ string: String) -> Int8 {
return string.utf8CString.first!
}
func contains(character: Int8, inCString cString: UnsafeBufferPointer<Int8>) -> Bool {
let length = cString.count
let stringBaseAddress = cString.baseAddress!
guard length != 0 else {
return false
}
for i in 0..<length {
if stringBaseAddress.advanced(by: i).pointee == character {
return true
}
}
return false
}
Вопрос 4
Когда-то давно Мидори сгенерировал пароль для аккаунта на сайте по продаже мёда. Тогда Мидори ещё не пользовался менеджером паролей Kaspersky Password Manager, поэтому записал пароль на листок. Но решил записать его в зашифрованном виде.
На листе были записаны только цифры, а рядом таблица соответствия этих цифр неким символам. Каждая цифра может означать один из этих символов, и одна из комбинаций символов — и есть его пароль.
Мидори решил, что имея варианты пароля, он сможет перебором подобрать нужный. Вам нужно помочь ему, и перечислить все возможные варианты паролей.
Конечно же, Мидори не хочет слишком долго ждать, чтобы купить мёд. Постарайтесь найти все варианты как можно быстрее.
Предлагается дописать функцию `resolve(input: String) -> [String]`
Таблица для дешифровки пароля:
0: ["!", "@", "$", "#"]
1: ["(", "_", "-", ")"]
2: ["a", "b", "c", "^"]
3: ["d", "e", "f", "*"]
4: ["g", "h", "i", "A"]
5: ["j", "k", "l", "B"]
6: ["m", "n", "o", "C"]
7: ["p", "q", "r", "D"]
8: ["s", "t", "u", "v"]
9: ["w", "x", "y", "z"]
1: ["(", "_", "-", ")"]
2: ["a", "b", "c", "^"]
3: ["d", "e", "f", "*"]
4: ["g", "h", "i", "A"]
5: ["j", "k", "l", "B"]
6: ["m", "n", "o", "C"]
7: ["p", "q", "r", "D"]
8: ["s", "t", "u", "v"]
9: ["w", "x", "y", "z"]
Входные данные: комбинация из цифр: 0123456789.
Выходные данные: набор вариантов паролей.
Пример
Входные данные:
02
02
Выходные данные:
["!a", "!b", "!c", "!^", "@a", "@b", "@c", "@^", "$a", "$b", "$c", "$^", "#a", "#b", "#c", "#^"]
["!a", "!b", "!c", "!^", "@a", "@b", "@c", "@^", "$a", "$b", "$c", "$^", "#a", "#b", "#c", "#^"]
func resolve(input: String) -> [String] {
//Enter your code here
}