2週間前にInfoQがSQLiteが.NETに移植されたとアナウンスしたところ、コミュニティがこのプロジェクトに対して特に興味を示したので、どのようにSQLiteをC#で書き直したかについて明らかにするために、我々は開発者のNoah Hart氏にインタビューを行った。
どうしてSQLiteの移植を行ったのですか?
最初の目標は追加のDLLなしで組み込みデータベースを利用するアプリケーションをデプロイすることでした。いくらか調査してSQLiteを見つけ、私が作ったPunjabi Koshというフリーウェアのデータベースエンジンコードの一部として使えるかどうか確かめてみることにしました。最初のころはVBを使って書き直していましたが、VBは相応しいとは言えないと思いました。私はKoshの修正と同時にC#も学びたいと思っていました。
どういうアプローチで移植を行ったのですか? ツールを利用? それとも手動で?
ステップ1:空のC#プロジェクトを作り、SQLiteのソースとヘッダファイルを全てそこに追加しました。この時点では大量のエラーメッセージが表示されました。
ステップ2:Cのコードを全てコメントアウトしました。徐々に変更していこうと思っていましたし、プロジェクトをコンパイルできるようにする必要もありました。
ステップ3:C#に不慣れだったので、次はCとC#の違いが何かを調べることにしました。別に驚くことでもないですが、シンタックスの変更のほとんどはささいなもので、Visual Studioの自動置換マクロでほとんどプログラミングできてしまいました。シンタックスの違いには例えばこんなものがありました。
C C# -> . & ref assert Debug.Assert ==0 ==null #ifdef #if #ifndef #if ! ステップ4:Cのコード全体を1つのsqliteクラスでラップすることにしました。Cでは処理がファイルからファイルへと移っていくのに対し、C#は各ファイルが独立しています。だから、各ファイルをpartialクラスとすることで、別のファイルのルーチンへアクセスできるようにしました。
ステップ5:CのインラインコンパイラマクロはC#にないので、ほとんどの#DEFINEを小さなルーチンや定数に変える必要がありました。
ステップ5a:この時点でプロジェクトがコンパイルできることを確認しました。ステップ6:structを全てオブジェクトに変更するという大変な作業を行いました。
ステップ6a:この時点でもコンパイルできることを確認しました。ステップ7:ルーチンの非コメント化を始めました。面白くなってきたのはこの辺りからです。CとC#についての微妙な違い、例えばnullポインタの処理、C#でのunionの欠如、値型と参照型、switch case文の振る舞いの違い、バイト配列や文字列のアドレス指定といった点について多くを学びました。また、acoi、printf、memcpy、strcmpなどのような多くの"ヘルパー"関数が必要になりました。ほとんどの場合はコードを書き直さず、単純にそれらをエミュレートしました。コードの変換に時間をかけずにアプリケーションが動くようにし、それから中心となるコードをC#に書き直していこうという考えで進めました。
ステップ7a:この時点でもコンパイルできることを確認しました。それからは
ステップ8:まだやっていないことについてステップ7と7aを繰り返しています。
Hart氏はC#-SQLiteを、Cから移植したものというよりもC#によってCをエミュレートしたものと考えているという。
C#はオブジェクト指向言語ですが、Cはそうではありません。移植したと呼ぶのは本当は相応しくなくて、実はC#によるCのエミュレーションです。コードのほとんどはまだCスタイルで書かれていて、オブジェクト指向やC#の機能はほとんど使っていないんです。
移植は趣味として、2年ちょっとかけて行ったようだ。基にしたCのコードは106,700行だったが、C#のコードは117,329行に達している。しかし、Hart氏はこう言う。
これは適切な比較とは言えません。なぜなら、オリジナルのCコードを参考のためにコメントアウトして残してあるところがたくさんありますから。
移植作業はつらかったですか? それとも楽しかったですか?
実にいい経験になりました。SQLiteがどうやって動作しているかを学ぶことも私の目標で、SQLiteの内部をのぞき見ることができて楽しかったです。
CからC#への移植についてどんな教訓が得られましたか?
移植する必要のない箇所を決める。
常に自分自身の目標を忘れない。
可能な限り自動化する。
徐々に移植していけるように移植作業の手順を決める。
ポインタに気をつける。
質問をして、答えを真に理解する。
C#-SQLiteはすでに30,000以上のテストにパスしていますが、これらはSQLiteの標準テストですか? それともC#-SQLite用に特別に作ったものですか?
sqlite.orgが提供しているテストスイートの標準テストです。http://sqlite.org/faq.htmlにはこのように書かれています。
(17) SQLiteの品質保証はコンパイラの警告や静的コード分析ツールによってではなく、複数条件網羅テストによって達成しています。言いかえれば、単にコーディングスタイルの制約を満たすのではなく、実際に正しい結果が得られることを検証しています。SQLiteのコードベースの2/3以上はテストに当てられています。SQLiteのテストスイートは何千ものテストケースを実行します。これらのテストケースの多くは、何百万ものSQLステートメントを含んだ数十万のテストを実施し、毎回のリリース前に正当性を評価できるようパラメータ化されています。
しかしながら、これらのテストは全てTCLだったので、同じようにC#に移植する必要がありました。すでにJavaに移植されたものがあったので、そこからC#へと移植しました。
ちなみに、これはとても大変でした!
まだパスしていないテストはどれくらいの数ですか? それらを全てパスさせるにはどのくらいかかりそうですか?
9. テストがC#にとって必要なものかどうかを調査しています。例えば、いくつかのテストはビッグエンディアンとリトルエンディアンに関するテストですが、これらはC#では不要なものです。
SQLiteの.NETラッパ/アダプタと比べて、C#-SQLiteの最大の利点は何ですか?
SQLiteの.NET向けラッパ/アダプタの多くはすばらしいものであり、私はC#-SQLiteがこれらを置き換えるとは思っていません。
C#-SQLiteによって得られる利益は何でしょう? あなたはどんなことに使おうと思っていますか?
外部DLLの必要なしにアプリケーション中にSQLiteエンジンを埋め込んで、Midium信頼レベルにおいてフルマネージコードでSQLiteを使えるようにします。
今後の計画はどんなものですか(もちろんC#-SQLite関連で)?
P/Invokeを使っているところをなくし、Silverlightで動くようにしたいと思っています。
SQLiteの今後のバージョンも移植していくつもりですか?
そのつもりです。現在はバージョン3.6.17を移植したものです。
このプロジェクトのサポート(バグの参照や機能拡張)はどうしようと考えていますか?
Webサイト(http://code.google.com/p/csharp-sqlite/)とディスカッショングループ(http://groups.google.com/group/csharp-sqlite)を立ち上げました。
コミュニティの協力を必要としていますか?
もちろんです。私はどう考えても熟練したC#プログラマではありません。パフォーマンス向上やC部分のC#化については開発者の追加によって得られるところが大きいと考えています。
Noah Hart氏は英語からパンジャブ語への機械翻訳に関心を持っている開発者でもある。