Краткий обзор .NET Core, как это соотносится с .NET Framework и что это все означает для кросс-платформенной разработки и разработки с открытым кодом.
Взгляд назад – мотивация для .NET Core
Прежде всего, давайте оглянемся назад, чтобы понять, как платформа .NET была устроена раньше. Это поможет понять мотивы отдельных решений и идей, которые привели к появлению .NET Core.
.NET – набор вертикалей
Когда мы изначально выпустили в 2002 году .NET Framework, они был единственным фреймворком. Вскоре после этого мы выпустили .NET Compact Framework, который был подмножеством .NET Framework, умещающимся на небольших устройствах, включая Windows Mobile. Компактный фреймворк требовал отдельной базы кода и включал целую вертикаль: среду выполнения, фреймворк и модель приложений поверх них.
С тех пор мы повторяли упражнение по выделению подмножества несколько раз: Silverlight, Windows Phone и совсем недавно Windows Store. Это приводит к фрагментации, потому что фактически платформа .NET – это не что-то единое, а набор платформ, независимо управляемых и поддерживаемых разными командами.
Конечно, в самой идее предлагать специализированный набор возможностей, удовлетворяющих определенными потребностям, нет ничего плохого. Это становится проблемой, когда отсутствует системный подход и специализация происходит на каждом слое без учета того, что происходит в соответствующих слоях других вертикалей. Последствием таких решения является набор платформ, которые имеют ряд общих API только потому, что они когда-то начинались из единой базы кода. Со временем, это приводит к росту различий, если только не проводить явные (и дорогие) упражнения для достижения единообразия API.
В какой момент возникает проблема с фрагментацией? Если вы нацелены только на одну вертикаль, то в реальности никакой проблемы нет. Вам предоставлен набор API, оптимизированный именно для вашей вертикали. Проблема проявляет себя, как только вы хотите делать что-то горизонтальное, ориентированное на множество вертикалей. Вот теперь вы задаетесь вопросом о доступности различных API и думаете, как производить блоки кода, которые работали бы на разных целевых вертикалях.
Сегодня задача разработки приложений, которые покрывают разные устройства весьма распространена: практически всегда есть какой-то бек-энд, работающий на веб-сервере, часто есть административный фронт-энд, использующий десктопный Windows, и также набор мобильных приложений, доступных для людей с самыми разными устройствами. Поэтому для нас является критичным поддержать разработчиков, создающих компоненты, покрывающие все вертикали .NET.
Рождение переносимых библиотек классов (Portable Class Library, PCL)
Изначально не было никакого специального концепта для разделения кода между различными вертикалями. Не было переносимых библиотек классов или разделяемых проектов. Вам буквально было нужно создавать множество проектов, использовать ссылки на файлы и множество #if. Это делало задачу нацеливания кода на множество вертикалей действительно сложной.
К моменту выхода Windows 8 мы пришли к плану, как бороться с этой проблемой. Когда мы проектировали профиль Windows Store, мы ввели новую концепцию для лучшего моделирования подмножества: контракты.
Когда проектировался .NET Framework, было предположение, что он всегда будет распространяться как единый блок, поэтому вопросы декомпозиции не рассматривались как критичные. Самое ядро сборки, от которой все зависит – это mscorlib. Библиотека mscorlib, поставляемая с .NET Framework, содержит многие возможности, которые при этом не могут быть поддержаны повсеместно (к примеру, удаленное выполнение и AppDomain). Это приводит к тому, что каждая вертикаль делает свое подмножество самого ядра платформы. Отсюда возникают сложности с тем, чтобы создавать библиотеки классов, рассчитанные на множество вертикалей.
Идея контрактов заключается в том, чтобы предоставить продуманный набор API, подходящих для задач декомпозиции кода. Контракты – это просто сборки, под которые вы можете компилировать свой код. В отличие от обычных сборок, сборки контрактов спроектированы именно под задачи декомпозиции. Мы четко прослеживаем зависимости между контрактами и пишем их так, чтобы они отвечали за что-то одно, а не были свалкой API. Контракты имеют независимую версионность и следуют соответствующим правилам, например, если добавляется новый API, то он будет доступен в сборке с новой версией.
Сегодня мы используем контракты для моделирования API во всех вертикалях. Вертикаль может просто взять и выбрать, какие контракты она будет поддерживать. Важным моментом является то, что вертикаль обязана поддерживать контракт целиком или не поддерживать вовсе. Другими словами, она не может включить в себя подмножество контракта.
Это позволяет говорить о различиях в API между вертикалями уже на уровне сборок в отличие от индивидуальных различиях в API, как это было раньше. Это позволяет нам реализовать механизм библиотек кода, которые нацелены на множество вертикалей. Такие библиотеки сегодня известны как переносимые библиотеки классов (portable class libraries).
Объединение формы API против объединения реализаций
Вы можете рассматривать переносимые библиотеки кода, как модель, объединяющую различные вертикали .NET на основании формы API. Это позволяет адресовать самую главную потребность – возможность создавать библиотеки, работающие в разных вертикалях .NET. Такой подход также служит как инструмент планирования архитектуры, позволяющий сближать различные вертикали, в частности, Windows 8.1 и Windows Phone 8.1.
Впрочем, у нас по-прежнему есть различные реализации, — форки (ответвления кода), — платформы .NET. Эти реализации управляются различными командами, имеют независимую версионность и имеют разные механизмы доставки. Это приводит к тому, что задача унифицировать форму API становится движущейся целью: API переносимы только тогда, когда их реализации двигаются вперед по всем вертикалям, но так как базы кода различаются, это становится довольно дорогим удовольствием, а потому предметом для (ре-)приоритизации. Даже если бы мы могли идеально реализовать единообразие API, тот факт, что все вертикали имеют разные механизмы доставки, означает, что некоторые части экосистемы будут всегда отставать.
Намного лучше унифицировать реализации: вместо того, чтобы только предоставлять хорошо декомпозированное описание, мы должные подготовить декомпозированную реализацию. Это позволит вертикалям просто использовать одну и ту же реализацию. Сближение вертикалей больше не будет требовать дополнительных действий; оно достигается просто за счет правильного конструирования решения. Конечно все равно будут случаи, в которых необходимы различные реализации. Хороший пример этого – это файловые операции, требующие использования разных технологий в зависимости от окружения. Однако, даже в этом случае намного проще попросить каждую команду, отвечающую за конкретные компонент, подумать, как из API будут работать в разных вертикалях, чем постфактум пытаться предоставить единый набор API поверх. Переносимость – это не есть что-то, что вы можете добавить после. К примеру, наш File API включает поддержку Windows Access Control Lists (ACL), которые не поддерживаются всем окружениями. При дизайне API нужно учитывать такие моменты и, в частности, предоставлять подобную функциональность в отдельных сборках, которые могут отсутствовать на платформах, не поддерживающих ACL.
Фреймворки для всей машины против локальных фреймворков для приложения
Еще один интересный вызов – это то, как .NET Framework распространяется.
.NET Framework – это фреймворк, ставящийся на всею машину. Любые изменения, сделанные в нем, влияют на все приложения, которые от него зависят. Иметь единый фреймфорк на всю машину было осмысленным решением, потому что это позволило решить следующие проблемы:
- Централизованное обслуживание
- Уменьшает размер требуемого места на диске
- Позволяет разделять нативный код между приложениям
Но все имеет свою цену.
Прежде все, разработчикам приложений трудно сразу переходить на только что вышедший фреймворк. Фактически, вы зависите либо от свежей версии операционной системы, либо должны подготовить установщик приложения, способные поставить также .NET Framework при необходимости. Если вы веб-разработчик, возможно, у вас даже нет такой опции, так как ИТ-департамент диктует вам, какую версию разрешено использовать. А если вы мобильный разработчик, у вас в общем-то нет выбора, вы определяете только целевую ОС.
Но даже если вы взялись решить задачу подготовки установщика, чтобы убедиться в наличии .NET Framework, вы можете столкнуться с тем, что обновление фреймворка может нарушить работу других приложений.
Стоп, разве мы (Microsoft) не говорим, что наши обновления высоко совместимы? Да, говорим. И мы рассматриваем задачу совместимости очень серьезно. Мы тщательно анализируем любые изменения, которые мы вносим в .NET Framework. И для всего, что может быть «ломающим» изменением, мы проводим отдельное исследование, чтобы изучить последствия. У нас есть целая лаборатория совместимости, в которой мы тестируем многие популярные .NET-приложения, чтобы убедиться, что мы их не сломаем. Мы также понимаем, под какой именно .NET Framework было собрано приложение. Это позволяет нам поддерживать совместимость с существующими приложениями и при этом предоставлять улучшенные поведение и возможности для приложений, готовых работать со свежей версией .NET Framework.
К сожалению, мы также знаем, что даже совместимые изменения могут нарушить работу приложения. Вот несколько примеров:
- Добавление интерфейса к существующему типу может нарушить работу приложений, так как это может повлиять на то, как тип сериализуется.
- Добавление перегрузки к методу, который раньше не имел любых перегрузок может нарушить работу с рефлексиями в тех случаях, когда в коде не обрабатывается вероятность найти более, чем один метод.
- Переименование внутреннего типа может нарушить приложения, если имя типа определялось через метод ToString().
Это все очень редкие случаи, но, когда у вас пользовательская база в 1.8 миллиарда машин, быть совместимым с 99.9% по-прежнему означает, что 1.8 миллиона машин затронуто.
Интересно, что во многих случая исправить затронутые приложения требует довольно простых действий. Но проблема в том, что разработчик приложения не всегда доступен в момент поломки. Давайте рассмотрим конкретный пример.
Вы протестировали приложение с .NET Framework 4 и именно его вы ставите со своим приложением. Но в один прекрасный день один из ваших заказчиков поставил другое приложение, которое обновило машину до .NET Framework 4.5. Вы не знаете, что ваше приложение сломалось до тех пор, пока заказчик не позвонит в вашу поддержку. В этот момент исправить проблему совместимости уже может оказаться дорогостоящим занятием: вам нужно найти соответствующие исходники, настроить компьютер для воспроизведения проблемы, отладить приложение, внести необходимые изменения, интегрировать их в релизную ветку, выпустить новую версию программного обеспечения, протестировать ее и, наконец, передать обновление клиентам.
Сравните это с такой ситуацией: вы решили воспользоваться преимуществами какой-то функциональности, добавленной в свежей версии .NET Framework. В этот момент вы находитесь на этапе разработки, вы уже готовы вносить изменения в ваше приложения. Если есть небольшая проблема совместимости, вы можете легко ее учесть в последующей работке.
Из-за таких проблем выпуск новой версии .NET Framework требует заметного времени. И чем более заметное изменение, тем больше времени нам требуется на его подготовку. Это приводит к парадоксальной ситуации, когда наши бета-версии уже практически заморожены и мы почти не имеем возможности отрабатывать запросы на изменения в дизайне.
Два года назад мы начали распространять библиотеки через NuGet. Так как мы не добавляли эти библиотеки в .NET Framework, мы помечаем из как “out-of-band” (дополнительные). Дополнительные библиотеки не страдают от проблем, которые мы только что обсуждали, так как являются локальными по отношению к приложению. Другими словами, они распространяются так, как если бы они были частью вашего приложения.
Такой подход в общем-то почти полностью снимает все проблемы, мешающие вам обновиться до свежей версии. Ваши возможности перейти на новую версию ограничены только вашей возможностью выпустить новую версию вашего приложения. Это также означает, что вы контролируете, какая версия библиотеки используется конкретным приложением. Обновления производятся в контексте одного приложения, никак не затрагивая другие приложения на той же машине.
Это позволяет выпускать обновления в гораздо более гибкой манере. NuGet также предлагает возможность попробовать предварительные версии, что позволяет нам выпускать сборки без строгих обещаний относительно работы конктретного API. Такой подход позволяет нам поддерживать процесс, в котором мы предлагаем вам наш свежий взгляд на дизайн сборки – и, если вам не нравится, просто его изменить. Хороший пример это – это неизменяемые коллекции (immutable collections). Бета-период длился порядка 9 месяцев. Мы потратили много времени, пытаясь добиться правильного дизайна прежде, чем выпустить первую версию. Нет необходимости говорить, что финальная версия дизайна библиотеки, — благодаря вашим многочисленным отзывам, — намного лучше, чем начальная.
Добро пожаловать в .NET Core
Все эти аспекты заставили нас переосмыслить и изменить подход к формированию платформы .NET в будущем. Это привело к созданию .NET Core:
.NET Core – это модульная реализация, которая может использоваться широким набором вертикалей, начиная с дата-центров и заканчивая сенсорными устройствами, доступная с открытым исходным кодом, и поддерживаемая Microsoft на Windows, Linux и Mac OSX.
Давайте посмотрим детальнее, что собой представляет .NET Core и как новый подход адресует проблемы, которые мы обсуждали выше.
Единая реализация для .NET Native и ASP.NET
Когда мы проектировали .NET Native, было очевидно, что мы не можем использовать .NET Framework в качестве основы для фреймворка библиотек классов. Именно поэтому .NET Native фактически сливает фреймворк с приложением и далее удаляет части, которые не нужные в приложении, перед тем, как генерировать нативный код (я грубо упрощаю этот процесс, более детально можно изучить тут). Как я объяснял ранее, реализация .NET Framework не декомпозирована, это существенно затрудняет компоновщику задачу уменьшения той части фреймворка, которая будет «вкомпилирована» в приложение – область с зависимостями просто очень большая.
ASP.NET 5 испытывал похожие проблемы. Хотя он не использует .NET Native, одной из целью нового веб-стека ASP.NET 5 было предоставить стек, который можно было бы просто копировать так, что веб-разработчикам не приходилось бы координироваться с ИТ-отделом, чтобы добавить возможности из свежей версии. В этом сценарии важно минимизировать размер фреймворка, так как его нужно размещать вместе с приложением.
Фактически, .NET Core – это форк .NET Framework, чья реализация была оптимизирована с учетом задач декомпозиции. Хотя сценарии для .NET Native (мобильные устройства) и ASP.NET 5 (серверная часть веб-разработки) порядком различаются, мы смогли сделать унифицированную базовую библиотеку классов (Base Class Library, BCL).
Набор API, доступный в .NET Core BCL, идентичен для обоих вертикалей: как для .NET Native, так и для ASP.NET 5. В основе BCL имеет очень тонкий слой, специфичный для среды исполнения .NET. В настоящий момент у нас есть две реализации: одна, специфичная для среды .NET Native, и вторая, специфичная для CoreCLR, которая используется в ASP.NET 5. Однако этот слой не меняется очень часто. Он содержит типы вроде String и Int32. Большая часть BCL – это чистые MSIL сборки, которые могут быть переиспользованы как есть. Другими словами, API не просто выглядят одинаково, они используют одну и ту же реализацию. К примеру, нет причин иметь разные реализации для коллекций.
Поверх BCL есть API, специфичные для модели приложений. В частности, .NET Native предоставляет API, специфичные для клиентской разработки под Windows, такие как WinRT interop. ASP.NET 5 тоже добавляет API, например, MVC, которое специфично для серверной части веб-разработки.
Мы смотрим на .NET Core как на код, не специфичный ни для .NET Native, ни для ASP.NET 5. BCL. Среды выполнения нацелены на обобщенные задачи и спроектированы, чтобы быть модульными. Таким образом, они формируют основу для будущих вертикалей .NET.
NuGet как первоклассный механизм доставки
В отличие от .NET Framework, платформа .NET Core будет доставляться в виде набора пакетов NuGet. Мы опираемся на NuGet, так как это именно то место, где уже находится большая часть экосистемы библиотек.
Чтобы продолжить наши усилия в направлении модульности и хорошей декомпозиции, вместо того, чтобы предоставить.NET Core целиком как единый пакет NuGet, мы его разбиваем на набор NuGet-пакетов:
Для слоя BCL у нас будет прямое соответствие между сборками и пакетами NuGet.
В дальнейшем NuGet-пакеты будут иметь те же имена, что и сборки. К примеру, неизменяемые коллекции перестанут распространяться под именем Microsoft.Bcl.Immutable и вместо этого будут в пакет, называющемся System.Collections.Immutable.
В дополнение, мы решили использовать семантический подход для версионности сборок. Номер версии NuGet-пакета будет согласован с версией сборки.
Согласованность именования и версионности между сборками и пакетами сильно облегчит их поиск. У вас не должно возникнуть вопроса, в каком пакете содержится System.Foo, Version=1.2.3.0 – он находится в пакете System.Foo с версией 1.2.3.
NuGet позволяет нам доставлять .NET Core в гибкой манере. Так что, если мы выпускаем какое-либо обновление любого из NuGet-пакетов, вы можете просто обновить соответствующую ссылку на NuGet.
Доставка фреймворка как такового через NuGet также стирает разницу между собственными зависимостями от .NET и сторонними зависимостями – они теперь просто NuGet-зависимости. Это позволяет, сторонним пакетам объявлять, что они, к примеру, требуют более свежей версии библиотеки System.Collections. Установка стороннего пакета теперь может предложить вам обновить вашу ссылку на System.Collections. Вам не обязательно необходимо разбираться в графе зависимостей – нужно только согласие на внесение изменений в него.
Доставка, основанная на NuGet, превращает платформу .NET Core во фреймворк, локальный для приложений. Модульный дизайн .NET Core позволяет убедиться, что каждое приложение должно установить только то, что ему нужно. Мы также работаем над тем, чтобы разрешить умное разделение ресурсов, если несколько приложений используют одни и те же сборки фреймворка. Однако цель заключается в том, чтобы убедиться, что каждое приложение логически имеет свой собственный фреймворк так, что обновление не будет затрагивать другие приложения на той же машине.
Наше решение использовать NuGet как механизм доставки не изменяет нашей приверженности совместимости. Мы по-прежнему воспринимаем эту задачу максимально серьезно и не будем вносить в API или поведение изменений, способных нарушить работу приложения, как только пакет помечен как стабильный. Однако локальное для приложения развертывание позволяет убедиться, что редкие случаи, когда добавляемые изменения ломают приложения, сводятся только к процессу разработки. Другими словами, для .NET Core такие нарушения могут возникнуть только в тот момент, когда вы обновляете ссылки на пакеты. В этот самый момент у вас есть два варианта: исправить проблемы совместимости в вашем приложении или откатиться до предыдущей версии NuGet-пакета. Но в отличие от .NET Framework такие нарушения не возникнут после того, как вы доставили приложение до заказчика или развернули на производственном сервере.
Готов для корпоративного использования
Модель доставки через NuGet позволяет перейти гибкому процессу релизов и более быстрым обновлениям. Однако мы не хотим при этом избавляться опыт получения всего в одном месте, который сегодня присутствует в работе с .NET Framework.
Собственно говоря, .NET Framework тем и прекрасен, что он поставляется как один единый блок, это означает, что Microsoft протестировала и поддерживает его компоненты как единую сущность. Для .NET Core мы также будет предоставлять такую возможность. Мы введем понятие дистрибуции .NET Core. Проще говоря, это просто срез всех пакетов в конкретных версиях, которые мы протестировали.
Наша базовая идея заключается в том, что наши команды отвечают за отдельные пакеты. Выпуск новой версии пакета одной из команд требует от нее тестирования только своего компонента в контексте тех компонент, от которых они зависят. Так как вы можете смешивать различные NuGet-пакеты, мы можете прийти к ситуации, когда отдельная комбинация компонент не будет хорошо стыковаться. Дистрибуции .NET Core не будут иметь подобных проблем, так как все компоненты будут протестированы в комбинациях друг с другом.
Мы ожидаем, что дистрибуции будут выпускать с меньшей частотой, чем индивидуальные пакеты. В настоящий момент мы думаем примерно о четырех выпусках в год. Это даст наст необходимый запас времени для проведения необходимых тестов, исправления ошибок и подписи кода.
Хотя .NET Core распространяется как набо пакетов NuGet, это не означает, что вам нужно загружать пакеты каждый раз, когда вы создаете прокет. Мы предоставил оффлайн-установщик для дистрибуций и также включим их в Visual Studio, так что создание нового проекта будет столь же быстрым, как и сегодня, и не будет требовать интернет-соединения в процессе разработки.
Хотя локальное для приложения развертывание прекрасно с точки зрения изолирования последствий зависимости от новых возможностей, не во всех случаях оно полностью подходит. Критичные исправления ошибок должны распространяться быстро и целостно, чтобы быть эффективными. Мы полностью привержены стремлению выпускать обновления безопасности, как это всегда было для .NET.
Чтобы избежать проблем совместимости, которые мы наблюдали в прошлом с централизованными обновлениями .NET Framework, критически важно, что мы нацелены только на уязвимости в безопасности. Конечно, при этом все равно остается маленький шанс, что такие обновления нарушат работу приложений. Именно поэтому мы будем выпускать обновления только для действительно критичных проблем, когда приемлемо допустить, что небольшой набор приложений перестанет работать, чем если все приложения будут работать с уязвимостью.
Основа для открытого кода и кросс-платформенности
Чтобы сделать .NET кросс-платформенным в поддерживаемом виде, мы решили открыть исходный код .NET Core.
Из прошлого опыта мы знаем, что успех открытого кода зависит от сообщества вокруг него. Ключевой аспект этого – это открытый и прозрачный процесс разработки, который позволит сообществу участвовать в ревью кода, знакомиться с документам по проектированию и вносить свои изменения в продукт.
Открытый код позволяет нам расширить унификацию .NET на кросс-платформенную разработку. Ситуации, когда базовые компоненты вроде коллекций нужно реализовывать несколько раз, негативно влияют на экосистему. Цель .NET Core в том, чтобы иметь единую базу кода, которая может использоваться для создания и поддержки кода на всех платформах, включая Windows, Linux и Mac OSX.
Конечно, отдельные компоненты, например, файловая система, требуют отдельной реализации. Модель доставки через NuGet позволяет нам абстрагироваться от этих различий. Мы можем иметь единый NuGet-пакет, предоставляющий различные реализации для каждого из окружений. Однако важный момент тут как раз в том, что это внутренняя кухня реализации компонента. С точки зрения разработчика это единый API, который работает на разных платформах.
Еще один способ смотреть на это заключается в том, что вывод в открытый код – это продолжение нашего стремления выпускать компоненты .NET более гибким образом:
- Открытый код дает возможность понимать «в реальном времени» реализацию и общее направление развития
- Выпуск пакетов через NuGet.org дает гибкость на уровне компонентов
- Дистрибуции дают гибкость на уровне платформы
Наличие всех трех элементов позволяет нам добиться широкого спектра гибкости и зрелости решений:
Связь .NET Core с существующими платформами
Хотя мы проектировали .NET Core с тем, чтобы он стал основной всех последующих стеков, мы очень хорошо знакомы с дилеммой создания “одного универсального стека”, который все бы могли использовать:
Нам кажется, что мы нашли хороший баланс между тем, чтобы заложить основу для будущего, сохраняя при этом хорошую совместимость с существующими стеками. Давайте посмотрим детальнее на часть из этих платформ.
.NET Framework 4.6
.NET Framework по-прежнему ключевая платформа для создания насыщенных десктопных приложений, и .NET Core это не изменяет.
В контексте Visual Studio 2015 наша цель в том, чтобы убедиться, что .NET Core – это чистое подмножество .NET Framework. Другими словами, здесь не должно быть провалов в функциональности. После выпуска Visual Studio 2015 мы ожидаем, что .NET Core будет развиваться быстрее, чем .NET Framework. Это означает, что в какой-то момент времени будут появляться возможности, доступные только в платформах, основанных на .NET Core.
Мы будем продолжать выпускать обновления для .NET Framework. Наш текущий план включает такую же периодичность новых выпусков, как и сегодня, то есть примерно раз в год. В этих обновлениях мы будет переносить инновации с .NET Core в .NET Framework. Однако мы не будет просто вслепую переносить все новые возможности, это будет основано на анализе затрат и получаемых преимуществ. Как я отмечал выше, даже просто дополнения в .NET Framework могут приводить к проблемам в существующих приложениях. Наша цель тут – минимизировать различия в API и поведении, не нарушая при этом совместимость с существующими приложениями на .NET Framework.
Важно! Часть инвестиций наоборот делается эксклюзивно в .NET Framework, например, планы, которые мы объявили в дорожной карте WPF.
Mono
Многие из вас спрашивали, что означает кросс-платформенная история .NET Core для Mono. Проект Mono, по сути, — это (повторная) реализация .NET Framework с открытым исходным кодом. Как результат, он не только имеет общий богатый API от .NET Framework, но и его же проблемы, особенно в части декомпозиции.
Mono жив и имеет широкую экосистему. Именно поэтому, независимо от .NET Core, мы также выпустили части .NET Framework Reference Source под дружественной для открытого кода лицензией на GitHub. Это было сделано именно с тем, чтобы помочь сообществу Mono закрыть различия между .NET Framework и Mono, просто используя тот же код. Однако из-за сложности .NET Framework мы не готовы запустить его как проект с открытым кодом на GitHub, в частности, мы не можем принимать запросы на изменения для него.
Другой взгляд на это: .NET Framework имеет фактически два форка. Один форк предоставляется Microsoft и он работает только на Windows. Другой форк – это Mono, который вы можете использовать на Linux и Mac.
C .NET Core мы можем разрабатывать целиком .NET-стек как проект с открытым исходным кодом. Таким образом, больше нет необходимости поддерживать отдельные форки: вместе с сообществом Mono мы сделаем .NET Core прекрасно работающим на Windows, Linux и Mac OSX. Это также позволяет сообществу Mono вносить инновации поверх компактного стека .NET Core и даже переносить его в те окружения, в которых Microsoft не заинтересован.
Windows Store и Windows Phone
Обе платформы Windows Store 8.1 и Windows Phone 8.1 – это достаточно небольшие подмножества .NET Framework. Однако, они также являются подмножеством .NET Core. Это позволяет нам в дальнейшем использовать .NET Core как основу для реализации обеих этих платформ. Так что, если вы разрабатываете для этих платформ, вы можете напрямую использовать все инновации не дожидаясь обновления фреймворка.
Это также означает, что количество BCL API, доступных для обеих платформ, будет идентично тому, что вы сегодня можете видеть в ASP.NET 5. К примеру, это включает необобщенные коллекции. Это позволит вам намного проще переносить существующий код, работающий поверх .NET Framework на приложения для сенсорных устройств.
Другой очевидный эффект заключается BCL API в Windows Store и Windows Phone полностью совместимы и будут оставаться такими, так как обе платформы .NET основываются на .NET Core.
Общий код для .NET Core и других .NET платформ
Так как .NET Core формирует основу для всех будущих .NET-платформ, возможность использования общего кода между платформами, базирующимися на .NET, уже заложена в них.
Тем не менее остается вопрос, как использование общего кода работает с платформами, которые не базируются на .NET Core, например, с .NET Framework. Ответ такой: также как и сегодня, вы можете продолжить использовать переносимы библиотеки классов и общие проекты:
- Переносимые библиотеки классов прекрасно подходят, когда ваш общий код не завязан на платформу, а также для повторного использования библиотек, в которых платформо-специфичный код декомпозирован.
- Общие проекты хорошо использовать, когда ваш общий код содержит немного платформо-специфичного кода, так как вы можете адаптировать его, используя #if.
Более детально выбор между двумя подходами описан в статье «Sharing code across platforms».
В дальнейшем переносимые библиотеки классов также будут поддерживать нацеливание на платформы, основанные на .NET Core. Единственная разница заключается в том, что если вы нацелены только на платформы с .NET Core, то вы не ограничены фиксированным набором API. Вместо это, вы будете завязаны на NuGet-пакеты, которые вы сможете обновлять по желанию.
Если вы добавите хотя бы одну платформу, которая не базируется на .NET Core, вы будете ограничены списком API, которые являются общими с ней. В этом режиме вы по-прежнему сможете обновлять NuGet-пакеты, но при этом вы можете получить требование выбрать более высокую версию платформы или полностью потерять их поддержку.
Такой подход позволяет сосуществовать двум мирам, получая при этом преимущества, которые несет .NET Core.
Итоги
Платформа .NET Core – это новый .NET-стек, оптимизированный для разработки с открытым исходным кодом и гибкой доставки через NuGet. Мы работаем с сообществом Mono, чтобы он прекрасно работал на Windows, Linux и Mac, причем Microsoft будет поддерживать его на всех трех платформах.
Мы сохраняем качества, которые .NET Framework привносит в разработку корпоративного уровня. Мы будем выпускать дистрибуции .NET Core, которые представляют собой набор NuGet-пакетов, которые мы протестировали и поддерживаем как единое целое. Visual Studio остается вашей ключевой точкой для разработки, причем добавление NuGet-пакетов, являющихся частью дистрибуции не требует интернет-соединения.
На нас лежит ответственность за продолжение выпуска критичных обновлений безопасности, не требующих работы со стороны разработчиков приложений, даже если затрагиваемые компоненты распространятся эксклюзивно как NuGet-пакеты.