クラウド名刺管理『Sansan』『Eight』を提供するSansan株式会社は、スキルアップを目指す.NETエンジニアのための勉強会を定期的に開催しています。
第1回は、Microsoft MVP(Most Valuable Professional)ホルダー、株式会社gloops 尾上雅則氏を講師に迎え、「できるC#エンジニア」「C#の言語仕様」「C#を取り巻くOSSの動向」といったテーマでお話を伺い、参加してくれた40名超のエンジニアと活発な議論を交わしました。その様子を完全レポートします!
(開催:2014年3月12日、モデレータ:Sansan株式会社 藤倉成太)
※2014年9月追記:一部実際に使われた用語と誤りがあったので修正しています。
■できるC#エンジニアとは?
――レベルの高いC#エンジニアは何が違うのでしょうか。
(尾上氏)C#のエンジニアには、Javaベースの人が結構多いという印象を受けます。JavaとC#は似ていますが、C#はJavaとは違い、関数型のパラダイムを含みます。そのため、Javaの発展版のような使い方をすると、C#のポテンシャルを十分に活かせないと思います。
単純に言語レベルで考えれば、異なるパラダイムにも興味を持ち、深くC#を学んでいる人が「できるエンジニア」でしょう。
「仕事」という意味では、C#に限ったことではありませんが、自分のスキルを活用して新しい価値を生み出せる人が「できるエンジニア」だと思います。ただ、「技術力がある」=「価値を生み出せる」ではありません。
C#は、Windowsのスタンドアロンアプリやリッチクライアント、Windows Phoneアプリ、Web開発など、複数の技術分野にまたがって利用されており、それぞれの分野でしか使わない機能もあります。スタンドアロンアプリだけ、Webだけ、と各分野に閉じている状態では、レベルが高いとは言えないと思います。エンジニアとしてのレベルを上げるには、C#で何ができるか、さまざまな技術分野について横断的に興味を持って取り組むことが必要でしょう。
――JavaとC#の違いは?
(尾上氏)C#は、構造型や列挙型を含め値型が多い、アンマネージコードの呼び出しが可能など、Win32 APIとの相互運用を強く意識した文法が多く取り込まれています。
また、C#にラムダ式やジェネリクスが導入されたとき、Javaではまだ同等の機能が完全な形では利用できず、書けるコードにも違いがありました。C#は、Javaに比べると、発展の速度が速いと思っています。
var
――C#では、varでローカル変数を宣言し、コンパイル時に型を推測できます。けれど、GitHubのUIでのコードレビューでは変数の型がわかりにくいことがあったりするのですが、varについてどう思いますか?
(参加者)自社では、基本的にvarを使うようにしています。varを使うと、型部分のコードが短くなり、コンパクトにまとめやすい、見やすいなどのメリットがあるからです。
コードレビューに関しては、そのコードのコンテキストを共有できており、命名規則がしっかりしていれば、varがレビューの障壁になることはないと思います。
(尾上氏)使えるところでは積極的にvarを使うという姿勢には賛成です。ただ、必ずvarを使わなければいけないわけではなく、必ずvarを使ってはいけないというわけでもないと思います。ラムダ式などvarを使えないところもあります。
(その他の意見)
拡張メソッド
――クラスを定義しなくても新しいメソッドを追加できる拡張メソッドはとても便利ですが、柔軟すぎてやばいときがありませんか?
(尾上氏)インターフェイスに拡張メソッドを追加する使い方は、全面的に賛成です。ただ、Objectクラスに拡張メソッドを追加するような使い方はダメ。共通クラスライブラリに勝手に追加するのはやめてほしいですね。
(参加者)LINQ to XMLを使う際には、基底クラスであるXObjectに拡張メソッドを追加して利用することもあります。XObjectクラスがDSL(Domain Specific Language)という閉じた空間にあるので、特に問題は生じません。DSLとしてコンテキストが閉じていれば、基底クラスに追加するような使い方も有用だと思います。
部分メソッド
――メソッドの宣言と定義を分離させる部分メソッドですが、どのように使えばよいでしょうか?
(尾上氏)Visual StudioのVisual DSL系のツールが自動生成するコードに自分の処理を組み込みたいときに部分メソッドを使います。
自動生成されたコードに自分の処理を追加しても、ツールの更新時に消えてしまうことがあります。自動生成コードを安全に扱うために、部分クラスや部分メソッドを使うことが多いです。
(参加者)自分が実装したクラスのコードを自動生成したときに、クラスを継承しないで機能をカスタマイズしたい場合に部分メソッドを使います。
dynamic
――dynamicを使えば、コンパイラでの静的な型チェックをバイパスする動的な型付け変数を定義できますが、なぜ導入されたのでしょうか。
(尾上氏).NET FrameworkのCLRに、DLR(動的言語ランタイム)と一緒に導入されました。
(参加者)以前、C#のプログラムから利用する際にOfficeのバージョンによってOLEオートメーションオブジェクトの実装がばらばらという問題がありました。COM/OLEとの相互運用のために、OLEオートメーションオブジェクトのディスパッチを可能にするためという理由もあります。
――dynamicはどのようなところで利用するのでしょうか。
(参加者)C#の閉じた世界ではデータは型付けされますが、外の世界のデータはC#からは型がわかりません。外の世界にあるデータとC#の世界をつなげるのがdynamicの役割だと思っています。
C#の閉じた世界で作っている限り出番はありませんが、外の世界とデータをやりとりするときにdynamicを使うと便利です。
(尾上氏)JSONのメンバーをダックタイピングでアクセスしたいときなどに使います。
簡単なリッチクライアントならいくら使ってもよいと思う。
(参加者)遅延バインドが必要なときによく使います。型なしデータセットにアクセスしたり、レガシーの共用体を今風に使えるようにしたりといったときには、dynamicを使うと楽です。
――dynamicを使うときのデメリットや制約はありますか?
(尾上氏)パフォーマンスが求められるWebアプリなどでは、dynamicの使用により全体のスケーラビリティが損ねられる可能性がある。dynamicは、内部で動的に生成したコードをキャッシュしていますが、そのキャッシュの効率がわからないので、スケーラビリティを重視する場合はあまり使わないほうがよいでしょう。
ジェネリクスの共変性
――ジェネリクスの共変性とはどういうものなのでしょうか。
(尾上氏)共変性は指定した型より具体的な型を利用できること、反変性は指定された型より汎用的な型を使用できることです。共変性はout、反変性はinキーワードを使います。
反変性については、具象クラス型のコレクションをそのスーパークラス型のコレクションに入れられるというのは、Domain Model的な実装で役に立ちます。
共変性、反変性は、単にキャストすれば済むところではなく、スーパークラスのコレクションとして包括的に扱いたいときに、代入操作が伴う場合やスーパークラスのオーバーライドされたメソッドを呼び出したい場合などに威力を発揮すると思います。
async/await
――C# 5.0で導入されたasync/awaitはWebアプリで使いますか?
(尾上氏)実行時間がかかるところに使います。非同期にするとスケーラビリティが上がり、アプリ全体のスループットが一時的に増えるかもしれません。ただし、スレッドのコンテキストスイッチが頻繁に起こり、ユーザのレスポンスタイムに影響が及ぶ可能性があります。
(参加者)非同期化の対象には、I/O依存の処理とCPU依存の処理がありますが、Webアプリでは原則としてI/O依存の処理に使うべきです。
(尾上氏)async/awaitはシュガーシンタックス(糖衣構文)で、非同期の問題は何ひとつ解決していないことに注意してください。なので、確実に効果が得られるところを選別して利用し、乱用すべきではないと思います。
また、リッチクライアントでasync/awaitによりUIに問題が発生するという話を聞きますが、これは間違いです。リッチクライアントでは、非同期処理をモデルの内部に閉じるように設計すべきであり、そうできていればUIには問題は生じません。
(参加者)データベースアクセスなど、複数の処理をシーケンシャルで行うと時間がかかる場合は、スケーラビリティではなくパフォーマンスを上げるために、async/awaitで並列で処理することがあります。
(尾上氏)async/awaitは、非同期に関する問題を理解したうえで、使う場所を選ぶべきですね。
(その他の意見)
――Microsoftのさまざまな機能がオープンソース化されていますが、どう思いますか?
(尾上氏)Microsoftがプロプライエタリからオープンソースへ向かう流れには賛成です。
.NET Frameworkは、オールインワンで何でもできるというのが売りでしたが、その分アーキテクチャを縛られるという傾向がありました。たとえば、Visual Studio 2005で導入されたTableAdapterは非常に便利ですが、テーブルモジュールのパターンや業務のコンテキストがある程度限定され、用途が限られていました。最近では、周辺技術がOSS化されることで、いろいろなアーキテクチャを選べるようにきています。
Microsoftは、たとえば、単体テストの自動実行ツールとしてオープンソースのNUnitがあるのに、MSTestを開発して対抗するようなことをしてきました。けれど、結局はVisual StudioでNUnitをサポートしています。今後はOSSを受け入れていくことが増えていくと思います。
――MVC、Web API、Web Pages(Razor)、Entity Frameworkなど、多くがオープンソース化されています。
(尾上氏)Entity Frameworkは、データベースアクセスに関わるいろいろなパラダイムを詰め込みすぎて、重厚長大になってしまっていますね。
Microsoftの技術のオープンソース化が進んでいるからといって、すぐにでも開発者からのコードのPull Requestがどんどん採用されるようになるわけではありませんが、この流れによってC#コミュニティの寿命が延びていくだろうと考えています。
――MicrosoftのコードライセンスであるMS-PLはどのようなライセンスなのでしょうか。
(尾上氏)MS-PLは当初、OSSのライセンスとしては疑問視されていましたが、現在ではきちんと機能しています。
(参加者)MS-PLが作られたのはおそらく、MicrosoftではOSSに他のライセンスを適用することが許されなかったという背景があったと思います。今ではそんなことはなく、Microsoft自身、他のライセンスを使うようになっています。
MS-PLは、MITライセンスに非常に似ているため、OSSコミュニティではあまり歓迎されません。差異があまりなく、MITライセンスで対応できるからです。今後はあまり使われなくなるのではないでしょうか。
――注目のOSSフレームワークは?
――Windows Serverを運用に使う場合、B2CとB2Bではどのような違いがありますか?
(尾上氏)現在ソーシャルゲーム開発を行っていますが、B2Cではパフォーマンスによりシビアになります。前職でB2BのASP.NET案件を受託していましたが、そのようなことはありませんでした。
B2Cでは、お客さんの反応が直接見えるというのがB2Bとの最大の違いですね。
――Microsoftの技術は企業内システム向けで、B2Cではあまり実績がないという印象がありました。
(尾上氏)Windows Serverは安定していないと言われていた時代があったことに驚くほど、今は非常に安定しており、トラブルがあってもしっかりと情報が収集できています。少なくとも自分が関わっている1年半ほどの間に、ハードウェアの故障やアプリに起因するトラブルはあっても、OSやIISが原因で致命的なバグが起こったことはありません。B2CでもWindows Serverでの運営でよいと思います。
ある商用データベースではバージョンアップに伴い、メソッドが利用できなくなったといったトラブルがありましたが、Microsoftは下位互換性を慎重に管理しているので、バージョンアップした後即座に問題が起こるようなことはあまりありません。Microsoftはバージョンごとの差異をしっかりと提示しているので、事前にそれを調査することで対応できます。
また、Windows Serverで運用するなら、IISのメモリダンプを読めるとよいでしょう。ツールを使ってわかりやすいレポートを出力するだけで便利に利用できますし、.NET Frameworkへの理解も深まります。
この後の質疑応答では、「.NET Frameworkを利用する企業を増やすには」という議論が行われました。また、セッション後には交流会も行われ、ご好評のうちに終了しました。
Sansanでは定期的に.NET勉強会を開催しております。ぜひご参加ください。
★ただいま参加受付中!