MonoDevelop勉強会では、MonoDevelopの使い方を基礎の基礎から応用まで説明する。これはその補完的な事前資料とする。
C#と.NET Frameworkは、ECMA CLI標準に従っており、プラットフォーム中立の中間言語を使用するので、本来はどんなOS環境でも動作できるようになっている。しかし、Microsoftの.NET FrameworkはWindowsでしか動作しない。これをLinuxやMac OS Xでも使えるようにしようと始まったのがMonoプロジェクトである(MicrosoftはsscliというFreeBSDベースの実装を公開している)。
.NET Frameworkがそうであるように、monoにもC#コンパイラと基本ライブラリ、そして中間言語コードを実行するランタイムがある。monoのC#コンパイラはC#で書かれていて、それ自身monoで動作する(.NET Frameworkのcscもいずれそうなる予定)。.NETはP/Invoke(プラットフォーム呼び出し)によって、ネイティブコードを呼び出すことができるようになっていて、.NETではWin32 APIが頻繁に呼び出されている。monoでもこの仕組みを利用してgtk+のアプリケーションをC#で開発できる、Gtk#というライブラリが提供されている。
Monoの開発は、フリーソフトウェアのLinuxデスクトップ環境を開発していたGNOMEプロジェクトのリーダーであったMiguel de Icazaが始めたもので、その成り立ちには強いGNOME指向がある。 Miguel de Icazaは、1990年代後半当時にLinuxに自由かつモダンなデスクトップ環境が無かったことからGNOMEプロジェクトを立ち上げた。Gtk+は、Gimpで使用されていたGUIツールキットのライブラリgtkから発展したもので、元々はLinux環境用のGUIフレームワークであった。GNOMEではこのGtk+を利用してGUIを構築している。
一方でMicrosoftの技術に強い関心があり、GNOMEにもCOM相当の技術を持ち込もうとしてCORBAベースのBonoboを発案し、.NETが公開されるとC#およびCLRを持ち込むためにMonoを立ち上げた。Gtk+のアプリケーションをC#で開発できることは、Monoの主要な目的のひとつである。実際、MonoDevelopの他に、Banshee、F-Spot、Beagleなど、色々なアプリケーションがC#で開発されている。
Gtk+はその後、WindowsやMac OS XのCocoaでも実行できるように、バックエンドをプラットフォーム中立な設計にしている。それぞれのバックエンドの実装は、まだ完全とは言えない(たとえばCocoaのテキスト入力メソッドに対応できていない)。
monoにおけるP/Invoke呼び出しは、クロスプラットフォームに実行できるように設計することができ、Gtk#は実際そのようになっている(現状ではWindowsにおけるGtk+はWin32用ビルドしか存在せず、monoランタイムも32ビット環境で動作する)。
MonoDevelopは、mono用に作られたIDE(統合開発環境)で、Gtk#を使用して作られている。MonoDevelopは、Windows環境用にVisual Studio類似のフリーソフトウェアとして開発されていたSharpDevelopをもとにしている。SharpDevelopは当時他に類を見なかった独自のアドインフレームワークを発展させていて、その技術をまとめた書籍まで発行されている。
MonoDevelopはSharpDevelopのWindows依存部分を全て切り捨ててGtk#に置き換えたかたちで実装された。その後MonoDevelopでは独自のアドインフレームワークmono-addinsを開発し、SharpDevelopのコードの多くを独自のコードで置き換えている(その過程でライセンスもGPLからLGPLになった)。
現在は当初SharpDevelopのリーダーであったMike Krugerも開発メンバーとなっており、SharpDevelopとも継続的にコードを共有している。C#のコード自動補完エンジンとして採用されているNRefactoryはその成果のひとつである。
MonoDevelopは現状では自由に配布できるC#開発環境の唯一の選択肢で、UnityやPlayStation Mobile SDK、MonoTouch、Mono for Androidに同梱されている。
MonoDevelopはIDEだが、一言でIDEといってもその実態は判然としない。IDEは単なるテキストエディタと何が異なるのだろうか。ここではIDEとして人々が期待する機能をもとに、MonoDevelopの技術要素を解説していく。
IDEは、一般的には、単なるエディタとは異なり、特定のソースコードを編集しやすくする機能を提供する。具体例として、文法に沿ったソースのリッチフォーマッティング(色付け、太字、下線など)から、識別子やキーワードの自動補完、エラー箇所へのジャンプ、変数・型の定義へのジャンプおよび参照の検索などが挙げられる。
通常、プログラムをビルドして実行するために、単一のソースファイルだけを作成することは無い。複数のソースコードや外部データファイルが存在しており、それらをひとつのプログラムとしてまとめるための「プロジェクト」のような単位で、プログラムがビルドされる。これはそれぞれのIDEで実現されるものだが、.NET Frameworkの場合は、Visual Studio .NET (2002) に端を発する「ソリューション」と「プロジェクト」をビルドする仕組みが用いられる。.NET 2.0からは、MSBuildと呼ばれる、Apache Ant類似のプロジェクトビルドの仕組みがVisual Studioと統合されて、コマンドラインからもビルド出来るようになっていた。
MonoDevelopでは、Visual Studioで使用されているソリューションファイル(.sln)やC#プロジェクトファイル(.csproj)を開くことができる。ただし、プロジェクトの内容はプロジェクト種別によって異なり、サポートされているプロジェクトの種類は限られている。逆にMonoDevelopがVisual Studioで開くことができないプロジェクトファイルを作成することもある(MonoTouchやC/C++, Valaのプロジェクトなど)。
IDEを使う目的の大きなひとつがデバッグである。デバッグを実現するためには、デバッグを実現するために実行プログラム上の位置とソースコードの位置を関連付けるデバッグ情報、デバッグ情報を参照しつつプログラムの実行を一時停止・再開できる処理系(ランタイム)、ランタイムから停止時点でのメモリ情報などを取り出したり逆にランタイムに停止位置を指示したりするデバッグエンジン、そしてエディタ上からそれらを設定できるフロントエンドが必要になる。
歴史的には、monoにはデバッガーが存在していたが、並列実行を高度に処理する等の高度な設計が先行し、結果的に安定的に機能していなかった。その後、単純な機能のみを提供するsoft debugger (sdb)と呼ばれる実装が取って代わり、現在ではリモートで実行されているmonoランタイム上のプログラムをデバッグすることもできる。sdbは、ランタイムにデバッグ命令を送る機能を実装している。
.NET Frameworkでは、デバッグ情報は*.pdbというファイルに保存されている。このpdbファイルの仕様はECMA標準に含まれていなかったため、Monoでは*.mdbという独自フォーマットのファイルを採用している。(ちなみに、pdbとmdbは、バイナリ処理エンジンcecilに含まれるツールによって、相互に変換可能である。)
monoランタイムは、sdbの一部として、デバッグのための一時停止・再開等の機能をサポートしている。
MonoDevelopのデバッガーと呼べる機能は、マネージドコードについては、フロントエンドのみである。一方、MonoDevelopにはC++プロジェクトのサポートも含まれており、これはCプロジェクトのアドイン機能が実現している(アドイン機構については後述)。また、別のアドオンで、gdbを利用したgccネイティブなプログラムのデバッグも可能になっている。
ちなみに、Visual Studioには、IDEの機能を利用して、任意の処理系のプログラムをデバッグできるVisual Studio Debugging APIが存在しており、Mono for Androidのような製品ではこれが活用されている。
IDEに人々が期待する機能とIDEが実際に提供する機能との間には、通常は小さくないギャップが存在するし、大抵のIDEにはその機能を拡張する仕組みが存在する。通常はプラグイン、アドイン/アドオン、エクステンションといった名称になっている。
Visual Studioの場合、Visual Studio SDKを使用して、pluginを開発することができる。また、SharpDevelopにもアドイン機構があり(#Dは高度なアドイン機構を最初に提供したIDEでもある)、その設計は「Dissecting a C# Application: Inside SharpDevelop」で詳解されている(絶版に伴いフリー版が公開された)。
MonoDevelopは、Mono.Addinsという仕組みによってアドイン機構を提供している。ファイルメニューやエディタのコンテキストメニューを拡張したり、ファイルの変更などにフックを仕掛けて、状態の変更を通知するなどの仕組みは、このアドイン機構によって実現できる。MonoDevelopの機能とされているものの大半は、実際にはこのアドイン機構に基づいている。
IDEの典型的な機能のひとつが、ユーザーインターフェースのヴィジュアルな設計だろう。Visual Studioでは、Windows FormsやWPF、Silverlight、ASP.NETなどでこれが実現できている。また、GUIではないが、Visual Studioでは、ヴィジュアルにデータベースのエンティティなどを設計することができる。
IDEにデザイナー機能として求められるのは、主に、ヴィジュアルなオブジェクトをIDE上に、あるいはIDEを経由して、描画し編集できる機能と、デザインされたオブジェクトからデザインクラスを生成する機能だ。デザインクラスは、アプリケーションのコードが、ヴィジュアル オブジェクトを操作できるように生成される。典型的には *.designer.csというファイルとして生成される。
MonoDevelopでは、Gtk#について、これが実現されている。このデザイナは、内部的にはsteticというツールのライブラリを利用していて、Gtk+の描画を実行しつつ、Gtk#のプロパティやイベントを設計できるようになっている。ただし、Windows FormsやWPFにはDesignModeプロパティなどdesign timeの概念があるが、Gtk#には存在しない。
(ちなみに、Gtk+の世界では、元々gladeというGUIデザインツールが存在しており、libgladeというライブラリを使用することによって、これがglade以外でも利用できるようになっていた。MonoDevelopでも当初glade-sharpというlibgladeのC#バインディングを使ってGUIデザイナーが設計されていたが、バグフィックス待ちや依存関係など様々な問題から、C#用に設計し直したほうが早いということになって、steticが開発された。)
Gtk#のデザイナーは、描画もGtk#でコントロールをIDE上に配置して行なっている例だが、MonoDevelopを経由して行われるヴィジュアルデザイナーは、必ずしもマネージドコードで描画しているとは限らない。Mono for Androidでは、Android ADT (Eclipse プラグイン)に含まれるJavaのライブラリを利用して、描画をJavaに行わせている。また、MonoTouchでは、*.xibファイルの編集はXCode付属のInterface Builderを起動して行うので、自ら描画を指示することはないが、ファイルの更新のみを検出して、動的にデザインクラスを生成する。
MonoDevelopが提供するRADツールの例としては、gettext翻訳サポート機能が挙げられる。これは*.poファイルの翻訳を視覚的に容易に行うために作られたそれなりに手軽なアドインである。
(古いバージョンのMonoDevelopにはデータベース接続とデータの視覚的な確認などを可能にしたアドインが提供されていたが、現在では安定的にサポートされているとは言いにくい。)
バージョン管理システム(version control system, VCS)の統合は、IDEに共通する(そこそこ最近の )課題だ。具体的には、headなど特定のバージョンとローカルのコードとの差分表示や、ログの表示と特定のリビジョンへのロールバック、blameなど変更者の確認、コミットやマージ、リモートリポジトリとのpush/pullのやり取りなどが期待される。
Visual Studioには、古くからVisual SourceSafe統合が含まれていた。MonoDevelopでは、GitとSubversionがサポートされている。Gitサポートは完全にマネージドコードで動作するもので、gitコマンドに依存しない(svnの方はパスを設定して呼び出せるようになっている必要がある)。
多くの開発の場面において、ユニットテストはコード品質の維持のために必要となる。ユニットテストについては、IDEで便利になる場面が多いとは言えないが、それでもテストの実行結果の視覚的な確認や失敗したテストへのジャンプなどは、便利な機能と言える。
MonoDevelopでは、NUnitによるテスト実行と、その結果の視覚的な確認が、NUnitサポートのアドインによって可能になっている。