「.NET Core5から概観する、.NETのOSSへの取り組み」 – Nagoya ComCamp 2016 powered by MVPs

WP_20160220_10_04_02_ProNagoya ComCamp 2016 powered by MVPsが開催されました。そこで登壇してきた話です。

ComCampは、Microsoft MVPが登壇するコミュニティ主体勉強会です。MVPだけではなく、技術的な強みを持つ方も招きます。一年に一度のペースで、全国の各会場で同日に一斉に開催するので、トータルで見るとかなりの規模となってます。名古屋会場は約60名近い動員がありました。

今年の名古屋会場は「オープンソースソフトウェア」が一つのキーワードとして、様々な角度から発表がありました。私は表題の通り、「.NET Core5」のリリースが迫っていることもあり、ここから展開して、現在のマイクロソフトのOSSに対する取り組みを概観出来たら良いなと考えました。

# ちなみにComCampは初登壇でした。


「.NET Core5」じゃなくて「.NET Core 1.0」とか

タイトルとデスクリプションを決めろと言われて連絡し、公式サイトに掲載されてから3日後、いきなり「.NET Core5は.NET Core 1.0と名称変更」などと言う話が流れ、既にアカンやつやと言う流れにww

まあ、それはそれとして、今回の発表でどんな話を展開しようかと、日程的にギリギリまで考えあぐねてました。と言うのも、マイクロソフトがと言うより、OSSと言う枠組みでなぜ業界がその方向に向かうのかと言うのは非常に幅が広くて、自分が考えている事だけでも1日で話が出来ないような大きな「うねり」です。

で、あまり一般論みたいな話をしても、ComCampで私に期待される話でもない気もするし… 幸いその方面は、OSSコンソーシアムの吉田さんから丁寧に解説して頂いて、私の出る幕などない感じだったので良かったです。

今までの.NET開発とこれからの開発が、OSSというエッセンスが加わることによってどんなふうに変わるのか、そしてマイクロソフトはなぜその方面に向かっているのか。やっぱり技術方面で入口を紹介するのが良いかなと思いました。また、口でしゃべり続けてもアレなので、多分がりっちもデモで攻めてくるだろうと考え、私も全部デモみたいな流れでやってみることにしました(ちなみに、デモ主体は初めての試み)。

大きくは、以下のような構成です。詳しくはスライドを参照してください。

  • What is .NET Core? (.NET Coreって何?)
  • Disposable Infrastructure (破棄可能な環境)
  • Integrated Development Environment (統合開発環境)
  • まとめ

オリジナルスライドはこちら: NETCoreから概観するNETのOSSへの取り組み.pptx


裏話 – デモの悪魔

… やっぱり現れた、それも凶悪な奴が (;´Д`)

まず、登壇前日までデモ機材の不調に悩まされ続けました。.NET Coreがマルチプラットフォーム対応を目指している事を鮮明にしようと、UbuntuをインストールしたノートPC(非仮想マシン)を使って、スライドも含めて完全に非Windows環境でデモしようと準備していたのですが、UEFI BIOSにバグがあって64ビットUbuntuがブートしない…

# これは動いた気がしただけで、実はダメだった

デモでは.NET CoreとDockerを使うので64ビット版がどうしても必要(.NET Coreは現在はまだamd64のみサポート)で、前日まで横でトライし続けていたのですが、これ以上やってるとスライドも完成しないというギリギリ状態になり、泣く泣く断念…

それ以外にも、当日朝からOneDriveの同期が長時間やりまくり、何故か過去のフォルダ構成を再現しようと一生懸命ダウンロードしはじめる… もう危なくてスライドをOneDriveに置いておけないので、OneDriveを切断してローカルディスクにコピーしてUSBメモリにも入れて準備。

デモについては、ThinkPad X201sのHyper-Vで動かす事にしました。所が、このX201sも最近は能力不足が露呈していて、Hyper-Vで仮想マシンを動かしているとどうにも重くて辛い。LibraOfficeでスライドを披露というのも妥協するしかないかなと思っていました。

こういう状況で「とどめを刺される」というのは、何度も経験しているので嫌な予感しかしない。当日会場に入ってからも、念のためにAzure上でUbuntu VMを作り、本当の最悪はこれでデモしようと、2つ目のバックアッププランをちまちまと用意していました。

Azure VM、X201sでローカルで動かすよりも速い! 以前よりも格段にパフォーマンスが向上しているのが体感できます。しかし、Azure VMでは、Ubuntu Desktopを使い、VNC使えるようにするまで持っていかない限り、Visual Studio Codeのデモが出来ないという問題もあり、やっぱり最終手段として取っておくつもりでした。

が、奴はそれだけでは飽き足らず、X201sのHyper-Vをハングさせてボイコットの構えに (*´Д`) 勘弁してくれー (この時点で11時ぐらい)

それからスライドを一部修正したり、脳内で立ち回り方法を再構築したりなど、それはもう酷いプレッシャーぶりで。あとはリアルタイムで聞いて頂いた方ならお分かりの通りな内容でした… すいません。

# 特にVisual Studio Codeのお話は大幅にカットせざるを得ませんでした。幸い殆どの方は使ったことがあるとの事だったので、良かった。Ubuntuでも殆ど使用感は変わらないです。多分!きっと!!

でも、それなりに楽しくやれました。特にDocker周りは語ってない事も多いのですが、事前準備でも結構面白かったです。折角.NET Coreで依存性が大幅に緩和され、MacやLinuxでも動くようになるので、Dockerと組み合わせて是非遊んでみて下さい。そのための足掛かりになるような解説は行ったつもりです。

それではまた!!

NamingFormatterを作りました

NamingFormatterNamingFormatterというライブラリを作りました。このライブラリは単純で、string.Formatの代替です。使い方や狙いなどを紹介したいと思います。

ソースとNuGet

GitHub: CenterCLR.NamingFormatter
NuGet: CenterCLR.NamingFormatter

ライセンスはApache V2です。PCLのProfile1とProfile259、NET2.0、NET3.5に対応させたので、ほとんどの環境で使用可能です。
(NuGetで簡単に導入するには、VS2010以降が必要です。確認はVS2015以降で行っています)

使い方と狙い

標準のstring.Formatは、引数との突き合せに「インデックス番号」を使用します。しかし、NamingFormatterでは「任意の名前」が使えます。以下は、普通のstring.Formatの例:

var formatted = string.Format(
    "Index0:{0}, Index1:{1}",
    arg0,
    arg1);

このコードの問題は、フォーマット文字列内のインデックス番号が、単なる数値であり、コード上のarg0やarg1と直接的な関係が無い事です。C# 6において、「文字列挿入」という機能が追加されましたが、これはあくまでコンパイル時の評価です。

例えば、フォーマット文字列をユーザーが任意に指定可能となるようなシチュエーションがあると思います。ログ出力のフォーマット指定などが良い例ですが、インデックス番号で指定させると、各番号が何を示すのかが分かりにくくなります。ログ出力の例を示します:

// デフォルトのフォーマット文字列:(App.configで変更可能)
//   "Date: {2:yyyyMMdd}, UserName: {0}, Action: {1}"
var formatString = Properties.Settings.Default.LogFormat;

// フォーマットする(引数との対応付けは?)
var formatted = string.Format(
    formatString,
    userName,
    action,
    date);

上記のように、フォーマット文字列を外部入力によってカスタマイズ可能にした場合、インデックス番号の何番が何かと言う事が非常にわかりにくくなります。このような場合に、NamingFormatterを使うと、以下のようにフォーマット文字列を指定することが出来ます:

using CenterCLR;

// デフォルトのフォーマット文字列:(App.configで変更可能)
//  "Date: {date:yyyyMMdd}, UserName: {userName}, Action: {action}"
var formatString = Properties.Settings.Default.LogFormat;

// フォーマットする(NamedクラスのFormatメソッドを使う)
var formatted = Named.Format(
    formatString,
    Named.Pair("userName", userName),
    Named.Pair("action", action),
    Named.Pair("date", date));

Named.Pairメソッドは、KeyValuePair<string, object>を生成するためのユーティリティメソッドです。もちろん自分でnewしても問題ありません。オーバーロードとしては以下のものがあります。

  • params KeyValuePair<string, object>[] : つまり、上記の例で使用した可変引数対応のメソッドです。
  • IEnumerable<KeyValuePair<string, object>> : LINQの結果を渡してフォーマットさせる場合に使用します。IEqualityComparerを指定してキーの特定方法をカスタマイズする事も出来ます。
  • Dictionary<string, object> : 既に辞書として存在する場合には、これを使うことが出来ます。また、IDictionaryやIReadOnlyDictionaryを使う事も出来ます。
  • 一番基礎的なオーバーロードとして、Func<string, object>を指定するメソッドもあります。このメソッドを使うと、キー名に対応する値を完全にカスタマイズ出来ます。
  • IFormatProviderインターフェイスをフォーマットに使用出来るオーバーロードもあります。

フォーマットオプション

フォーマットオプションとは、インデックス番号の指定だけではなく、書式の形式を追加指定させることが出来る機能です。上記の例でも示しましたが:

// 日付(DateTime構造体)の書式指定を行う
var formatted = Named.Format(
    "Date: {date:yyyy/MM/dd HH:mm:ss.fff}",
    Named.Pair("date", date));

のように、string.Formatで指定する書式指定と同じように、オプションを指定することが出来ます。

あるいは:

// 数値の桁数を指定する
var formatted = Named.Format(
    "Result: {result,10}",
    Named.Pair("result", 123));

のように、桁数指定を行う事も出来ます。もちろん、これらを組み合わせ、更に複数のパラメータを同時に指定させることも可能です。

プロパティのトラバース機能

パラメータに対応するインスタンスがプリミティブ型ではなく、任意のクラスや構造体である場合、パブリックプロパティを探索させることもできます。これは丁度XAMLのバインディング式のように、ドットで区切られた式を書きます:

// DateTimeのプロパティをフォーマット文字列で探索させる
var formatted = Named.Format(
    "Millisec: {date.TimeOfDay.TotalMilliseconds}",
    Named.Pair("date", DateTime.Now));

条件としては、パブリックかつインスタンスプロパティである必要があります。ここではDateTime構造体を例として使用しましたが、もちろん独自のクラスや構造体でも使うことが出来ます。プロパティの指定に失敗している(名前が間違っているなど)場合は、空文字列としてフォーマットされます。


特にカスタマイズ要件がある場合などに、小粒ですが応用できるのではないかと思います。ライセンスもゆるくしてあるので、使ってみて下さい。何か問題があればフィードバックを貰えるとありがたいです。