MOSA Multi-OS Software Artists

MOSAはソフトウェア開発者を支援します

プログラマーに興味がある方なら誰でも入会いただけます。
MOSA Multi-OS Software Artists
===SINCE 1995===

  • iPhone/iPod touch アプリ紹介
  • MOSA掲示板
  • 活動履歴
  • About MOSA(English)

MOSADenバックナンバー 2008年2月発行分

  • MOSA Developer News[MOSADeN=モサ伝]第288号

     2008-02-26

    目次

    • 「「Wonderful Server Life」    第65回   田畑 英和
    • 小池邦人のCarbon視点でCocoa探求
    • ターミナルの向こうから      第20回  海上 忍 

    「Wonderful Server Life」  第65回  田畑 英和

    ■  〜Open Directory編〜

     Leopardのアップデートv10.5.2がリリースされました。Mac OS XとMac OS XServerの両方でアップデートが配布されています。またサーバ関連ではSAN用のファイルシステムXsanの最新版Xsan 2が発表されています。Xsan 2の発表の影ではハードウェアRAIDのXserve RAIDがひっそりとその歴史に幕を閉じました。今後大容量ストレージを利用するにはサードパーティ製品を活用することになるでしょう。

    ◇まずは「システム環境設定」
     さて今回からアカウント管理について取り上げていきます。Tiger Serverのころはアカウント管理には主に「ワークグループマネージャ(以下WGM)」を使用していました。WGMを使用すればローカルアカウントとネットワークアカウントの両方を管理できます。「システム環境設定」でもローカルアカウントの管理はできますが、WGMを使ったほうがより細かな設定が出来ていました。例えばユーザIDの確認や変更はWGMを使う必要がありました。

     この「システム環境設定」なのですが、実はLeopardになってかなり機能強化されていますので、まずはこちらをみていきましょう。アカウント管理には「システム環境設定」の「アカウント」を使用しますが、画面構成も若干変更されています。「パスワード」と「ピクチャ」が1つの画面に統合され、.Macのアカウントも設定できるようになりました。また「ペアレンタルコントロール」は独立した設定項目になりました。「ログインオプション」は設定項目が増え、ネットワークユーザのログインの許可を設定できます。
     さらに大きな変更点としては、登録可能なアカウントの種類が増えたことです。Leopardでは次の種類のアカウントを登録できるようになりました。

    ・Leopardの「システム環境設定」で登録可能なアカウント
      - 管理者
      - 通常
      - ペアレンタルコントロールで管理
      - 共有のみ
      - グループ

     管理者、通常ユーザ、ペアレンタルコントロールで管理の3つはTigerでも登録可能なユーザアカウントでした。Leopardではまず「共有のみ」のユーザが登録できるようになっています。このユーザを登録するとホームフォルダを持たずログインもできないユーザが作成されます。つまりファイル共有のためだけに使用するユーザを作成することができます。具体的にはユーザ属性が次のように設定されます。

    ・ホームのパス(NFSHomeDirectory)
    /dev/null
    ・ログインシェル(UserShell)
    /usr/bin/false

     基本的にはローカルユーザの一部の属性を制限しているので、Tigerでも手動でユーザ属性を変更すれば同じようなユーザを作成することはできましたが、Leoaprdでは「システム環境設定」で手軽に作成できるようになっています。
     またグループアカウントを登録できるようになったのもLeopardでの大きな変更点です。Tigerでも「NetInfoマネージャ」やコマンドラインからグループを作成することはできましたが、Leopardでは「システム環境設定」で名前を入力するだけで簡単にグループを作成できます。ちなみにユーザがデフォルトで所属するプライマリグループの仕様も変更になりました。Tigerではユーザの新規作成時に自動的作成されるグループがプライマリグループとして使用され、ユーザごとに専用のグループが存在していましたが、Leopardでは新規作成したユーザのプライマリグループはグループIDが20のstaffグループに変更になりました。Tigerからアップグレードした場合、Tiger時代の既存のユーザか、Leopardからの新規ユーザかでグループの扱いが異なることになります。

     さらにLeopardではゲストアカウントが用意されています。このアカウントを有効にするとパスワードなしでログイン可能なユーザが作成されます。ゲスアカウントでログインした場合、ログアウト時にはホームフォルダ内に作成したデータは自動的に削除されます。ただし、ホームフォルダ外に作成したデータはそのまま残ります。このゲストアカウントですが、ユーザ属性は次のように設定されます。

    ・ゲストアカウントの主なユーザ属性
      ホームのパス:/Users/Guest
      名前:ゲストアカウント
      ユーザ名:Guest
      ユーザID:201

     ログインウインドウをユーザのリストではなく、名前とパスワードにしていると名前もしくはユーザ名を手入力する必要がありますので、よく覚えておきましょう。ちなみにゲストアカウントが存在しない状態で「Guest」というユーザ名のユーザを作成していると、「Guest1」というユーザ名のアカウントがゲストアカウントとして作成されます。混乱を避けるため今後は「Guest」というユーザ名のユーザアカウントは作成しないほうがよいでしょう。

     これだけではありません、Leopardでは細かなユーザ属性も「システム環境設定」で管理できるようになっています。「アカウント」画面で左側に表示されるアカウントのリストから任意のアカウントを選択し、Ctrlキーを押しながらクリックします。すると「詳細オプション」メニューが表示され、次のユーザ属性が変更可能になります。

    ・詳細オプションで変更可能なユーザ属性
      ユーザID(UniqueID)
      グループID(PrimaryGroupID)
      ユーザ名(RecordName)
      ログインシェル(UserShell)
      ホームディレクトリ(NFSHomeDirectory)
      UUID(GeneratedeUID)
      エイリアス(2つめ以降のRecordName)

     LeopardになってからNetInfoおよび「NetInfoマネージャ」が廃止されたため、GUI上から任意のユーザ属性が管理できなくなってしまいましたが、「システム環境設定」が大幅に拡張されましたので、かなりの部分がまかなえるようになりました。また、「ワークグループマネージャ」を使ってもローカルアカウントの管理ができるのはTigerのころと同様です。

     今回は「システム環境設定」の解説になりましたが、ここで解説したことはMac OS XだけではなくMac OS X Serverにも共通のことですので、ぜひ参考にしてみてください。次回は新しい管理ツール「サーバ環境設定」でのアカウント管理について解説します。
    次回へつづく                             

    小池邦人のCarbon視点でCocoa探求(2008/02/22)

    〜 Document-based Application 〜

    今回は、「しんぶんし 3」プロジェクトを「Cocoa Document-basedApplication」に切り替えてみます。こちらのアプリケーションタイプで注意すべき点を調査しながら、モデル・オブジェクトの実装を考えたいと思います。

    さて、プロジェクトの引っ越しをしましょう。Xcodeで新規プロジェクトを作成する時に「Cocoa Document-based Application」テンプレート(雛形)を選択します。プロジェクトの名称は「Shinbunshi3」を引き継ぎます。新規プロジェクトが保存されたら、前回のプロジェクトの「Resources」フォルダ内の画像、アイコン、InfoPlist.stringsファイルを移動させます。nibファイルについては、About.nibの方は、そのまま移動してもかまいませんが、MainMenu.nibは作り直す必要があります。

    メニューオブジェクト(MainMenu)のタイトルやアイテムを日本語にローカライズしたら、ApplicationConrollerを再度作成して、アバウトメニューにopenAboutWindow:(アクション・メソッド)を割り当てます。この作業を行っていて気づいたのですが、編集メニューの「検索」と「自動置換」アイテムのサブメニューに、まったく同じコマンドキーが割り振られています。Xcodeのテンプレート作成時のバグだと思いますので(多分)、「自動置換」の方のコマンドキー割り当ては消しておきましょう。

    前プロジェクトとは異なり、MainMenu.nibの方にはメインウィンドウのオブジェクトは登録されていません。プロジェクトのウィンドウ(今回はドキュメントウィンドウと呼ぶ)は、新規作成されたMyDocument.nibの方に登録されています。また、Info.plistファイルも、ターゲットの情報ダイアログの「プロパティ」で編集し直し、前回と同等に仕上げておきます。ただし、この時に注意しなければいけないのは、「書類のタイプ」の一番上に登録されている「名称」がDocumentTypeで「クラス」がmyDocumentの内容を消さないことです。

    一番上の設定が「しんぶんし 3」のドキュメントタイプとなりますので、「拡張子」にsinbを「OSタイプ」に’SinB’を追加しておきます。その下に、前回の画像ファイルのタイプなどを追加すればOKです。それから、せっかくですので、ドキュメントファイル用のアイコンも「SinB.icns」という名称で登録しておきます。アイコンファイルの方は、アプリアイコンと同じ場所に保存しておき、アプリケーション・バンドルへとコピーされるように新プロジェクトのResourcesグループにも登録してきます。

    最後はソースファイルです。アバウトダイアログ用に作成した、ApplicationConroller.mとApplicationConroller.hは、そのまま新プロジェクトに登録しても大丈夫です。それから、新プロジェクトにはMyDocument.mとMyDocument.hいう2つの新しソースファイルが登録されています。これが、Info.plistでも記載されていた、MyDocumentクラス(NSDocumentクラスのサブクラス)の実装先となります。具体的に言えば、「しんぶんし3」のドキュメントファイルの読み込み(ロード)や保存(セーブ)処理などを記述するソースファイルとなります。MyDocument.hの方は、前回からの定義を引き継げば…

    @interface MyDocument : NSDocument
    {
        NSMutableArray     *_list;
    }
    @end
    


    といった内容になります。「しんぶんし3」のドキュメントファイルの中身は、ズバリNSMutableArrayとして保存されている_listの中身(前回示したImageFileオブジェクトの配列)ということになります。

    後々必要となるオブジェクトは、先んじてMyDocument.nibの方に登録しておくこともできます。そのため、MyDocument.nibの「File’s Owner」は、MyDocumentクラスと定義されており、MyDocumentクラスの「window」アウトレットにはドキュメントウィンドウ(初期の名称はwindow)が、ドキュメントウィンドウの「delegate」には File’s Ownerが設定されています。ぜひ一度、Interface Builderのインスペクターで、この両者の関係を調べてみましょう。参考になると思います。

    「Cocoa Document-based Application」がどういった物かと言うと、ワープロやペイントソフトなどのアプリケーションを思い浮かべれば良いと思います。特定のファイルをオープンしてウィンドウに表示し、それを編集した後に再度HDへ保存するという一連の処理を提供するアプリケーションのことです。こうしたアプリケーションについては、ある程度「やらなければいけない事柄」が決まっていますので、その部分をCocoa AppKit Framework(クラス)が助けてくれる仕組みが用意されていると思ってください。

    助けてくれるのは、NSDocumentController、NSDocument、NSWindowController
    の3つのクラスです。NSDocumentControllerはアプリケーションに関連付けされたドキュメント(Info.plistに記載されている)を管理し、ドキュメントの新規作成やファイルの読み込み処理を受け持ちます。このクラスのインスタンスはひとつだけ作られており、アプリケーションの裏方さんとして働きます。NSApplicationと似たような役割ですね。

    NSDocumentのインスタンスは、ひとつのドキュメントファイルに対してひとつだけ作られます。クラスの実装は、NSDocumentのサブクラスである「MyDocument」を作成し、NSDocumentクラスのメソッドをオーバーライド(書き直す)して行きます。テンプレートから作成されたMyDocument.mには、既にオーバライドすべき(必要であれば)いくつかのメソッドが記述されており、英語のコメントで何の処理をするメソッドなのかが表記されています。とりあえず、以下の5つのメソッドがそれに相当します。

    - (id)init
    
    - (NSString *)windowNibName
    
    - (void)windowControllerDidLoadNib:(NSWindowController *)aController
    
    - (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError
    
    - (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName
                                                      error:(NSError **)outError
    


    3つのうち最後のNSWindowControllerは、ドキュメントを表示するウィンドウのコントロール・オブジェクトです。通常、ひとつのファイルに対しドキュメントウィンドウはひとつ用意されるので、NSDocumentにひとつのNSWindowControllerのインスタンスが関連付けられます。ただし、大規模で複雑なアプリケーションによっては、ひとつのドキュメントに複数のウィンドウ(ビュー)が必要となる場合があります。そうした場合には、ウィンドウと同数のNSWindowControllerインスタンスが作成されます。

    つまり、「Document-based Application」においては、NSDocumentが、モデル・コントローラ・オブジェクトで、NSWindowControllerがビュー・コントローラ・オブジェクトの役割を持ちます。次回は、MyDocument.mでオーバライドしなければいけない上記メソッドの内容を解説しながら、アプリケーション開発を進めて行きましょう。

    つづく                                

    ターミナルの向こうから      第20回  海上 忍

    〜 スプレッドシートとの共存を考える (2)〜

     前回は、Perlモジュール「Spreadsheet::WriteExcel」を利用すれば、Excel97-2007互換のExcelブックを作成できることを紹介しました。今回は、このモジュールで日本語を扱うときの約束事を紹介します。

    ・MS-Office文書仕様へ自由にアクセス
     Microsoftが、保有資産の活用とサードパーティーに対する姿勢を大きく変えました。前回から(オープンソースソフトウェアを利用した)Excelブックの読み書きを取り上げているため、少し触れておきます。
     まず、MS-Office 97-2007のファイルフォーマット仕様書が自由に閲覧可能になりました。従来はメールアドレスの登録など手続きが必要でしたが、すでにWebサイト(http://www.microsoft.com/interop/docs/OfficeBinaryFormats.mspx)から自由に仕様書をダウンロードできます。ライセンスにはMicrosoft OpenSpecification Promise (OSP) が適用されるので、特許権は主張されないうえ経済的な負担も発生しません。OOXMLの普及を待たずして、MS-Office 97-2007文書完全互換のアプリケーションが開発可能になったわけです。

    MS-Office 97-2007のバイナリフォーマット仕様がOSPで公開
    http://journal.mycom.co.jp/news/2008/02/19/005/

     その数日後、Windows VistaやOffice 2007などMicrosoftの主要製品についても、30,000ページ以上のドキュメントがMSDNで公開されました。巷では、EUにおける独禁法訴訟対策と揶揄されているようですが、この決断により(MS社製品とそれ以外の製品との)相互運用性が高まることは確実だと思います。決断の背景はともかく、歓迎すべきことは確かだろうと思います。

    Microsoft、主要製品のオープンネスを武器に – 相互運用を高める新4原則
    http://journal.mycom.co.jp/news/2008/02/22/005/index.html

    ・Spreadsheet::WriteExcelで日本語を使う
     さて、本題に入ります。前回は、Perlの「Spreadsheet::WriteExcel」モジュールについて、なにができるかをサラリと紹介しましたが、今回はいくつかポイントを絞り解説してみます。すぐにリファレンスに当たりたい方は、こちら
    (http://search.cpan.org/~jmcnamara/Spreadsheet-WriteExcel2.20/lib/Spreadsheet/WriteExcel.pm)を参照してください。

    1) UTF-8で統一する
     Spreadsheet::WriteExcelにおける日本語の扱いですが、2月22日現在最新のバージョン2.20では、フォント指定を含めほぼ思い通りに利用できます。
     注意点としては、文字コードをUTF-8で統一することが挙げられます。Perlには、内部の文字コードにUTF-8を利用するようになったバージョン5.8以降を用意しましょう。なお、Leopardに収録のバージョンは5.8.8なので問題ありません。
     スクリプトの冒頭には「use utf8;」と記述し、ソースコード中の文字列がUTF8であることを明示する必要があります。UTF-8で記述するのですから、スクリプトを保存するときにもエンコード形式にはUTF-8を指定します。

    2) ワークシートデフォルトのフォントスタイルを設定する
     Spreadsheet:WriteExcelには、行・桁・セル毎にスタイルを指定するメソッドが用意されていますが、ワークシートデフォルトのスタイルを指定するメソッドがありません。その結果、空白セルすべてがモジュールの標準値(Arial 10pt)に設定されてしまい、思いがけないフォントで表示されます。
     以下のスクリプトでは、デフォルトのセル書式を「12ポイントのヒラギノ丸ゴ Pro、セル中央に配置」に設定しています。フォント名には、日本語を含む一般的なもの(Font Book.appに表示されるフォント名)を使用できます。メイリオやDFP勘亭流といったフォントもOKです。
     なお、「MSゴシック」ではなく「MS ゴシック」とするなど、フォント名の綴りには注意が必要です。Excel 2008で試したところ、綴りに誤りがあるフォントはOsakaに置換されてしまいました。

    - - - - -
    #!/usr/bin/perl -w
    use strict;
    use utf8;
    use Spreadsheet::WriteExcel;
    
    my $mybook  = Spreadsheet::WriteExcel->new('sample.xls');
    
    $mybook->{_formats}->[15]->set_properties(
          font  => 'ヒラギノ丸ゴ Pro',
          size  => 12,
          align => 'vcenter',
    );
    
    my $mysheet = $mybook->add_worksheet('MOSA1');
    $mysheet->write(0, 0, 'もうすぐ春ですね!');
    - - - - -
    

    ニュース解説   MOSAic

    ★★★ 開発関連のニュースはwebに掲載中 ★★★
    http://www.mosa.gr.jp/?page_id=1017

    ・1月のニュース
    http://www.mosa.gr.jp/?p=1515

    ◇MOSAからのお知らせと編集後記は割愛します◇

     

     MOSA Developer News   略称[MOSADeN=モサ伝]
            配信停止 mailto:mosaden-ml@mosa.gr.jp
     記事内容に関するご意見 mailto:mosaden-toukou@mosa.gr.jp
          記事投稿受付 http://www.mosa.gr.jp/?page_id=850
    Apple、Mac OSは米国アップル社の登録商標です。またそのほかの各製品名等
    はそれぞれ各社の商標ならびに登録商標です。
    このメールの再配信、および掲載された記事の無断転載を禁じます。
    特定非営利活動法人MOSA  http://www.mosa.gr.jp/
    Copyright (C)2007 MOSA. All rights reserved.

  • MOSA Developer News[MOSADeN=モサ伝]第287号

    2008-02-19

    目次

    • りんご味Ruby         第19回  藤本 尚邦
    • 藤本裕之のプログラミング夜話   #132
    • 高橋真人の「プログラミング指南」  第130回
    • 開発ツールよもやま話     Cocoa Tutorial日本語版

    りんご味Ruby   第19回  藤本 尚邦

    前々回から、Xcode ToolsのサンプルアプリケーションSketchに、RubyCocoaフレームワークをリンクして、Rubyプログラムで機能を追加していく様子を示しています。前回は、角丸四角形(rounded corner rectangle)を表すSKTRoundedRectangleクラスをRubyプログラムとして定義しました。今回は、角丸四角形がツールとして使えるようにするための変更に着手します。

    ■ ツールパレットに角丸四角形ボタンを追加する

    Sketchアプリケーションのツールパレットには5つのボタン(選択ツール、四角形、楕円形、線分、テキスト)があります。ここに6つめのボタンとして角丸四角形ボタンを追加します。SketchプロジェクトのToolPallete.nibファイルをInterface Builder 3で開き、以下のような手順で角丸四角形ボタンを追加してください。

    (1) Panelを開いてPanelウィンドウの高さをボタン1つ分引き伸します
    (ToolsメニューにあるSize Inspectorで変更することもできます)

    (2) Panel内のMatrix(NSMatrix)を選択して、Attributes Inspectorで、
    MatrixのCellsを5から6に変更します(ボタンが1つ増加)

    (3) 新しいボタンを選択、Attributes Inspectorを表示します

    (4) ModeをPush On Push Offに変更します

    (5) Tagを5にします

    (6) Imageを設定します(もし角丸四角形アイコンをお持ちなら)

    できたら保存してXcodeに戻ってください。

    ■ プログラムの変更すべき箇所を探す

    次に、SKTRoundedRectangleを使えるようにソースコードを変更しましょう。といっても、どこから手を付けたらいいのかわかりません。何か手がかりが必要ですね。手がかりは、SKTRectangleやSKTCircleなど既存のグラフィックオブジェクトです。これらについてプログラム中で何かしらやっているところを見つけて、SKTRoundedRectangleについても同じことをするように変更すればよいのではないでしょうか。

    Xcodeの編集メニューの中の検索のサブメニューに「プロジェクトの検索」というコマンドがあるので、これを使って、とりあえずSKTRectangleが出てくるところを探してみます。すると、以下の6つのソースコードからSKTRectangleが見つかりました。そのうち、SKTRectangle.mとSKTRectangle.h の2つは見つかって当然で変更する必要はありません。残りの4つのソース(以下)は何かしら変更する必要がありそうです。

    ・SKTToolPaletteController.m
    ・SKTDocument.m
    ・Sketch.scriptSuite
    ・Sketch.scriptTerminology

    ■ SKTToolPaletteController.m を変更する

    SKTToolPaletteController.mから見ていきます。ファイル名から、ツールパレットのボタンが押されたときには、この中のコードが呼ばれることが想像できます。まず

     #import "SKTRectangle.h"

    という行が見つかっています。しかし、Rubyで書いたSKTRoundedRectangleクラスにはヘッダーファイルはないのでこの行は無視します。次に

     theClass = [SKTRectangle class];

    という行が、currentGraphicClass というインスタンスメソッドの定義の中にありました。このメソッドは、パレット上で選択されているグラフィックオブジェクトのクラスを返すメソッドのようです。

     - (Class)currentGraphicClass {
          NSInteger row = [toolButtons selectedRow];
          Class theClass = nil;
          if (row == SKTRectToolRow) {
              theClass = [SKTRectangle class];
          } else if (row == SKTCircleToolRow) {
              theClass = [SKTCircle class];
          } else if (row == SKTLineToolRow) {
              theClass = [SKTLine class];
          } else if (row == SKTTextToolRow) {
              theClass = [SKTText class];
          }
          return theClass;
      }
    


    どうやら、パレット上で選択されているグラフィックオブジェクトツールを表すrowの値によって返すクラスを決めているようです。ということは、ここに角丸四角形用の分岐を書き加えればよいでしょう。SKTTextの条件分岐のあとに

         } else if (row == SKTRoundedRectToolRow) {
              theClass = [SKTRoundedRectangle class];
    


    を書き加えましょう...としたいところなのですが、実はこれはちょっと問題があり

         } else if (row == SKTRoundedRectToolRow) {
              theClass = NSClassFromString(@"SKTRoundedRectangle");
    


    とする必要があります。前者の場合、Sketchのビルド時(静的リンク時)にSKTRoundedRectangleという名前が解決される必要があります。しかし、SKTRoundedRectangleクラスはRubyプログラムで記述されており、Sketchアプリケーションを実行してRubyプログラムがロードされるまでは存在しません。したがって、ビルド時にリンクエラーが発生してしまうはずです。

    そこで、アプリケーション実行時に指定された名前を持つクラスを返すFoundationフレームワークの関数NSClassFromStringを使います。アプリケーション実行時にNSClassFromStringが呼ばれた時点では、Rubyで書かれたSKTRoundedRectangleがすでにロードされていて、SKTRoundedRectangleクラスが存在するので、後者のコードはうまく動くはずです。

    このあたりは、RubyやObjective-Cの動的な性質がにじみ出ているところなのですが、C++派の方などは少しむずがゆさを感じたりするかもしれません。「まあそんなもんなんだな」と適当に読み流してください。

    そういえば、SKTRoundedRectToolRowはまだ定義していませんでした。SKTRectToolRowが定義されている箇所を探して、そこにSKTRoundedRectToolRowの定義を書き加えます。SKTRectToolRowが定義されている箇所は、Xcodeのソースコード上の”SKTRectToolRow”を選択してコンテキストメニューで「定義へジャンプ」コマンドで見つけることができます。他のグラフィックオブジェクトクラスと一緒にenumで定義されているので、SKTTextToolRowの下にSKTRoundedRectToolRow を書き加えてください。これはさきほどInterface Builderで設定したタグの値と同じにする必要があるので順番に注意してください。

    以上で、SKTToolPaletteController.mの必要な箇所の変更は完了しました。次回は続けて、SKTToolPaletteController.mの変更をすることにしましょう。

    藤本裕之のプログラミング夜話 #132

     前回はどこまで書いたんだっけ? 昔はマシンもソフトウエアも今よりずっと高くて、市場もすっげぇ小さかったのに、買ってみたいソフトウエアが山ほどあった、当時一種類しかなかったMac雑誌の後ろの方に印刷された、ソフトの名前(しかもたまにミススペルしてた)と売値だけの広告を眺めながら、これはいったい何をするソフトなんだろうか、こっちのこれを買ったらいったいどんなことが出来るんだろうかと想像を巡らすだけで楽しく時間が過ぎて行ったもんなんである。あれはいったいなんだったんだろうか(笑)。

     月満ち星は流れ昭和は平成になり、金髪のネーチャンにでっかいわぁ♪と驚かれた「イシマルデンキのアキハバラ」は、いつの間にかよう分らん「世界のアキバ」に変貌し、先日そのアキバで逢った大学生は「高校生のとき最初に買ってもらったパソコンはハードディスクが10ギガくらいしかなくて」とか言うし、あ、いやそんなことはどうでもいいんだが、Macと言わずPCと言わず、コクミンの少なくとも半数はパソコンを使える環境にあり、テレビコマーシャルの終わりに「詳しくはWebで!」と言われて誰も文句を言わなくなった状況で、我々はあのころほどコンピュータにわくわくしてるか、と言うと……なんかしてないような気がするのである。

     いや「してないような気がするのである」ってな自信なさげなことではいかんのだけど、前述した「生まれて初めてのコンピュータのハードディスクが10ギガ青年」……長いな、以下「10ギガ青年」と略します、などと話していると、そもそも彼らはコンピュータというものを当時我々が思ってたみたいな「モノ」と思ってないみたいに感じるんだよね。「コンピュータですか? やっぱり高校生くらいになったら必要だろって感じで買ってもらったってゆーか」とか「何をするかって、主にネットですよね。あ、メールはケータイの方が多いです。あとは……自分はその写真とかの趣味もないんで」てな具合。

     そう言われて気がつくと、普及した普及したというけれど、結局パーソナル・コンピュータって「コンピュータ」として普及したのではなくて、「インターネット端末」として普及したみたいなもんなのだ。適当な喩えぢゃないかも知れぬが、お燗だ牛乳だ解凍だ、ついでにオーブンにもなってケーキも焼けます、マニュアルの他にレシピブックも付いていますてな電子レンジを、実はほとんどのヒトがコンビニ弁当温めるためにしか使ってませんという状態で、しかも2ちゃんよろしく「それが何か?」とか言われちゃうのである。

     前回(前々回だっけ?)、パソコンの出荷台数の伸びに比べてソフトの売れ行きが伸びないと書いたが、つまりそれは電子レンジの普及に比べ、それを使って手料理をするヒトの数は増えていないという、聞きようによってはとっても当たり前のことだったのかも知れない。

     これまた前回(これは間違いなく前回だ、覚えてる)書いたことだが、オレが MacPlus と一緒に MacWriteを買ったのは当時の飲み仲間の会報をキレイに印刷したかったからだし、MacPascal は Macで動くプログラムを作りたかったからだ(買ってみて分ったがこれはインタプリタでスタンドアロンのそふとは作れなかった)。FullPaint は当然、絵(つってもモノクロのドット絵だけどさぁ)を描きたかったからだし、Super Studio Session も適当に音符を並べるとそれが演奏されるのがとっても嬉しかったからである。

     こう並べてみると、我ながらなかなか創造的、クリエイティブやないの(でもオレ、真面目な顔で「ボクはクリエイティブな仕事がしたいんです」とかいうヤツ信用しないんだけどさ)。つまるところコンピュータは電子レンジみたいに誰でも買うが、その使い道、使い方によってその後ソフトを買う人間と買わないヒトがいるのであり(この「人間」と「ヒト」の使い方はわざとです)、前者は言うほど増えてないのだ、ということになるんだろうか。……確かにそれもあるだろうけど、それだけで納得できるかと問われたら、まだなんかありそうな気がするよねぇ。
                           (以下次回 2008_02_16)

    高橋真人の「プログラミング指南」第130回

    プログラマのためのオブジェクト指向再入門(36)

    〜XcodeによるPowerPlant X入門(19)〜

     こんにちは、高橋真人です。
     さて、連載2回分の間が開いてしまったためPPxの話がどこまで行ったか忘れてしまった方もおいでかもしれませんが、前回までにやったのは以下のようなことです。
     PPx::BaseViewは、サブクラス作ってViewに関連するCarbonイベントのハンドラを加えると、様々な挙動を加えることができます。その手始めとして、“単なる黒い四角”が表示されるだけのViewを実装するプログラムを作りました。
     いよいよここからさらなる拡張をして、PPx::Viewの秘める可能性を見ていくわけですが、今の単純な段階で仕組みをしっかりと理解しておくと、今後の拡張も抵抗なく理解できます。今の段階で理解が怪しい方は、しっかりと復習しておくことをお勧めします。
     さて、それではいよいよ拡張の作業に入ります。手始めにViewにボタンの機能を持たせてみたいと思います。
     ところでボタンといった場合、どのような挙動をするものであるか分かりますか? 以下にざっとボタンの特徴を列挙してみます。

    ・マウスダウンに反応する
    ・ドラッグをトラッキングする
    ・クリックに反応する
    ・(ウインドウのアクティベーションに反応する)

     今さらですが、「クリック」というのは、マウスボタンを押すことではなく、「押して、すぐに放す」ことです。最近では「マウスボタンを押す」と「クリックする」が同じ意味で使われることも多いのですが、プログラムを書く人はきちんと違いを意識しておきましょう。
     それと、トラッキングも重要です。初心者ユーザーですと、意識していない人もいるかもしれませんが、ボタンが機能するのは、マウスボタンを放した時です。ボタンのエリア内でマウスボタンを押しても、指でマウスボタンを押さえたまま、マウスポインタをボタンのエリア外に出してからマウスボタンを放せば、キャンセルすることになります。
     きちんと認識しているユーザーには常識ですので、ちゃんとこのように動作しないと、「とんでもないボタン」が出来上がってしまいますので注意しましょう。
     では、これらの挙動を実現するために早速プログラムを作成してみます。
     前回のPPxForXcode05を複製して、PPxForXcode06というプロジェクトを作り、例のごとく各所の05を06に変更しておいてください。

     それではソースコードです。新しいファイルはありません。変更個所だけを掲出します。それ以外は変更ありません。

    =============MyView.h =============

    ・クラス定義の部分を以下のように書き替えます。

    class MyView : public PPx::BaseView,
                   public PPx::ControlDrawDoer,
                   public PPx::ControlHitDoer,
                   public PPx::ControlHitTestDoer,
                   public PPx::ControlHiliteChangedDoer
    {
    public:
        void                Initialize(
                                // 変更ないので省略
                                bool                    inEnabled);
    
    protected:
          virtual OSStatus   DoControlDraw(
                                // 変更ないので省略
                                CGContextRef            inContext);
    
        virtual OSStatus    DoControlHit(
                                    PPx::SysCarbonEvent&    ioEvent,
                                    ControlRef              inControl,
                                    ControlPartCode         outPartCode,
                                    UInt32                  inKeyModifiers);
    
        virtual OSStatus    DoControlHitTest(
                                    PPx::SysCarbonEvent&    ioEvent,
                                    ControlRef              inControl,
                                    const HIPoint&          inHitPoint,
                                    ControlPartCode&        outPartCode);
    
        virtual OSStatus     DoControlHiliteChanged(
                                    PPx::SysCarbonEvent&    ioEvent,
                                    ControlRef              inControl);
    
    private:
        virtual void        FinishInit();
    
    };
    
    


    =============MyView.cp=============

    ・FinishInit()の末尾に、以下を追加。
    
        PPx::ControlHitDoer::Install(targetRef);
        PPx::ControlHitTestDoer::Install(targetRef);
        PPx::ControlHiliteChangedDoer::Install(targetRef);
    
    ・DoControlDraw()を以下にさしかえ
    
    OSStatus
    MyView::DoControlDraw(
        PPx::SysCarbonEvent&    ioEvent,
        ControlRef              inControl,
        ControlPartCode         inPartCode,
        RgnHandle               inClipRgn,
        CGContextRef            inContext)
    {
    #pragma unused (ioEvent, inControl, inPartCode, inClipRgn)
    
        HIRect frame;
        GetLocalFrame(frame);
    
        float alpha = 0.4;
    
        if (::IsControlHilited(inControl) and ::IsControlActive(inControl)) {
            alpha = 0.8;
        }
    
        ::CGContextSetRGBFillColor(inContext, 0.3, 0.6, 1.0, alpha);
        ::CGContextFillRect(inContext, frame);
    
        return noErr;
    }
    


    ・上記に続いて、以下を追加

    OSStatus
    MyView::DoControlHit(
        PPx::SysCarbonEvent&    ioEvent,
        ControlRef              inControl,
        ControlPartCode         outPartCode,
        UInt32                  inKeyModifiers)
    {
    #pragma unused (ioEvent, inControl, outPartCode, inKeyModifiers)
    
        SInt16 itemHit;
        ::StandardAlert(kAlertPlainAlert, "\pClicked", "\p", nil, &itemHit);
    
        return noErr;
    }
    
    OSStatus
    MyView::DoControlHitTest(
        PPx::SysCarbonEvent&    ioEvent,
        ControlRef              inControl,
        const HIPoint&          inHitPoint,
        ControlPartCode&        outPartCode)
    {
    #pragma unused (ioEvent, inControl)
    
        OSStatus status = eventNotHandledErr;
    
        HIRect frame;
        GetLocalFrame(frame);
    
        if (::CGRectContainsPoint(frame, inHitPoint)) {
            outPartCode = kControlButtonPart;
            status = noErr;
        }
    
        return status;
    }
    
    OSStatus
    MyView::DoControlHiliteChanged(
        PPx::SysCarbonEvent&    ioEvent,
        ControlRef              inControl)
    {
    #pragma unused (ioEvent, inControl)
    
        SetNeedsDisplay(true);
    
        return noErr;
    }
    

    ============= MyApplication.cp =============

    ・DoSpecificCommand()を以下にさしかえ

    OSStatus
    MyApplication::DoSpecificCommand(
                                PPx::CommandIDType,
                                PPx::SysCarbonEvent&  ioEvent)
    {
    #pragma unused (ioEvent)
    
        OSStatus status = eventNotHandledErr;
    
         MyWindow* theWindow =
            PPx::NibDecoder::CreateWindowFromNib(
                CFSTR("main"), CFSTR("MainWindow"));
        if (theWindow) {
            PPx::View *contentView = theWindow->GetContentView();
    
            HIRect contentFrame;
            contentView->GetLocalFrame(contentFrame);
    
            HIRect frame = CGRectOffset(
                contentFrame, 20.0, contentFrame.size.height - 60.0);
            frame.size = CGSizeMake(120.0, 40.0);
            MyView *view =
                PPx::CreateView(contentView, frame,true, true);
    
            PPx::BindingsFrameAdapter *adapter = new PPx::BindingsFrameAdapter;
            adapter->SetBindings(true, false, false, true);
            view->SetFrameAdapter(adapter);
    
            ::RepositionWindow(
                theWindow->GetSysWindow(), nil, kWindowCascadeOnMainScreen);
            theWindow->Show();
            status = noErr;
        }
    
        return status;
    }
    


     解説は、次回に。

    開発ツールよもやま話    Cocoa Tutorial日本語版    高橋 政明

     MOSAicのお知らせにも載っていましたのでご覧になった方も多いと思いますが、待望の「Cocoaアプリケーションチュートリアル」の日本語訳が公開されました。
    http://developer.apple.com/jp/documentation/Cocoa/Conceptual/ObjCTutorial/01Introduction/chapter_1_section_1.html

     残念ながらwebページの後半(『識別子、バージョン番号、著作権情報を指定する』以降)はリンク切れの状態です。でもPDFではすべて読む事ができます。またここで解説しているプロジェクトファイルもダウンロードできるので完成状態を確認できます。もちろんチュートリアルなのですから、実際に読みすすめながら自分自身で作ってみる事をおすすめします。

     現代の若者なら「チュートリアル」と言えばすぐに通じるのかも知れませんが、私の若い頃〔^_^;〕はこの「チュートリアル」なる言葉に馴染みがありませんでした。
     初代Macが登場した1984年の暮れに「MacTutor」なる雑誌がUSで登場しました。表紙も含め全ページがイメージライタの出力をそのまま使っているとすぐにわかる本でした。貴重でディープな開発情報が載っていましたが、この『Tutor』はチュートリアルを教える人の事だそうです。

     一般にチュートリアルは予備知識が最小限の読者を想定していて、概要を説明し、初歩の使い方をていねいに指導していてそれを順にこなして行けば一通り体験できる構成の物が多いです。そのためページ数もそれほど多くないイメージを持っていたのですが、この「Cocoaアプリケーションチュートリアル」は82ページもあります。(英語版でも80ページ)
     このチュートリアルには「学習の目的」が明示されています。
     ◆Cocoa とは何か
     ◆オブジェクト指向環境においてアプリケーション開発プロセスがどのように見えるか
     ◆Cocoaアプリケーションの作成方法
     ◆知識の適応により、ここから進むべき方向

     普通のチュートリアルであれば「Cocoaアプリケーションの作成方法」だけを(あるいは重点に)説明するところ、予備知識もふんだんに盛り込んでいるためにページ数が増えているのです。

     開発ツールよもやま話でご紹介するのは、新しいXcodeとInterface Builderの使い方が具体的に説明されているからですが、Cocoaの本質、モデルの定義、ビューの定義:ユーザインターフェイスの作成、モデルとビューのブリッジ:コントローラ、アプリケーションの設定、基本事項の詳細などの章がそろっています。他のプラットフォームでプログラムの経験を持つ方が新しくMacで開発をはじめる場合に役立つ内容もたくさん書かれています。
     逆にこれからプログラムをはじめようとする方には詳し過ぎるかも知れません、多少わからない技術用語などがあっても最後まで読み進んでください。(そして質問はMOSA de BBの掲示板をご活用ください)

     チュートリアルは予備知識のない状態で読むわけですから、書いてある内容と実際が一致しないと読者はとても混乱してしまいます。その点レパードで大きくツールのメニューや画面が変わったため、新しいツールに対応したチュートリアルが必要でした。このチュートリアルではさらにObjective-C 2.0の新機能も追加されています。

    ◆本日のまとめ
     「Cocoaアプリケーションチュートリアル」は10.5でCocoaで開発をはじめるときに最適のドキュメント。

    ニュース解説   MOSAic

    ★★★ 開発関連のニュースはwebに掲載中 ★★★
    http://www.mosa.gr.jp/?page_id=1017

    ・1月のニュース
    http://www.mosa.gr.jp/?p=1515

    ◇MOSAからのお知らせと編集後記は割愛します◇

     

     MOSA Developer News   略称[MOSADeN=モサ伝]
            配信停止 mailto:mosaden-ml@mosa.gr.jp
     記事内容に関するご意見 mailto:mosaden-toukou@mosa.gr.jp
          記事投稿受付 http://www.mosa.gr.jp/?page_id=850
    Apple、Mac OSは米国アップル社の登録商標です。またそのほかの各製品名等
    はそれぞれ各社の商標ならびに登録商標です。
    このメールの再配信、および掲載された記事の無断転載を禁じます。
    特定非営利活動法人MOSA  http://www.mosa.gr.jp/
    Copyright (C)2007 MOSA. All rights reserved.

  • MOSA Developer News[MOSADeN=モサ伝]第286号

    2008-02-12

    目次

    • 「「Wonderful Server Life」    第64回   田畑 英和
    • 小池邦人のCarbon視点でCocoa探求
    • ターミナルの向こうから      第19回  海上 忍 

    りんご味Ruby   第18回  藤本 尚邦

    前回から、Xcode ToolsのサンプルアプリケーションSketchに、RubyCocoaフレームワークをリンクして、Rubyプログラムで機能を追加していく様子を示しています。

    今回は、角が丸みを持つ四角形(rounded corner rectangle)を表現するクラスをRubyで実装します。その前に、簡単に前回のおさらいをしておきましょう:

    ・Sketchのプロジェクトフォルダをコピー。Sketchは
    /Developer/Examples/AppKit/Sketchにあります

    ・コピーしたXcodeプロジェクトを開いてRubyCocoa.frameworkを追加

    ・SKTMain.mのmain関数にRubyCocoaを初期化するコードを追加。Sketchが起
    動したら、RubyCocoaのAPI関数である RBApplicationInit が呼び出される
    ようにしました。RBApplicationInit の引数として渡した “main.rb” が最
    初に実行されるRubyプログラムとなります。

    ・main.rbを追加。新規ファイル追加で「Ruby application init」を選択し
    ます。main.rbに、標準出力にRubyやRubyCocoaのバージョンを出力する
    コードを追加しました。

    これで、Rubyプログラムで機能を追加するための準備ができました。

    ■ Sketchのグラフィックオブジェクト

    画像や図形などグラフィカルなドキュメントを編集するアプリケーションは、ペイント系(MacPaintを源流とする)とドロー系(MacDrawを源流とする)に分類されることがありますね。ペイント系では、キャンバス(描画空間)上の各点の色を直接変更します。ドロー系では、キャンバス上に各種図形などのグラフィックオブジェクトを配置していきます。

    私は、”Sketch”という名前からペイント系アプリケーションを連想したのですが、実際のSketchは、キャンバス上にグラフィックオブジェクトを順に置いていくタイプの、典型的なドロー系のアプリケーションです。

    Sketchのソースをざっと見ると、楕円形・画像・線分・四角形・テキストと5種類のグラフィックオブジェクトを扱えるらしきことがわかります。それぞれ、SKTCircle, SKTImage, SKTLine, SKTRectangle, SKTText という名前が付けられています。みな、SKTGraphicクラスの派生クラスとしてObjective-Cにより定義されています。

     NSObject
        +- SKTGraphic
             +- SKTCircle
             +- SKTImage
             +- SKTLine
             +- SKTRectangle
             +- SKTText
    


    ■ SKTRoundedRectangleの実装

    では6番目のグラフィックオブジェクトとして、角丸四角形を表現するクラスSKTRoundedRectangle をRubyで実装しましょう。

    「新規ファイル」コマンドで SKTRoundedRectangle.rb を追加します。テンプレートには「Ruby NSObject subclass」を選んでください。SKTRoundedRectangle は SKTGraphic の派生クラスなので、親クラスをNSObjectからSKTGraphicに書き換えます。

    -------------------------- SKTRoundedRectangle.rb #0 --
    require 'osx/cocoa'
    
    class SKTRoundedRectangle < OSX::SKTGraphic
      include OSX
    end
    --------------------------
    


    それでは角丸四角形の特徴を定義していきましょう。

    手がかりとして SKTRectangle.m を見てみます。bezierPathForDrawing というメソッドが定義されているのみですね。bezierPathForDrawingはグラフィックオブジェクトの形状を返すメソッドのようです。これだけ定義しておけば、その他のことは親クラスの SKTGraphic がやってくれるのでしょう。

    ということで、SKTRoundedRectangle に角丸四角形のパスを返すbezierPathForDrawing を実装します。SKTRectangleのbezierPathForDrawingをRubyで書き換えて、パスの形状を変えるだけでよいでしょう。以下のようになります。

    -------------------------- SKTRoundedRectangle#bezierPathForDrawing --
      def bezierPathForDrawing
        path = NSBezierPath.bezierPathWithRoundedRect_xRadius_yRadius(
                 self.bounds, 24.0, 24.0)
        path.setLineWidth(self.strokeWidth)
        path
      end
    -------------------------------------------
    


    これだけで十分そうですが、念のため SKTCircle.m を見てみます。するとSKTRectangle にはなかった isContentsUnderPoint というメソッドが定義されていました。名前と引数から、指定された点がグラフィックオブジェクトの中にあるかどうかを示す真偽値を返すメソッドということになるでしょう。

    SKTGraphic.mでの定義を見ると、NSPointInRectを使って、指定された点がboundsのなかにあるかどうか調べています。 SKTRoundedRectangle の場合、角の削れた部分で偽を返す必要があるので実装することにします。SKTRectangleのisContentsUnderPointと同じく、NSBezierPath#containsPoint を使います。

    ということで SKTRoundedRectangle.rb ができあがりました:

    -------------------------- SKTRoundedRectangle.rb --
    require 'osx/cocoa'
    
    class SKTRoundedRectangle < OSX::SKTGraphic
      include OSX
    
      def bezierPathForDrawing
        path = NSBezierPath.bezierPathWithRoundedRect_xRadius_yRadius(
                 self.bounds, 24.0, 24.0)
        path.setLineWidth(self.strokeWidth)
        path
      end
    
      def isContentsUnderPoint(point)
        self.bezierPathForDrawing.containsPoint(point)
      end
    end
    --------------------------
    


    しかし、SKTRoundedRectangle を定義しただけでは、まだSketchアプリケーションで角丸四角形のオブジェクトを作ることはできません。ということで次回に続きます。

    (おまけ) ペイント系、ドロー系のことを書いていたら...昔のMac 用の開発ツールThink C や Think Pascal には、Think Class Ligraryというアプリケーションフレームワークが付属していたのですが、そのサンプルのひとつとして、Art Class という素敵なペイント系アプリケーションのソースがまるまる入っていたことを思い出しました。

    「Wonderful Server Life」  第64回  田畑 英和

      〜Open Directory編〜

     今回はLeopard ServerのディレクトリサービスであるOpen Directoryについて解説します。これまで説明してきましたように、Leopard Serverには標準/ワークグループ/詳細の3つのサーバ構成があります。LDAPベースのディレクトリサービスであるということは共通していますが、サーバ構成によって細かな違いがありますので、それぞれの違いを詳しくみていきたいと思います。

    ◇詳細構成
     まず詳細構成から説明します。詳細構成の場合はTiger Serverとよく似ており、Open Directoryを使用するには手動で設定を行う必要があります。つまりデフォルトの状態ではローカルユーザの管理しかできず、ネットワークユーザを管理するにはOpen Directoryのマスターを手動で構築する必要があります。
     Tiger ServerのころはOSの初期セットアップ中にOpen Directoryのマスターを構築することができましたが、Leopard Serverではセットアップ後でないとマスターが構築できなくなりました。ただし、Open Directoryのマスターをきちんと構築するにはDNS関連の設定が正しく行われている事が前提になるため、セットアップ後に確実に動作確認を行ってから構築したほうが安全です。
     このように、詳細構成では必要に応じて管理者がOpen Directoryの設定を行うことになります。

    ◇標準構成
     次は標準構成です。実はOpen Directoryを使用するのであればこの構成を選択することにより、自動的にOpen Directoryのマスターが構築できます。ですので手っ取り早くOpen Directoryのマスターを構築したい場合には、まずは標準構成で始めてみるのもよいものです。標準構成であればあとから詳細構成に変更(「サーバ管理」で変更可能)できますので、最初はシンプルに始めて、必要に応じて詳細構成に移行することも可能です。
     ところで標準構成の場合、セットアップ中に登録した管理者アカウントは、どのように管理されているのでしょうか。詳細構成の場合は、Tiger Serverと同様にローカルアカウントとして登録されます。標準構成の場合は、第61回の連載でも解説したように、セットアップ中に登録した管理者アカウントはネットワークアカウントとして登録され、同時に「localadmin」という名前のローカルアカウントも登録されます。
     選択したサーバ構成によって、セットアップ中に登録した管理者アカウントの扱いが変わってきますので注意が必要です。

    ◇ワークグループ構成
     ワークグループ構成でも標準構成と同様に、Open Directoryのマスターが自動的に構築されます。管理者アカウントがネットワークアカウントとして登録されることも同様です。
     標準構成との違いは、ワークグループは他のディレクトリサーバに接続することにあります。そして接続先のディレクトリサーバ上のユーザアカウントをワークグループ上に読み込むことができます。
     読み込むといっても、ワークグループ上に新たなアカウントとして再登録するのではなく、アカウントの実体はあくまでも接続先のディレクトリサーバ上で管理し、ワークグループ上では読み込んだアカウントに対して追加の属性が管理できるようになります。このようなユーザのことをAugmented Userと呼びます。
     この仕組みを利用することで、ユーザアカウントの実体は直接編集せずに、追加の属性を管理できるようになります。
     なお、セットアップ時に標準構成を選択していても、あとから他のディレクトリサーバに接続すれば、サーバ構成はワークグループになります。

    ◇アカウントの管理ツール
     Open Directoryの主な役割にアカウント管理がありますが、ここでアカウント管理に使用するツールをおさらいしておきましょう。アカウントの種類に応じて次のようなツールが使用できます。

    「システム環境設定」
      ローカルアカウント
    「ワークグループマネージャ」
      ローカルアカウント、ネットワークアカウント

     「ターミナル」を使ってコマンドライン上でアカウント管理を行う事も可能です。Tigerまでは「NetInfoマネージャ」でローカルアカウントの管理も可能でしたが、LeopardではNetInfoは廃止されました。

     これらのツールに加え、Leopard Serverには新しい管理ツール「サーバ環境設定」が加わり、このツールからもアカウント管理が可能です。「サーバ環境設定」ではユーザおよびグループの管理が可能ですが、管理対象となるアカウントはネットワークアカウントです。また、「システム環境設定」と同じくら簡単にアカウントの管理ができます。
     それでは次回は「サーバ環境設定」を使ったアカウント管理について解説します。
                                 次回へつづく

    小池邦人のCarbon視点でCocoa探求(2008/02/08)

    〜 モデル・オブジェクトを考察する 〜

    今回は、「しんぶんし 3」で必要とされるだろうデータ構造(モデル・オブジェクト)について考えてみます。基本的には、複数の画像ファイルを管理するのに必要とされるデータ構造を用意します。

    その前に、前回はウィンドウに表示させたいJPEG画像ファイルを用意し、プロジェクトの「Resources」グループに登録しておけば、これらの画像アイコンがInterface Builderのライブラリの「Media」タブに表示されると解説しました。しかし、Carbonプロジェクトの場合、表示用のPICT画像やアイコンがリソースファイルとして保存されているケースが多々あります。旧バージョンのInterface Builderでは、リソースファイルに登録した画像も、InterfaceBuilder上でその内容を確認しながら編集作業(ボタンに貼付けるとか)が出来ました。

    ところが、最新バージョンでは、それが表示されなくなってしまいました(ボタン上に画像が何も出てこない)。加えて、テキストフィールドへの文字入力がインスペクタ上でしかできないようになっていたりと、引き続きCarbonプロジェクトをメンテしなければいけない開発者にとっては不便きわまりない状態です。「ユーザインターフェースの処理はCocoaでやりなさい!」という話は分かるのですが、前に可能だったことを出来なくするのだけは止めていただきたいと思います。実作業に支障が出るのは大変に困ります。

    さて、アプリケーションのメイン・データ構造を決定する場合には、そのアプリケーションが「何をするのか?」を考えれば良いことになります。「しんぶんし 3」の場合には、画像ファイルをオープンし、そのシンメトリ(対称)画像を作成して保存するという一連の作業を行います。一枚一枚画像ファイルをオープンしていては面倒ですので、画像ファイルを含むフォルダを選び、中の画像をすべて得るという処理も必要です。カット&ペーストやドラッグ&ドロップによる画像やフォルダの登録も必要でしょう。

    例えば、複数の画像ファイルを管理するなら、とりあえずファイルの「パス名」リストとその「個数」を保存しておけばOKです。まあ、実際のシンメトリ処理には、その機能に付随する幾つかのアトリビュート(パラメータ)も必要となりますので、パス名だけという訳には行きませんが、今回のアプリケーションでは、それほど多くのパラメータは必要ないでしょう。Carbonで作成していた前バージョンは、画像ファイルの管理用としてパス名の代わりにFSSpec構造体を利用していました(これもパス名みたいなものですが...)。
    すべての管理用データは以下のようなImageFile構造体にまとめられています。

    typedef struct {
        FSSpec       sys_fsc;          // 画像ファルの保存場所を示すFSSpec構造体
        Rect         sys_srt;          // 画像選択用の矩形枠情報
        OSType       sys_type;         // 画像ファイルのタイプ
        short        sys_flag;         // 状態の管理用フラグ
        short        sys_kind;         // シンメトリ(対称)方向
        short        sys_para;         // オプション用パラメータ
    } ImageFile,*ImageFilePtr;
    


    この構造体を予想される最大個数(前回は2000個に定義していました)確保し、画像ファイルの管理に利用します。ソースコードで書けば...

    #define         MAX_FILE    2000     // 最大が像ファイル管理個数
    ImageFilePtr    sys_image;           // 構造体配列の先頭アドレス
    
    sys_image=(ImageFilePtr)NewPtrClear( MAX_FILE*sizeof(ImageFile) );
    if( sys_image==NULL )
          // 確保できなかった場合のエラー処理
    
    といった感じです。その後の処理で「n個目」の構造体を参照する場合には、
    sys_imageを起点として以下のようにアクセスします。
    
    ImageFilePtr    nowImagePtr;
    
    nowImagePtr=sys_image+n;
    


    構造体データをすべてコピーしたければ、最近のコンパイラでは以下の書式でOKです。

    この方法、構造体用メモリを一度に全部確保してしまいますので、必要となるメモリ容量の予想がしやすく(エラー処理も簡単)全体的な管理が楽です。また、逐次確保の手続きが不要な分だけデータアクセス処理が高速となります。欠点は、余分な(未使用)メモリ領域が確保されてしまっている点と、どうあがいても2000個以上登録できないと言うことです(笑)。しかし、今となっては2000を20000に変更したところで、消費されるメモリは2MByte程度ですので「どおってことない」という感じはします。

    これをObjective-Cの「オブジェクト」として実装してみると、以下のような感じになります。上記の構造体のメンバーは、インスタンス変数として定義されます。今後の展開からして、CGRectはNSRectの方が良いかもしれません(内部構造的には同じ)。

    @interface ImageFile : NSObject
    {
        NSString       *_name;
        NSString       *_type;
        CGRect          _srt;
        unsigned int    _flag;
        int             _kind;
        int             _para;
    }
    @end
    


    そして、モデルのコントロール・オブジェクトの方にNSMutableArrayのインスタンス変数を定義しておいて、その配列要素に、[[ImageFile alloc] init];で確保したImageFileオブジェクトを登録して管理します。

    @interface ImageList : NSObject
    {
        NSMutableArray     *_list;
    }
    @end
    


    こちらの方法の利点は、登録個数に制限がない点です(Mac OS Xが管理できるメモリ容量最大までOK)。それに特定オブジェクトを削除したり順番を入れ替えたりする仕事は、NSMutableArrayのメソッドが引き受けてくれますので、リスト管理が大変楽です。先に説明した構造体一括管理の場合には、そうした処理が必要であれば自分で処理ルーチンを実装する必要があります(そんなに難しくはないですが...)。旧「しんぶんし」でも、そうした処理(削除のみで順番変更はなし)を独自で実装していました。

    さて、旧バージョンのデータ構造では、ドラッグ&ドロップで登録した画像ファイルはOKなのですが、カット&ペーストで登録したい画像(ファイルではなく画像データ)の情報を保存できません。だとすると、画像データ自体を保存しておくインスタンス変数も用意しておいた方が良いかもしれません。旧バージョンでは、画像ファイル一覧(台帳)をファイルへ保存して再利用するという機能はありませんでした。しかし、今回はCocoaの練習の意味もあるので「台帳」のファイルへの保存も考えることにします。

    であれば、パス名の管理だけでは、登録後にその画像が別の場所に移されてしまった時に台帳に登録したファイルが見つからない場合があります。Carbonアプリでは、構造体内にファイルの「AliasHandle」を保存しておくことで、Aliasマネージャがファイルを探し出してくれました。Cocoaではどうしたものでしょうか? また、台帳ファイルを保存するという機能を追加するとなれば、Cocoaのアプリケーション形式を「Cocoa Document-based Application」へと切り替えた方が良さそうです。色々と課題が山積しています。

    次回は、「しんぶんし 3」プロジェクトを「Cocoa Document-basedApplication」に切り替えてみます。こちらのアプリケーションタイプで注意すべき点を調べながら、モデル・オブジェクトの実装を試みたいと思います。
    つづく                                

    ターミナルの向こうから      第19回  海上 忍

    〜 スプレッドシートとの共存を考える (1)〜

     今回は、スプレッドシート、特に「Excel」という存在感の大きいアプリケーション、およびそのファイルフォーマットについて考えてみます。

    ・Excelという巨大な存在
     Microsoft Excelというアプリケーションは、PCの世界のみならず、実社会にも大きな影響力を持っています。Windows 95ブーム以降、"PCを使える"ことすなわちExcelを一通り操作できること、といった風潮がありましたが、それは今なお健在です。Excelの使い方を授業に取り入れている学校、新入社員教育にExcelを使う会社は、かなり多いはずです。
     しかしExcelが普及すること、誰もが使い方を覚えることは、問題にならないと思います。むしろ問題は、Excelがあまりに機能豊富で文書処理の広範囲に応用可能なため、なんでもかんでもExcelで済ませてしまおうという層が出現することです。
     実例を挙げてみましょう。顧客の住所録をExcelでつくる、これはよく耳にする話ですね。巨大なワークシートを顧客管理DB代わりに使う、これもなんとなく想像できると思います。ここまでは、想定の範囲内です。では、ワープロ文書のようにきちんとレイアウトされた送達状の作成に使われているとしたら……プレゼンで使うグラフのみならず本文までが、しかもセルではなくテキストボックスに入力されていたとしたら……そして、そのExcelブックを「相手の事情を考えずに」送りつけてきたとしたら……Excel依存が進みすぎることの弊害はご理解いただけたでしょうか?

    ・過度なExcel依存にどう対処するか
     MOSA伝の主旨からは外れてしまうかもしれませんが、この話題をもう少し続けましょう。今はメールやWebで他プラットフォームとも密接に連係している時代、Macでも無関係ではないからです。
     対策の1つには、フォーマットの誘導を図ることが挙げられます。最新の
    Office Open XML(.xlsx)形式は、すべての項目を忠実に開こうとすれば最新のExcel 2008が必要になりますから、Excel 97-2000(.xls)で保存してもらいます。そうすれば、OpenOffice.orgなどのフリーなソフトで開けますから、少なくとも開けなくて困ることはなくなります。ユーザを無理に慣れた操作体系から離れさせる必要もありません。
     もう1つは、Excelブックを自動変換する処理系をつくりあげること。メールにExcelブックが添付されていた場合、自動的にCSVなどの汎用的なフォーマットに変換してしまう、というものです。こちらは費用も時間もかかりますから、おいそれとは着手できないでしょうが、1つの方向であろうとは思います。
     Office Open XMLの普及を待つ、という消極的な方法もアリだと思います。このフォーマットはオープンですから、いずれはExcelブックのコンバートに使えそうな実装系が登場することでしょう。実際、OpenXML4J(http://www.openxml4j.org/)などのオープンな開発プロジェクトもスタートしています。

    ・Excelブックの処理系
     プログラミングで解決を図るという方向性を、もう少し角度を変えて考えてみましょう。Excelはプロプライエタリなアプリケーションですが、データの取得/追加や保存などの作業を行えるオープンな処理系がいくつか存在するからです。
     1つは、Rubyの拡張ライブラリ「win32ole」。Windowsで用いられるComponent Object Model(COM)にRubyからアクセス、Excelブックのデータハンドリングを可能にするというものです。バージョン1.8以降のRubyに標準装備されていますから、ある程度ポピュラーな方法といえますが、Win32環境専用ですので、Mac OS Xでは利用できません。
     もう1つは、Perlの「Spreadsheet::WriteExcel」および「Spreadsheet::ParseExcel」モジュール。こちらはクロスプラットフォームですから、Mac OS Xでも利用できます。CPAN(http://www.cpan.org/)からいくつかモジュールをダウンロードする必要がありますが、作業自体はとてもかんたんです。

    ・Spreadsheet::WriteExcelを入手する

     Perlモジュールは、cpanコマンドでダウンロードできます。紙幅が残り少ないので、細かい環境設定は抜きで参りましょう。まずはTerminalから以下のコマンドを実行してください(はじめて実行したときは色々と質問されますが、基本的にデフォルト値でOK)。

    - - - - -
    $ sudo -H cpan
    cpan> force install Spreadsheet::WriteExcel
    cpan> exit
    - - - - -
    


     これで、以下のリストが動作するようになります。適当なファイル名で保存したあと、「perl filename」として実行してください。数値と数式が入力されたExcelブック「sample.xls」が、カレントディレクトリに作成されたはずです。次週に続きます!

    - - - - -
     #!/usr/bin/perl -w
     use strict;
     use Spreadsheet::WriteExcel;
    
     my $mybook  = Spreadsheet::WriteExcel->new('sample.xls');
     my $mysheet = $mybook->add_worksheet();
    
    $mysheet->write(1, 0,  123453);
    $mysheet->write(2, 0,  4.34567);
    $mysheet->write(4, 0,  '=A2 + A3');
    - - - - -
    

    ニュース解説   MOSAic

    ★★★ 開発関連のニュースはwebに掲載中 ★★★
    http://www.mosa.gr.jp/?page_id=1017

    ・1月のニュース
    http://www.mosa.gr.jp/?p=1515

    ◇MOSAからのお知らせと編集後記は割愛します◇

     

     MOSA Developer News   略称[MOSADeN=モサ伝]
            配信停止 mailto:mosaden-ml@mosa.gr.jp
     記事内容に関するご意見 mailto:mosaden-toukou@mosa.gr.jp
          記事投稿受付 http://www.mosa.gr.jp/?page_id=850
    Apple、Mac OSは米国アップル社の登録商標です。またそのほかの各製品名等
    はそれぞれ各社の商標ならびに登録商標です。
    このメールの再配信、および掲載された記事の無断転載を禁じます。
    特定非営利活動法人MOSA  http://www.mosa.gr.jp/
    Copyright (C)2007 MOSA. All rights reserved.

  • MOSA Developer News[MOSADeN=モサ伝]第285号

    2008-02-05

    目次

    • りんご味Ruby         第18回  藤本 尚邦
    • 藤本裕之のプログラミング夜話   #131
    • 高橋真人の「プログラミング指南」  第129回
    • 開発ツールよもやま話     Xcode3のスナップショット機能

    りんご味Ruby   第18回  藤本 尚邦

    前回は、Rubyのブロック付きメソッドによる繰り返しの抽象化の効果を示しました。今回は、I/O(ファイルやソケットとの入出力)への読み書きアクセスを題材として、ブロック付きメソッドによるシステム上のリソースへのアクセスの抽象化とその効果を示します。

    ■ (1) I/Oの開け閉めを直接プログラムする

    ファイルへの読み書きやTCPソケットによる通信では、ほとんどの場合、以下のような手順で処理が行なわれます。

    (1) まずI/Oを開く
    (2) I/Oを介してデータを読み書き処理する
    (3) 最後にI/Oを閉じる

    まず、この手順を直裁的にプログラムしてみましょう。

    -----------------------------------------------
    require 'socket'
    require 'rss/2.0'
    io = TCPSocket.open("www.mosa.gr.jp", 80)   # I/Oを開く
    io.write "GET /?feed=rss2 HTTP/1.0\r\n\r\n" # HTTP GET要求を送信
    rss = RSS::Parser.parse(io, false)          # 受信しながらRSSをパース
    io.close                                    # I/Oを閉じる
    rss.items.each { |i| puts i.title }         # 結果を表示
    -----------------------------------------------


    【編集部注:\r\n部分が『円記号』に見える場合は『バックスラッシュ』に置き換えてください。以下も同様です】

    このプログラムは以下のような処理をしています。

    ・モサのWebサイトにTCP接続する
    ・HTTPプロトコルのGETを送信し、RSSデータを要求する
    ・RSSデータを受信しながらパースする
    ・接続を閉じる
    ・パース結果の各エントリのタイトルをプリントする

    同時に開くことのできるファイルやソケットの数にはシステム上の制限がありますから、不要になった時点でそのI/Oは閉じるべきでしょう。しかし、上記のようなプログラムで I/O を閉じる部分を書き忘れてしまうというのはありがちな話だと思います。書き忘れなかったとしても、RSSパース時に例外が発生したりしたら、I/Oは開きっぱなしのままプログラムの実行は外に移ってしまいます。

    ■ (2) I/Oの開きっぱなしを避ける – ensure の導入

    書き忘れはどうしようもありませんが、例外の発生によるI/O開きっぱなし問題には解決策があります。例えば Java の finally

      try { ... } finally { ... }
    


    のようなものを使う方法が考えられます(何が起ころうともtry節から出るときには必ずfinally節を実行する)。Rubyにも、beginとensureを使う同様の構文があります。さきほどのプログラムを改良してみましょう。

    -----------------------------------------------
    require 'socket'
    require 'rss/2.0'
    io = TCPSocket.open("www.mosa.gr.jp", 80)     # I/Oを開く
    begin
      io.write "GET /?feed=rss2 HTTP/1.0\r\n\r\n" # HTTP GET要求を送信
      rss = RSS::Parser.parse(io, false)          # 受信しながらパース
    ensure
      io.close                                    # I/Oを閉じる
    end
    rss.items.each { |i| puts i.title }           # 結果を表示
    -----------------------------------------------
    


    begin節(beginとensureで挟まれた2行)の実行中に何が起きようと、ensure節(ensureとendで挟まれた1行)は必ず実行されます。つまり、ioは必ず閉じます。

    I/Oが閉じられるようになって少し安心しました。このように書いている時点でI/Oを閉じることを意識しているわけですから、それを書き忘れることはおそらくないでしょう。

    ■ (2) I/Oの開け閉めを抽象化 – ブロック付きのopen呼出し

    ところで、このプログラムは少し冗長な気がしませんか?とくに、I/Oの開閉に関する部分は、I/Oにアクセスするどんな目的のプログラムであろうとさほど変わるものではありません。言い換えると、TCPソケットで通信するプログラムには以下のようなパターンがあります。

      io = TCPSocket.open(ホスト名, ポート番号)
      begin
        I/Oアクセス処理 ...
      ensure
        io.close
      end
    


    何度も同じようなパターンが出てくるときは、それを出来る限り抽象化して繰り返さないようにするのが正しいプログラマの姿勢(DRY原則-後述)。ここでブロック付きメソッド呼出しの登場です。TCPSocketクラスのクラスメソッドであるopenは、I/O(ソケット)へのアクセス処理をブロックとして渡すことにより、上記のようなパターンのI/Oの開け閉めを裏でやってくれます。この場合、ブロックの実行結果がopenメソッドの返す値となります。

    TCPSocket.open(ホスト名, ポート番号) {|io| I/Oアクセス処理 … }

    では、ブロック付き呼出しでさらにプログラムを書き換えてみましょう。

    -----------------------------------------------
    require 'socket'
    require 'rss/2.0'
    rss = TCPSocket.open("www.mosa.gr.jp", 80) { |io|
      io.write "GET /?feed=rss2 HTTP/1.0\r\n\r\n"
      RSS::Parser.parse(io, false)
    }
    rss.items.each { |i| puts i.title }
    -----------------------------------------------
    


    とてもすっきりした上、I/Oの閉じ忘れも書き忘れも起こりえないプログラムになりました。

    ここまで、TCPSocketを実例としてI/Oへの読み書きアクセスの抽象化を説明しましたが、これはIOクラス(TCPSocketの上位クラス)でサポートしている機能です。ファイルI/Oに関しても同様に使うことができます。もちろん、このような抽象化をサポートするブロック付きメソッドをプログラマが定義することもできます。

    ■ [補足] HTTPアクセスについて

    今回、説明の都合からTCPSocketを直接使いましたが、実際のRubyプログラムでHTTPプロトコルを使う場合には、Rubyに付属しているライブラリの net/httpあるいは単純な GET だけであれば open-uri (RSSリーダで使っているもの)を使うのが手軽かつ安全で良いでしょう。

    ■ [補足] DRY原則

    DRY = Don’t Repeat Yourself の略。「同じコードの繰り返しは抽象化してひとまとめにしよう」というプログラミング上の原則のこと。「達人プログラマ」(ISBN-13: 978-4894712744)という本などで紹介されています。

    藤本裕之のプログラミング夜話 #131

     
     前回あんなことを書き始めたら、いきなりエルゴソフトがegword、egbridgeなどのパッケージソフト事業を終了するという発表をした(1月28日)。公式見解では「Mac OS Xにおける日本語環境の成熟などから、パッケージソフト事業を終了する時期である」としている。システムについてくる、いわば只の「ことえり」が良くなれば「egbridge」と「ATOK」が分け合うパイが小さくなるのは必然だし、Intel チップの採用、Boot Campの実現などで Windows との垣根が低くなったことも、デファクト・スタンダードとしてのMS Wordの立場を強化しこそすれ、egwordにプラスには働かない。企業としてはそういう言葉は使わないが、アリテイに言えば「事業として続けていても将来の展望がない」ということなんだろう。

     egwordに限ったことではない。ここ数年、iPodのおかげでアップルのブランドイメージは向上、Macintoshにも波及してプラットフォームとしてのシェアは上向いているにも関わらず、Macintosh用のパッケージソフトの売り上げは伸びていない。いやWindows用のソフトだって、品数こそ多いが我が世の春を謳歌してるわけではないようだ。早い話がどこでも「マシンは普及したがソフトは売れない」という状況。まるでケーザイ評論家が言う「大企業の景気の良さが、中小企業や被雇用者にまで波及してこない」という話のインスタンスのようである。こんな感じ?

    我らが現状 = [[NS日本の経済状況 alloc] initWithソフトウエア業界];

     オレはこういう話を大所高所からするのが苦手なので(だって大所高所にいたことがないんだからしょうがねぇよな)、ごく私的な実体験を元にしての話しかできないのだが、考えてみればオレ自身がここ数年、ずっと使っているもののバージョンアップを除いて新たに購入したソフトウエアは数えるほどなのである。いや具体的に行こうか。全く新規にソフトウエアを買ったのは、一昨年3月の Yojimbo(Bare Bones Software, Inc.)が最後だと思う。なんで買わないのかな、と考えてみると、まぁビンボーなのはデフォルトとして、欲しくなるようなソフトがないんだよね。

     昔話をしよう。おじいさんが山に芝刈りに、おばあさんが川に洗濯に行き、ワタシが足繁く秋葉原に通っていた(今は年に一度くらいだが)ころの話である。1986年に自分にとって最初のMacintosh(個人用としては最初のパソコンでもあった)であるMac Plusを買ったとき、その購入価格は「Macintosh Plus+ ImageWriterII + External FD Drive に3.5インチのフロッピーディスク10枚とソフトウエア10万円分をセットにして998,000円というものだった。MacPlus 本体がカタログ価格で898,000円だったからずいぶんオトクなセットだと思った(2ヶ月後本体は648,000円に値下げされたんだけどね)。

     このときオレが本体と一緒に手に入れた「10万円分のソフト」の内訳は、MacWrite、MacPascal、FullPaint、それに Super Studio Session だった。いや信じられないと言うかも知れぬがこれで10万円になってしまったんですよ、奥さん。よく覚えていないが千数百円は負けてもらったかも知らん。はい? Super Studio Session て何だって? その話は長くなるので別の機会に譲るけど、何が言いたいかというと当時のソフト(ハードも)はとっても高かった……ということではなくて、これら4本のソフトウエアを選ぶのにオレがどんだけ悩んだか、他にも買ってみたいソフトがどれほどあったか、それも
    Macintosh用ソフトウエアの市場なんて今と比べ物にならないくらい小さかったのに、ということなんである。

    (以下次回 2008_02_01)

    高橋真人の「プログラミング指南」第129回

    コミュニケーション能力を高めよう(2)

     皆さんこんにちは、高橋真人です。さっそく続けます。
     前回のお話は、「本として出版されている時点で作者側の“変換作業”は終わってしまっているので、重要なのはどのように本を選ぶかだ」というところまででした。
     本を選ぶのは、普通は自分の必要とするテーマに沿って書かれた本の中からより自分に適した本を選び出すというやり方になるでしょうか。選び出す判断基準としては価格、ページ数、知り合いの推薦やWebの書評などといろいろあげられます。ですが、他人から得た情報はあくまで参考でしかありません。人によって“ふさわしい”の判断基準は変わってきますから、自分自身で見極められるようになることも必要です。
     かといって、いくら経験を積んでも完璧な本選び(つまり自分に必要な本のみを的確に選び出すこと)ができるようになるわけではありません。ただ、経験を積めばいろんな勘も身に付き、本選びの確度は確実に上がってくるのではないかと思います。

     自分にふさわしい本が選べたら、次は読む作業です。これは前回の話に当てはめると「D/A変換」となります。人間は機械ではないので、本を読んで得られる情報は一定ではありません。読む時の心身のコンディションのせいで単に文字を目で追っているだけになったり、筆者の文体とか、本のレイアウトが気に入らないなどの理由で読む気が失せてしまうなどということが起こり得るのは、人間ならではのことだと言えるでしょう。
     ところで、この連載の初期のころに「翻訳本は、それだけ多くの選抜を経ているのでヒット率が高い」というようなことを書いた記憶があります。ですがこれをデジタルとアナログの話で考えると、少し違った要素も考慮する必要が出てきます。
     それは、著者と読者の間に翻訳者という存在が介在するということです。翻訳者が原書を読むD/A変換作業と、訳した内容を日本語で書き記すA/D変換作業が一連の情報伝達の過程に加わるために、情報の劣化がさらに進む可能性があるのです。例えばAmazonの書評を読んでいて「翻訳の質が悪いので、原書を読むことを勧める」などという記述を見かけることも多く、原書を自在に読むことのできない私のような人間にとっては残念でなりません。
     もっとも、翻訳者という存在が介入することは悪いばかりではありません。時には翻訳者がかえって情報の質を高めてくれることもあったりします。例えば、訳している最中に原書の誤記と思われる部分に気付き、わざわざ原著者に問い合わせて確認をした上で原著にはない注記を付けてくれたり、原著のサンプルコードのバグを修正してくれていたりする例も私は経験しています。
     質の低い翻訳本に当たって、さらにそれが原書に比べてかなり高価であった場合には「人の文章を翻訳するだけで儲けやがって…」と苦々しく思うこともありますが、逆に原書に負けないクオリティを保った上に、原書を買うよりも安い価格で発売してくれている翻訳本に当たったときには、とても得をした気持ちになるものです。
     このような“良い翻訳”である時にポイントなのは、翻訳者が単なる仲介者ではなく、まず訳者自身が原著の“良い読者”であることです。よく言われることですが、良い翻訳者の条件は、英語力よりもその本のジャンルに通じていることなのです。

     さて、今の翻訳者の話には読者としての重要なポイントも含まれています。つまり、読者として本を読む場合にも、その本に書かれている分野の知識が多ければ、それだけ本から多くのものを得ることができるということです。
     一言で言えば、予備知識などということになるのでしょうが、これから読もうとする本の分野に通じていれば、それだけその本から得られる情報も多くなります。時には“行間を読む”などといって、文章に書かれていないことまで読み取れることがあるわけです。
     行間を読めるようになるためには、背景知識・経験が多ければ多いほどよいわけですが、実は、プログラマという仕事には、行間を読む能力が資質として要求されるのです。
     プログラマは、ソースコードを書くのが役目ですが、そのためには当然ソースコードを読む作業も発生します。人間が日常会話で使う言語に比べますと、プログラミング言語というのは極端に表現力が低いので、“どうするのか”しか表現できません。実際にコードで表現されている処理が具体的には何を意味しているのか、それを読み取れないと、ソースコードを読むということにはならないわけです。(言ってみれば、行間を読めないプログラマは、まだ一人前だとは言えないということです)
     プログラマとして行間を読む力が鍛えられてくると、さらなる力を発揮できます。例えば、ドキュメントも充分でなく、サンプルすら存在しないAPIでも、ヘッダファイルに記述されている情報を頼りに、試行錯誤で使えるようにしてしまうなんてことも、プロとして活躍されているプログラマであれば珍しいことではないと思います。

     見てきましたように、人間というD/A変換機は、時にデジタルの入力からあまり多くの情報を引き出せないこともあれば、逆に入力された以上の変換結果を生み出すこともできるという特徴を持っているわけです。

     「『経験を積んで、行間を読め』と言われても、そもそもその力がないから困っているんじゃないか」ですって? ごもっとも。
     まだ行間を読む力のない皆さんが、本からより多くのものを得られるにはどうしたらよいのでしょうか?
     私の経験上、最も効果のある方法は“繰り返し”です。
     先ほども言いましたように、本を一回読んだだけでそこからすべてを吸収できるなんてことはまず無理で、書かれている内容が今の自分のレベルから離れていればいるほど、いくら頑張って読んでも中身は全然頭に入ってきません。
     まあ、書かれている内容が全く理解できない場合には、その本はあなたに必要のない本であるか、まだ今のあなたには早過ぎる本なのでしょう。ですが、全部がスッキリ理解できるまで待っていては、時間がいくらあっても足りません。少し分からない部分があるぐらいの段階で、どんどん挑戦していく方が、力が付くのも早まるでしょう。
     もし、通して読むのは厳しいと思っても、ところどころ拾い読みできそうな場合には、ざっと目を通してみましょう。これはほとんど“読んでいる”ということにはならないかもしれませんが、とりあえず行けるところまでページをめくってみて、何か印象が残ればよしとします。

     次は、忘れる作業です。
     どうも、日本の学校教育で育ってくると(最近は違うのかも分かりませんが)、学習というのは記憶することだというふうに考えてしまう傾向があります。ですが、私はあえて「プログラミングの学習は記憶ではない」と申し上げておきます。
     暗記することには、大した価値はありません。忘れることなど気にせずに、何度でもしつこく調べましょう。そのうち、調べなくても自然に頭から出てくるようになってしまいます。
     で、パラパラと眺めるなりして一通り目を通した本は、とりあえず本棚にでもしまっておきます。まあ、できれば常に目に付くところに置いておくといいでしょう。そして、その本のことはとりあえず放っておいて、別の勉強をします(関連のあるジャンルのことだとよりベターですが、プログラミング関連であればよしとします)。しばらくすると、ふと「今なら、あの本をもう少し読めるもしれない」と思う時が来るかもしれません。その時さらにその本を読みたいという気持ちになっていたら最高です。迷わず手に取ってみましょう。あくまで、初めて読む本のように読み始めるのがポイントです。
     読み進めてみて(それが無理なら、再び拾い読みでもいい)、「あれ、こんなこと書いてあったっけ?」と思ったら、ラッキーです。間違っても、「この部分は前に読んだから、適当に読んでおけばいいや」とは思わないでください。もし、「あれ、ここ、前にも読んだぞ」と感じて、一ページまるごと読んでも、一つも新しく読んだ気がしないとしたら、それはちょっと本棚に寝かす時間が少なすぎたのかもしれませんね。もう少し忘れるまでしまっておきましょう。
     こんな形で、何度も繰り返して「読んでは、寝かせる」というサイクルを行っていると、そのうちその本が「まともに」読めるようになってきます。さらに面白いのは、ある程度「読めるようになった」と感じても、時間を空けて再度読み返すと、少なからず「あれ、こんなこと書いてあったっけ?」という部分が見つかることです。こういうことを繰り返していると次第に“行間も読める”ようになってきます。

     まあ、以上は私のやってきた経験のお話ですので、必ずしもこの通り忠実にやる必要はないのかもしれません。ですが、私自身はこんなやり方で、最初は全く歯の立たなかった本を何冊も読めるようになりました。正直、「読んでは、寝かせて、また読んで…」という繰り返しを何度したかすら分かりませんが、本は大切に読むタイプの私であっても、その本が読めるようになった時には、手あかがついて、カバーの隅が切れかかるぐらいになったほどですから。
     何より、「読めるようになった」ことの充足感は何ものにも代え難いものだったということは申し上げておきます。皆さんが、皆さんご自身の本や筆者とのコミュニケーション能力を磨いていく上で、私の経験談が参考になれば嬉しい限りです。

    開発ツールよもやま話   Xcode3のスナップショット機能 

     高橋 政明

     スナップショットはXcode3のファイルメニューにある簡易ソースコード管理機能です。
     「スナップショットを作成」を選ぶだけでその時点のプロジェクトの状態を文字通りスナップショットとして保存します。スナップショットを作成するとファイルメニュー「スナップショット」項目が有効になり、スナップショットパネルを表示できます。パネルで作成したスナップショットにコメントをつけることができます。もちろん日本語入力もまったく問題なしです。

     ソースを修正したあと区切りの良い時点でいつでもスナップショットパネルの「作成」アイコンクリックでスナップショットを作成できます。

     通常の開発ではsubversionなど本格的なソースコード管理をおすすめしますが、実験コードやファイル数が少なく変更回数も少ないプロジェクトにはスナップショットが手軽です。

     スナップショットの保存先はホーム直下のライブラリフォルダでパスは
    ~/Library/Application Support/Developer/Shared/SnapshotRepository.sparseimage
    です。ディスクイメージファイルに圧縮されています。
     このディスクイメージファイルはXcodeを終了すると開く事ができます。開くとArchivedDirectoriesフォルダとSnapshotArchive.plistがありす。plistに圧縮ファイル別のコメント情報などがあり、ArchivedDirectoriesの中に各プロジェクトがあります。ArchivedDirectoriesフォルダ内の各プロジェクトのパスはXcodeでスナップショットパネル内の『アーカイブ:』に表示されています。

     ディスクイメージには変更の有無に関係なくすべてのファイルが保存されているようです。この点は変更のあったファイルの差分だけを保存して行く本格的なソースコード管理とは違います。ただしスナップショットパネルではスナップショットと現在の状態の差分を見る事ができます。

     差分を見るにはスナップショットパネルのツールバー「ファイルを表示」アイコンをクリックします。ファイル名欄にはソースヘッダ以外にもXcodeのバンドル内部の開発には直接関係しないものも表示されるようです。ソースやヘッダファイルを選択すると違いを示す表示になります。右側が現在の内容で、左側が選択したスナップショットの内容になります。
     差分表示はFileMergeなどでもおなじみの変更(追加/削除)部分の対応を明示した見やすいものです。この部分(スナップショットパネルの差分表示)では編集はできませんが、コピーはできますので、部分的にスナップショットの状態に手作業で戻すことは可能です。

     全体をスナップショットに戻すにはツールバー「復元」アイコンをクリックします。復元操作もスナップショットに記憶されます。

     スナップショットは手軽ですが、やはり長期で大規模な作業の必要なプロジェクトには本格的なソースコード管理が適します。ファイル別にコミットできるソースコード管理は運用しやすく便利です。

    ◆本日のまとめ
     Xcode3のスナップショット機能は、本格的なリポジトリを用意するほどではない小規模なプロジェクトには手軽で便利。
     スナップショットパネルには追加変更があったファイルだけ表示しているが全部を保存している。

    ニュース解説   MOSAic

    ★★★ 開発関連のニュースはwebに掲載中 ★★★
    http://www.mosa.gr.jp/?page_id=1017

    ・12月のニュース
    http://www.mosa.gr.jp/?p=1476

    ◇MOSAからのお知らせと編集後記は割愛します◇

     

     MOSA Developer News   略称[MOSADeN=モサ伝]
            配信停止 mailto:mosaden-ml@mosa.gr.jp
     記事内容に関するご意見 mailto:mosaden-toukou@mosa.gr.jp
          記事投稿受付 http://www.mosa.gr.jp/?page_id=850
    Apple、Mac OSは米国アップル社の登録商標です。またそのほかの各製品名等
    はそれぞれ各社の商標ならびに登録商標です。
    このメールの再配信、および掲載された記事の無断転載を禁じます。
    特定非営利活動法人MOSA  http://www.mosa.gr.jp/
    Copyright (C)2007 MOSA. All rights reserved.