Я люблю C#. После университета моим первым настоящим проектом по программированию была игра, написанная на Unity. И я сразу же влюбился в этот язык: он казался таким свежим. И был похож на Java… если бы в Oracle по-настоящему заботились о Java, это вернуло бы короткий золотой век Java. Слышал, что с тех пор они перешли на цикл ещё быстрее, так что всё могло измениться.
Я по-прежнему люблю этот язык. Может, он и не самый модный, но всё равно способен делать что угодно. Пример — многопоточность. Думаете, это сложно? Тогда попробуйте в Dart поиграть с Isolate и поймёте, как хорошо иметь C#.
В последние несколько лет меня стала очень беспокоить судьба языка. Я поделился своими мыслями в комментарии здесь. И раз уж комментарий привлёк так много внимания — решил конкретизировать его идеи.
Из-за чего весь сыр-бор?
В комментарии я написал:
«C# умирает, Microsoft убивает его, добавляя случайные штуки, о которых никто не просил. Это смерть от расползания функциональности».
Довольно ясно и понятно. И абсолютно никакой необходимости в написании статьи. Но всё-таки я её написал.
Я не знаю более эффективного способа, чем расползание функциональности, чтобы уничтожить язык программирования. Разве что бомбардировками. Эта перифраз цитаты из серии «Фрикономики»:
«Я не знаю более эффективного способа, чем регулирование арендной платы, чтобы уничтожить город. Разве что бомбардировки».
Я оставил слово бомбардировки — не нашёл подходящего эквивалента для языка программирования. Но бомбардировки не подходят: можно разбомбить штаб-квартиру компании, но нельзя этим уничтожить язык, можно только остановить его разработку. Надеюсь, меня не оштрафуют за такие слова.
Чем же чревато расползание функциональности? Оно затрудняет изучение и освоение языка. Хотите пример? Посмотрите интервью с создателем C++ Бьёрном Страуструпом. Оно забавное, хотя и ненастоящее.
1 января 1998 года Бьёрн Страуструп дал интервью журналу IEEE Computer.
1 января 1998 года Бьёрн Страуструп дал интервью журналу IEEE Computer. Естественно, редакторы ожидали от него ретроспективный обзор семи лет объектно-ориентированного проектирования, использующего созданный Страуструпом язык.
К концу интервью они получили даже больше, чем рассчитывали, и впоследствии решили скрыть его содержание «на благо отрасли». Но, как и бывает в таких случаях, произошла утечка.
Вот полный текст того, что было сказано во время интервью. Оно не отредактировано и не было подготовлено заранее, поэтому не такое складное, какими бывают запланированные интервью.
— Каково это — быть тем, кто изменил мир проектирования программного обеспечения? Прошло уже несколько лет с тех пор. Что можете сказать, оглядываясь назад?
— Вообще-то перед самым интервью я думал о том времени. Помните, все писали на С? Проблема была в том, что они чертовски хорошо это делали. И в университетах тоже очень хорошо этому учили. Настолько хорошо, что там с феноменальной скоростью подготавливали компетентных — я подчёркиваю, "компетентных" — выпускников. Это и привело к проблеме.
— К проблеме?
— Да, к проблеме. Помните, все писали на COBOL?
— Конечно. И я тоже.
— Вначале эти парни были как полубоги. У них была высокая зарплата, и с ними обращались как с членами королевской семьи.
— Вот было время!
— Да. Но что произошло? IBM это надоело, и они стали вкладывать миллионы в обучение программистов, пока тех не стало как собак нерезаных.
— Я поэтому и ушёл. Зарплата за год упала так, что выгоднее стало работать журналистом.
— Точно. То же самое произошло с программистами на С.
— Да? Ну и что?
— Однажды мне в голову пришла небольшая схема, которая немного восстановила бы равновесие. Я подумал: «Интересно: а что, если бы существовал язык настолько сложный, настолько трудный для изучения, что никто и никогда не смог бы наводнить рынок программистами?» На самом деле некоторые идеи я взял из X10, т. е. X-Windows. Это была такая плохая графическая система, что работала только на этих штуках Sun 3/60! Там были все нужные мне ингредиенты: смехотворно сложный синтаксис, непонятные функции и псевдообъектно-ориентированная структура. Даже сейчас никто не пишет сырой код на X-Windows. Почему? Это единственный путь, если вы хотите сохранить душевное здоровье.
— Вы шутите?
— Нисколько. На самом деле была ещё одна проблема. Unix писался на С, то есть любой программист на С очень легко мог стать системным программистом. Помните, сколько зарабатывал программист мейнфрейм-систем?
— Ну ещё бы! Я же им работал.
— Так вот этот новый язык должен был отделиться от Unix, скрыв все системные вызовы, которые так хорошо связывали их вместе. Это позволило бы неплохо зарабатывать и тем парням, которые знают только DOS.
— Не верю, что вы это произнесли…
— Прошло ведь уже достаточно времени. Думаю, большинство людей сами поняли, что C++ — это пустая трата времени. Только пришли они к этому намного позже, чем я надеялся.
— И как именно вы это сделали?
— Это должно было быть всего лишь шуткой. Никогда не думал, что люди воспримут книгу всерьёз. Любой, у кого ещё есть мозги, понимает: объектно-ориентированное программирование не является интуитивно понятным, оно нелогично и неэффективно.
— Что?
— А повторно используемый код? Вы когда-нибудь слышали, что какая-нибудь компания повторно использует свой код?
— Никогда не слышал, но…
— Вот видите. Правда, некоторые пытались на первых порах. Была эта компания из Орегона (кажется, Mentor Graphics), которая сильно простудилась, пытаясь переписать всё на C++ в 1990 или 1991 году. Мне, правда, было очень жаль их, но я думал, что они будут учиться на своих ошибках.
— Очевидно, ошибки их не научили?
— Нисколько. Проблема в том, что большинство компаний замалчивают все свои основные грубые ошибки, ведь нелегко объяснить акционерам убытки в 30 миллионов долларов. Однако, отдадим им должное, в конце концов у них всё получилось.
— Получилось? Вот видите: это доказывает, что объектно-ориентированное программирование работает.
— Ну, почти. Исполняемый файл был настолько огромным, что для загрузки на рабочую станцию HP со 128 Мб оперативной памяти потребовалось пять минут. А затем он очень медленно выполнялся. Я думал, это станет большой проблемой и за мной придут в течение недели, но никого это не волновало. В Sun и HP были только рады продать невероятно мощные коробки с огромными ресурсами, годившимися лишь для запуска простейших программ. Знаете, когда у нас в AT&T появился первый компилятор C++, я скомпилировал «Hello World» и не мог поверить в то, что размер исполняемого файла был 2,1 Мб.
— Да? Но с тех пор компиляторы далеко продвинулись.
— Неужели? Попробуйте последнюю версию g++ — вы не получите больших изменений от половины мегабайта. Кроме того, есть несколько совсем недавних примеров со всего мира. У British Telecom была крупная авария, к счастью, им удалось выбросить всё это и начать сначала. Им повезло больше, чем Australian Telecom. Теперь я слышу, что Siemens создаёт динозавра, и мне всё тревожнее, ведь размер аппаратного обеспечения под исполняемые файлы растёт. Что уж говорить о множественном наследовании…
— Да, но C++ — в принципе надёжный язык.
— Вы правда в это верите? Вы когда-нибудь работали над проектом на C++? Вот что происходит: во-первых, я заложил достаточно подводных камней, чтобы только самые простые проекты работали с первого раза. Возьмите перегрузку операторов. В конце проекта она есть почти в каждом модуле, потому что ребятам кажется, что так и должно быть, ведь так было в их учебном курсе. Один и тот же оператор значит что-то совершенно другое в каждом модуле. Попробуйте собрать всё это вместе, когда у вас примерно сотня модулей. А сокрытие данных… Боже мой, иногда не могу удержаться от смеха, когда слышу о проблемах компаний, заставляющих свои модули разговаривать друг с другом. Думаю, слово «синергетический» специально придумали, чтобы добавить мучений руководителю проекта.
— Должен сказать, всё это весьма шокирует. Вы говорите, что сделали это, чтобы повысить зарплату программистам? Это отвратительно.
— Ну что Вы?! У каждого есть выбор. Я не ожидал, что всё так выйдет из-под контроля. В любом случае я, в принципе, добился своего: C++ умирает, но ведь программисты получают высокие зарплаты. Особенно те бедолаги, которым приходится поддерживать всю эту околесицу. Понятно же, что невозможно поддерживать большой программный модуль на C++, если вы его не писали?
— Как это?
— А Вы не знаете? Помните typedef?
— Да, конечно.
— Помните, сколько времени уходило на прощупывание заголовочных файлов, а потом обнаруживалось, что RoofRaised — это число двойной точности? А представьте, сколько времени требуется, чтобы найти все неявно определённые типы во всех классах в крупном проекте.
— И как вы поняли, что достигли своего?
— Помните продолжительность среднего по размеру проекта на С? Около полугода. Недостаточно долго, чтобы обеспечить жене и детям достойный уровень жизни. А возьмите тот же проект и разрабатывайте его на C++. Что вы получите? Я Вам скажу. Один-два года. Разве не здорово? И это гарантированное рабочее место — всего лишь из-за одной ошибки в суждениях. И ещё кое-что. В университетах так давно не преподавали С, что сейчас не хватает приличных программистов на С. Особенно тех, кто что-нибудь знает о программировании систем Unix. Многие ли знают, что делать с malloc, когда все эти годы они использовали new и никогда не удосуживались проверить код возврата? На самом деле большинство программистов на C++ выбрасывают код возврата. А что случилось со старым добрым –1? По крайней мере вы знали, что у вас ошибка, не увязнув во всех этих throw, catch и try.
— Но ведь наследование помогает сэкономить много времени.
— Действительно? Вы когда-нибудь замечали разницу между планом проекта на C и на C++? Стадия планирования проекта на C++ в три раза длиннее именно для того, чтобы то, что должно наследоваться, наследовалось, а что не должно — нет. И потом, его до сих пор неправильно понимают. Кто-нибудь слышал об утечках памяти в программе на С? Теперь их поиск — целая индустрия. Большинство компаний сдаются и отправляют продукт на сторону (зная, что он протекает, как решето), просто чтобы избежать затрат на отслеживание утечек.
— Есть инструменты…
— Большинство из которых написаны на C++.
— Если мы опубликуем это, вас могут линчевать, вы это понимаете?
— Сомневаюсь. Как я уже сказал, C++ давно прошёл свой пик, и ни в одной компании, будучи в здравом уме, не начнут проект на C++ без пилотного испытания. Оно должно убедить их, что это путь к катастрофе. Если нет, то они заслуживают всего того, что получат. Знаете, я пытался убедить Денниса Ричи переписать Unix на C++.
— Боже мой! Что он сказал?
— К счастью, у него хорошее чувство юмора. Думаю, что и он, и Брайан понимали тогда, что я делаю, просто не подавали виду. Он сказал, что поможет мне написать версию DOS на C++, если мне будет интересно.
— И что Вы?
Страуструп: Вообще-то я написал DOS на C++, я дам вам демоверсию по окончании интервью. У меня она запускается на Sparc 20 в компьютерном зале. На четырёх ядрах работает, как ракета, и занимает всего 70 Мб на диске.
— А как на компьютере?
— А теперь Вы шутите. Вы что, никогда не видели Windows 95? Я считаю это своим самым большим успехом: она произвела эффект разорвавшейся бомбы прежде, чем я был к этому готов.
— Вы знаете, эта идея с Unix++ заставила меня задуматься. Кто-то ведь попробует это сделать.
Страуструп: Да, но не после прочтения этого интервью.
— Простите, но я не думаю, что мы опубликуем что-либо из этого.
— Но это история века. Я лишь хочу, чтобы мои коллеги-программисты запомнили меня за то, что я для них сделал. Вы же знаете, сколько сейчас можно получать на C++?
— Насколько я знаю, лучшие получают 70–80 долларов в час.
— Видите? И он этого полностью заслуживает. Нелёгкая работа — отслеживать все те подводные камни, которые я заложил в C++. И, как я уже говорил, каждый программист на C++ чувствует себя связанным каким-то мистическим обещанием использовать каждый элемент языка в каждом проекте. На самом деле меня это иногда очень раздражает. Спустя столько лет мне почти нравится этот язык.
— То есть раньше он Вам не нравился?
— Я его ненавидел. Он даже выглядит неуклюже, не находите? Но когда начали поступать гонорары от книги… Ну, Вы понимаете.
— Минуточку. А как насчёт ссылок? Вы должны признать, что улучшили указатели "С".
— Хм… Я всегда задавался этим вопросом. Сначала я думал, что улучшил. Но однажды я обсуждал это кое с кем, кто с самого начала писал на C++. Он сказал, что не запоминает, были ли его переменные ссылочными или разыменованными, поэтому всегда использует указатели. Он сказал, что маленькая звёздочка всегда напоминала ему…
— На этом месте я обычно говорю «большое спасибо», но сейчас это вряд ли уместно.
— Обещайте, что опубликуете это. Совесть не даёт мне покоя.
— Я дам вам знать. Но, кажется, знаю, что скажет мой редактор.
— Да и кто в это поверит? Хотя… пришлите мне копию этой записи.
— Это можно.
Очевидно, оно ненастоящее. Или всё-таки?.. Нет, ненастоящее.
Но это интервью стало вирусным, и понятно почему: оно могло быть правдой. Ведь все мы любим пошутить над тем, какое раздутое месиво этот C++. По этой причине его больше и не используют.
То есть, конечно, его обычно ещё используют, потому что единственная альтернатива в работе над чем-то низкоуровневым, — это C. Хотя Rust набирает популярность. Но когда вы в последний раз видели фреймворк высокого уровня, использующий C++?
Как это происходит с C#
Не хочется, чтобы та же участь постигла C#. Но, к сожалению, так и происходит. Я начал подозревать это, когда увидел новые выражения switch в C# 8. Фактически (из документации по C# 8) switch теперь можно определить так:
public static RGBColor FromRainbow(Rainbow colorBand) =>
colorBand switch
{
Rainbow.Red => new RGBColor(0xFF, 0x00, 0x00),
Rainbow.Orange => new RGBColor(0xFF, 0x7F, 0x00),
Rainbow.Yellow => new RGBColor(0xFF, 0xFF, 0x00),
Rainbow.Green => new RGBColor(0x00, 0xFF, 0x00),
Rainbow.Blue => new RGBColor(0x00, 0x00, 0xFF),
Rainbow.Indigo => new RGBColor(0x4B, 0x00, 0x82),
Rainbow.Violet => new RGBColor(0x94, 0x00, 0xD3),
_ => throw new ArgumentException(message: "invalid enum value", paramName: nameof(colorBand)),
};
Но что было не так с обычным оператором switch? Может быть, есть какое-то обоснование, почему это лучше в очень специфических обстоятельствах. Тогда как насчёт этого: в C# 9 можно опустить тип вот так:
private List<WeatherObservation> _observations = new();
Но ключевое слово var уже достаточно спорно. Зачем второе?
В C# 10 вы можете создать свойство для свойства. Это называется поля C#. Хорошо, сделано это для автоматических свойств. Но я не знаю, почему бы просто не использовать обычное свойство. Ведь свойства должны облегчать нам жизнь, а не усложнять её.
А жизнь будет только ухудшаться
Потому что у C# должна быть каждый год новая версия. Не знаю, почему все переходят на быстрые циклы выпуска. Как будто я год использовал бета-версию Firefox 4 и был совершенно доволен ей. А сейчас? У нас Firefox 91. Да, 91. Потому что, по-видимому, каждый браузер должен обновляться в течение 4-недельного цикла выпуска.
C# выпускается за год, а Java — за 6 месяцев. Не знаю, зачем. Ведь языки программирования не устаревают так быстро.
На самом деле я вроде как знаю ответ, почему это происходит с Java: подозреваю, что это связано с OpenJDK. Старые версии OpenJDK не получают никаких обновлений, поэтому, если хотите использовать 5-летнюю версию Java, как наверняка делает большинство компаний, нужно доплатить. Это довольно изобретательно.
Прямо сейчас C#, может быть, не так уж и плох. Но подождите несколько лет, и скоро расползание функциональности станет всеобъемлющим.
Аргумент: просто не используйте эти особенности языка
На эту часть моих доводов поступило самое большое количество жалоб. Я вроде бы и согласен. Поэтому не писал об этом раньше. Но знаете: неиспользование функций работает сейчас. Что, если этот темп расползания функций продолжится? Словами вымышленного интервью:
И, как я уже говорил, каждый программист на C++ чувствует себя связанным каким-то мистическим обещанием использовать каждый элемент языка в каждом проекте.
Что, если во всех руководствах по C# начнут пользоваться непонятным синтаксисом? Что тогда? Думаю, когда это случится, многие перестанут использовать C#.
Я любил С#
Проблема с C# была в том, что он всегда был слишком многословным. Это у него от Java. Настолько, что я часто в шутку называл его Java#.
Так что было бы разумно, если бы C# добавлял функции, чтобы сократить эту многословность, и они это делают. Но похоже на то, что они просто добавляют хакерское исправление вместо решения основной проблемы.
Такие языки, как Dart, спрашивают: «Как мы можем сделать это проще?» в то время как такие языки, как C#, спрашивают: «Как мы можем делать в точности то, что делали раньше, просто с меньшим количеством кода?»
И, конечно же, они приходят к ответу: «Просто бросьте в это макрос».
Конечно, иногда они думают о том, чтобы добавить что-то действительно полезное. Но чаще всего это оплошности. Познавательная работа. Конечно, они решили проблему необходимости печатать слишком много. Но основная проблема, связанная со сложностью, только усугубляется.
Уже есть сообщения о том, что люди отказываются от C#. Тенденции Stack Overflow показывают резкое снижение количества вопросов с середины 2009 года, а их ежегодные опросы (за исключением 2017–2018 годов) показывают медленное и постепенное снижение популярности языка.
И если уровень раздувания будет расти, я подозреваю, что уйдёт ещё больше.
А если вы по-прежнему любите C# и C++, то можете обратить внимание на наши курсы, чтобы прокачать свои навыки:
Также вы можете перейти на страницу пакета курсов по кодингу, чтобы узнать, как мы готовим специалистов в программировании.
Согласны ли вы с автором статьи? Проголосуйте или поделитесь мнением в комментариях.
Профессии и курсы
Data Science и Machine Learning
Python, веб-разработка
Мобильная разработка
Java и C#
От основ — в глубину
А также: