2011年2月7日月曜日

巡回セールスマン問題で、Qtの使い勝手を体感してみた

このエントリーをはてなブックマークに追加
Pocket

QtはC++のクロスプラットフォームなアプリケーション・フレームワークで、C++が抱える互換性の問題を大きく解消しつつ、スタイリッシュなGUIを扱いやすくするツールキットだ。2009年3月に無料だが業務開発に使いやすいLGPL版がリリースされており、Google Trendsでは2009年の秋からMacintosh OS XのCoCoaより人気の検索キーワードになっている

1. C++/Qtで巡回セールスマン問題を解く

こんなQt(バージョン4.7)を、ハチが得意な巡回セールスマン問題を解くミニ・アプリを作りつつ、その使い勝手を確認してみた。下の図が完成品で、ダイアログにキャンバス、プログレスバー、チェックボックス、ボタン二つがあるシンプルな構成となっている。

巡回セールスマン問題は、任意の地点を巡回する最短経路を求める問題だ。巡回箇所が多くなると演算回数が飛躍的に増えるNP問題の典型例として知られる。デスクトップ・アプリケーションにするとマルチスレッドの実装が必要になる一方で、確定的な解放は単純な力技しかなくコーディングの量が少ない。

この手の小さい非実用アプリの作成は、プログラミング言語の概要の調査・学習には効果的な手法である。

2. 開発環境の整備は容易

開発はUbuntu LinuxとNetBeans 6.9.1で行った。この組み合わせだと、パッケージ管理システムaptitudeでqt4-*とqt4-dev*をインストールするだけで必要最低限の環境が揃う。

Windows用の実行ファイルも作成するために、WindowsにはQt開発元のNokiaが配布しているQt SDKをインストールした。専用エディタとデバッガ(Qt Creator)、フォーム・デザイナ(Qt Designer)がセットで、mingw(gcc)が同時配布でコンパイラやリンカーも含まれるおり、単体でアプリの開発も可能だ。

Macintosh OS Xでも開発できるし、Eclipse、Visual Studioでのサポートも存在する。

3. 学習方法や資料は少ない

QtはPythonやPHP、Ruby、Perl、Javaからも扱えるのだが、基本的にはC++のフレームワークだ。C++で使うには、整理整頓以外は何でも実装していると言われるC++の知識がある事が前提となる。ただし、他のGUIフレームワーク(SwingやMFC)に慣れている人なら、Qt自体の難易度は高くない。

JavaやPHPなどに比較すると、圧倒的に資料は少ない。書籍もQt4に対応しているものは少ないようだ。英語が自由に読めても、公式ドキュメントには例が少ないので悩むことは多いと思う。Qt Creator付属デモのソースコードが貴重な資料になるが、コメントはほとんど無い。Qtチュートリアルもあるので、目を通しておくといいかも知れない。

4. QtはC++を補完する

C++は混沌とした言語仕様の割には、最近のスクリプト言語やJavaと比較すると、標準ライブラリは貧弱だ。この手の指摘には「(テンプレート・ライブラリの)Boostを使え」とコメントを頂くが、Boostが無いと正規表現も使えない。

しかしQtは、文字列の結合や置換、正規表現や文字コード変換、マルチスレッド、HTML表示などのライブラリを含んでおり、C++を補完してくれる。ポインタやガーベッジ・コレクションに起因する問題は残るが、資料不足な点を除けば開発効率は低くは無い。

5. フォームデザイナ(Qt Designer)

ごく普通にレスポンス良く使える。ただし、VB6やVBAのフォームデザイナは、貼り付けたボタンをクリックするとコード編集が出来たりするが、Qt4 Designerはウィンドウにウィジェット(≒コントロール)を配置できるだけだ。

低機能に思われるかも知れないが、これはQt4のウィジェットとイベントが疎結合である事が理由のようだ。VBやJavaと異なり、Qtは引数の型が一致する任意のメンバー関数を紐付けてイベントを処理する。VBやJavaは、コントロールから呼び出すロジックをコントロールに記述している事になるが、Qtのウィジェットは呼び出すコードを把握しない。

ゆえにQt Designerでは、このウィジェットの連携(signals/slotsの関係)を記述する事はできるが、直接コードの編集は行えないようだ。やや不便に感じるかも知れないが、疎結合であるのでデザイナからロジックのソースコードを破壊する可能性はなくなるし、プレゼンテーションとビジネスロジックの分離がはっきりするメリットもある。

6. C++拡張部分には癖がある

JavaのSwingは言語仕様を拡張している点は無いが、Qt4はプリプロセッサでC++の言語仕様を拡張しており、またコンパイルのために独自のファイルを自動生成している。

1. 拡張キーワード
C++には基本的には無いQ_OBJECT、singals、slotsキーワードが重要。クラス定義に付け忘れると、エラーメッセージからは原因が分かりづらい文法エラーが多発する。
2. Qt独自のファイル
Qtのビルド設定ファイル(*.pro)、ユーザ・インターフェイス・デザイン(*.ui)、*.uiを展開したui_*.hとmoc_*.cppがある。自動的に作られるがインクルードを忘れたり、存在しないとエラーになるので、知らないと開発に支障が出る。他にもビルドには関係ないが、端末のディレクトリ情報を含むQt Creatorの設定ファイル(*.pro.user)も自動で作られる。
3. 不要の消し忘れファイル
コンパイル・エラーが出る*.h、*.cppをワーキング・ディレクトリに残しておくとコンパイル・エラーになる。Qt Designerで削除をしても、完全に削除を選択していなければQt Designerの画面から消えるだけだったりするので、注意が必要だ。
4. シャドウビルド
Qt Creatorでプロジェクトのビルド設定で、ビルド・デイレクトリが不適切だとシャドウビルドをしてくれない。ソース・ディレクトリと並んだ位置のビルド・デイレクトリを指定するべきのようだ。

自動生成されるファイルがバージョン管理システムに登録されると気まずいので、あらかじめ除外対象にしておいた方が良い。また、NetBeansとQt Creatorで*.proの配置が異なり、両者でソースコードを共有するにはコツが必要だった。複数人で開発する場合は、IDEを統一した方が良いかも知れない。

7. 多言語化はシンプルだが問題を抱える

MFCよりシンプルな実装で、取り扱いはしやすいように感じる。ただし、Javaと比較すると2点問題がある。

まず、言語ファイルのファイル名や配置場所が任意であり、ロケールとの連係方法も任意であるため、開発者がルールを規定する必要がある。本質的ではないのでフレームワークの仕様として規定されている方が、開発者としては気軽だ。

次に、gettextと同じ元言語に対応する翻訳ファイルを設定する仕組みなので、元言語に変更があった場合に、他の全ての言語の翻訳ファイルに影響が出る。Javaの場合はプロパティのキーワードで、この問題が無い。

8. マルチスレッドと排他処理は普通にサポート

GUIのアプリで演算中に画面が固まらないようにするには、マルチスレッドは必須の機能となる。OSごとにAPIが異なる上に、C++では標準的な利用方法が無いが、QtではAPIをラッピングしてくれている。

QThreadでスレッド生成ができ、QMutex(ロック)、QSemaphore(セマフォ)、QWaitCondition(イベント)で排他処理を行う。実用上の問題は無い。ただし、Javaだと構文と基底クラスのメソッドで排他処理が行えるため、やや原始的な感じはする。

9. 実行に必要なDLLのサイズは大きい

LinuxやOS Xでは気にならないが、DLLのサイズは大きい。使っているQtのモジュールによるが、12MB~78MBのDLLが必要になる。

また、Windowsのバイナリはサイズが肥大化する傾向があるようだ。Linuxで65KBの実行ファイルが、Windowsで497KBに達していた。libstdc++を静的リンクしているためだと思われる。

10. 起動速度や実行速度は快適

ネイティブ・アプリケーションなので当たり前だが、起動速度や実行速度は快適だ。実行ファイルのサイズは大きいが、いまどきのPCの速度から言えば誤差なのだろう。

11. クロスプラットフォームの開発

カタログ通り、今回のアプリはUbuntu Linux、Windows XP/7、Macintosh OS Xでソースコードの修正無しに実行ファイルの生成ができた。インストーラをどうするかという問題もあるが、クロスプラットフォームな開発環境なのは間違いない。

ただし、Javaと比較するとクロスプラットフォーム性は劣る。Qtアプリケーションはバイナリ・レベルでは異機種互換性が無いため、対応するOSごとに開発環境を用意しないといけない。また、新しいOSやプロセッサが出てきた場合、僅かでも対応作業が発生する。

AndroidやiPhone版のQtも開発されており、スマートフォンでの開発にも期待されているが、現状では生成バイナリのサイズが大きくなるので実用性は低いようだ。

12. ライセンス

Qt4.5以降は、LGPL、Qtライセンスが選択できる。受託開発による業務アプリや、フリーソフトの配布ではLGPL版を利用していて問題ないので、ライセンス上の制約は少ない。

LGPLは、無償のオープンソース版だ。Qtと静的リンクをした場合は、開発したアプリのソースコードの公開義務が発生する。Qtを動的リンク(DLLとして扱う)にしている限りはソースコードの公開義務などは無い。ただし個人・組織内にとどまるリバース・エンジニアリングは拒否できない。

Qtライセンスは、有償だが、Qtの静的リンクができ、Qt自体の改編も可能で、その時にソースコードの公開義務も生じない。日本の代理店SRAによると、シングルOS版が538,650円、マルチOS版が771,750円と比較的高額になっている

13. Qtの平面描画はオブジェクト指向的に高機能

計算する地点をクリックして指定するだけではなく、マウス・ドラッグで移動させたり、ダブルクリックで消せるように後日改良を行ってみた。ここでもQtは慣れれば使い勝手が良いように感じる。

現在のバージョンのQtでは、JavaのCanvasにあたるQCanvasが非推奨で、QGraphicsView、QGraphicsScene、QGraphicsViewを中心とするキャンバスが提供されている。これらは高機能で再描画や、スクロールやズームを自動的に処理してくれる。またマウス・イベントの処理も、キャンバスに貼り付けたオブジェクトごとに取れるので、よりオブジェクト指向的に2D描画を扱うことができる。

ただし、Qt Programmingというサイトと公式APIドキュメントを参考に実装をしていったのだが、やはりと言うか、情報は不足気味だった。例えばキャンバスの内容をクリップボードに書き出すのは数行で終わる処理なのだが、それらしいAPIを探して試行錯誤した。

利用者が増えて、某Delphiのサイトのように情報が集積されれば快適そうなのだが、現状では四苦八苦することが多そうだ。

まとめ

C++/Qtは比較的導入がしやすいし、実行速度も速く、移植性も高いソースコードになるが、比較的情報量が少なく、細かい点では粗が見える。利用者数の増加で解決すると思うが、最初の開発には時間がかかると思われる。API自体は洗練されているようなので、時間とともに開発効率は高くなるであろう。

LinuxだとGnomeと双璧をなすフレームワークだが、WindowsだとMFC、Macintosh OS XだとCocoaがあるので、あえてQtを採用するような強い理由は無い。また、Javaを扱えるプログラマならば、Java/Swingを採用する方が生産性は圧倒的に高いであろう。

ただし、巡回セールスマン問題を解くミニ・アプリを書いた感じでは、C++/Qtは十分に取り掛かりやすい印象を受けた。ウェブ・アプリケーションをスクリプト言語で書いてきたプログラマは、既存のデスクトップ・アプリケーション開発環境にこだわる必要は無いので、C++/Qtの学習は一つの選択肢になるとは思う。

0 コメント:

コメントを投稿