Когда 10 лет назад я начинал работу с .NET Framework 3,5 (язык версии 3.0), для меня его функциональность была крайне ограничена, так как начинал я с SharePoint 2010. Постепенно изучив более широкий круг технологий и следя за развитием .NET, я могу отметить его огромный рост от сомнительного конкурента Java до крутой кросс-платформы с возможностью разрабатывать демонов для Linux (а ведь он предназначался исключительно для ОС Windows). Конечно, когда я впервые столкнулся с технологией, казалось, что всего достаточно: ведь находились способы реализовать задуманное. Но сейчас, имея опыт работы на разных платформах и их разных версиях, можно уже порассуждать о том, что жизнь была болью в те далекие времена.

В целом, если интересно мысленно вернуться в ту эпоху и вместе поразмышлять про .NET в разрезе «Было – Стало», то приглашаю под кат. Думаю, будет интересно как тем, кто кодит недавно и не знает об особенностях предыдущих версий, так и тем, кто хочет предаться ностальгии.



Эпоха Боли


Когда я начинал заниматься разработкой, SharePoint 2010 работал на .NET Framework 3.5 и уже включал многое: появился LINQ и был примитивный AJAX. Но он был сильно ограничен платформой, так как расширять ее было достаточно сложно, а адекватных инструментов тогда просто не было.

Боль 1: Cоздание единого приложения

Тогда технология разработки web part’ов под «шарик» была основана на WebForm’ах, при этом каждый web part являлся по сути отдельным приложением. Лично для меня нереально было так сделать единое приложение, потому что при разработке web part в каждом из них инициализируется свой контекст подключения к БД – получается, нельзя было сделать единый контекст. Ну, например, чтоб вывести данные из базы на страницы, я использовал SqlDataSource (отдельным подключением к базе данных в виджете), и, чтобы подключиться к 3-4 таблицам, у меня на виджете было 3-4 DataSource’а, которые, разумеется, влияли на скорость загрузки страниц. К тому моменту уже появился ADO.NET Entity Framework, но пользоваться им было неудобно в SharePoint до версии 4.1, т.к. были проблемы с взаимодействием продуктов.

Боль 2: Недосягаемость поддержки и шаблонов

Web part’ы для SP 2010 мы писали по технологии создания web part SP 2007 года, т.к. на 2008 студии не было шаблонов и поддержки. Постепенно с выходом Visual Studio 2010 появились их шаблоны, и работать стало проще: появилась возможность делать definition’ы списков и кодить их из студии, делать template сайта (закодить нужный контент-тайпа и описание списка). Раньше всё это делалось руками через правку XML-файлов, и это, несомненно, было болью для тех, кто только погружался в разработку на .NET, потому что человек не понимал, что за файл он правит и с какой целью, а ориентировался только на слова дядечки с форума.

Боль 3: Асинхронность…

В .NET Framework 3.5 не было асинхронности ¬¬в том виде, котором мы знаем её сейчас, и приходилось в другом потоке запускать определённый код, связываться через делегаты-обработчики, а в WinForm’ах была возможность использовать бекграунд воркера (то есть второй процесс, запущенный в параллель, в котором выполнялись работы). Получается, что программирование асинхронных приложений существовало, но их реализация была за гранью понимания джуна.

В .NET Framework 4 появилась Task Parallel Library, а, значит, появились и task’и, т.е. мы могли не объявлять делегаты, а делать task’у, передавая ей action, и выполнять ее в параллельном потоке, зная о статусе/ состоянии и, когда нужно, получать сигнал о ее выполнении. Это был прогресс для параллельной разработки, когда нужно обработать большое количество данных, потому что раньше это делалось с большей планкой вхождения.

… и замёрзшие окна

Нужно понимать, что web сильно отличается от разработки консольных приложений (здесь под ними понимаем не общемировой нэйминг, а тот, который используем при описании тезисов: не конкретно ConsoleApp, а все приложения, которые запускаются в интерфейсе ОС). В консольном приложении все операции по умолчанию производятся синхронно, и, если есть долгая обработка, то интерфейс будет «замерзать», как будто приложение зависло. Чтобы не было ощущения, что программа не отвечает, мы выполняли все операции в отдельном потоке и вводили progress bar’ы: таким образом пользователь видел активность приложения, а управлять можно было из другого потока через делегата, например.

Боль 4: Грядёт деплой

Также в .NET Framework 3.5 появилась еще одна болезненная технология — MS AJAX. Контент UpdatePanel обновлялся с бекэнда, тогда как все остальное вообще не перестраивалось. В SharePoint он работал очень криво из-за специфики инициализации контролов в жизненном цикле страницы. Вот у нас он работал после первого пост-бека (иногда после второго), и в общем было сложно сделать так, чтоб MS AJAX работал хорошо и с первого раза, хотя с чистых WebForm UpdatePannel использовался достаточно просто. А использовать в той версии «шарика» классический AJAX (XMLHttpRequest) не представлялось возможным, потому что нужно было для каждого действия писать отдельный обработчик на беке и вешать их в пачку каждого web part’a. При этом не всегда была возможность накручивать этот функционал.

Когда параллельно я работал с другими приложениями, написанными на WebForm’ах для «около-шариковых» задач, то удивился, что проблема деплоя проекта на SP является проблемой только для SP. В остальном приложения инициализировались в момент: окно загружалось, и оно работает (magic!). В шарике же деплой занимал от 2 до 3 минут, и ты находишься в постоянном цикле:



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

Боль 5: Windows и ничего кроме Windows

На тот момент .NET еще позиционировал себя как платформа для разработки под Windows. Да, был проект Mono, который, по сути, представлял собой «велосипед» .NET’a на Linux, но это была альтернативная версия основного Framework’a, и до сих пор на странице проекта www.mono-project.com/docs/about-mono/compatibility) перечислены фичи, которые не добавлены в него по версиям Framework’a. Когда ты разрабатывал что-то под Linux, то это было далеко не user-friendly, поскольку у Mono не было той поддержки и комьюнити, и, если ты обращался к каким-то нереализованным вещам, то код мог просто сломаться. То есть если не разрабатывать под Mono изначально, нельзя написать платформо-независимый код в принципе. Я не исключаю значимости этого проекта для развития .NET в целом, потому что без него не появился бы Core, но лично у меня не сложилось с ним боевого опыта.

Эпоха плюсов (обезболивающее)

Само использование чистого .NET последней версии в своих проектах устраняет практически все эти проблемы. Многие плюсы сейчас есть и в Framework, но дальше поговорим о плюсах с привязкой к Core, т.к. я работал с ним.

Плюс 1: Быстродействие

Когда появился .NET Core, появилась и возможность делать привычные операции намного круче и быстрее. Конечные приложения на нём работают по некоторым данным до 5000 раз быстрее, чем их аналоги на .NET Framework. Но сама компиляция и запуск иной раз занимает больше времени – «запрягаем долго – едем быстро».

Плюс 2: Кросс-платформенность

Главный плюс .NET Core – это тот факт, что написанный код работает одновременно на Windows, Linux и Mac. При этом можно написать приложение на микросервисной архитектуре асинхронного сервиса логирования через очередь сообщений. Помню, как я, разработчик, пишущий в основном под Windows, писал демонов (службы) под Linux, и они заработали стабильно, быстро и с первого раза, и вся система работала в тандеме: в приложении, API-сервисе и сама очередь сообщений. Это просто космос, когда ты пишешь на привычном тебе языке на платформе, изначально не предназначенной под эту ОС!

Плюс 3: Асинхронность всего

Сейчас есть возможность писать бэк не параллельно, не многопоточно, а полностью асинхронно (!), что позволяет вынести отдельные задачи из основного потока в специальные асинхронные методы или блоки кода. Это в свою очередь позволяет писать красивый, чистый код, который лишён громоздких конструкций: он легок к пониманию, асинхронные методы пишутся как синхронные, а работают как надо.

Плюс 4: Выгрузка библиотек и менее интенсивное пожирание памяти

Если смотреть на текущую 8-ю версию С#, то в ней много сахара, и изменения завораживают. Во-первых, раньше у нас не было возможности динамически выгружать изначально незагруженную DLL (мы динамически подгружали библиотеки в проект, но они оставались висеть в памяти). С выходом 3-го Core появилась возможность динамически загружать и выгружать библиотеки в зависимости от целей. Например, если мы хотим сделать приложение поиска по файлам, и пользователь выбирает расширение XML, мы динамически подгружаем XML парсер для документов и ищем по его дереву. Если мы хотим поиск по JSON, то начинаем искать по его телу – библиотекам, зависимым от определенных условий, и нет необходимости держать их в оперативной памяти. И да. Приложение перестало постоянно жрать память. Когда мы выгружаем сборку, мы освобождаем все ресурсы, которые этой сборкой цеплялись.

Плюс 5: кортежи

Язык до сих пор молодой, живой и активно развивается. В последней версии добавилось много крутых вещей: например, кортежи – активная тема. Да, tuple были и раньше, но как отдельный класс, который включал в себя много элементов. Сейчас ее трансформировали в кортежи, когда мы можем создать метод, возвращающий не 1 объект, а несколько. Раньше для возвращения более 1 параметра нужно было, чтобы был объявлен выходной/ссылочный параметр, либо придумывать отдельный класс и тащить его дальше, а теперь можно вернуть кортежем.

Подводим итоги!

У многих разработчиков такое отношение к изменениям языка: пока нам не сделали хорошо, мы не знали, что было плохо. .NET Core является open source’ом, так что каждый может сам добавить фичу, а на портале написать о своей боли. Там много, конечно, спорных моментов: кто-то ждёт изменений, которые другим кажутся абсолютно неудобными. Например, в 8 версию языка вошло управление Nullable Reference типами, и до сих пор вопрос удобства является спорным: нововведение было объявлено в 2 предыдущих версиях, а вошло только в финальную Core 3.0, и по умолчанию эта фича отключена, так как ее включение может привести к поломке крупного проекта. Но при написании приложения с чистого листа она крайне полезна и позволяет сделать приложение более чистым и прозрачным.

По моему мнению та платформа, что есть сейчас, – это уже сильный игрок в мире разработки с достаточно низким порогом вхождения (есть еще ниже, но работать на них сложнее). Конечно, выбор платформы – это работа с целым рядом факторов и зависимость от целей. Если это сложное приложение, которое обрабатывает терабайты данных и должно быть выверено до байта, то это сложное программирование на плюсах. Но нужно понимать, что это полгода на разработку и два – на доработку, а к моменту выхода оно устареет. К тому же не так много людей, которые кодят на плюсах. Если же мы говорим об enterprise-разработке, когда время до релиза 2 недели, то есть смысл выбирать другую технологию, которая помогает быстрее получить готовый результат (Java, .NET, php).

Комментарии (8)


  1. ICELedyanoj
    12.12.2019 15:30

    была возможность использовать бекграунд воркера (то есть второй процесс, запущенный в параллель, в котором выполнялись работы)

    Простите, а это точно соответствует истине? Даже гуглить пошёл — вдруг я 13 лет в неведении пребываю.
    Подозреваю неточную терминологию.


    1. SomebodyElse
      12.12.2019 16:36

      имеется в виду компонент BackgroundWorker


  1. Dotarev
    12.12.2019 16:09

    BackgroundWorker Class
    .NET Framework
    4.8 4.7.2 4.7.1 4.7 4.6.2 4.6.1 4.6 4.5.2 4.5.1 4.5 4.0 3.5 3.0 2.0


  1. anatoliy_rozhyn
    12.12.2019 23:30

    Я помню я начинал в 2005 с .Net 1.1
    Это была достаточно серьезная боль, которая закончилась с появлением версии фреймворка 3.0 (третья революция в .Net, как я считаю… Где первая — это сам .Net, вторая — это ThreadPool+AsyncProgrammingModel+Generics версии 2.0, а четвертая — .Net core).
    Но даже тогда асинхроность была ибо это принцип многозадачности операционных систем.
    Поэтому не могу разделить патетики.
    Писать на Линукс — основная ли это цель платформы? Не уверен.
    Но то что .Net core решила проблему многоплатформенности — это факт.
    Но… это практически и все «обезболивающее» :)

    P.S. оптимизация garbage collector и оптимизация ресурсов (используемой памяти и быстродействия) с .Net Core имеет слабую связь. Основное было сделано, по-моему, или в 4.6.2 или в 4.7 .Net Framework


  1. Greendq
    13.12.2019 01:31

    .Net Core с его возможностью компиляции в нативный исполняемый код решает одну из основных проблем — вы перестаёте распространять свои приложения (практически) в исходниках. Правда, компиляция в нативный код — те ещё танцы. У меня пока двоякое чувство от Core — вроде бы то, чего давно ждали, но есть и ощущение недоделанности…


    1. avenumDev
      13.12.2019 09:58

      «Недоделанность» присутствует это факт, ибо есть вещи, которые в Core и в Framework, работают по разному. По началу было сложно с Ef, но потом втянулся:-) и ещё остаются вещи которые ещё не переписаны к сожалению, но уже есть так-же механизмы которые есть только в Core. И все новое что появляется в Framework идёт из Core.


  1. unsafePtr
    13.12.2019 02:30

    Как по мне так создание Roslyn-a было революцией. До этого разработчики языка что бы делать язык использовали С++. .netcore это как раз плоды рослина


  1. ZetaTetra
    13.12.2019 12:30

    SqlDataSource

    Со времён 1.1, использование SqlDataSource и ObjectDataSource встречал только в мануаулах на сайтах M$, на практике их никто не использовал, ибо мешать слои UI и доступа к данным, даже тогда считалось плохой практикой. Моё предположение, что использование этих объектов в примерах, обуславливалось уменьшением текста для новичков: CC->CV->F5

    В .NET Framework 3.5 не было асинхронности ¬¬в том виде, котором мы знаем её сейчас

    Да, обёртку приходилось писать самостоятельно на основе ThreadPool'ов…
    Что в 4.0 из коробки сделали в TPL.

    Также в .NET Framework 3.5 появилась еще одна болезненная технология — MS AJAX

    M$ AJAX появился в 2.0, а не в 3.5. Тут даже за пруфами далеко ходить не надо:
    System requirements: Microsoft .NET Framework Version 2.0

    А использовать в той версии «шарика» классический AJAX (XMLHttpRequest) не представлялось возможным

    В обычных вебформах было несколько сценариев, от накручивания WebMethodAttribute, до IHttpHandler.
    Ну а далее — любые другие приложения на любых языках, способные обработать JSON.

    PS: С SP не работал.