За последний год многим разработчикам пришлось осваивать работу с Linux, погружаться в тему кросс-платформенности и портирования существующих продуктов в новую инфраструктуру. Несмотря на то что часть наших продуктов написана под Linux, мы не стали исключением, и нашему RnD в прошлом году тоже пришлось значительно перестраивать свою работу.
Споры о том, под какой ОС проще кодить – бесконечны, примерно как дискуссии об Android vs iOS или PlayStation vs Xbox. Поэтому начинать мы ее не будем, хотя очень хочется.
В посте рассказываем исключительно об опыте нашей компании: на какие грабли наступили и в каких местах обожглись, работая над портированием продуктов с Windows на Linux. И все это собрали в 10 основных пунктов-болей наших разработчиков под катом.
1. Различия в UI
Для написания интерфейса в Windows есть стандартные гайдлайны, которые практически универсальны для всех последних версий этой ОС, поэтому вероятность, что продукт будет некорректно работать на каком-то гаджете, стремится к нулю.
С Linux – совсем другая история. Во-первых, в отличие от Windows, в Linux большое количество дистрибутивов, и у каждого свой набор различных desktop environment (DE). Например, у одной из самых распространенных версий Linux Ubuntu в набор графических оболочек рабочего стола входят: Unity, KDE, GNOME, Xfce, Mate, LXDE. Помимо этого, в Ubuntu доступно большое количество независимых менеджеров окон и разнообразные панели рабочего стола. Однако как бы разработчики ни старались сделать красивый интерфейс для одной из оболочек, удовлетворить вкусы каждого пользователя вряд ли получится. При наличии такого богатого выбора всегда будут те, кому решение покажется кривым или не учитывающим какие-то важные факторы.
И самое главное, если, допустим, под Windows у приложения уже есть готовый UI, основанный не на кросс-платформенном фреймворке, то для Linux его придется переписать полностью или создать ветку под Linux-версию. Если же UI — кросс-платформенный, то во многих случаях он корректно запустится на обеих ОС.
Несмотря на то, что в компании может существовать общий стайлгайд, в котором указан предпочтительный набор утилит для разработки под определенный дистрибутив Linux, соблюсти его не всегда получается из-за различий в системах и библиотеках DE.
С другой стороны, мы столкнулись с такой ситуацией: если для Windows-пользователей наличие интерфейса в продукте важно и привычно, то для Linux-пользователей интерфейс может быть не приоритетным, в отличие от всем любимой консоли (на всякий случай отметим, что привычным UI мы тоже занимаемся). Так, например, для менеджера лицензий в продукте ContentReader Engine нам пришлось создавать консольный вариант, который ранее для этого продукта вообще не подразумевался.
Однако такой подход сразу ломает многое, к примеру, сценарии, которые теперь просто так не реализуешь, или возникают сложности с навигацией и показом информации. А если бизнес-логика исторически еще и переплетена с интерфейсом, то задача становится еще сложнее. Если же приложение изначально было консольным, то с этим пунктом сложностей возникнуть не должно.
2. Различия в правах доступа
Несмотря на то, что и в Windows, и в Linux для разработчиков есть довольно схожие гайдлайны по написанию кода, в том числе описывающие разграничения прав доступа для работы продукта, проблемы с правами возникают довольно часто.
Во-первых, некоторыми прописанными стандартами в Windows частенько пренебрегают, во многом за счет единообразия ОС. В Linux настолько расслабиться не получится – указанные в гайдлайне требования жесткие, особенно для некоторых дистрибутивов.
Во-вторых, в Windows мало кто обращает внимание на послабления в правах доступа, так как продукт работает корректно, в Linux же ошибки в правах могут привести к некорректной работе продукта.
В-третьих, в случае необходимости пользователи Windows могут самостоятельно внести изменения в права доступа, а для Linux-пользователей может потребоваться повышение привилегий.
В-четвертых, (и это самый главный и непредсказуемый фактор), клиент может прийти со специфическими требованиями к распределению прав доступа, которые обязательно нужно учесть. К примеру, мы однажды получили запрос на запрет создания временных файлов на диске. Да, их можно перенести в память и решить проблему. Но что делать, если все созданные приложением файлы должны иметь права 644, это же стандартная практика. А если с ними работает больше одного пользователя? Здесь бы помогло разрешение на редактирование группой, но клиент был не согласен. Говорить о том, что Windows-клиенты с подобными запросами не приходили, кажется, не нужно.
3. Docker
Поскольку Windows-контейнеры — это большая редкость, то программисты не занимались разработкой под такой тип развертывания. В Linux все наоборот, там есть всем известный Docker.
Поддержка Docker – один из частых запросов, который интересует заказчиков. Docker позволяет приложению пользоваться некоторыми ресурсами компьютера, но в то же время сильно ограничивает программу в правах и задает определенные требования к хранению данных.
И тут наступает проблема с хранением информации и отказоустойчивостью, ведь может потребоваться сохранить результаты в персистентном хранилище. И если ранее это можно было сделать просто в локальном файле, то в Docker/Kubernetes для этого существует огромное количество вариантов, начиная от подключенного диска или NFS, заканчивая базами данных и целыми сервисами, обеспечивающими S3-хранилище. Кроме того, еще необходимо обеспечить корректность данных при записи, то есть уметь работать с данными, которые меняются не одним, а множеством инстансов приложений.
Также достаточно непростой может быть реализация внутрисетевой аутентификации. В рамках Windows глубоко интегрирована и удобна пользователю для внутрисетевой работы всем знакомая Windows-аутентификация (Negotiate-аутентификация). Она позволяет ввести логин/пароль на одном компьютере сети и далее переходить на другие ресурсы, идентифицируясь прозрачно для пользователя. Вот только она основана на стабильности отдельных узлов сети и регистрации их в доверенном центре (Active Directory Controller/KDC).
Кроме того, особенность Kerberos-аутентификации (является частью Negotiate) в том, что ее ключи основаны на синхронизации времени, и это критически важно. Но платформа Doker-образов предполагает возможность динамического развертывания и stateless-работы. Таким образом, использование привычного и удобного механизма становится не таким уж удобным и тем более не таким простым.
4. Набор библиотек
Ввиду исторически сложившихся обстоятельств в разработке мы используем набор собственных библиотек, заменяющих стандартные API-системы, поэтому многих проблем, например, с их различиями, нам удалось избежать. Но даже с таким чит-кодом могут возникнуть проблемы.
У универсальности собственных библиотек есть две стороны медали: с одной стороны, у тебя один прикладной инструмент для всех продуктов, с другой – как только одна из команд захочет внести какие-то изменения в свой продукт, он автоматически будет применен и ко всем остальным продуктам, даже если они написаны на разных ОС.
Так, одна наша команда внесла изменение в библиотеку, которое автоматически задавало определенный набор прав к созданным файлам и папкам. По итогу такой стандартизации другой продукт, требующий иной набор прав, стал работать некорректно.
Решить эту проблему можно тремя способами (нужное подчеркнуть):
Можешь стать повстанцем, борющимся за справедливость, и убедить коллег «вернуть все взад».
Можешь смириться с тленностью бытия и написать собственные оболочки, исправляющие проблему.
До каких-либо изменений учесть все пожелания коллег и найти компромиссное решение.
5. Лицензирование
Пользователи Windows и Linux привыкли использовать продукты по-разному (одна физическая машина vs контейнеры/виртуальная машина), поэтому для продуктов требуются разные виды лицензирования. К примеру, если в решениях под Windows можно обойтись без онлайн-лицензирования, то в продуктах под Linux без него уже будет тяжело.
А поскольку многие сервисы и лицензии уже перешли на форматы онлайн/подписка, которая почти всегда завязана на онлайн-подключении, то у пользователей такой формат уже не вызывает отторжения, как раньше. Теперь стало нормой, что данные о твоей лицензии/потреблении ресурсов хранятся на внешнем сервисе и периодически проверяются. По этой причине использование онлайн-подключения в Docker или комплексе виртуальных машин уже становится приемлемым для пользователя, и он больше не зажат в тиски требований, по которым должен работать сервис лицензирования.
6. Привычные приложения одной ОС не работают под другой ОС
Когда готовый продукт под Windows требуется портировать или доработать под Linux, то наличие стандартных приложений значительно упрощает задачу. Однако если в продукте используются стандартные Windows-компоненты, тот же Internet Explorer, то их функции придется реализовывать заново на основе уже Linux-компонентов.
В данном случае при написании кросс-платформенного решения есть два пути: либо создавать две реализации одного компонента под каждую ОС, либо выбрать один компонент, который сможет корректно работать под обеими ОС.
К примеру, при регистрации пользователя есть необходимость делать запрос из продукта на сайт для передачи данных о пользователе. На заре создания продукта разработчики для простоты реализовали эту задачу через встроенный Internet Explorer. Спустя время его потребовалось портировать на Linux, и, конечно же, это вышло разработчикам боком. Теперь им придется перейти на использование, например, curl, а заодно переписать и добавить необходимую для его работы функциональность.
7. Слишком большой выбор тулзов с одинаковой функциональностью
Многообразие прикладных инструментов, которые способны решать идентичные задачи, может привести к отрицательному результату.
Во-первых, несмотря на то, что инструмент заявлен как кросс-платформенный, по итогу он может выдавать разное качество работы под разными ОС.
Во-вторых, использование только кросс-платформенных компонентов не может стать панацеей от всех багов, так как нередки ситуации, когда у ОС есть более удачный альтернативный инструмент для реализации задачи.
В-третьих, многие популярные для одной ОС инструменты, изначально встроенные в систему, могут полностью отсутствовать у другой ОС. К примеру, в Windows возможно работать с правами сразу на всю компанию и централизованно ими управлять (да, AD почти не имеет альтернатив), в ОС под Linux такой функциональности, можно сказать, вовсе нет.
И наоборот. В Windows очень долго отсутствовал стандартный централизованный пакетный обработчик для установки приложений, в отличие от Linux. Windows Store — это попытка создать в Windows подобие менеджера пакетов, пусть и со своими особенностями, например, с попыткой навариться на этом. Главное, каждый из «менеджеров» требует своего подхода в работе, и в этом нужно хорошо разбираться. К тому же, для этого могут потребоваться не только новые процессы, но и дальнейшая поддержка.
Несмотря на весь скачок темы кросс-платформенности, как правило, все разработчики продолжают писать продукт под одной, основной, ОС и использовать определенный набор библиотек. Поэтому невозможность реализовать какой-то набор фич под другой ОС – частая проблема, решение которой может сводиться даже к отказу от определенного набора функций в другой ОС.
И как итог этой кропотливой работы, даже с использованием всех кросс-платформенных тулзов и инструментов, продукт вряд ли на 100% будет кросс-платформенным, особенно учитывая здесь последующую сборку дистрибутивов и билдов.
8. Железо и драйвера
При портировании приложения, использующего специальные устройства, естественно требуются драйвера. И если они корректно работают под одной ОС, то это совсем не значит, что такой же результат будет и на другой.
А поскольку в коммерческой разработке железки под Linux не всегда поддерживаются (а если они и есть, то их функциональность может быть урезана), то может случиться и так, что у пользователя в принципе не будет никакой возможности использовать софт на этой ОС.
К примеру, вместе с драйвером под Windows поставляется специальное приложение от производителя, которое позволяет управлять дополнительными настройками продукта. В версии под Linux возможность управлять этими параметрами в принципе отсутствует. И если понадобится, например, обновить ключ для лицензии, то в Windows для этого есть менеджер ключей, окна и кнопка Update Firmware, а в Linux — скорее ничего.
9. Тестирование
Разработчики – не единственные специалисты, которые страдают от создания кросс-платформенных продуктов. Как только продукт готов, эта эстафета переходит команде тестирования.
Когда продукт разрабатывается и выпускается десятилетиями, в нем накапливается некое «наследие» (все мы помним иконки из Windows 3.11). Такое же «наследие» формируется и у команды QA, причем речь идет даже не о сценариях тестирования (они тоже наверняка поменяются), а об утилитах и скриптах.
И если скрипты можно переписать или адаптировать, то, например, специальные обертки для тестирования API нужно не забыть перенести, скорее всего переписать, а потом протестировать их работу на множестве ОС, чтобы исключить все возможные ошибки у пользователей.
10. Help desk
Автоматизация техподдержки для кросс-платформенных продуктов тоже требует намного больше ресурсов, так как знания по поддержке одной ОС могут не пригодиться в поддержке другой, пускай даже обе они будут под Linux. Универсального ответа на один и тот же вопрос для всех ОС скорее всего найти не удастся.
Если с поддержкой Windows все достаточно ясно и просто из-за схожести версий ОС, набора библиотек, окружения и в целом софта, а также предпочтений пользователей, то с Linux придется повозиться, так как разнообразие версий ОС под Linux ведет к наличию не менее разнообразных требований, набора софта и библиотек для каждой из них.
Вместе с разработчиками и тестировщиками также будут страдать и коллеги из техподдержки. Им для работы потребуется куча статей на wiki, в которых будут описаны различные сценарии, ошибки и их решения для каждой ОС, ее сборки, скриптов и пр.
К примеру, если Windows-клиента можно попросить в Event Viewer отфильтровать и отправить логи, то у Linux-клиента обычно нет даже UI для логов, не говоря уже об отсутствии привычных окон. Такие вещи обычного пользователя пугают, ведь может что-то сломаться, а как потом это чинить он даже не представляет. Это же Linux!
Наш совет всем, кто испытывает схожие симптомы при портировании продуктов – выдыхайте :)…и да пребудет с вами ново-пассит.