MOSA Developer News[MOSADeN=モサ伝]第130号
2004-09-28
目次
- SqueakではじめるSmalltalk入門 第12回 鷲見正人
- 小池邦人の「Carbon API 徒然草」
- 「Behind the WebObjects」 第28回 田畑 英和
- ニュース・解説
SqueakではじめるSmalltalk入門 第12回 鷲見正人
本連載では、名前は知っていてもなかなか触れる機会のないSmalltalkについて、最近話題のSqueakシステムを使って紹介しています。今回は、数多く存在するメソッドやクラスを把握しやすくする工夫である「カテゴリ」についてです。
前回、クラス「String」に定義された「#withCRs」という名前のメソッド、つまりString >> #withCRsをブラウズしてみました。この時、withCRsを選ぶのに使ったブラウザ上段の右端にあるペインには大量のメソッド名(セレクタ)がリストアップされていたのに気付かれたと思います。
String selectors asSortedArray ” => Stringに定義されているメソッドたち”
その数はなんと200個弱あります。
String selectors size ” => 181 ”
これは相当極端な例ですが、クラスによっては1000個を越える場合もあります。
| dictionary |
dictionary _ Dictionary new.
Smalltalk allBehaviorsDo: [:class |
dictionary at: (class selectors size) put: class].
^dictionary associationAt: (dictionary keysSortedSafely last)
" => 1090->Morph "
GUIフレームワークの中核を担うMorphのようなクラスはかなり特殊と言えそうですが、平均でも数十個のメソッドを単純にアルファベット順に並べたリストから、名前の分かっているメソッドの実装を調べるだけならともかく、注目したオブジェクトに欲している機能を探す(つまり辞書やリファレンスマニュアルで言うところの“逆引き”のような)作業はかなり骨の折れるものになりそうです。
そんなときに役立つのが、ブラウザ上段の右から2番目にあるリストです。これは「プロトコル」とか「メソッドカテゴリ」と呼ばれているペインで、各メソッドが定義時に分類されたカテゴリごとに共通するメソッドだけをすぐ右手のメソッドペインに表示する…という機構を提供します。たとえば、Stringなら、「accessing」というメソッドカテゴリを選択することで、その要素である文字などにアクセスする手段を提供するメソッドだけを選んで一覧できます。
[fig.A]accessingカテゴリに分類されているメソッドのみを呼び出したところ
http://squab.no-ip.com:8080/mosaren/uploads/12a.png
ちなみに、もとのように、全メソッドの一覧に戻すにはメソッドカテゴリペインで「– all –」を選びます。クラスペインでStringを2度クリックして解除・再選択しても同じです。
実は、メソッドはその定義時に(#’as yet unclassified’、つまり“未分類”という名のカテゴリを含め)必ず何らかのカテゴリに属すよう定められています。新たに作成したメソッドをどういったカテゴリに分類するかは開発者のセンスにゆだねられていますが、それほど的外れでなければ、システム内で慣例的に使われているカテゴリに分類することが推奨されます。システム内でポピュラーなカテゴリについて興味があれば、次のようなスクリプトでその一覧を得ることが可能です。システム内のクラスがメソッドの分類に使用している全カテゴリを抽出してカウント、その中から15個以上のクラスで使われているものを降順で列挙します。
| bag |
bag _ Bag new.
Smalltalk allClassesDo: [:class |
bag addAll: class organization categories].
ActiveWorld findATranscript: ActiveHand.
bag sortedCounts do: [:association |
association key > 14 ifTrue: [Transcript cr; show: association]]
なお、現在のブラウザはカテゴリを限らないメソッド一覧表示の状態時(クラスを選択してすぐ、あるいは「– all –」カテゴリ選択時)に、特定のメソッドをブラウズしても、それが属するカテゴリをメソッドカテゴリペイン内に探してくれません。もし選択したメソッドのカテゴリを知りたいときは、ブラウザ中段のボタン群のひとつ「browse」をクリックして別のブラウザを起動することで確認できます。
数が多いということでは、クラスも事情は同じです。Smalltalkシステムを構成するオブジェクトは、通常のOSが分担するサービスを担当するものから、基本的なデータ構造を定義したもの、GUIフレームワークやアプリケーションの要素となるもの、ユーザー定義のデータ構造やアプリケーションの構成要素に至るまで、幅広く存在します。それらを網羅するクラスもまた、当然、多くなります。Smalltalkシステムを単なる言語処理系としてしか考えられず、VMベースの独立した(ちょっと変わった仕組みで動く)コンピュータ環境と捉える習慣に馴染まない人には、このクラス数の多さはSmalltalkという“言語処理系”の明らかな欠点として認識される傾向にあるようです。
メソッド同様、クラスも、その定義時に特定のカテゴリに分類することが義務づけられています。ブラウザの上段、左端のペインは、このクラスカテゴリの一覧を表示するためのものです。クラスカテゴリ名は、メソッドのカテゴリと同様に、各クラス(あるいはそのインスタンスが)システム内でどのような役割りを期待されているのか、あるいはそれらがどういった位置づけにあるのかを知るのに、よい手がかりになるでしょう。一般にクラスカテゴリ名は、「大分類-小分類」というルールで付けられています。
ここでいったんブラウザの説明は終えて、次回は、システムブラウザと同様にSmalltalkシステムに欠かすことができないツールである「インスペクタ」を紹介します。
サポートページ:
http://squab.no-ip.com:8080/mosaren/
小池邦人の「Carbon API 徒然草」(2004/09/27)
ドキュメントウィンドウの基本ルーチン(後半)
今回は、メインウィンドウ(CatalogWindow)を操作するために用意した6つの基本ルーチンの残り半分を解説します。ウィンドウを閉じる処理を受けもつcloseCatalogWindow()、ウィンドウ自身と使用メモリ領域を解放するdisposeCatalogWindow()、ウィンドウの状態をメンテナンスするmainteCatalogWindow()の3つのルーチンです。
まずは、ウィンドウを閉じる処理を受けもつcloseCatalogWindow()からです。このルーチンは、ユーザがファイルメニューから「閉じる」を選んだ時か、もしくは、ウィンドウタイトルの左端にあるクローズボックスをクリックした時に実行されます。もし、アプリケーションのウィンドウが保存すべきドキュメントを管理していなければ、何も気にせずDisposeWindow()を呼んでウィンドウを閉じて(削除)してしまっても大丈夫です。しかし、CatalogWindowはドキュメントを管理していますので、閉じる前にその内容を保存するかどうかをユーザに尋ねる必要があります。
ドキュメントに対し何らかの編集を実行した場合には(画像ファイルの追加登録など)Window Manager APIであるSetWindowModified()に1を代入し、「ドキュメントが編集されたぞ!」という「印」をウィンドウに付けてやります。ドキュメントが編集され、その内容がまだHDに保存されていないと言う印は、クローズボックス内の「黒丸」表示で確認することができます。この「編集&未保存」の状態は、同じくWindow Manager APIであるIsWindowModified()で調べることができます。以下が、そうした手順をすべて組み込んだcloseCatalogWindow()ルーチンです。
short closeCatalogWindow( WindowRef window,short quit )
{
short chk,ret=0;
if( IsWindowModified( window ) ) // ドキュメントに何らかの変更があったか?
{
chk=navMySaveAlert( window,quit ); // 保存を行うか尋ねるアラートを表示
if( chk==1 )
ret=saveCatalogFile( window ); // 「保存」ボタン(ドキュメント保存)
else if( chk==2 ) // 「キャンセル」ボタン(処理中止)
ret=1;
} // 「保存しない」ボタンが押された時
if( ret==0 ) // もしくは正常に保処理が終了した時
disposeCatalogWindow( window ); // ウィンドウを閉じてメモリの解放
return( ret );
}
IsWindowModified()がTRUEを返した場合、そのウィンドウは「編集&未保存」状態なので、閉じる前にnavMySaveAlert()を呼んで「保存」「キャンセル」「保存しない」の3つのボタンが配置されたアラートをオープンします。navMySaveAlert()が返した値(chk)を調べることで、ユーザが「保存」「キャンセル」「保存しない」ボタンのうちどれを押したのかを判断します。「保存」ボタン(chk=1)を押していれば、saveCatalogFile()で保存処理を実行した後にウィンドウを閉じます。「保存しない」ボタン(chk=3)が押されていれば何もせずにウィンドウを閉じます。また「キャンセル」ボタン(chk=2)が押された場合には、「ウィンドウを閉じる処理」自体を中止します。
次はdisposeCatalogWindow()です。このルーチンは、closeCatalogWindow()から呼ばれ、CatalogWindowで使用されている様々なメモリ領域を解放してからウィンドウ自身も削除します。本サンプルアプリには、ブラウザに登録されているファイルをダブルクリックすることで、その画像を別ウィンドウに表示する機能があります。ですから、メインウィンドウ(CatalogWindow)を閉じる場合には、先んじて、そこから派生して表示されている画像ウィンドウも閉じる必要があるわけです。そこで、collectMyChildWindow()を使い、メインウィンドウから派生した「画像ウィンドウ」のWindowRefをすべて集めます。それをループ内でdisposeMyWindow()に渡し、すべての画像ウィンドウを閉じてしまいます。サンプルアプリに画像に対しての編集機能はありませんので、画像ウィンドウについては保存処理を行う必要はありません。
void disposeCatalogWindow( WindowRef window )
{
WindowRef wptr[MAX_BUF];
unsigned long i,ct;
ControlRef chd;
collectMyChildWindow( window,wptr,&ct ); // メインウィンドウに属している
for( i=0;i<ct;i++ ) // 子ウィンドウを集めて閉じる
disposeMyWindow( wptr[i] );
getMyControlRef( window,PICT_ID,&chd ); // ImageWellのControlRefを得る
disposeMyControlWellPict( chd ); // 表示していたPictureを削除
disposeObject( window ); // ドキュメントオブジェクトを削除
disposeMyWindow( window ); // ウィンドウ自身を削除
}
disposeMyControlWellPict()とdisposeObject()で解放しているメモリ領域は、画像表示に用いているPicture画像(PICT)とドキュメント本体です。ウィンドウに共通の汎用メモリ領域とウィンドウ自身を削除する処理は、disposeMyWindow()が担当しています。ところで、筆者のウェブサイトにアップロードされているサンプルプロジェクト内のソースコードでは、PICT_IDの箇所がBROW_IDと記述されています。これはバグでして(笑)、このままだとメモリ中にPicture画像が残ったまま放置されます。メモリリークという悪い見本ですので修正しておいてください(申し訳ないです)。
最後は、ウィンドウ状態をメンテナンスしているmainteCatalogWindow()ルーチンです。メンテナンスの内容は3点です。まずは、「登録数」表示(ブラウザに登録されたファイル数)の更新、続いて選択されたデータの画像、ファイル名、縦横サイズの表示更新、最後にウィンドウに配置されている「削除」「起動」「表示」の3つのボタンの使用可、不可(ハイライト表示)の切り替えです。ユーザが何らかのブラウザ操作(ドキュメント編集も含む)を行うことで、この3つのメンテナンス項目が発生するわけです。
void mainteCatalogWindow( WindowRef window )
{
unsigned long i,ct,nb,item[MAX_FILE];
ObjectPtr optr;
ControlRef chd;
getMyControlRef( window,1000,&chd ); // StaticTextのControlRefを得る
getWObjCount( window,&ct ); // 登録ファイル数を得る
setMyControlValue( chd,ct ); // 登録ファイル数を表示する
DrawOneControl( chd ); // StaticTextコントロールを描画する
getMyControlRef( window,BROW_ID,&chd ); // DataBrowserのControlRefを得る
getSelectedDataBrowser( chd,item,&ct ); // ataBrowserの選択データ数を得る
if( ct ) // 選択データが存在すれば...
{
nb=item[ct-1]-1;
getWObject( window,nb,&optr ); // 最初の選択データを得て
drawImageFile( window,&optr->o_fsc ); // その画像をImageWellへ表示する
}
else
eraseImageFile( window ); // 選択データがなければ消去する
for( i=3;i<=5;i++ )
{ // 削除、起動、表示ボタンの
getMyControlRef( window,i,&chd ); // ControlRefを得る
if( ct ) // 選択データがあれば....
ActivateControl( chd ); // コントロールを利用可に
else // なければ...
DeactivateControl( chd ); // 利用不可に切り替える
}
}
ファイル登録数はgetWObjCount()で得ることができます。また、ブラウザで選択されているデータ数はgetSelectedDataBrowser()で得ることができます。この両方の数値を調べることで、ウィンドウの表示内容を色々と切り替える(メンテナンスする)ことが可能となります。例えば、ブラウザでファイルが選択されていなければ、「削除」「起動」「表示」といったボタンは使用できない(押しても意味無し)わけですから、すべてハイライト表示にしておくのが正しいユーザインターフェースと(マナー)です。こうした気配りを忘れると、使えないはずの機能をユーザに実行されてしまい、思わぬバグの原因を作ることがあります。くれぐれも注意致しましょう。
次回からは、メインウィンドウを操作するために用意した6つの基本ルーチンの中で使われている自作ルーチンについて解説して行きます。まずはnewCatalogWindow()ルーチンで使われているcreateMyNibWindow()やsetupCatalogWindow()などと、その関連ルーチンを調べてみることにします。
つづく
「Behind the WebObjects」 第28回 田畑 英和
前回の原稿を執筆しているときはちょうどPowerBookが故障してしまい修理に出していましたが、修理のほうは数日で終了してなんとか戻ってきました。HDDとロジックボードが交換されて戻ってきたのですが、今度は液晶ディスプレイの表示が乱れる症状に悩まされています。今回の修理との因果関係は不明ですが、また修理に出すとなると数日間使えなくなってしまいますので、時間に余裕ができるまでしばらく我慢して使い続けようかと思います。もっとも余裕ができるかどうかは疑問ですが。
さて今回は書籍の紹介をおこないたいと思います。最近新しいWebObjectsの解説書が出版されました。洋書ですがAmazonなどで注文することができます。私が購入したときは到着までしばらく時間がかかってしまいましたので、これから購入される方は早めに注文することをおすすめします。
タイトル:「Practical WebObjects」
著者:Charles Hill, Sacha Mallais
ページ数:363
価格:$49.99
http://www.amazon.co.jp/exec/obidos/ASIN/1590592964
内容のほうですが、「Practical WebObjects」というだけあって実用的な内容になっており、中級者〜上級者のデベロッパー向きです。といいますのもいきなり最初の章からWO標準のProject Builder/Xcodeではなくて、Javaの世界ではすっかりおなじみになった開発環境Eclipseでの開発方法から話が始まっています。ですのでこれからWOの開発をスタートする人には少しハードルが高いかもしれませんし、内容的にも初心者向けの入門書ではありません。
話が少し横道にそれますが、Windows上でのProject Builderはすっかりアップデートが止まっていますので、今となっては開発環境としてかなり貧弱な状態にあります。そんなこともありWindows上で開発をおこなう場合、Eclipseが利用できるということはデベロッパーにとって大きな助けとなることでしょう。
とはいいましてもEclipse単体では標準的なJavaの開発はできても、WO固有なプロジェクト形式の面倒まではみてくれません。そこで実際にはEclipse上でのWOの開発を支援するために開発されたEclipse用Plug-inの"WOLips"や、ビルド用のAntスクリプトの"WOProject"を組み合わせて開発をおこなうことになります。
こういったEclipse上での開発に関する情報や、開発を支援する他のツールに関する情報などもこの「Practical WebObjects」では紹介されていますのでより開発効率を高めるための情報源としてこの書籍を利用するのもよいのではないでしょうか。
ちなみに"WOLips"や"WOProject"はObjectStyleのWebサイトで配布されていますが、Javaで実装されたORマッパーの"Cayenne"をご存知の方はObjectStyleの名前を聞いたことがあるのではないでしょうか。"Cayenne"もObjectStyleのWebサイト上でリリースがおこなわれています。
・WOProject/WOLips
http://www.objectstyle.org/woproject/
・Cayenne
http://www.objectstyle.org/cayenne/
さて、本題に戻りまして「Practical WebObjects」のその他の内容ですが、EOF関連からJ2EEネタまで幅広く取り上げられており、認証、バリデーション、ローカリゼーションについて解説した章もあります。これらはただテクニックが紹介されているだけではなく、背景となる基礎技術なども合わせて解説されていますので(例えばローカリゼーションならエンコーディングの解説)開発のスキルアップをおこなうにはちょうどよいかと思います。
また巻末のAppendixでは、本文中で紹介されている各種ソフトウェアのインストールやセットアップ方法が解説されています。
WebObjectsで開発を始める場合よく情報量が少ないといった意見を聞きますが、洋書にまで幅を広げればそれなりに出揃ってきたように思います。Appleが提供しているドキュメントもVer 5のリリース以降新たに改訂されたものが公開されていますし、すべてではないですが日本語訳も出ています。
たしかに雑誌などでWebObjectsの記事をみかけることは残念ながらめったにないですが今回紹介した書籍やAppleのドキュメントなどリソースは色々ありますので、こういったものを開発に役立てていただければと思います。もちろんこのメールマガジンもよろしくお願いします!!
・WebObjectsドキュメント(英文)
http://developer.apple.com/documentation/WebObjects/WebObjects.html
・日本語のリソース
http://www.apple.com/jp/webobjects/wo_docs_j.html
http://www.apple.com/jp/webobjects/techinfo/index.html
ニュース・解説
今週の解説担当:新居雅行
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┃USB関連開発についてのQ&A集が公開
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Technical Q&AにUSB関連開発のQ&A集が掲載されている。関連文書へのリンクなどがまとまっているので、USBに絡むソフトウエアの開発をする前に目を通しておくと良いだろう。開発ツールなどの情報に加えて、アプリケーションでUSBデバイスを使う方法と、カーネルレベルでのUSBドライバの開発方法などのテーマで、要点がまとめられている。
Technical Q&A: Common QA and Roadmap for USB Software Development on
Mac OS X
http://developer.apple.com/qa/qa2004/qa1370.html
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┃Open Directoryのプラグインを作成する
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Open Directoryのプラグインを作成する方法の文書が公開されており、サンプルプログラムも含む詳しい内容のものだ。Open DirectoryはMac OS Xに組み込まれたディレクトリアクセスのためのAPIであり、複数のプロトコルに対応しているのが特徴である。LDAP、NetInfo、Active Directoryといった代表的なプロトコルにはシステムが対応しているが、その他のプロトコルでディレクトリサービスを利用する場合にはプラグインが必要になる。プラグインを作る事自体は特殊な作業かもしれないが、Open Directoryへの知識を得るためにこうした情報を参照することは役に立つだろう。また、アプリケーションからOpen Directoryのプラグインへのアクセス方法なども紹介されている。
Writing Open Directory Plug-in
http://developer.apple.com/networking/opendirectory.html
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┃Java 1.4.2 Update 2では日本語テキストの問題も改良
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Java 1.4.2 Update 2がリリースされた。8月にリリースされたUpdate 1と同様、Java2 Standard EditionのVer.1.4.2_05であり、Java VMについては同一バージョンである。改良点はMac OS Xに絡む部分だけとなっている。SafariでのJavaアプレットの動作の改良に加えて、ダブルバイト文字の入力が遅くなる問題が改良されており、日本語での利用が改善されている模様だ。
Java 1.4.2 Update 2 Release Notes
http://developer.apple.com/releasenotes/Java/Java142RNUpdate2/index.html
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┃Mac OS XでX11のsshフォワーディングをできるようにする方法
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
X11のsshによるフォワーディングをできるようにする方法が解説されている。文書では、Mac OS Xは既定値ではセキュリティ的な理由でフォワーディングをオフにしていると説明している。/etc/sshd_configというファイルを修正すればよく、コマンドで行う方法を解説している。
Technical Q&A: Enabling X11 Forwarding
http://developer.apple.com/qa/qa2004/qa1383.html
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┃QuickTime関連の文書が公開
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Technical Q&AにQuickTime関連の文書がいくつか公開されている。概要を紹介しよう。
Technical Q&A: Adjusting the movie brightness
http://developer.apple.com/qa/qa2004/qa1382.html
ムービー再生時に明るさを調節できるようにするにはQuickTimeのフィルタの
機能を利用すれば良い。
Technical Q&A: Adding a movie reference to a movie
http://developer.apple.com/qa/qa2004/qa1376.html
あるムービーから別のムービーを参照する簡単な方法として、InsertMovieSegmentというAPIを使う方法が紹介されている。
Technical Q&A: Movies - Saving movie playback hints
http://developer.apple.com/qa/qa2004/qa1366.html
ムービーに高品質のヒント情報とともに保存する方法が説明されている。APIとしてはSetMoviePlayHintsだけでなく、他にいくつかのAPIを呼び出す必要がある。
MOSAからのお知らせと編集後記は割愛します
Apple、Mac OSは米国アップルコンピュータ社の登録商標です。またそのほかの各製品名等はそれぞれ各社の商標ならびに登録商標です。
このメールの再配信、および掲載された記事の無断転載を禁じます。
Macintosh OS Software Association http://www.mosa.gr.jp/
Copyright (C)2004-2006 MOSA. All rights reserved.