.NET Framework => .NET Core vNext を考える

前提条件

.NET Coreへのマイグレーションは.NET CoreがGAになった当初から課題としてある。
今年はMicrosoftもDeveloper Dayが開催されていて、そこでマイグレーションの話題のSessionがあった。

www.slideshare.net
同じ意見な部分も多くありつつ、私が所属しているチームの開発パワー等の都合もあり、そのまま取り入れられないものもあったため、2022年2月現在の考えを整理するためにもまとめていく。

マイグレーションの前準備

プロジェクトファイルをSDKスタイルに変更する

スライドだとこの項目は2番目に来ているが、自分がマイグレーションを行う際には、package Reference形式に変更するのはSDK形式に変更する業と同時に行う。
package Reference形式は結局のところ、csprojに変更を入れる必要があるため、変更後の確認やレビューを考えるとSDK形式にしてしまったほうが筋が良い。
また、ここでpackage.configの削除も行う。 ここで注意しなければならないのは、プロジェクト構成のすべてをcsprojが握っていた旧時代と違い、SDKスタイルだと配下のフォルダは基本的にProjectにincludeされること。
そのため、Projectからファイルを除外だけしてSCM管理外にしていない。といったファイルが含まれる可能性がある。 チーム開発で且つ、チームメンバーのパワーにグラデーションがあるチームだと起きがちなので、コードレビューでガードしていきたい。
スライドを見てもらうとわかるが、推移的な参照の説明があるのが素晴らしかった。
Package Referenceにした際に、ついでに無駄な参照は破棄しておきたい。

Build&駆動検証

SDKスタイルにした際に不要な参照が入ってしまう問題があるため、Buildと駆動検証を必ず行う。
駆動検証は、もしテストがあるならば楽が出来る。

依存しているnuget Packageが.NET 6で利用できるか確認する

ここが、Activeな.NET6のプレイヤーじゃないと些かややこしい部分かもしれない。
.NET6 のApplicationは、

  • .NET6
  • .NET5
  • .NET Core 3.1
  • .NET Standard2.1
  • .NET Standard 2.0

のpackageを参照できる。 つまり、性能さえ気にしなければ、.NET Standard 2.0に上げてしまえば、駆動は可能となる。
なので、ここでいう利用可能は、最低でも.NET Standard 2.0版のpackageが存在しているかどうか。という観点になる。
これがもし存在していれば、移行が可能。
もし存在していなければ、移行先packageの選定、もしくは自作が要求される。

依存している非nuget packageの.NET6で利用できるか確認する

ここは、開発組織のパワーによってはチーム間で調整が必要なので大変かもしれない。

nuget package化のススメ

非対応が、サードパーティーのdllを購入している。という場合はまた別の話になるが、そうでない場合……例えば別チームの作ったpackageを読み込んでいる。という場合はnuget packageでの管理を検討したほうが良い。
csprojを見れば利用しているpackageのバージョンが自明な状態であることはソフトウェアを開発するにあたって結構大事なので。

マイグレーションの実行

Target Frameworkを.NET6に変更

.NET Coreで開発している人にはおなじみのTFMを変更しよう業。

docs.microsoft.com

変更すること自体は容易だが、.NET Frameworkからの激しいジャンプの場合、依存しているProjectもすべて.NET6で利用可能なTFMに変更する必要がある。
また、Windowsやxamarin等はTFMがプラットフォーム固有のものになるため、注意が必要。(Application Modelの項で別途補足する。)

依存packageを.NET6で駆動可能なバージョンにアップデート

あくまで、「なるべくジャンプが少ない状態」を選択し続ける必要がある。 ダイナミックにコードレベルですべて変えるのは、テストコードを書いて仕様を保護した後にしたい。

Application Model対応

マイグレーションにおいて、おそらくこれが本丸なため、後述する。

Build&駆動確認&deploy方法再構築

これが完了すればマイグレーションは完了となる。

.NET Core 3.0にて非対応となったApplication Model

.NETにはBCLと呼ばれる基本クラス群と、Application Modelと呼ばれるApplicationのRailの部分が存在する。 ここではRailとなるApplication Modelのうち、.NET Core 3.0にて非対応となってしまったものを列挙する。

.NET Core3.0以降も対応しているApplication Modelの移行

Windows Form / WPFの移行

Windows互換性packageの参照を追加する ※ TFMはnet6.0-windowsにする必要がある。 www.nuget.org

マイグレーション時にやることは比較的シンプルに収まっている印象。

ASP.NET MVCの移行

スライドにもあるが、ASP.NET MVCはBreaking Changes が大量にあるため、移行が難しい。

ASP.NET Core MVCは 3.0未満の時代は.NET Framework でも開発が可能なため、一度ASP.NET Core Mvc 2.2に刻んでいくかどうか問題

というマイグレーションパスがスライドでは示されていた。
ここは、通常は非常に良いアイディアだなあという気持ち。
一方で、Owinを本格利用していない場合、ASP.NET Core Mvc 2.2がそもそも最難関なので、OwinのStartupを利用していない場合、最早ここは.NET6へのジャンプのほうが筋が良いように見える。

.NET Core3.0以降で対応していないApplication Modelの移行

WebFormの移行

なるべくWebForm Project内に存在しているコードを別のProjectに移す
※ この際、System.Webに依存しているProjectは作成しないよう注意。 HttpContext等への依存が切れないとやる意味がなくなってしまう。

マイグレーション先として採用すべきApplication Modelの判断

個人的には、

  • ActiveではないApplication(なるべく塩漬けにしたい) => Blazor Server or ASP.NET Core Razor Pages or ASP.NET Core MVC
  • ActiveなApplication(積極的に変更や改善を行いたい) => ASP.NET Core MVC

説を推して行きたい。

Blazor Serverが移行先として挙げられることが多いがなぜMVCなのか???

.NET Core3.0以降で対応していないApplication Modelについては書き直しを要求される。 また、上記はどれも、本来必要な技術を高度に隠蔽することで、本来必要であるべき技術の学習コストを省き、短期的な生産性を上げるという思想のApplication Modelである。
一定の成果を上げたという意味で大変素晴らしいという尊敬の念はあるものの、Webに関するApplicationを開発する以上、Webに関する知識や技術から遠ざかることで、例えばWebFormの開発者はWebFormしか書けないプレイヤー、しかもWebFormについても熟知していない状態になってしまう風潮が強かった。
ActiveなApplicationについては、今一度Blazor Serverを採用してWebFormと似た書き味に行くよりは、ASP.NET Core Mvcへのマイグレーションを素直に行うほうがプレイヤーの確保、及び育成面で筋が良いように感じる。

一方で、なるべく塩漬けにしたいApplicationについては、Blazor Server が選択肢に入ってくる。
特に塩漬けのようなperformanceを考えなくて良い場面であれば、AWSのツールサポートが.NET6時代の今ならある程度受けることも可能である。 aws.amazon.com

WCFの移行

gRPCに関してはMicrosoft特有の技術でもなければ、高度に隠蔽するApplication Modelでもないため、個人的には推奨したい。
一方で、WCFの移行先がgRPCというのは、WSDLSOAP)形式からの乗り換えであればワンチャンありそうだが、HttpRequest + REST APIに近しいデザイン(ステートレス、URL Resourceベース等々)をしている場合、gRPCにしてしまうと、Client側がgRPC対応のカロリーを消費する必要が出てくる。(Protocol Buffersからリバース生成できる仕組みが各言語にあるとはいえ、対応はそれなりに時間が必要。)
これを踏まえると、

  • HttpRequest + REST APIに近しいデザインのエンドポイントを提供している場合 => ASP.NET Core Mvc(WebApi)
  • WSDL(SOAP)形式からの乗り換えである場合 => gRPC

説を推して行きたい。