Build Insider MEETUP with Grani 第1回レポート(1)
「using CSharp;」な企業を支える技術方針とベスト.NETライブラリ
「最先端のC#技術活用」を掲げる会社の開発現場では、どのような技術やライブラリが、どんな理由で使われているのか。C#開発者必読の、勉強会レポート。
2015年3月25日(水曜日)、Build Insider主催&グラニ共催の勉強会「Build Insider MEETUP with Grani 第1回」を開催した(場所は、六本木ヒルズ森タワー15Fにあるグラニのファンスペース)。この勉強会では、下記の2つのセッションがあった。
- 1A Framework for LightUp Applications of Grani
- 2Grani's way of thinking Infrastructure
本稿は、グラニCTO(最高技術責任者)の河合 宜文 氏が登壇した1のセッション内容の中から、筆者が重要だと感じたポイントを簡潔にまとめたものである。文章によるレポートの他、本稿の最後にはセッションスライドと動画もあるので、全内容を詳しく知りたい場合は併せて閲覧・視聴してほしい。
セッション1: A Framework for LightUp Applications of Grani
株式会社グラニ 河合 宜文(かわい よしふみ)
グラニでは、開発部のポリシーとして「最先端のC#技術を使った開発」を掲げ、実際に現在提供している製品・サービスではC#+.NET Framework 4.5+ASP.NET MVC 5という最新C#&.NET技術やUnityを活用している。また河合氏の個人活動では、2011年からMicrosoft MVP for C#/.NETを連続して受賞しており、ブログやTwitterでC#/LINQ/Rx(Reactive Extensions)関連の情報を発信したり、オープンソースライブラリとして「UniRx」というUnityで動くReactive Extensionsを開発したりしている。2012年に創業したグラニでは、これまで図1のような製品をリリースしているとのことだ。
ちなみに、「神獄のヴァルハラゲート」のキャラである「マンモン伯爵」のLINEスタンプもあるとのこと。
技術選択について
「using CSharp;」を標語に掲げており、開発では「C#を使っていく」と決めているという。ちなみにC#は現在、下記のようにあらゆる領域で使えるようになっている。
- Windows: Windowsフォーム、WPF
- Mac: Xamarin.Mac
- Windowsタブレット: Windowsストアアプリ
- Webアプリ: ASP.NET MVC、OWIN(Open Web Interface for .NET)
- クラウド: Microsoft Azure、AWS、Google Cloud Platform
- ゲーム: Unity、Paradox、Unreal Engine
- モバイル: Xamarin.iOS、Xamarin.Android、Windows Phone 8 SDK
- 組み込み: Windows Embedded、.NET Micro Framework
- NUI(ナチュラル・ユーザー・インターフェース): Kinect、Leap Motion
C#を選ぶ理由
この方針のため、C#言語一つに依存することになるわけだが、「逆にそれは強みでもある」と河合氏は語る。多様な言語を使い分けると技術・ノウハウは分散してしまうが、C#、1本に絞ればそういった問題を回避できるからだ。最近は「モバイルアプリ+Webサービスの組み合わせ」で開発することがトレンドになっており、C#であれば「iOS/AndroidのUnityクライアント」+「ASP.NET MVCのWebサービス」の両方が開発できる。これだとサーバーとクライアントの開発スキルが統一できるので、開発者間のコミュニケーションが取りやすくなったり、両方を同じ開発者が担当したりできるなど、かなりメリットが大きい。
これが「グラニがC#を選ぶ理由である」が、もちろん「C#が好きだから」というのもあると、河合氏は話した。
グラニのフレームワーク
グラニでは、開発で必ず使うフレームワークのようなものは、基本的に作らないことに決めているそうだ。あるのは最低限のルールだけ(コーディング規約すらなく、コードの書き方も既存のコードを見て“習うより慣れろ”形式である)。
こうしている理由は、「フレームワークによってプログラミングに制約を課すことなく、自由に開発できる体制を維持したいからだ」という。共通ライブラリを使う場合も、DLLファイルによるアセンブリ参照ではなく、プロジェクト参照にすることで、ライブラリのソースコードをデバッグ時にすぐに参照できるようにしている。要は、自分で考えて自分で解決できる環境を作ることで、フレームワーク側を強化するのではなく、開発者自身の成長を促しているわけだ。
「フレームワークは作らない」といっても、便利なメソッドをまとめたような小さな共通ライブラリは作っているとのこと。次節で、それを紹介しよう。
共通ライブラリ「Grani.CoreLib」
共通ライブラリのGrani.CoreLib.dllはグラニ社内唯一の共通ライブラリで、グラニのあらゆるプロジェクトがこのライブラリを参照している。なお河合氏は、その特徴を捉えて「ヒュージ・モノリシック・ライブラリ」(=内部に実装がまとまったシンプルなクラスやメソッドを数多く集めた、単一のライブラリ)と呼んでいる。そのライブラリ・プロジェクト内には、例えば以下のようなフォルダーが存在する。
- AsyncOAuth
- Batch
- Core
- Data
- Diagonostics
- Extensions
- Geography
- Glimpse
- Gree
- IO
- Math
- OpenSocial
- Redis
- Reflection
- Serialization
- Text
- Threading
- Web
このうちの1つを見ると、例えばBatch
フォルダーには、図2に示すようにバッチ実行するコンソールアプリで使える共通的なコードなどが存在する。
第1引数にクラス名、第2引数以降にパラメーター群を指定してコンソールアプリを実行すると、そのクラス名のクラスに実装されたExecute
メソッドを、パラメーター群を使って実行する。コンソールアプリのバッチ実行には、Windows標準のタスクスケジューラーなどを使っている。
その他、以下のようなGrani.CoreLibが提供する機能も紹介されたが、本稿ではその内容説明は割愛する。ポイントだけ説明するが、「TableGenerator」に書かれているMicroORMとしてはDapperを使っているとのことだ。
ここまでが現在のライブラリだが、次バージョンの計画もある。内容もかなり出来上がってきているとのことで、河合氏はその内容についてさらに紹介を続けた。
次期共通ライブラリ「Grani.CoreLib.vNext」
次期版では、実はライブラリを分割して、ヒュージ・モノリシックに「さよなら」することにしたという。具体的には下記の7つのライブラリに分けた。
- Grani.Core
- Grani.Data.MySql
- Grani.Data.Redis
- Grani.Diagnostics
- Grani.Glimpse
- Grani.Owin
- Grani.Unity
「なぜ分割することにしたか」というと、「NuGetで依存関係を解決してくれて、プロジェクトにアセンブリ参照を自動的に追加できる」としても、ヒュージ・モノリシックではその依存関係が大きくなりすぎてNuGetで大量のアセンブリ参照が追加されてしまい、「開発効率が悪い」と感じられるようになったからだ。そこで、特に多くのプロダクトで使っているCore
フォルダーを分離することで、Coreだけは依存関係ゼロにして開発効率を高めたいと考えたと河合氏は説明した。残りの部分も同様に、分離しすぎず、かつ依存関係も最小になるようにバランスを見極めて、さらに6つに分割することにしたというわけだ。
グラニが2015年に選択した.NETライブラリ
この次期版の各ライブラリ・プロジェクトから使っている、外部の.NETライブラリは次の通り。つまりこれらは、2015年にグラニが選出した、必要最小限のベスト.NETライブラリといえる。
- Grani.Data.MySql: Dapper、MySql.Data
- Grani.Data.Redis: CloudStructures、StackExchange.Redis、Jil、LZ4 for .NET
- Grani.Diagnostics: Json.NET、SLAB(Semantic Logging Application Block)
- Grani.Glimpse: Glimpse
- Grani.Owin: Owin、LightNode.Server、Jil、Json.NET
- Grani.Unity: UniRx、LINQ to GameObject、websocket-sharp、Json.NET
河合氏はまず、この中からGrani.Diagnosticsプロジェクトのロギング(Logging)について説明した。
2015年時点でベストなログ出力技術とは?
.NETプログラムでロギングを実装する場合は、Log4netやNLogといったログ出力用ライブラリ(=ロガー)を使うことがこれまでの定番だった。しかしこれからの時代では、下記の3要素が必須となっていくであろう。その要件においては、これらのロガーはふさわしくない。
- 構造化ログ(Structured Log): ログは、個別のデータを人が読むものではなく、大量のログからの解析結果だけが読めればよい
- ストリームロギング(Stream Logging): ファイルやコンソールに出力するだけでなく、ログをStreamに見立てて柔軟に処理できるように
- 外部プロセス化(Out of Process): ログ出力は通信して外部に保存することが一般的。通信の安全なシャットダウンや負荷分散のためにも、ログ処理を外部プロセスに移すべき
Grani.Diagnosticsライブラリが提供するLoggingの次期バージョン機能では、これらの要件を満たすものになっている。具体的には以下の内容を採用している。
1. 構造化ログ
構造化ログを実現するために、.NET 4.5から標準搭載されたEventSource
クラス(System.Diagnostics.Tracing名前空間)を使用している(図4)。このクラスを使うと、Event Tracing for Windows(以下、ETW)にログを出力できる。
EventSource
クラスは標準ライブラリに含まれているので、外部ライブラリへの依存もない。ETWはWindowsネイティブ機能であるため、アプリからETWへのログ出力も軽快だ。
2. ストリームロギング
ストリームロギングを実現するために、ETWからのログの受け取りには、外部ライブラリのSemantic Logging Application Block(以下、SLAB)を使用している(図5)。先ほどのEventSource
クラスが出力する構造化ログはそのままでは扱いづらいが、SLABを使えば、ログがIObservable<EventEntry>
として扱えるのでRxにより処理できる。
3. 外部プロセス化
SLABには「内部プロセス(In-Process)」と「外部プロセス(Out-of-Process)」の2形態がある。外部プロセスにすることで、ロギング処理がアプリ本体のクラッシュなどの影響を受けなくなるし、逆にロギング処理が重くなっている際にはアプリ本体に影響を与えなくて済むというメリットがある(図6)。
このようにしてログを収集したら、それを解析していく必要がある。
2015年時点でベストなログ解析技術とは?
Azure HDInsightや、AWS RedShift、Hadoop、自分でプログラムを書くなど、ビッグデータとなったログを解析する手法はいくつか考えられるが、「2015年に入った現段階では、グーグルのBigQuery一択。さまざまな点で機能が優れていることももちろんだが、何より圧倒的に簡単である。オライリーの日本語書籍『Google BigQuery』も最近発行されたので情報も十分ある」と河合氏は力説した。もちろんBigQueryは、C#とLINQ to BigQueryを使って処理が書ける(※ちなみに、その手法はBuild Insiderの連載記事で解説予定)。
2015年時点でベストなプロファイリング技術とは?
河合氏はGrani.Glimpseプロジェクトに含めるプロファイリング機能の説明に入る前に、「ASP.NET開発をしているなら、Glimpseを使わないのはあり得ない」と語った。それほどGlimpseは良いらしい。特に良いのは、タイムラインがかなり見やすいこと。さらにカスタマイズ性も高く、必要な場合はカスタムプラグインで問題を可視化したりできる(図7)。
2015年時点でベストなデータキャッシング技術とは?
グラニでは、永続ストレージ層にMySQL、NoSQL層にRedisを使っており、Redisにおいては2015年もStackExchange.Redis+CloudStructuresの組み合わせを使っていく予定とのこと(Grani.Data.Redisプロジェクト)。
2015年時点でベストなシリアライズ技術とは?
グラニでは、Redisキャッシュに、C#のクラスからシリアライズしたバイナリを入れている。そのシリアライズ&バイナリ形式としては、JSON/MessagePack/Protocol Buffersなどのいくつかの候補の中から、「シリアライズ速度(速いか)」や「バイナリサイズ(小さいか)」の良さを考慮して、今まではProtocol Buffersを採用してきた。だが「扱いやすさ」があまり良くなかったため(例えば「Dumpが全くできない」など)、次期版ではJSON形式+LZ4圧縮に切り替える予定とのことだ。JSONは非常に取り扱いやすく、LZ4は圧縮率はそこそこだが、圧縮/展開がかなり高速だからだ。
2015年時点でベストなWebサービス開発技術とは?
現時点はOWINからDNX(.NET Execution Environment)への過渡期であり、OWINはDNXへのつなぎにすぎない。しかし、DNXのこれまでの名称変更(KREやXREなどと呼ばれていた)や、安定版のリリースもかなり先になりそうなことを考えると、現時点でDNXに乗っかるわけにもいかない。そこでグラニは、「DNXに対しては待ち」と判断したとのこと。
では「将来性のないOWINを使うべきか」という点だが、DNXでのMiddlewareの作り方やパイプラインの構築概念はOWINのそれに似ており、しかもOWIN自体は薄いレイヤーでしかないので移行時の影響範囲は小さいと考えられるため、現時点であれば「OWINで開発した方がいい」だろう。グラニはそう判断した(Grani.Owinプロジェクト)。
なお、OWIN上のWeb API構築には、内製のLightNodeを活用しているとのこと。.NET開発ではASP.NET Web APIが一般的なWeb API構築フレームワークだが、これ以外を見ても、Web API構築だけに特化したコンパクトなMicroフレームワークは標準ライブラリ内には存在しない。そのため、「RubyにおけるRailsに対するGrapeフレームワークの存在」と同じ構図で、このLightNodeを作成したとのこと。なお、LightNodeは前述のGlimpseにも対応している。
Unityでのライブラリ活用について
すでに少し紹介したが、Unity向けのReactive Extensions「UniRx」も河合氏が自作したオープンソースのフレームワークで、これをUnityによるゲーム開発で活用している(Grani.Unityプロジェクト)。社内で報告されたUniRxのバグの修正は、随時、GitHubのリポジトリにも反映しているとのこと。現在、GitHub上でも注目度が上がってきており、人気も出てきている。
また、Unity 4.6から搭載されたuGUIをWPF風に拡張する「uGUI.Ext(仮)」を制作中で、今後、オープンソース化する可能性もあるとのこと。
まとめ
グラニでは、外部ライブラリはそれほど多く使っておらず、共通ライブラリにおいても派手な実装はなく、DLLファイルのサイズも小さい。C#や.NET自体がよくできており、Glimpseなどの外部サービス/OSS(オープンソース・ソフトウェア)も充実しているので、小さなそれらの組み合わせで、グラニが達成しているような大きな結果をもたらせる。ただし、外部ライブラリやサービスの組み合わせだけで全てが完成することはないので、「何を作るべきか、何を作らないべきか」の判断基準を、本セッションで紹介した事例から感じとってもらえるとうれしい、と河合氏は締めくくった。
■
このセッションのスライドと動画
セッションスライド
セッション動画
■
次回は、齋藤 龍一 氏による「Grani's way of thinking Infrastructure」のセッション内容を紹介する。
1. 【現在、表示中】≫ 「using CSharp;」な企業を支える技術方針とベスト.NETライブラリ
「最先端のC#技術活用」を掲げる会社の開発現場では、どのような技術やライブラリが、どんな理由で使われているのか。C#開発者必読の、勉強会レポート。
2. 最新Windows技術中心で実現するとこうなる! ソーシャルゲームのインフラ構築&運用
ソーシャルゲームの運用環境を、LinuxからWindows(PHP→C#)に変えた企業が最終的に実現したインフラとは? Windows系インフラエンジニア必読の、Build Insider主催勉強会のレポート記事。