.NET Core 2016年の締め – .NET Core Advent Calendar 2016

この記事は「.NET Core Advent Calendar 2016」の25日目の記事です(遅刻しました)。

今年は.NET CoreのRTMがあったので、知名度も上がったのではないかと思います。その辺りを適当に回想したいと思います(深い話はなし)。


.NET Coreという存在

.NET Coreは次世代の.NET Framework、のようなざっくりとした紹介をされる事が多いです。製品的にはそのような位置づけであり、実際初期のプロジェクトはそういう方向性であったのではないかと思いますが、現在はちょっと印象が異なります。

netcore1.NET Coreが議論に上がる頃にMSが度々提示していた図がコレです。図自体もシンプルで、.NET Framework 4.6と.NET Core 5が両立され、従来の.NET Framework 4.6は互換性のために維持され、.NET Core 5はマルチプラットフォーム対応となることが示されています。

netcore2次のこれは、.NET Core 5がリバージョニングされて.NET Core 1.0となり、正式リリースされた頃の図です。見たところ、.NET Frameworkと.NET Coreの位置づけは変わっていません。そして、このころはまだ.NET Coreの役割としては「ASP.NET Core」に向けられていたことが分かります。

これを見ると、この時点ではまだ「Xamarin」が壇上にないですね。実際、まだMSはXamarinを買収していません。

netcore3この辺から変化が始まります。まず、.NET CoreとUWPの関係が示されるようになりました。それどころか「Any other app model」のような何かが示されていますね。そして、それらを統括するかのような「Unified BCL (Base Class Library)」という中間レイヤーのようなものが鎮座するようになりました。

# この図では、.NET Frameworkは省かれています。

netcore41一時、もっとも状況を良く表した図がコレだと思います。C#とVB.NETが上辺に、それらを使って従来通りのWebFormやMVC、WebAPIが.NET Framework上でサポートされる一方、新しいASP.NET CoreはCore CLRと.NET Native(あまり語られていないように思うのですが、.NET Coreはコンパイル時にネイティブバイナリを生成できます)が.NET Coreの上で動くこと。そして、.NET Framework上でもASP.NET Coreが動くことが示されました。

この図から、各コンポーネントの関係性が段々と複雑化してきていることがうかがえます。

netcore5最近語られるのがこの図です。Xamarinが正式に.NETのエコサイクルの一部として認知され、.NET Coreは「ランタイム」と「インターフェイス仕様」に二分されました。.NET FoundationというOSS団体が、「.NETの基本となるライブラリの外部規約」(例えば、どんなクラスがありどんなメンバが定義されているべきか)を査定し、これに「.NET Standard」と名前を付けました。

.NET Framework、.NET Core、Xamarin (Mono) など、各個別の.NET実装はこの外部規約に沿って再定義されたバージョンを、リリースする(あるいはリリースする予定)となりました。


.NET Standard(仕切り直し)

開発者は.NET Standardの規約を想定して開発を行うことで、これらのプラットフォームで共通に使用可能なライブラリのセットを想定できるようになりました。但し、これにはバージョンがあり、1.0~1.6、そして現在2.0を正式査定する準備を行っています。

netcore6この図は、.NET Standardのバージョンと、各プラットフォーム別のバージョンの対応を示した図です。わかりにくいのですが、例えば.NET Core 1.0の環境を使う場合、.NET Standard 1.0~1.6の規約を想定できる、と言うように読みます。

最も歴史の古い.NET Frameworkについてみてみると、.NET Framework 4.6の環境を使う場合は.NET Standard 1.0~1.3までの規約が想定できるわけです。また、.NET Standard 2.0を見ると、.NET Framework 4.6.1を想定するように「後方互換性」を取り戻していることも読み取れます。.NET Frameworkの更新が追い付かない(.NET Frameworkのランタイムの更新が早すぎることを良しとしない顧客の都合のような)事が見て取れます。

# 注: 私の勝手な想像です。

「Windows」というのは、紛らわしいのですが、Windows 8.1までの「ストアアプリ」に相当するプラットフォームの事です。ごく自然な流れでUWPに移行してしまったのと、Windows 8系列が失敗とみなされている(たぶん)事から、影が薄い存在です。ストアアプリでは、.NET Standard 1.0~1.2までを想定出来ますが、1.3以降の規約は「使用できない」ことも読み取れます。

Xamarin環境は、全部.NET Standard 2.0以降の規約でしか使用できないように読み取れます。実際には従来通り、PCL (Portable Class Library) を使えば、ほかのプラットフォームとの共通利用可能なライブラリを使う/作ることが出来ます。将来的には対応してくはずです。

.NET Standardは従来のPCLの規約を置き換えるものですが、主な動機付けとしては、PCLは各プラットフォーム毎に上位互換とか下位互換とかの概念が希薄で、それぞれのプラットフォームの都合に合わせて共通仕様を決めていた都合で、プラットフォームの増加に合わせて非常に複雑化してしまった、という事があります。その複雑性は組み合わせで増加するため、何か新しいプラットフォームに対応させようとすると、もう人間には正確に判断出来ない所まで来てしまっていました。.NET Standardに規約を統合していくのは、仕方のない面もあります。

そのようなわけで、私は.NET Standardを、.NETのライブラリ規約に置いての「仕切り直し」と位置付けています。

OSSに引っ張られ始めたマイクロソフト

dotnet_logo先日、某氏と話をしていて改めて再認識したのですが、MSがOSSに舵を切り始めた時から、MSの製品プロジェクトは遅かれ早かれOSSプロジェクトに引っ張られざるを得ない、という仮説です。と言うのも、この記事を書いていても思ったのですが、上のバージョンの表からも、.NET Framework(厳密に言うなら: プロプラエタリなWindows上の.NETランタイム実装)のリリースタイミングを、.NET Standardの歩調に合わせられていない、という事実です(もちろん、様々な要因があるのだとは思いますが)。

Windows環境は、環境を固定的に扱ったり想定したりする用途が多いように思います。何か問題が発生することを極度に恐れ、変化を肯定的に捉えられない環境で使われるために、ちょっとした問題が大きく取り上げられたりします(主観なので、もちろんそうではない環境もあると思います)。そういう環境での変化が許されないという文化が、.NET Frameworkの想定バージョンをあえて戻している(4.6.1)ようにも思えます。

しかし、そんなことはお構いなしに、OSSプロジェクトは進行します。また、多くの人がかかわっているので、もやはこの流れを止めることは出来ないでしょう。また、もたもたしていると、競合に技術で抜かされてしまいます。そうなっては、何のためのプロジェクトかわかりません。

# しかも競合はそういう足かせが無かったりするので、あまり拘っているとそもそも土俵にすら登れない。

結果として、プロプラエタリ製品はOSSプロジェクトの都合に引っぱられるようになるのではないかと予想していました。これが解消されるためには、プロプラエタリ製品もその進行の速さにしがみ付いていくしかないんじゃないかなと思っています。それはWindows Updateのようなサブコンポーネントにも表れるだろうし、その土台の上で開発をする私たちにも影響すると思います。

MSが批判を受けて、何らかの形で.NET Foundationを操ろうとしてももう無理なところまで来ているし、以前にも増して、.NETとMSの行動を「厳しい目で見ている人たち」が増えているはずです。私自身は、今後MSがどのようにこの問題に対処していくのかを、楽しみに見ています。


project.json(安楽死)

netcore7project.jsonは.NET Core 1.0で導入された、新しいプロジェクトの管理手法で使うファイルです。JSON形式で、従来*.csprojや*.fsprojが担っていた「プロジェクトの構成情報」を格納しておきます。何故*.csprojをやめたのかと言うのは良く知らないのですが:

  • XMLでの管理がイケてない – 最近のjs界隈ではJSONで管理するのが流行っているので、それに合わせたい(?) ひょっとするとVSCodeのようなエディタ回りを拡張する開発環境での発展を見込んだという事もあるかもしれません。
  • .NET Coreはマルチプラットフォームなので、MSBuildが使えない – MSBuildはWindowsに依存する部分が多いため、移植を端から諦めて、全く新しい方法に乗り換えることを模索した(?)
  • NuGetによるライブラリの管理が複雑化しそうなので、これを統合したい。

で、.NET Coreのビルド制御には「dotnetコマンド」を使うので、こいつが直接JSONを解析すればいいのでは? と言う発想から生まれたような感じがしています(主観)。しかし、皆さんご存知のようにRTM直前になって急にproject.json方式は放棄すると言い出した… あまりに反対が多かったからと言う事のようです。

ですが、結局対策はRTMに間に合わず、.NET Core 1.0ではproject.jsonを使うという仕様で見切り発車。で、どうなったかと言うと、MSBuildをオープンソース化してこれをマルチプラットフォーム対応させるように移植して、*.csprojを復活させるという、初めからやれば順当な手段を採用することになりました。

# ここでもプロプラエタリ技術がOSSに振り回されている、という見方も出来る…
# (否定的文だけど、私的にはむしろ歓迎)

MSBuildの移植は結構問題もあったようですが、現在は.NET Standard 2.0の規約に合わせて(つまりVS2017のリリース?)使えるようにしようとしているようです。すると、.NET Core 1.0で使えたproject.jsonは、さっそく.NET Standard 2.0で非推奨となると。まあ、死ぬなら早い方が良いですね、どうせまだ本気で.NET Core使っているところは少ないだろうし(こなみ

それに、MSBuildが復活することで、これまでMSBuildスクリプトで使えたテクニックが再び使用可能になるのは大きいです。おまけにNuGetのどうしようもないアレな仕様も、とうとう完全にMSBuildに統合され、さんざん煮え湯を飲まされてきた仕様が一気に解決に向かいそうです。例えば:

  • NuGetパッケージを導入すると*.csprojを書き換えたりしますが、これが失敗して*.csprojが壊れたりおかしなことになったり。
  • NuGetパッケージの位置を示すパスがバージョンの更新でなぜか正しいパスを示さなくなってビルドに失敗するとか。
  • 古いパッケージの定義がゴミとして残り続けたりとか。
  • 古いNuGetを想定しているパッケージが、PowerShellで無理やり構成書き換えてて壊れるとか。

振り上げた拳の着地点に毎回困ったりしたのですが、NuGet 4.0と新しいMSBuildでかなり解消しそうです。MSBuild自体どうなのかという感もあるにはあるのですが、カオスな状態を一度はきちんとした着地点に落として、それから次に進んでもいい内容だと思います。


総評

.NET Core 1.0は決して順調な仕上がりではありませんでした。ただ、楽観視はしています。何故なら、OSSプロジェクトで進行することにより、開発プロセスが多くの人の目にとまり、明らかにおかしな方向に行くことに対してフィードバック(ツッコミ)が早く入れられるようになった事が大きいです。project.jsonのような過ちへの対処も、いつまでも汚い手法で姑息に対処し続けるのではなく、可能な方法で最善な手法は何か、と言う事に、多くの頭脳が取り組んでいると思います。

従来のWindows周りの開発では「変わらない」と言う事を主軸に、一種の安心感を持ってプラットフォームを採用してきたと思います。これが未来永劫うまくいくという確信がある話なら、全く問題ない、むしろ安定していて欲しいと願うばかりですが、残念ながら現実はそうじゃない。であれば、変化に追従できるような柔軟さを、.NET自身も、技術者の我々も、持ち続けられるようにしたいと思います。

来年は.NET Standard 2.0のリリースとともに.NET Coreの新しいバージョンもリリースされます。バラバラになっている様々な要素が次第に近寄ってくることになり、ようやくシナジーが生まれ始める年になるんじゃないかなと楽しみです。

.NETの新たな幕開けに期待して。

投稿者:

kekyo

A strawberry red slime mold. Likes metaprogramming. MA. Bicycle rider. http://amzn.to/1SeuUwD