Асинхронность в .NET, популярность на Stack Overflow, «церковный» софт: интервью со Стивеном Клири

p4dyr0efo0syh-cecbgzpacf7wy.jpeg

Стивен Клири входит в топ-100 пользователей Stack Overflow. Главным образом благодаря своим ответам, связанным с асинхронностью в .NET. Программированием его жизнь не ограничивается: в Твиттере он первым делом пишет о себе «Christian», а уже потом «developer».

Сейчас в связи с появлением async streams его познания особенно актуальны: в качестве докладчика по такой теме фигура Стивена прямо-таки напрашивается. И совсем скоро на DotNext он об этом и расскажет. А пока что мы расспросили его обо всём этом: и о религии, и о Stack Overflow, и об асинхронности.

Биография


— Первый вопрос простой: расскажите о своей профессиональной биографии.

— Я заинтересовался программированием довольно рано, мне было лет 7–8. Тогда в школе я смог написать маленькую программу на языке Logo, и это было моим первым опытом программирования. Позже, когда мне было 12–13, я накопил на свой первый компьютер. И когда при поступлении в колледж я выбрал Computer Science, это было довольно очевидным решением: я и так уже ощутимое время интересовался компьютерами.

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

— Забавно, что вы начали с Logo, а теперь в компании, главный продукт которой называется Logos. А чем именно вы там занимаетесь?

— Бэкендом: веб-сервисами, к которым обращается и Logos, и другие продукты компании. У Faithlife целый ряд продуктов, связанных с церковью. Logos — для изучения Библии. А есть ещё Proclaim, предназначенный для тех, кто выступает с проповедями (помогает со слайдами и тому подобным). Исторически Faithlife делали продукты для пасторов, но сейчас добавляют вещи, помогающие обычным людям.

Я занимаюсь бэкендом, там часто приходится иметь дело с ASP.NET Web API, а прямо сейчас я работаю с Docker. Прямо сейчас у нас часть в облаке, а часть on-premise, и что-то вообще не стоит переносить в облако, но некоторые вещи мы хотим перенести туда — и я занимаюсь этим.

Религия


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

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

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

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

— В вашем Твиттере в поле «bio» есть слова «христианин» и «разработчик». А эти две части вашей идентичности как-то пересекаются?

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

 — Ну, в вашем bio ещё написано «addicted to writing OSS», а давать людям свободное программное обеспечение — это звучит альтруистично и по-христиански. В этом случае нет корреляции?

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

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

 — Вы ещё и на Stack Overflow активны — это для вас тоже способ бескорыстно дать что-то сообществу?

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

Stack Overflow


— У нас есть ещё ряд вопросов про Stack Overflow, первый дурацкий. Вы недавно получили там бейдж за ответы по Windows Phone 8:

Как получилось, что вы в 2019-м получили бейдж за ответы о практически мёртвой технологии? Кто-то до сих пор задаёт по ней вопросы?

— Чтобы получить бейдж, обычно нужно не меньше определённого количества ответов с определённым количеством голосов за эти ответы. Предполагаю, что я получил этот бейдж, потому что сейчас кто-то проголосовал за какой-то мой ответ, опубликованный ещё годы назад, и с ним наконец набралось нужное число голосов. Это забавно, потому что я очень давно не видел вопросов по Windows Phone 8! (смеётся)

— На SO ваша репутация составляет 320 000 — и это больше четверти от репутации легендарного Джона Скита, хотя ответов вы дали на порядок меньше него. Как удалось набрать такую?

— Полностью я и сам не уверен. Репутацию проще получать тем, кто пришёл на сайт раньше всех, а я хоть и был в числе early adopters, но всё-таки пришёл позже многих. Я начал отвечать на вопросы — поначалу на 1–2 в день, что безумно далеко до Джона Скита. Сосредоточился на теме async/await, а также параллелизме и многопоточности — просто потому что это тогда, по сути, стало моей специальностью. Я многие годы назад уже занимался асинхронностью, и тогда это было больно. Так что, когда появились async/await, я сразу же видел, в чём их смысл. Так что я оказался в нужное время в нужном месте, а моя «учительская кровь» помогла объяснять всё понятным людям языком. И в случае со Stack Overflow я оказался местным специалистом по async/await. А Джон Скит — ну, напрямую он этого не говорил, но я это предполагаю — оставляет большинство вопросов по async/await мне. Но он, конечно, отвечает куда больше меня, его не догнать!

— Глядя на числа репутации, легко подумать «у человека на ответы уходит полжизни» —, а сколько на самом деле вы тратите времени на SO?

— Не так уж много. Я проверяю Stack Overflow пару раз в день, и обычно отвечаю на 1–3 вопроса. А большинство положительных голосов получаю за ответы, оставленные ещё годы назад. Вот как SO помогает тем, кто пришёл раньше: они первыми ответили на вопросы годы назад, получили голоса, а голоса делают эти ответы заметнее, и в итоге они же получают новые голоса. Это лавинообразный эффект, поощряющий старые ответы.

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

— Когда Джон Скит прилетал к нам на DotNext, мы спрашивали его о текущем состоянии Stack Overflow и о том, что он считает проблемами сайта. Интересно сравнить: что по этому поводу думаете вы?

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

И это проблема, которая присутствовала в интернете всегда. В 90-х, когда все сидели в ньюзгруппах, она тоже была. Десять лет спустя всё происходило в мейлинг-листах и Google Groups. Теперь новым ресурсом для вопросов о программировании Stack Overflow. Но вопросы о программировании были всегда, и как задать хороший вопрос, всегда представляло собой проблему, и как поддерживать дружественное сообщество — тоже. Возможно, эти проблемы никогда не решить полностью. Я не говорю, что нам не следует над этим работать — нам точно следует. Но если заглянуть в прошлое, окажется, что даже в 90-е уже писали туториалы о том, как задавать технические вопросы.

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

И потом, представьте, что вы работаете над задачей. Вы по уши в коде, ваша голова заполнена всем этим. И вы смотрите на какую-то конкретную вещь, которая никак не поддаётся. Это мелкая конкретная деталь большой системы, и обычно вы спрашиваете «Как мне сделать эту мелкую вещь?», не осознавая, что у вас есть весь этот известный вам контекст, а в вопрос вы его не вкладываете. Зачастую на вопрос «Как мне сделать X» правильным ответом будет «Не надо делать X, делайте Y». Это ловушка, в которую люди часто попадаются при сочинении первых вопросов. Они не осознают, что их ответ в его текущем виде «неотвечабельный».

А помимо проблемы качества вопросов, есть ещё и тенденция — особенно на Stack Overflow, где все борются за баллы, пытаясь ответить как можно быстрее — стремительно закрывать вопрос или быстро строчить не самые приятные ответы. Я не имею в виду «злобные», я видел очень мало откровенно злобных комментариев — лишь несколько за все годы. Скорее, они резкие, и для автора вопроса это считывается как недружелюбность.

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

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

Асинхронность


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

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

Думаю, большим шагом стало появление Promise. В JavaScript это так и назвали, а в C# это Task или ValueTask. И это стало большим шагом вперёд, потому что теперь у нас появился объект, представляющий операцию. Можно следить за его прогрессом и так далее. А async/await в любом языке — это, по сути, просто синтаксический сахар вокруг Promise.

Я бы сказал, что появление Promise — событие, сильнее всего сказавшееся на асинхронном коде. А ещё в случае с async/await важно, что стейт-машину создают за вас. В старые времена, когда мы работали с колбэками, нам приходилось самим делать свои стейт-машины. И это всегда было сложно, потому что вы неизбежно забывали какое-нибудь состояние или переход, и ничего не работало. И было очень сложно отлаживать. Async/await принесли не саму возможность писать асинхронный код, но возможность писать такой код, который можно поддерживать.

— А теперь вы видите ситуацию устаканившейся, или нас скоро могут ждать новые перемены?

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

А сейчас другое событие приходит с .NET Core 3. Они делают то, что все называют async streams, хотя на самом деле это асинхронные enumerables. Думаю, это будет сбивать людей с толку, потому что уже есть тип Stream, не имеющий никакого отношения к async streams. В общем, будут более инкрементальные улучшения. Увидим ли мы что-то настолько же масштабное, как когда async/await впервые заявили о себе? Не думаю.

Если вы хотите новой смены парадигмы, всегда остаётся возможность системы, основанной на акторах. Или что-то вроде горутин, где вся асинхронность неявная. По-моему, эти вещи в некотором смысле похожи. Проблема в том, что в .NET подобное так просто не добавить. Думаю, ограничений слишком много, чтобы на это в .NET пошли, так что вряд ли это случится. Если мы увидим масштабный переход к Actor-миру или горутинному миру, где подход к concurrency будет не таким, как с сегодняшней многопоточностью, это потребует совсем новых языков и рантаймов. А .NET на такое не стоит идти. И не думаю, что программирование в целом сделает такой прыжок. Может, я и ошибаюсь, но моя текущая позиция такова.

— Ещё к вопросу о том, насколько всё меняется со временем. Многие книги о программировании стремительно устаревают, но там, где изменений меньше, они держатся дольше. А что с вашей «Concurrency in C# Cookbook», насколько она требует обновлений?

— Хороший вопрос. Я только недавно опубликовал второе издание, а первое вышло в 2014-м. То есть прошло пять лет, и мы уже на втором издании — для меня это выглядит быстрым развитием.

Думаю, это ещё зависит от того, как написана книга. Я пытался написать так, чтобы она как можно дольше не устаревала. Надо просто стараться не ссылаться на вещи вроде Windows Phone 8. Но она неизбежно всё равно устареет. Появляются async streams и тому подобное, и я хотел включить такие вещи в книгу. В итоге что-то устарело, но большинство материала перекочевало в новое издание без изменений.

И, конечно, всё зависит от того, на кого рассчитана книга. Конечно, книга по использованию Visual Studio 2008 устареет очень быстро. Но думаю, что есть и место подлинной классике. Я считаю «Code Complete» одной из лучших в мире книг о программировании. И как давно она была написана? Даже не знаю. Десятилетия назад. И это по-прежнему фантастическая книга! Что-то в ней устарело, но в целом она по-прежнему отличная.

 — Недавно в Твиттере были бурления по поводу async/await, начавшиеся с твита Вона Вернона — автора нескольких книг о DTD и модели акторов:

Latest update on @dotnet and blahAsynch (…) and await.

It leaks EVEYWHERE.

It is EFFECTIVELY BLOCKING.

It’s nearly impossible for a toolkit to NOT LEAK it EVERYWHERE once it is used anywhere.

I hate this idiom/API even more than ever.

We are going to find a way around this.

— Vaughn Vernon (@VaughnVernon) May 19, 2019

Ему не нравится назойливость async/await — по его мнению, это растекается по всему коду и способно привести к блокировке тредов. Что вы думаете об этом? Стоило ли что-то спроектировать иначе?

— Да, пожалуй, то, что async/await «расползается» по проекту — самая частая претензия. Мне хочется отметить тут пару вещей.

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

Есть пара разных подходов к тому, как избежать повсеместного засилья async/await. Первый заключается в том, чтобы изолировать весь ввод/вывод в отдельные объекты. Можно использовать паттерны проектирования вроде Ports & Adapters: это позволяет содержать весь ввод/вывод вне вашей бизнес-логики, и тогда в ней не потребуется вообще никакого async/await. Недавно я видел целый доклад о том, как предотвратить «async повсюду», отрефакторив проект так, чтобы бизнес-логика никогда не занималась вводом/выводом. Я бы рекомендовал этот подход.

Есть другой подход к борьбе с засильем async/await, но он невыполним в .NET. По-моему, Go попробовали сделать это с горутинами. По сути, там вообще всё — это сплошной async/await. Можно убрать async/await из языка, добавив его там вообще во всё и сделав неявным.

Других способов нет. При появлении async/await кто-то (не помню, кто именно) сказал, что это как зомби-вирус: как только часть вашего кода инфицирована, начинается распространение.

— Некоторые разработчики используют модель акторов, объясняя это простотой управления потоками (акторы, по сути, однопоточны). Думаете ли вы, что с помощью правильного выбора библиотек разработчики могут избавиться от сложности programming concurrency?

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

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

Также использование акторов с асинхронными сообщениями может привести к тому, что управление состоянием будет довольно запутанным, если только оно не происходит целиком в сообщениях. И даже в таком случае у вас будут сложности с eventual consistency. В общем, с моей точки зрения, модель акторов не может решить все проблемы. Я бы описал это так: она может лишь изменить то, где именно проблемы будут возникать.

— Вас знают как дотнетчика, но вы используете и другие языки вроде TypeScript. Когда вы их пробуете, как это заставляет вас смотреть на C# и .NET? Встречаете ли вы там что-то, что вам хотелось бы увидеть в C#?

— Отличный вопрос. C# много брал из других языков. Один из них, из которого он брал много — Python. И мне это нравится. Я уже годы не писал на Python, но я считаю, что это очень хорошо спроектированный язык. Я очень ценю enumerator blocks, которые C# позаимствовал у Python. А ещё Python был одним из первых, где появились Async streams, так что можно сказать, что C# и это взял оттуда.

В разных языках мне нравится разное. Я в целом предпочитаю статическую типизацию, поэтому в последнее время особо не использую Python, и по этой же причине вместо JavaScript использую TypeScript. У JavaScript есть свои преимущества просто из-за его однопоточности. Например, если вы посмотрите на востребованность Reactive Extensions, то увидите, что в .NET это особо не приняли. А в JavaScript можно увидеть Rx повсюду.

— Последняя пара вопросов — о вашем докладе на DotNext. Вы собираетесь рассказывать там про Asynchronous streams — можете ли вкратце сказать .NET-разработчикам, чего ждать и почему им будет полезен этот доклад?

— Итак, мой доклад про asyncronous streams: зачем их добавили в язык, и какой основной сценарий их использования. Я подхожу к этому очень прагматично, и не вдаюсь во все детали происходящего под капотом. Есть вещи, которые вам нужно знать чтобы самим правильно использовать async streams, и есть вещи, которые нужно знать, чтобы в своём коде потреблять async streams, а вам придётся это делать по мере их выхода на сцену.

— И последний вопрос. Вас очень сложно заполучить на конференцию — почему вы решили приехать на DotNext?

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

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

DotNext 2019 Moscow пройдёт 6–7 ноября. Помимо выступления Стивена Клири, там будут десятки других докладов для дотнетчиков — на сайте можете увидеть полную программу.

© Habrahabr.ru