«Ми намагаємося, щоб User Experience не відрізнявся в різних операционках» — Інтерв'ю з розробниками Rider з JetBrains

На початку січня JetBrains оголосила про розробку Rider, кроссплатформної IDE на основі ReSharper і платформи IntelliJ, доступною під Windows, Linux і Mac OS X, і включає в себе всі фішки ReSharper, та підтримує .NET Framework, Mono і CoreCLR. Передбачається, що розробка буде завершена до осені цього року, а всі бажаючі зможуть спробувати середовище «на зубок» в рамках Early Access Program.



На хабре Rider вже неодноразово згадувався, але щоб дати нашим читачам поглянути на процес розробки «зсередини», при цьому зрозумівши специфіку процесу на різних етапах виробництва, ми звернулися до JetBrains, і на наші питання відповіли:

  • Кирило Скрыган, тимлид проекту Rider і старший розробник;
  • Дмитро Іванов, головний розробник протоколу реактивного многопроцессного взаємодії у Rider;
  • Андрій Акіньшин, срібний призер ACM ICPC, Rider відповідає за NuGet-менеджер.

За яку частину проекту Rider ви відповідаєте? Які завдання перед вами поставлені?
Кирило Скрыган:

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

Дмитро Іванов:

Я займаюся реактивним протоколом передачі даних між Java і .NET.

Андрій Акіньшин:

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

Що виявилося найскладнішим у реалізації з технічної точки зору?
Кирило Скрыган:

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

При проектуванні Rider ми закладываемся на важливий інваріант: фронтэнд може приєднатись до вже працюючого бекенду, в будь-який момент часу — і навпаки. Це дає потенційні функціональні переваги: наприклад, можливість при працюючому фронтэнде перезапускати бекенд, якщо в ньому сталося щось фатальне. Однак головне, що дає цей підхід — це зручність написання консистентним працюючого коду. Адже без цього інваріанта, тобто без збереження стану бекенду і фронтенду, взаємодія зводилося б до банальної request — responce архітектурі. У випадку зі складною многопоточной IDE це призводило б до купах зайвих перевірок в коді, в дусі «а чи можу я зараз прийняти цей request — або почекати поки у мене тут все завантажиться і сказати бекенду відправити мені повідомлення, яке я вже зможу прийняти?»

Враховуючи, що у нас і фронтэнд і бекенд — це складні багатопотокові процеси, такий підхід був би прямою дорогою в пекло рейсів і дедлоков. У підсумку, ми прийшли до моделі, де у нас є реактивний і змінюване стан моделі, що розповсюджується на обидві сторони протоколу, на обидва процеси. Вийшло щось на зразок MVVM архітектури. «Начебто» суто тому, що нам все ж без транзиентных пересилок великих даних не обійтися. Можливо, якщо б у нас не було такого потужного фронтенду як Intellij Platform, наш MVVM був би більш чистим.

Дмитро Іванов:

Отримати здорову Threading-модель в многопроцессном програми. Уявіть, у нас є дві кодових бази — Intellij Idea і ReSharper, у кожної з яких є своє розуміння як жити в багатопотоковому оточенні, свої локі, свій головний тред з керованою reentrancy і т. д. Плюс до цього — кілька додаткових процесів: msbuild tasks, debuggers. І тепер треба з усім цим «злетіти», плюс отримати вільну від лагів і не розвалюється по швах середу.

В самому першому прототипі — коли він ще навіть і не називався Rider — ми використовували Google Protobuf, і будували роботу на основі звичайного RPC. Досить швидко прийшло усвідомлення, що «Ідею» ми хочемо використовувати як View, а взаємодія побудувати за принципом MMVM. В .NET-світі ми звикли до реактивного XAML, і будувати UI по іншим принципам, які ми вважаємо вже застарілими, не хотілося. Виникло питання — як змусити джавовый Swing встати на реактивні, межпроцессные, та ще й кросплатформені рейки? Як це часто буває в JetBrains, жодне з існуючих рішень нам не підійшло, і ми стали розробляти своє.

Тепер ViewModel описується в дуже стислій формі з допомогою можливостей DSL, наданих Kotlin. З моделі генеруються реальні Java і C# класи, синхронізовані між процесами. Будь-яка зміна моделі, що з одного, що з іншого боку породжує реакцію.

Скоро з'ясувалося, що в рамках чесної ViewModel, в силу обмежень UI-контролів та складності програмування, ми не можемо втриматися, і довелося для деяких функцій передавати дані цілком — наприклад, Code Completion може передати всі свої 50 тисяч елементів. Дуже допомогло, що ми відразу робили протокол бінарним і оптимізованим (привіт всім противникам передчасної оптимізації =). Загалом, продуктивність протоколу ми ніде не натикаємося. Моя думка, що, за показником «зручність\швидкість» ми потрапили в десятку, вирішивши вибрати саме таке технічне рішення.

Андрій Акіньшин:

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

Які проблеми виникли при розробці версій Linux? MacOS?
Кирило Скрыган:

Під Linux і MacOS на даний момент код бекенду виконується на Mono. Головним завданням було переписати код проекту так, щоб він під Mono запускався в принципі, а також поправити відповідну інфраструктуру проекту під це. Крім цього, ми регулярно стикаємося з різного роду специфічними багами Mono, пошук та налагодження яких приємним процесом не назвеш.

Банальні відсутності перевірок на null в певних випадках призводили до повного фарбую бек-ендом. До неподобства просто і повільно Mono написаний I/O код, який, приміром, без всякого мерджа тримав відкритий FileSystemTracker handle на кожен запит (і тут ми відразу ж передаємо привіт OutOfMemory і неочевидним проблем з продуктивністю). Починаючи з якихось версій, Mono перестали підкладати таргети для веб проектів. Окремого слова заслуговує xbuild, API якого працюють дуже «творчо», що особливо стосується модифікації проектної моделі. Що з цього ми фиксим в самомо коді Mono, поставляючи свої патчі, щось обходимо своїми засобами. І все ж в цілому, можу сказати, що приємно здивований якістю роботи Моно. Так, є помилки, але в цілому, все якось працює, і навіть більш або менш стабільно на різних платформах — я особисто очікував гіршого.

Дмитро Іванов:

Виникали і виникають проблеми з Mono. Наприклад, у версії 4.4 у нас почали зависати сокети — виявилося, що баг. Все-таки .NET Framework набагато стабільніше. Але ми не скаржимося — шолом патчі =)

Андрій Акіньшин:

Спершу вирішувалися проблеми по запуску R# на Mono (довелося спилювати залежності на WPF і COM, переробляти unsafe-магію, правити баги в самому Mono тощо). Потім ми вирішували платформо-специфічні проблеми (наприклад \r\n в R# vs \n в Idea; взаємодія з файловою системою і все таке). Зараз ми активно намагаємося доопрацювати кросплатформені стеки розробки (наприклад, навчитися добре дружити з XBuild).

Відрізняється функціонал IDE під різними ОС? Якщо так, то в чому?
Кирило Скрыган:

Немає практично ні в чому не відрізняється. Принаймні, не має :)

Дмитро Іванов:

Ми намагаємося, щоб User Experience не відрізнявся в різних операционках. Ну хіба що билдсистемы використовуються різні.

Андрій Акіньшин:

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

Що функціоналу Rider, на вашу думку, є killer feature, якщо порівнювати Rider з MSVS?
Кирило Скрыган:

По-перше, просто на порядок більш потужний функціонал у всіх напрямках. У десятки разів більше навігацій, аналізів коду і рефакторингов (quick fixes, intentions, context actions), Solution Wide Analysis, unit test runner, чудова підтримка практично всіх VCS, і ще безліч решарп-фіч, які успішно створювалися останні 10 років. Так, ми поки ще не всі встигли «синхронізувати», але не бачу ніяких причин, чому ми цього не зможемо зробити найближчим часом. Крім усього іншого, у Rider відмінна підтримка не тільки C#, але і багатьох інших мов: JavaScript, TypeScript, HTML, CSS, Razor, VB.NET, Regex, і багатьох інших.

По-друге — це, звичайно, складно назвати функціоналом, але вже зараз багато наші користувачі відзначають дуже високу швидкість роботи Rider. І це ще до того, як ми почали активну фазу оптимізації проекту. Цілком можливо, що справа в тому, що у нас немає всередині 20-річного COM'a :).

Спробуйте в Visual Studio при відкритому більш або менш великому проекті, зробити git pull, який оновить .csproj файли — після цього можна сміливо йти пити чай на півгодини. Всьому виною код самої Visual Studio, які як-то неправильно перезапускає MSBuild для нових проектів. Взагалі, за 5 років роботи в Resharper, багато чого я набачився в коді VS, наприклад GC.Collect(), що викликається в циклі :) В цьому сенсі ми відчуваємо себе на порядок вільніше при написанні повністю своєї IDE.

Дмитро Іванов:

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

Андрій Акіньшин:

Якщо піти від порівняння з Visual Studio, то моя улюблена фіча в Rider — консоль, вбудована в IDE. Це просто чудово, я кожен день запускаю які-небудь консольні додатки і радію.

Який ви бачите сферу застосування Rider вже сьогодні?
Кирило Скрыган:

Робота з усіма тими проектами, з якими ви працювали в Visual Studio, а також розробка крос-плафторменных мобільних додатків під MacOS, Linux — тобто Rider цілком може замінити Xamarin Studio і Mono Develop. Велика частина команди розробки програмує Rider в ньому ж самому :)

Дмитро Іванов:

У JetBrains догфудинг — одна з основних практик розробки. Ми використовуємо Rider для розробки Rider. Немотря на нестабільність, вже зараз писати в Rider IDE з його гладким тайпингом — це задоволення.

Андрій Акіньшин:

Головним чином, це платформна .NET-розробка. Якщо ви любите Linux або MacOS, але при цьому хочете писати на C# в дуже крутий повнофункціональної IDE, то Rider — ваш вибір.



Ви вже зібралися в Санкт-Петербург? Адже ми як і раніше чекаємо вас 3 червня на конференції DotNext 2016 Piter, на якій будуть круті доповіді про Rider:



А третій учасник нашого інтерв'ю виступить з хардкорним доповіддю… про арифметику (насправді, не все так просто):



Будуть і інші доповіді. Так що беріть футболку, піджак, куртку, светр — і в Пітер. Хто знає, як зміниться погода за день.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.