MOSA Multi-OS Software Artists

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

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

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

MOSADenバックナンバー 2009年3月発行分

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

    2009-03-31

    目次

    • りんご味Ruby         第44回  藤本 尚邦
    • 藤本裕之のプログラミング夜話   #157
    • 高橋真人の「プログラミング指南」  第155回
    • mosa entranceだより       第4回   高松 和広

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

    引き続き、Ruby+RubyCocoaを使って「CoreGraphicsによるPDFの描画」を記述するための簡易言語(DSL)を作っていきます。

    前回、CoreGraphicsの描画コンテキストについて、CGContextという名前のRubyのクラスを定義して、そのインスタンスとして扱うことにしました。PDFコンテキスト(やBitmapコンテキストなど)は、CGContextクラスの派生クラスとして定義し、その中でコンテキストの種類を context_type という疑似構文によって宣言することにしました:

     class CGPDFContext < CGContext
       context_type :PDF   # PDFコンテキスト
       ...
     end

    context_type という宣言風の疑似構文の実体は、いつもどおり、CGContextクラスのプライベートなクラスメソッドです。context_type メソッドは、引数で指定された描画コンテキストのためのCoreGraphics関数をインスタンスメソッドとして自動定義します。

    【編集部注:以下バックスラッシュを¥で置き換えて表現します】

      

     def context_type(type)
         pattern = /¥ACG#{type}Context(.*)¥Z/
         OSX.methods.each do |func_name|
           matched = pattern.match(func_name)
           methodnize(func_name, matched[1]) if matched
         end
       end
    


    この実装の中身を見ていきます。

    ■ 正規表現リテラル

    context_type では、まず、引数として渡された描画コンテキストを扱う関数の名前にマッチする正規表現のバターンを作ります。すなわち、コンテキストが"PDF" であれば "CGPDFContext" で始まる関数名にマッチし、"Bitmap" であれば CGBitmapContext で始まる関数名にマッチするパターンです。

    これまでにもしばしば出てきていますが、Rubyには、文字列などと同様に、正規表現オブジェクトを直接記述(リテラル表記)する構文があります:

     

    pattern = /¥ACG#{type}Context(.*)¥Z/

    右辺の "/" で挟んだところが、目的の関数名にマッチする正規表現オブジェクト(Regexpクラスのインスタンス)のリテラル表記です。生成された正規表現オブジェクトには、pattern という名前(変数名)をつけています。

    このパターンで使われている正規表現の構文をざっと順に説明します:

     

    ¥A      -- 文字列の先頭にマッチ
     CG      -- "CG" という文字の並びにマッチ
     #{type} -- context_type の引数 type を評価した結果の文字列にマッチ
     Context -- "Context" という文字の並びにマッチ
     .       -- 任意の1文字にマッチするパターン
     ・      -- 直前のパターンの0回以上の繰り返しにマッチするパターン
     (.*)    -- 任意の1文字の0回以上の繰り返しにマッチした部分をグループ化
     ¥Z      -- 文字列の末尾にマッチするパターン
    


    中でもポイントは、#{type} の部分と (.*) の2点になります。文字列リテラルの場合と同様、#{…} というパターンは、…の部分のRubyプログラムを評価した結果を文字列化し、その文字列をパターンとして埋め込みます。

     

    context_type :PDF

    と宣言された場合、引数typeの値は :PDF というSymbolオブジェクトです。それを文字列化すると "PDF" なので、/¥ACGPDFContext(.*)¥Z/ というパターンになります。また、(.*)のように括弧で囲まれた部分は、パターンマッチを実行したときに、その部分にマッチした文字列を取り出すことができます。この部分は、生成するインスタンスメソッドの名前になります。

     context_type nil

    のように nil が渡された場合には、nil を文字列化すると空文字列 "" になるので、/¥ACGContext(.*)¥Z/ というパターンになり、これは CGContext 全般を扱う関数名にマッチすることになります(注 - 実を言うとそうでないものにもいくつかマッチしてしまうのですが、話をシンプルにするためそこは目をつぶってください)。

    ■ 正規表現のパターンマッチ

    必要なパターンはできたので、次は、全ての関数名の中からパターンにマッチする関数名を見つけて、インスタンスメソッド化します:

      

       OSX.methods.each do |func_name|
           matched = pattern.match(func_name)
           methodnize(func_name, matched[1]) if matched
         end
    


    OSX.methods は、RubyCocoaで使うことの出来る Objective-C の関数名の配列を返します。それぞれの関数名について、Regexp#matchによりパターンマッチさせ、成功した場合は methodnize を呼び出します。methodnize は別途定義したプライベートクラスメソッドです。

    matched[1] には、(.*) の部分にマッチした文字列、つまり生成するインスタンスメソッド名になる文字列が入ります。matched[0] はパターン全体にマッチした文字列で、matched[1]以降には括弧で囲まれたグループに部分マッチした文字列がグループの出現順に入ります。

    (余談) ところで、Objective-C でも、Foundationフレームワークあたりに正規表現関連のクラスを導入して、@/パターン/ みたいな感じのリテラル表記を導入すればいいのに、と思いませんか?さらに欲を言うと、NSArray やNSDictionary のリテラル表記があればいいのになぁと思うこともあるのですが、単に私がRubyに毒され過ぎてるだけなのかもしれません。

    次回は、見つけた関数をインスタンスメソッド化する methodnize を見ていく予定です。

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

     バブル崩壊前、80年代末のソフトウェア業界を概括しておこう。前述のように労働者派遣法の制定によって、ソフトウェア技術者の派遣を受ける側はそれ以前の「形式的受託開発」のクビキを逃れ、ホントに使える人材だけを派遣元に要求できるようになった。

     既にそれなりのスキルを身につけている技術者にとって、これは必ずしも悪いことではなかった。だってそうでしょ? ものになるかどうか分からないワカモノとカップリングで仕事にあたり、彼らを指導し……と言えば聞こえはいいが大概の場合、彼らの尻拭いをしながらクライアントの要求に応え、報酬はそのワカモノに比べてそれほど高いわけではない、という立場だったのが「自分のハタラキ分をきっちり貰えて他人の面倒は見なくていい」という、なんつかプロのスポーツ選手みたいな感じの働き方になれたんだから。

     前回も書いたが派遣会社も楽だ。主たる仕事は上のような人材をきっちり集めて売り込むことであり、時間がかかる上に成功の保証もない「人材育成」なんてものに金を使わなくて済む。派遣を受ける側のメリットは言うにおよばず、つまり最近(でもない?)流行のコトバで言えば「WIN-WIN」……いや三者だから「WIN-WIN-WIN」かな? の関係がここに成り立ったわけである。あ、断っておくがオレ自身はこういう「WIN-WIN」とか言う言葉をしたり顔で使ってみせるヤツは嫌いなんだけどさ。

     しかし、である。忌野清志郎がかつて喝破したように、世の中「いい事ばかりはありゃしない」のだよね。

     考えれば誰でもすぐ分かることなんだが「今スキルのあるヒトだけを使って次の世代を育てなければ次の世代はスキルのないバカばっかりになる」のである。いやもちろん若い世代にも自分で学べる優秀なヤツはいるし天才だって生まれるさ。でもこんだけ肥大した、そして今も肥大を続けてるソフトウェア産業を下支えするには、そういうヒト達だけでは絶対数が足りないのだ。

     しかもである。ソフトウェア技術者のレベルというのは他の職業のそれに比べて維持するために努力を要する。ボブ・ディランの旧い歌にあったでしょ? 「昨日のトップが今日はビリになる」んである。マシンが進歩し、プラットフォームが新しくなり、新しいプログラミング言語が生まれ、開発手法に革新が起きればそれに追随していかなければ「スキルのある技術者」という立場は維持できない。

     ということは、たとえキチンと育てようとしていたとしても、次の世代がその域に達するためのハードルは日を追って高くなっていくのである。ダーウィンが言うように「獲得形質は遺伝しない」。今後何があっても「Cでプログラムが書ける頭脳を持って」子供は生まれてこない。たとえゴールが38万キロの彼方でも、みんな最初の1mから歩かなければならない。

     まぁ細かいことを言えば、高水準言語やIDE、あるいは各種フレームワークのブラックボックス化によって多少の下駄……というか、ジャンピングボードみたいなものが存在するわけではあるが、誰の助けも借りずスキルを身につける困難さがそれによって軽減しているとも思われない。いや下手をすると逆にそれが枷となって「Javaは分かるけどObjective-Cは駄目です」とか「Visual
    Studioでないとボクなんにもわかりません」みたいな「偽のスキル」(こういうのは偽のスキルだと思う)の横行を助長している側面もあるのではないか。

     と、話がちと逸れた。何が言いたかったかというと、バブル崩壊直前のこの業界では「次世代の技術者を育てる」という意識の減退もタケナワであったということなんである。では次回はいよいよバブルを崩壊させてしまおう(笑)。
    (以下次回 2009_03_27)

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

    これから始めようとする人へ(6)

     皆さんこんにちは、高橋真人です。
     さて、前回予告したように、今回からObjective-Cについてのお話をしていきます。ただ、今までの話の流れに沿う意味で、あくまで「これから始める人」に向けての説明が中心になります。

     Mac/iPhoneのプログラミングを始めるに当たっての質問で頻繁に見られるものに「Objective-Cを学ぶにはあらかじめC言語を学んでおく必要があるのか?」というのがあります。
     Objective-CがCを拡張して作られた言語であることを知っていれば、答えを待つまでもないようにも思うのですが、このような質問をする側には、もう少し深い理屈があって、それだけではなかなか理屈通りには納得できないようです。
     そこで、具体的な例を示してこの辺を説明したいと思います。

     最初に、「Objective-CはCを拡張して作られている」ということですが、このことをよく「CはObjective-Cのサブセットである」とか「Objective-CはCのスーパーセットである」などと言います。サブセットのサブは「部分」、スーパーセットのスーパーは「上位」ということで、これらの表現はすべて「Objective-CがC自体を含んでいる」ということを意味しています。
    では、簡単なサンプルを挙げてみます。
    まずは、Cの例。

    #include 
    
    void foo(int n);
    
    int main()
    {
       foo(10);
    
       return 0;
    }
    
    void foo(int n)
    {
       printf("%d", n);
    }
    


     fooという名の関数に10を渡して、それをコンソールに表示するという単純なプログラムです。
    次にObjective-Cの例です。

    #import 
    
    @interface Foo : NSObject {
    }
    - (void)foo:(int)n;
    @end
    
    int main ()
    {
       Foo* f = [[Foo alloc] init];
       [f foo:10];
       [f release];
    
       return 0;
    }
    
    @implementation Foo
    - (void)foo:(int)n
    {
       NSLog(@"%d", n);
    }
    @end
    


     こちらも、Cの例と同様に10を渡してそれを出力をするだけのものです。Cの例と大きく違うのは、Cでは単なる関数を一つ作るだけで済んだのに、わざわざFooというクラスを定義して、foo:という名のメソッドを持たせているところです。
     この結果、実際の呼び出しの部分でも、Cでは1行で済んでいるところが、Objective-Cでは3行にわたっています。
     何故このようになるのかと言いますと、Objective-Cではメソッドは何らかのクラスに属している必要があるからです。このため、Cでは単なる関数を定義すれば済むところを、Objective-Cの例ではあらかじめクラスを定義しなければなりませんし、呼び出しの前には、クラスをオブジェクトとして実体化し、用が済んだら後始末をする必要まで出てきます。(実体化をさせない書き方も、できないことありませんが)

     さて、両者の違いが分かったところで、「Cを学ばずにObjective-Cを...」という点について考えてみます。
     冒頭に申し上げましたように、CはObjective-Cの一部であるという位置付けになるため、CのコードはそのままObjective-Cのコードとしても正当です。よって、先のCの例のコードも、単にソースファイルの拡張子をcからmに変更するだけでObjective-Cのコードとしてコンパイルされ、実行されます。
     さらに、Objective-Cの方の例をつぶさに観察してみると、NSLog()というC形式の呼び出しを行う関数があることが分かります。Objective-Cというと、どうしても

    [object message:parameter]
    


    という呼び出し形式が目に付いてしまうために、C形式の呼び出しを見ると「これはObjective-Cじゃない」と思ったりする人もいるかもしれませんが、CがObjective-Cの一部である以上、Cの呼び出し形式も正当なObjective-Cですし、実際に、全くC形式の呼び出しを使わずにObjective-Cのプログラムを書くことはほとんど不可能だと言ってもいいのではないかと思います。(作為的に作ることは可能でも、それが実用的に価値があるかというと疑問)

     今回は見た目の話での説明に近かったので、まだ納得の行かない方も多いと思います。次回は、Objective-Cとは切っても切りはなせないCocoaのフレームワーク、特にFoundationフレームワークについて見ていくことで、さらに本質的な部分に迫っていきます。

    mosa entranceだより       第4回   高松 和広

     今週は埼玉工業大学 工学部 情報システム学科1年 高松 和広さんにメールでインタビューし、そのお返事を編集してお届けします。

    ◇情報システム学科ではどんな講義があるのですか?

    日進月歩な情報技術の幅広い知識が学べる講義が揃っています。
    農業地帯のど真ん中にある大学ですが、ビックリするほど充実したカリキュラムになっています。
    1,2年次では、専門科目の他にも情報技術の知識を身につける上で必要な物理や数学の知識を磨き、人間としてのコミュニケーション能力を高められるようになっています。3年次以降では研究室に所属し、専門的で高度な知識を更に身につけます。

    ◇大学や専攻はいつ頃、何を決め手に選んだのですか?

    大学に進学しようと決めたのは、高校3年生の時です。
    決め手は、大学が地元にあることと、学科のカリキュラムが私にピッタリだと判断したからです。
    私は幼い頃からコンピュータが好きでした。コンピュータに携わる仕事に就きたいという気持ちが中学生のときに芽生え、工業高校の情報技術科に入学しました。
    コンピュータに携わる仕事に就きたい‥‥コンピュータに携わる仕事と言っても、色々な分野があります。そこで、コンピュータの幅広い知識を身につけ、将来的にはどんな仕事に就いても汎用的に働ける社会人になりたいと思いました。
    私の住んでいる埼玉県深谷市に「4年間の間に情報技術の幅広い知識を学べる大学」の条件にピッタリな専攻のある大学がありました。その大学が、現在在学中の「埼玉工業大学」です。
    進学したい理想の大学が地元にあるのなら、行かない手はないと思い、埼玉工業大学の情報システム学科に進学することにしました。

    ◇今つくってみたいソフトウェアやサービスはどんなものですか?

    私はコンピュータを始めた時から、画像や映像を扱う作業が好きでした。なので、そのような作業が楽しくなるようなアプリケーションを作りたいです。
     例えば、デジカメの写真をMac上で扱う際に、iPhotoでは出来ないような便利な機能を搭載した写真専用のビューア、など‥‥

    ◇開発環境を教えてください。

    MacにIntelのアーキテクチャが採用されたのを機に、Macを使うようになりました。
    iMac(ポリカーボネートボディのCore 2 Duo搭載モデル)とMacBook(2008年秋登場のアルミユニボディモデル)の2台を使っています。iPhoneは持っていませんが、1世代目のiPod touchを持っています。

    ◇MOSA学生会員になったきっかけは何ですか?

    大学に入学する前までは、正直に言うとプログラミングには全く興味を抱きませんでした。現在、大学では希望通りにコンピュータに関する様々な知識を身に付けているところです。大学での色々な体験が、インスピレーションを与えたんだと思います。最近になって、急にプログラミングがやりたくなったんです。
    プログラミングがやりたいと思っていた矢先、iPodで何気なく聞いていたPodcastの番組「Apple Tips」で、MOSAの存在を知りました。
    「私が好きになったMacでプログラミングをしながら、Macユーザーとのコミュニケーションを沢山することができそうだ!」と思い、MOSA学生会員になりました。

    ◇MOSA学生会員になった目的を教えてください。

    最近になって、プログラミングに興味を持ち始めました。大学では、2年次以降よりC言語によるプログラミングを習得します。
    MacやiPhone向けのプログラミングで使うCocoaやObjective-Cは、C言語がベースになっているので、大学でプログラミングを行う際は、MacやiPhone向けのプログラミングの知識が少しでも役に立つだろうと思いました。
    プログラミングを習得するのなら、大好きなMacやiPhone向けのプログラミングを覚えた方が楽しそうだと思い、それを機にMOSA学生会員になりました。
    それから、MOSAの活動でMacユーザーの方々と沢山のコミュニケーションを取りたいと思ったのも1つの入会した理由です。

    ◇アプリケーションプログラムとwebのサービスではどちらに興味がありますか?

    Webで提供されている色々なサービスは、様々なOSから利用できるものが多いです。
    私はMac OS XとWindowsの両方を使っていますが、現在興味を持っていて、作りたいのはMacやiPhone向けのアプリケーションです。
    2つのOSを使っているので、OSに依存しないWebのサービスには興味がありますし、機会があれば自分でも作ってみたいと思います。

    ◇MacとiPhoneではどちらに興味がありますか?

    どちらにも同じ位の興味があります。
    Macを携帯電話に変化させたのが「iPhone」というイメージを持っています。また、MacとiPhoneのアプリは同じ開発環境で制作できます。
    なのでこれから先、MacとiPhoneで出来る事がどのように増えていくかが気になります。自分でもアプリケーションを作って、両プラットフォームの可能性を広げたいです。

    ◇自己PRや仲間募集など、書きたい事があればどうぞ

    Mac OS Xを使い始めてから2年、Mac・iPhone向けの開発を学び始めてから1ヶ月が経ったばかりの、ひよっこのMacユーザーです。
    今後も積極的に、MOSAの活動に参加をしていきたいです。その節には、ご指導ご鞭撻の程、宜しくお願い申し上げます。

    ◇mosa entrance参加して良かった事は何ですか?

    Mac・iPhone向けの開発をする技術の習得を始めたばかりで、この先も続けられるか時々不安に思うことがありました。しかし、mosa entranceに参加し、色々なお話を聞かせて頂くことによって、どんどん頑張っていこうという気持ちになれました。それが自分にとっては良かったです。

    ◇期待していたけど果たせなかった事があれば書いてください

    開発以外に、皆様が日頃どのようなMacの使い方をされているのかが気になっていたので、そういった話題もあれば良いなと思いましたし、自分から積極的にそういった疑問を質問しておけば良かったと後悔しております。

    ◇ほかの参加者のMacやiPhoneに対する『思い入れ』のようなものは感じましたか?

    アップル関連のグッズを愛用している方がいらっしゃいました。
    ここにいる皆さんは、MacやiPhoneを愛されているんだなぁと思いました。私も参加した日にはアップルのトートバッグを持参していて、「あ、私もいつのまにかMacやiPhoneが好きになってたんだ」と感じさせられました(笑)

    ◇mosa entranceの印象に残ったシーンやエピソードがあれば書いてください

    冗談を交えながら、楽しく話題が進んでいったことが楽しく、印象に残りました。
    mosa entranceは楽しくコミュニケーションをしながら、色々な知恵を交換することができるイベントだと思います。
    今後も積極的に参加し、コミュニケーションを通して、将来へ繋げたいです。

    ◇そのほか思い出した事やこの際書きたい事があればどうぞ!

    これからもmosa entranceには積極的に参加させて頂きます。
    まだまだ未知な部分が多いので、皆様に色々と教えて頂く機会が沢山あると思います。今後とも、宜しくお願い致します。

    ◇以上です、ありがとうございました。

    ◇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)2009 MOSA. All rights reserved.

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

    2009-03-24

    目次

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

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

    〜「Podcast プロデューサー」編〜

     iPhone OS 3.0の発表がありましたが、さっそくこの発表会の模様を収録したムービーが第85回の連載で紹介したPodcast番組でも配信されています。映像のフォーマットを確認してみると640×360のサイズでH.264を使用していることが分かります。収録時間は1時間27分、データサイズは786.7MBとなっています。

    ・Apple Keynotes
    http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=275834665

     さて、前回まででPodcastを制作するためのサーバ側の準備は完了しましたので、いよいよコンテンツの収録を行ってみたいと思います。コンテンツの収録には「Podcast キャプチャ」を使用します。

    ◇「Podcast キャプチャ」による収録
     第86回の連載でも説明したように「アプリケーション」>「ユーティリティ」フォルダには「Podcast キャプチャ」がインストールされています。このツールはサーバ上のPodcastプロデューサーと連携して動作し、クライアント上で収録したコンテンツをネットワークを経由してサーバにアップロードすることができます。「Podcast キャプチャ」はクライアントとサーバの両方にあらかじめインストールされていますが、Podcastの収録には通常はクライアントのMac OS Xを用いることになるでしょう。

     「Podcast キャプチャ」を起動するとまずログイン画面が表示されます。ここでは、「サーバ」にPodcastサーバが稼働しているサーバのアドレスを入力し、さらにサーバ上のユーザで認証を行います。前回サーバ側の設定を行ったときにpcastuserユーザを登録していますので、今回はこのユーザで認証を行うことにします。必ずしもpcastuserユーザを使う必要はありませんので、必要に応じて新しくサーバ上に追加したユーザ(あるいは既存のユーザ)を使ってもかまいません。

    ・「Podcast キャプチャ」の起動画面(認証)
    http://www.htabata.com/img/MXS105/podcast/Capture_02.png

     ログイン認証に成功すると次にPodcastのタイプを選択する画面が表示されます。ここでは4つのタイプを選択することができ、それぞれ異なるタイプのPodcastを制作することができます。選択可能なタイプは次のとおりです。

    ・ビデオ
    ・オーディオ
    ・スクリーン
    ・ファイル

    ・タイプの選択
    http://www.htabata.com/img/MXS105/podcast/Capture_03.png

     「ビデオ」では、Macに内蔵されているカメラを使って動画をキャプチャすることができます。内蔵カメラだけではなく外付けのカメラを使用することもできます。「オーディオ」は音声のみのPodcastを制作する場合に使用します。
     「スクリーン」はMacの画面をそのままキャプチャします。例えばKeynoteなどであらかじめスライドを作成しておき、フルスクリーンでスライドショーを再生しながら画面をキャプチャするといったことができます。このとき音声も同時に録音することができます。最後の「ファイル」ですがあらかじめなんらかの方法で制作しておいたムービーファイルがあれば、そのムービーファイル
    を指定してPodcastプロデューサーにアップロードすることができます。

     いずれかのタイプを選択するといよいよキャプチャです。キャプチャを開始するとカウントダウンが始まり収録が行われます。キャプチャですが「ビデオ」と「オーディオ」の場合は、リモートのカメラを使用することもできます。たとえば学校の教室で授業の様子をキャプチャするとします。このとき教室にあらかじめ収録用のMacを設置しPodcastプロデューサーに登録しておきます。すると講師は、自分のMac上で動作する「Podcast キャプチャ」から収録用のMacに内蔵(あるいは接続)されたカメラを指定することができます。教室のように常に同じ場所で収録するような場合には便利でしょう。
     Podcastプロデューサーへのカメラの登録にも「Podcast キャプチャ」を使用します。カメラを登録するには「Podcast キャプチャ」>「ローカルカメラ設定」メニューを選択し、画面左下のアイコンをクリックしてロックを解除します。そして「カメラ名」にカメラの名前を自由に入力し、「サーバ」にPodcastプロデューサーが稼働しているサーバのアドレスを入力して「バインド」ボタンをクリックします。「バインド」ボタンをクリックすると、サーバの管理者としての認証を求められます。
     登録済みのカメラは「サーバ管理」を使って確認できます。このときカメラにアクセス可能なユーザ/グループを制限することもできます。

    ・ローカルカメラ設定
    http://www.htabata.com/img/MXS105/podcast/Capture_04.png
    ・Podcastプロデューサーに登録したカメラ
    http://www.htabata.com/img/MXS105/podcast/pdcast_admin03.png

    ◇Podcastの公開
     キャプチャが完了したら「Podcast キャプチャ」のウインドウで「公開」ボタンをクリックし、キャプチャしたデータをPodcastプロデューサーに転送します。このときワークフローを選択してタイトルと説明(省略可)を入力します。あらかじめいくつかのワークフローが用意されており、選択したワークフローによっては、イントロやウォータマークを追加することもできます。また
    ストリーミング用のワークフローも用意されています。実際にストリーミングを公開するには、あらかじめサーバ上でQuickTime Streamingサービスを開始しておきます。

    ・ワークフローの選択
    http://www.htabata.com/img/MXS105/podcast/Capture_05.png

     Podcastプロデューサーに転送されたデータはXgridを利用してエンコーディング処理が行われます。このとき「Xgrid Admin」を使用すれば処理状況を確認できます。エンコーディング処理が完了すると、pcastuserやpcastadminにE-mailで通知が届きます。pcastadminにはXgridでの処理状況もE-mailによる通知が送られます。場合によってはエンコーディング処理に失敗することもありますが、そんなときはXgridの処理状況をメールで確認することで原因を特定することができます。
     Mac OS X Serverでブログを使用している場合には、エンコーディング済みのデータが自動的にポストされます。ブログへのリンクは結果通知のE-mailに埋め込まれており、他にもiTunesでの購読用のリンクや、ダウンロード用のリンクが埋め込まれています。通知メールはデフォルトでは英語になっていますが、設定をカスタマイズすることで日本語の通知メールを送信することもできます。

    ・メールでの通知
    http://www.htabata.com/img/MXS105/podcast/mail_01.png
    ・ブログに自動ポストされたPodcast
    http://www.htabata.com/img/MXS105/podcast/blog_01.png

     以上がPodcastプロデューサーを利用したPodcastの制作方法です。Xgridを用意したりと他のサービスとの連携もありますので、なかなか簡単にはいかないところもありますが、設定を1つ1つ確実に行って行けば必ず成功するはずです。また、Mac OS X Server Snow Leopardでは2つの入力ソースをサポートするなどさらに機能が強化されたPodcast Producer 2が搭載される予定になっています。

     最後に実際にPodcastプロデューサーを使って作成したムービーを下記のURLにアップしておきました。このムービーでは最初にイントロムービーとタイトルが追加され、ムービーの本編にはQuartz Composer Filterを使ったエフェクト(アスキーアート)が適用されています。さらに画面右下には、アップルのロゴがウォータマークとして入っており、最後にExitムービーが追加されています。
     音声にはノイズのような音が入っていますが、これはサーバで別のムービーのエンコーディング処理の真っ最中にキャプチャをおこなったので、そのときのサーバのファンの音をひろってしまったものです。エンコーディング中はかなりCPUパワーを消費し処理には時間もかかりますので、その点は注意が必要です。

    ・Podcastプロデューサーで作成したムービー
    http://www.htabata.com/img/MXS105/podcast/089.mov
    次回へつづく 

                                

    小池邦人のCarbon視点でiPhone探求(2009/03/20)

    〜 Documentクラスを用意する 〜

    今回は、Modelオブジェクトのドキュメントファイルへの書き出しと読み込み処理を実装してみます。また、「しんぶんし 3」で、どのように画像ファイルを取り扱うのかも考えてみます。

    まずは、Modelオブジェクトのドキュメント処理のために、新しくDocumentクラスを定義します。Documentクラスのおもな仕事は、以下の3つとなります。

    ・新規でModelオブジェクト用の配列(NSMutableArray)を作成しておく。
    ・ファイルをアンアーカイブ(デコード)してModelオブジェクトへ代入する。
    ・全てのModelオブジェクトをアーカイブ(エンコード)しファイルへ保存する。

    つまり、ドキュメントの作成、ロード、セーブの3つの処理を担当するわけです。以下がDocumentクラスの定義(Document.h)となります。

    #import 
    
    @interface Document : NSObject
    {
       NSString              *do_path;    //  ドキュメントファイルパス
       NSMutableArray      *do_array;    //  モデルの配列
    }
    
    @property(nonatomic,retain)NSString            *do_path;
    @property(nonatomic,retain)NSMutableArray    *do_array;
    
    - (BOOL)create;    //  作成
    - (BOOL)load;      //  ロード
    - (BOOL)save;      //  セーブ
    - (NSString *)path;  //  ファイルパスを得る
    
    NSString *getDocumentPath( NSString *name );  //  ユーティリティ
    
    @end
    


    インスタンス変数は、ドキュメントのファイルパス(保存場所)を保存しておくためのNSString  *do_pathと、複数のModelオブジェクトを保存しておくための配列であるNSMutableArray  *do_arrayの2つをとりあえず用意します。両方ともretainプロパティとして定義しておきます。これによりアクセッサメソッドを作成しなくともドット(.)演算子経由でアクセスすることができます。メソッドは create、load、saveの3つと、ドキュメントのファイルパスを得るためのpathの4つです。最後のgetDocumentPath()は、iPhoneアプリ固有のファイル保存場所(Documentディレクトリ)を返すCルーチンです。

    Mac OS X用の一般的なCocoaアプリケーション(Documentタイプ)では、ドキュメントウィンドウをオープンするたびに、それに対応したDocumentオブジェクトがひとつ作成されます。そのため、複数のDocumentオブジェクトの管理を受け持つDocument Controllerクラスなどが別途用意されていました。しかしiPhone版の「しんぶんし3」では、ドキュメントはひとつしか扱いませんので、Document Controllerクラスを作ることはせず、その役割はSymmetryAppDelegateクラス(アプリケーション・デリゲート)に担ってもらうことにします。

    まずは、SymmetryAppDelegateのクラス定義(SymmetryAppDelegate.h)にインスタンス変数Document *ap_documentを追加ます。

    @class    Document;  //  先んじてクラス宣言しておかないとエラーになる
    
    @interface SymmetryAppDelegate : NSObject 
    {
       UIWindow                *window;
       UINavigationController  *navigationController;
       Document                *ap_document;    //  作成されるドキュメント
    }
    


    アプリケーション起動時に呼ばれるapplicationDidFinishLaunching:メソッドに、ドキュメントオブジェクトの作成とファイルの読み込み処理(アンアーカイブ)を追加します。対象となるソースファイルは、SymmetryAppDelegate.mです。ドキュメントの保存については、アプリケーション終了時に呼ばれるapplicationWillTerminate: メソッドに記述します。どちらもUIApplicationのデリゲートです。

    - (void)applicationDidFinishLaunching:(UIApplication *)application  //  起動時
    {
       if( ap_document=[[Document alloc] init] )  //  ドキュメント作成
       {
           if( [ap_document load]==NO )        //  ドキュメント読み込み
           {
               //  ファイルの作成や読み込みに失敗した場合(エラー処理)
           }
       }
       [window addSubview:[navigationController view]];
       [window makeKeyAndVisible];
    }
    
    - (void)applicationWillTerminate:(UIApplication *)application  //  終了時
    {   
       [ap_document save];    //  ドキュメントファイル保存
    }
    


    続いてDocumentクラスの実装(Document.m)です。ドキュメントの作成、ロード、セーブの3つのメソッドと、ひとつのCルーチンを記述します。ドキュメントファイルの名称は「Symmetry.archive」で固定します。

    #import "Document.h"
    
    @implementation Document
    
    @synthesize do_path,do_array;
    
    - (BOOL)create    //  ドキュメントの新規作成
    {
       BOOL  ret=NO;
    
       if( do_array=[[NSMutableArray alloc] init] )    //  モデル配列を作成
           ret=YES;
       return ret;
    }
    
    - (BOOL)load    //  ドキュメントファイルの読み込み
    {   
       BOOL      ret=YES;
       NSString  *path;
    
       path=[self pathDocument];  //  Symmetry.archiveファイルのパスを得る
       if( [[NSFileManager defaultManager] fileExistsAtPath:path]==YES )
       {                            //  ファイルが存在しているか?
           do_array=[[NSKeyedUnarchiver unarchiveObjectWithFile:path] retain];
                                   //  ファイルからdo_arrayt配列から読み込む
           if( ! do_array )          //  ファイル読み込み失敗
               ret=NO; 
       }
       else
           ret=[self create];  //  ファイルが存在しない場合はドキュメント新規作成
       return ret;
    }
    
    - (BOOL)save    //  ドキュメントファイルへの書き出し
    {
       BOOL  ret=NO;
    
       if( do_array )
           ret=[NSKeyedArchiver archiveRootObject:do_array toFile:[self path]];
                   //  do_array配列をアカーブ化しSymmetry.archiveファイルへ保存
       return ret;
    }
    
    - (NSString *)path    //  保存用のドキュメントファイルのパスを返す
    {       
       if( ! do_path )    //  既に設定済みならそのまま返す
           self.do_path=getDocumentPath( @"Symmetry.archive" );
                 //  ドキュメントファイル(Symmetry.archive)のパスを得る
       return do_path;
    }
    


    最後はドキュメントディレクトリ経由のパス名を得るためのgetDocumentPath()ルーチンです。このルーチンは画像ファイルのロードやセーブでも利用する予定ですので、pathメソッドから分離して用意しておきます。こうした処理において、インスタンス変数を扱わないのであれば、Cルーチンとして用意しておくと、どのオブジェクトからも呼び出し可能で便利です。

    NSString *getDocumentPath( NSString *name )
    {
       NSString    *path=nil;
       NSArray     *paths;
       NSString    *dir;
    
       paths=NSSearchPathForDirectoriesInDomains( 
                               NSDocumentDirectory,NSUserDomainMask,YES );
                               //  ドキュメントディレクトリーを含むリスト配列
       if( [paths count] > 0 ) 
       {
           dir=[paths objectAtIndex:0];      //  ドキュメントディレクトリそのもの
           path=[dir stringByAppendingPathComponent:name]; 
                                         //  ファイルパス名の作成(名前を追加)
       }
       return path;
    }
    


    次回は、画像ファイルの話です。画像ファイルは、Modelオブジェクトのドキュメントからは分離して別に保存します。登録一覧(UITableView)に画像を表示するためには、画像ファイルから小サイズ画像(UIImage)を作る必要もあります。

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

    〜 いま敢えて学ぶTerminalのイロハ(11) 〜

    ・シェルスクリプトをFinderから実行する
     これまでシェルスクリプトについて紹介してきましたが、1つ肝心なことを失念していました。作成したシェルスクリプトをどのように実行するか、Mac OS Xらしく実行するにはどうすればいいか、ということです。シェルスクリプトに関する知識のないユーザに配布する可能性を考慮し、いくつかのシチュエーションに分けて考えてみたいと思います。
     まず、Finderでの利用について。ファイルをダブルクリックすれば実行開始ということは、敢えて説明するまでもないMacユーザ共通の約束事ですが、シェルスクリプトは3つの条件をクリアしなければダブルクリックでは実行できません。
     1つは、ファイルの拡張子が「.command」であることです。この拡張子に変更しなければ、ダブルクリックでターミナルに処理を受け渡すことはできず、ターミナルが起動していない場合は起動後に実行、という処理もできません。
     もう1つは、改行コードです。Macintoshでは伝統的に、テキストファイルの改行コードを「CR」としますが、UNIXでは「LF」、Windowsでは「CR+LF」です。Terminal(正確にはインタープリタであるシェルの「bash」)は、改行コード「CR」と「LF」のファイルは正しく解釈できますが、「CR+LF」はエラーになります。シェルスクリプトを実行したとき、

    「/bin/sh^M: bad interpreter:」

    というエラーメッセージが表示された場合には、テキストエディタの改行コードが「CR」または「LF」に設定されているかどうか確認しましょう。

    ・chmodコマンドで実行権限を与える
     以上の作業により、シェルスクリプトをダブルクリックで実行できるようになりますが、「ファイル”XXX.command”は、適切なアクセス権がないため実行することができません」とエラーメッセージが表示されることがあります。この場合は、ファイルに「実行権限」を与える必要がありますが、エラーメッセージの指図通りFinderの「情報」ウインドウから実行権限を与えようとしても、期待どおりにはなりません。
     シェルスクリプトに実行権限を与えるには、Terminalから「chmod」コマンドを利用します。基本的な書式は以下のとおりで、オプション「+x」に続けて、シェルスクリプトのファイル名を引数として与えればOKです。これで、適切なアクセス権がない、と実行を拒否されることはなくなるはずです。

    - - - - -
    $ chmod +x filename.command
    - - - - -
    


    ・実行権限とは
     chmodコマンドの話が出ましたので、ファイルの「実行権限」についても説明しておきましょう。なお、ここでいう実行権限とは、TigerからサポートされたACL(Access Control List)レベルの話ではなく、Darwinの原型となったBSD UNIX時代から続く(POSIX標準の)ファイルアクセス権限に関する話ですので、念のため。
     ほとんどすべてのUNIX互換OSが採用するPOSIX準拠のファイルシステムでは、ファイル/フォルダには個別に「パーミッション」と呼ばれる情報が割り当てられます。このパーミッション情報は八進数で表現されますが、直感的にわかりにくいため、chmodなどのコマンドでは読み取り権限(r)、書き込み権限(w)、実行権限(x)という記号で表現されます。
     この情報は、Terminalから「ls」コマンドに「-l」オプションを付けた「ls -l」で確認できます。実行権限の有無は属性項目に「x」があるかどうか、つまり「x」があればシェルスクリプトとして実行でき、なければ実行できない、ということになります。
     前述の「chmod +x」は、引数に与えたファイルに実行権限を与えることを意味します。ちなみに、実行権限を剥奪したければ、オプションは「-x」です。読み取り権限(r)と書き込み権限(w)についても、同様に「+」と「-」で変更できます。ただし、自分が所有者でないファイルは作業対象にできないため、sudoコマンドを使い管理者の権限でchmodコマンドを実行(sudo chmod 〜)しなければなりません。

    - - - - -
    $ ls -l test.command
    -rwxr-xr-x  1 shinobu  staff  38  3 21 16:13 test.command
    - - - - -
    


    - - - - - -
    表:chmodコマンドで使うパーミッション関連の記号
    
    8進数 記号  意味
    = = = = = = = = = = = = = = = =
    0400  u+r 所有者に読み取りを許可する
    0200  u+w 所有者に書き込みを許可する
    0100  u+x 所有者に実行/検索を許可する
    0040  g+r 同一グループのユーザに読み取りを許可する
    0020  g+w 同一グループのユーザに書き込みを許可する
    0010  g+x 同一グループのユーザに実行/検索を許可する
    0004  o+r その他のユーザに読み取りを許可する
    0002  o+w その他のユーザに書き込みを許可する
    0001  o+x その他のユーザに実行/検索を許可する
    - - - - - -
    

    ◇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)2009 MOSA. All rights reserved.

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

    2009-03-17

    目次

    • りんご味Ruby         第43回  藤本 尚邦
    • 藤本裕之のプログラミング夜話   #156
    • 高橋真人の「プログラミング指南」  第154回

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

    前回に引き続き、Ruby+RubyCocoaを使って「CoreGraphicsによるPDFの描画」を記述するための簡易言語(DSL)を作っていきます。

    ■ CGContext をクラスとして定義

    まず、CoreGraphicsの描画コンテキストであるCGContextをRubyのクラスとして定義します。

     class CGContext
       def initialize(context)
         @context = context
       end
     end
    


    PDFのための描画コンテキスト CGPDFContext は、いわば CGContext の派生クラスと考えられますからそのように定義します。

     

    class CGPDFContext < CGContext   # CGContextの派生クラスとして定義
     end

    今回の描画言語の対象は、とりあえず PDF としていますが、CGBitmapContextや CGGLContext についても同じように扱うことが出来るはずです。

    ◇ オブジェクトを初期化する initialize メソッド

    ここで、Ruby の initialize メソッドについて簡単に説明しておきましょう。Rubyでは、オブジェクトを初期化するためのインスタンスメソッドであるinitialize を定義しておくと、オブジェクトが生成されたときに暗黙に呼び出されます。インスタンスオブジェクトの生成には、Class#new を呼び出します。new に渡された実引数がそのまま initialize の実引数になります。

    c = CGPDFContext.new(context)

    というプログラムは:
     (1) CGPDFContextクラスのオブジェクトを生成して
     (2) 生成したオブジェクトに対してinitialize を呼び出し
     (3) そのオブジェクトに c という名前をつける

    というような意味になります。初期化時に引数として渡された描画コンテキストは、オブジェクト内部のインスタンス変数として @context という名前がつけられています。

    ◇ 描画メソッドの自動定義

    次に、CGContext をレシーバ的に扱うCoreGraphicsの関数をインスタンスメソッドとして定義しましょう...と言っても、前回 irb を使って調べたように、該当する関数は大量に存在します。それを手でひとつひとつ定義していくのは大変ですから、正規表現や define_method を使って自動的に定義します。

    この自動定義の実行を、CGContextの種類 (PDFとかBitmap とか) を引数にとるprivate なクラスメソッド context_type として定義することにします。すると以下:

     class CGContext
       context_type nil    # "CGContext"で始まる関数のメソッドを自動生成
       ...
     end
    
     class CGPDFContext < CGContext
       context_type :PDF   # "CGPDFContext"で始まる関数のメソッドを自動生成
     end
    
     class CGBitmapContext < CGContext
       context_type :Bitmap
     end
    


    のように、CGContextの派生クラスの定義中で描画コンテキストの種類を宣言するだけで、そのコンテキストに関連する関数のインスタンスメソッドが自動的に定義されるようになり、プログラムの見映えがよくなります。

    では、context_type の実装にとりかかります。手順は、おおよそ以下のようなものになります:

    ・OSX.methods ですべてのメソッド名(関数名)を取得する
    ・それぞれの名前について...
    ・"CGContext" または "CGなんとかContext" で始まる名前なら
    ・名前から "Context" より後の部分を取り出し
    ・最初の文字を小文字にした名前(文字列)を作る
    ・元の名前の関数を呼び出すメソッドを、生成した名前で定義

    以下が CGContext.context_type の実装です:

    -------------------------- pdf_drawer.rb (未完成) --
    class CGContext
     class << self    # この2行はprivateなクラスメソッドを定義するための
       private        # おまじないだと思ってください
    
       def methodnize(original_name, name)
         method_name = name[0].chr.downcase + name[1..-1]
         define_method(method_name) do |*args|
           OSX.__send__(original_name, @context, *args)
         end
       end
    
       def context_type(type)
         pattern = / ACG#{type}Context(.*) Z/
         OSX.methods.each do |func_name|
           matched = pattern.match(func_name)
           methodnize(func_name, matched[1]) if matched
         end
       end
     end              # end of class << self
     ...
    end
    ----
    


    この中身については次回見ていくことにします。

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

     前回も書いたように,たとえ建前であっても「受託開発」として客先に行って仕事をしていた場合……悪く言えば「抱き合わせ販売」だけど,スキルの劣る新人とかをチームに入れ,彼または彼女を現場で教育しながら仕事をこなして行く,というということがよくあった。クライアントの側としても,本音は「十分なスキルを持ったニンゲンだけを送って欲しい」だったかもしれないが,表立ってそれに文句を言うことは(あんまりひどけりゃ別だけど……ひどい実例も知らないわけぢゃないしね)差し控えるという雰囲気があった。

     が,派遣法が成立すると,徐々にそういうことが難しくなった。なにしろ名実ともに派遣するのは「個人」になったため,クライアントに「●●くんは優秀だからいいけど★★くんは要らない」と言われるようになっちゃったのだ。

     確かに建前としては「ウチの会社から御社に派遣する人員はみんな一人前の仕事をこなせるスキルを持ったプログラマ,あるいはSEです」というものだからクライアントの言い分ももっともなんだが,実態として大卒,高卒を問わず入ったばかりの新人をそのレベルまで「育て上げる」役割を「現場」まかせにしてきたため,最初から「現場」に即戦力を求められてしまうとツラいわけ。

     いや,これはオレ自身にも言えることで,もしオレがこの仕事を始めたのが1983年ではなく1993年だったら,プログラマとして現在持ってるスキルを(現在のオレがそれほどたいしたスキルを持ってるのかと言われれば「おうよ」と胸を張れるわけぢゃないけどさ)身につけることができたか,つまりは2009年の現在もプログラマとして飯が食えていたかどうかココロもとない。

     いろいろウラミツラミもないわけぢゃないが(笑),やはり当時の上司,先輩達のご指導ご鞭撻,同輩達との切磋琢磨に負うところは甚大であり,最初に送り込まれた会社であの時点でのスキルをチェックされていたらと思うと「そりゃヤバいだろ」と思うのね。なにしろオレは人文学部の出身だし,コンピュータというものを実際に触ったのは就職してからなんだから,一応入社後1ヶ月弱の研修はあったとは言え,今のオレに言わせれば「ズブズブの素人」だったのである。

     まぁオレのことはいいや。問題は,そういう世の中の変化に派遣する側がどう対応したかである。

     大きく分けて二種類の会社があった。第一はそういう口入れ屋みたいな人貸し業務を減らし,お題目どおりの「受託開発」をメインにしていこうというもの。当時のソフトウェア会社には「今は受託でやっていてもゆくゆくは自社開発の商品を世に問いたい」と考えている経営者がかなりいたので,その後成功したかどうかはともかくこっち方面に舵を切った企業はかなり多かった。

     そして第二のミチが,天下晴れて法律で認められた「人貸し業務」専門になろうというもので,こういう企業は上で指摘した問題をもっともシンプルなやり方,つまり「自社でこれから育てなければならないような,スキルのないやつは雇わない」というやり方で解決した。「スキルのあるヒト,寄っといで。ウチの信用で高い報酬が得られるところに紹介するよ」というわけだ。……もちろんピンハネする額もそれなりに高いのだが,スキルの高いプログラマが自分を売り込む渉外活動にも長けているわけではないからね。

     日本のソフトウェア業界の不幸(違う意見のヒトもいるかも知れないが,マクロに観てこれは不幸だったとオレは思ってる)は,前者よりも後者を選んだ企業のほうがビジネスとして成功したこと,言い換えれば法律がどんどん彼らの成功を後押ししたことである。一時,偉いヒョーロンカの人たちとかが「日本人は優秀なのにマイクロソフトみたいな企業がなぜ生まれない」と嘆いてみせていたが,実力的にマイクロソフトみたいなことが出来るかも知れない人材をどんどんスポイルしていくほうが利潤を楽に上げられる仕組みだったのだ。

     そして90年代,「バブルの崩壊」と「インターネットの普及」という2つのパラダイムシフトがソフトウェア業界を襲った。
    (以下次回 2009_02_26)

                           

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

    これから始めようとする人へ(5)

     皆さんこんにちは、高橋真人です。
     前回まで、「マシン語から始めて徐々に高いレベルに向かって」ということでお話をしてきました。
     しかし、高水準言語の説明に入ってすぐに言うのもナンなのですが、この先も「少しずつ高いレベルに向かって」というのは、あまりうまいやり方ではありません。何故なら、低水準言語は基本的にマシン語に準ずるものであって、これらはIntelであるとかIBMであるとかのチップメーカー(CPUを出しているメーカー)が定義するものだからです。あくまで私たちの書くコードがいずれ
    かのチップメーカーのCPUを対象とする限り、アセンブリ言語を使うにしても「メーカーの決めたやり方」を踏襲するしかないのです。
     いくつかのプログラミング言語を習得してくると、「こういうふうに書けたらなぁ」と、言語仕様に対しての要望が出てくる方もおいでです。しかし、このような「夢」は、低水準言語に対してはまず不可能と考えていいです。自分でCPUを設計するならば別ですが。ですが、高水準言語であればその可能性はぐっと高まります。自分で新しい言語を作ってしまえばよいからです。
     これからプログラミングを学ぼうという人に対して「自分の言語を作ってしまえ」もないものですが(笑)、それでも、将来の目標としてそのようなものを掲げるのは充分にアリなのかもしれません。たとえば、Ruby on Railsの功績で今では世界的にも知名度の上がった日本発のスクリプト言語であるRubyですが、作者のまつもとゆきひろさんは「プログラマとしての自分を満足させる
    ような自分自身の言語を作りたいと思った」ことをRubyを作った動機として挙げています。
     まつもとさんは、自らを「プログラミング言語オタク」と称するほどたくさんの言語を使ってきて、それでも本当に自分に満足の行く言語に巡り会えなかったため、自分で作ることにしたとのことです。最初は本当に自分自身だけで使うつもりで、公開する気もなかったのだそうです。
     これを読まれている皆さんが自分用に言語を作るかどうかは別にしても、「いざとなったら自分で作ることも可能だ」と聞けば、プログラミング言語に対する見方は、今までとは違ったものになるのではないでしょうか。
     ウィキペディアで「プログラミング言語一覧」という項目を見ますと、全部で100近くの言語が載っています。「手続き型言語」としてアセンブリ言語と機械語も含まれていますが、この二つを除けば、残りはすべて高水準言語ということになります。
     これだけ多くのプログラミング言語が生まれてきた背景には様々な事情やニーズがあったのでしょう。それに、ここに載っているのは世の中に存在するプログラミング言語のごく一部ではないかと思います。きっとこの世には名前すらないものも含めて数えきれないほどの「プログラミング言語」が存在しているでしょう。

     連載の第152回でも触れたように、私がプログラミングを学び始めた当時は高水準言語を語る場合に「コンパイラとインタープリタ」という分類がよく使われていました。この分類は今でも意味がないわけではないのですが、同時に、当時ほど重い意味を持たないことも事実です。
     確かに、コンパイルして実行専用の形態になったものと、何らかの形で「内部変換機構」が走りながら動作する形のもので比較すればどちらが速度的に有利なのかは議論の余地がないかもしれません。しかし「速い」は今の時代では実行時のスピードだけを意味するものではありません。たった一回限り必要なデータ処理を行うのに、わざわざ時間をかけてCのような言語でプログラムを
    作るより、表現力の高いスクリプト言語でさらっと書いてしまえば、トータルでかかる時間はずっと短時間で済むという局面はたくさんあります。
     また、ネットワーク処理のようにプログラム自体の処理速度よりも、データが到達するのを待つための時間が比率として大きいものであれば、プログラムだけが速くても、さほどメリットはないからです。たとえば、コンパイル言語で作った0.01秒で動作するプログラムとスクリプト言語で作った1秒かかるプログラムがあった場合、処理の速度差は1:100ですが、これらが、10秒間のネットワークトラフィックを伴うプログラムであった場合、両者のトータルに要する時間は1:1.1程度まで縮まってきます。
     現代のように、パソコンの用途の大半がネットユースであることを考えると、純粋に処理速度が速いだけではなく、日々変化するユーザーの要望に応じて迅速に書き換えが行える表現力の多彩なスクリプト言語の方が適した場面も多いのです。事実、商用に使われているシステムにおいても、Webの場合にはコンパイル系のものはJavaぐらいであって、あとはPHPとかPerlとかRubyのものが大半を占めているようです。

     もっとも、だからといってコンパイル言語は不要なのかと言えば決してそんなことはありません。Webサーバーの多くを占めるApacheやRuby、PHP、Perlなどのスクリプト言語自体はCやC++で書かれていますし、恐らくこの連載を読まれている方のほとんどが望んでいるiPhoneプログラミング言語は今のところC/Objective-C/C++以外の選択肢は実質的にないと言えます。Macに限って言えば、RubyCocoaやPyObjC、AppleScript Studioといった言語を使ってもCocoaア
    プリケーションを作ることは可能ですが、仮にこれらの仕組みを使うにしても、あらかじめ用意されていないことをするためには、Cocoaのネイティブ言語であるObjective-Cの知識も必要になってくると思います。
     そんなわけで次回はObjective-Cについて考えてみたいと思います。

    ◇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)2009 MOSA. All rights reserved.

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

    2009-03-10

    目次

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

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

    〜「Podcast プロデューサー」編〜

     前回はPodcastプロデューサーを稼働させるためにXgridの設定を行いました。今回はいよいよPodcastプロデューサーを稼働させてみたいと思いますが、あといくつかサーバ上で必要な設定がありますのでその手順を説明していきましょう。Xgridが設定済みの場合、残りの手順は次のようになります。

    1. メールサービスの設定
    2. ユーザ登録
    3. Webサービスの設定
    4. グループの設定
    5. Podcastプロデューサーの設定

     またサーバ上ではOpen Directoryのマスターが稼働しKerberosが利用可能な状態にあるものとします。Open Directoryのマスターを正しく構築するには、あらかじめDNSの正引きと逆引きができるようになっている必要があります。それでは手順を1つ1つみていきましょう。今回の設定はすべて1台のサーバ上で行うものとします。設定には「サーバ管理」を使用し次のサービスを利用します。

    ・Podcastプロデューサーに必要なサービス
    DNS、Open Directory、Podcastプロデューサー、Web、Xgrid
    ※QuickTime Streamingサービスを組み合わせる場合も考えられます

    ◇メールサービスの設定
     Podcastプロデューサーはサーバ上での処理が完了するとメールで通知を行いますので、まずはメールサービスを設定します。実際にメールサービスを運用するとなると設定可能な項目は色々とありますが、最低限必要な設定はSMTPの許可です。あとはデフォルトの設定のままでもとりあえず動作確認は可能になります。
     SMTPを許可するには「サーバ管理」でサーバに接続し、コンピュータとサービスのリストから「メール」を選択し、「設定」>「一般」から「SMTPを許可する」をチェックして設定を保存します。あとは画面左下の「メールを開始」ボタンをクリックすればメールサービスが起動します。

    ・メールサービスの設定
    http://www.htabata.com/img/MXS105/podcast/mail_admin01.png

    ◇ユーザ登録
     「ワークグループマネージャ」を使用してPodcastプロデューサーで使用する以下の3つのユーザをOpen Directory上に登録します。

    ・Podcastプロデューサー用のユーザ
     pcastadmin(管理者)
     pcastuser
     pcastxgrid

     pcastadminは管理用のユーザ、pcastuserは「Podcastキャプチャ」を操作するときに使用するユーザです。またPodcastプロデューサーからXgridにアクセスするためのユーザとしてpcastxgirdユーザを登録します。
     メールでの通知を受け付けるために、pcastadminとpcastuserではメールを有効にしておきます。

    ・Podcastプロデューサー用のユーザ
    http://www.htabata.com/img/MXS105/podcast/users_wgm01.png

    ◇Webサービスの設定
     作成したPodcastを公開するためにWebサービスの設定を行います。ここではブログでPodcastを公開するための設定も行ってみます。
     まず「サーバ管理」で「Web」サービスを選択してツールバーの「サイト」をクリックしデフォルトのサイトを選択します。次に「Webサービス」を選択してグループのサービスから「Wikiとブログ」をチェックし設定を保存します。あとは画面左下の「Webを開始」をクリックすればWebサービスの設定は完了です。

    ・Webサービスの設定
    http://www.htabata.com/img/MXS105/podcast/web_admin01.png

    ◇グループの設定
     グループは「ワークグループマネージャ」でも設定できますが、Leopardで新しく追加された「ディレクトリ」(iCalサービスで使用しましたね)を使って設定をしてみましょう。サーバ上で直接設定してもかまいませんし、クライアントからネットワーク経由で設定することもできます。この「ディレクトリ」はデフォルトでKerberos認証を使用しますが、「環境設定」メニューから認証方式を変更することもできます。Open Directory上のデータを編集しますので、ディレクトリ管理者として認証します。
     「ディレクトリ」を起動したら、あらかじめ登録したPodcastプロデューサー用のユーザが表示されていることを確認します。次に画面左下の「+」ボタンをクリックして「新規グループ」を選択し、「Podcasts」という名前のグループを作成します。グループのメンバーにはpcastadminとpcastuserを登録します。「所有者」画面ではpcastadminをオーナーとして設定し、「サービス」画面では「Wikiとブログ」を選択して保存します。

    ・Podcastsグループの設定
    http://www.htabata.com/img/MXS105/podcast/group_directory01.png
    http://www.htabata.com/img/MXS105/podcast/group_directory02.png
    http://www.htabata.com/img/MXS105/podcast/group_directory03.png

     グループの設定が完了したらPodcastブログの設定も行っておきましょう。Webブラウザを使ってhttp://<サーバのアドレス>/groups/podcastsにアクセスしpcastadminユーザでログインします。画面右側のメニューから「管理機能」>「設定」をクリックし編集(鉛筆のアイコン)ボタンをクリックしてPodcastブログを選択し、iTunesカテゴリにカテゴリ名を入力して保存します。

    ・ブログの設定
    http://www.htabata.com/img/MXS105/podcast/blog01.png

    ◇Podcastプロデューサーの設定
     いよいよPodcastプロデューサーの設定です。「サーバ管理」で「Podcastプロデューサー」サービスを選択し「設定」>「一般」画面を表示します。作業用のフォルダとして「共有ファイルシステム」を設定します。ここで指定したフォルダはPodcastキャプチャやXgridがファイルをアップロードするのに使用します。指定したフォルダにはさらにサブフォルダが自動作成されますので、なにか専用のフォルダを作成しておくのがよいでしょう。
     次に「Xgirdコントローラ」にXgridコントローラのアドレス(今回の場合は同一サーバ)を入力し、Xgirdのユーザとしてpcastxgridを指定しpcastxgridのパスワードを入力して設定を保存します。
     「一般」の設定の次は「プロパティ」の設定になります。「プロパティ」の設定画面では次のパラメータを設定します。

    ・プロパティ設定
    Administrator Short Name:pcastadmin
    Group Short Name:pocasts
    Group Administrator User:pcastadmin
    Group Administrator Password:pcastadminのパスワード

     またApproval Email List、Audience Email Listにそれぞれ通知を受け取るメールアドレスを入力しておきます。

    ・Podcastプロデューサーの設定
    http://www.htabata.com/img/MXS105/podcast/pdcast_admin01.png
    http://www.htabata.com/img/MXS105/podcast/pdcast_admin02.png

     これらの設定が完了すれば設定を保存し、画面右下の「Podcastプロデューサーを開始」ボタンをクリックすればすべての設定が完了します。今回紹介した手順はPodcastプロデューサーのマニュアルをもとにしていますが、使用するユーザやグループの名前などは自由に変更してもよいでしょう。

    ・Podcastプロデューサーのマニュアル
    http://images.apple.com/server/macosx/docs/Podcast_Producer_Admin_v10.5.pdf

    それでは次回はPodcastプロデューサーを使って実際にPodcastを制作してみたいと思います。
    次回へつづく                             

    小池邦人のCarbon視点でiPhone探求(2009/03/06)

    〜 iPhoneでもNSCodingプロトコルのお世話に 〜

    今回から本格的にモデルコントローラクラスを実装していきます。まずは、モデルのアーカイブ化を行うために、NSCodingプロトコルに準拠したencodeWithCoder:とinitWithCoder:の2つのメソッドを用意することから始めましょう。

    以前に定義したModelクラスをもう一度見てみます。スーパークラスとして定義されているNSObjectのさらに右側に と表記されていますが、これが、このクラスがNSCodingプロトコルに準拠していることを示しています。

    @interface Model : NSObject 
    {
       NSString        *md_name;
       NSString        *md_type;
       UIImage         *md_image;
       CGRect          md_rt;
       NSUInteger      md_flag;
       NSInteger       md_kind;
       NSInteger       md_para;
    }
    


    NSCodingプロトコルに準拠させるためには、ModelクラスにencodeWithCoder:とinitWithCoder:の両メソッドを実装する必要があります。これは、Mac OS X用のCocoaアプリケーションとまったく同じです。具体的には、ModelオブジェクトからNSDataへ変換するアーカイブ処理(エンコード)と、NSDataからModelオブジェクトへ戻すアンアーカイブ処理(デコード)の両方を実現することになります。

    まず最初は、encodeWithCoder:メソッドです。Modelクラスのインスタンス変数それぞれに対してエンコード処理を行い、6つすべてに実行すれば処理は終了となります。エンコード対象のクラスにNSCodingプロトコルが実装されていれば、NSCoderクラスのencodeObject:メソッドを使うことができ、対象オブジェクトのencodeWithCoder:メソッドをが呼び出されることで処理が芋ズル式に進みます。この処理は、ドキュメント(ファイル)を外部記憶装置に保存する時に実行します。つまり、NSMutableArrayに保存されているModelオブジェクトがアーカイブ化される時に、このメソッドが逐次呼び出されるわけです。

    - (void)encodeWithCoder:(NSCoder *)coder
    {
       [coder encodeObject:md_name];
       [coder encodeObject:md_type];
       [coder encodeValueOfObjCType:@encode(CGRect) at:&md_rt];
       [coder encodeValueOfObjCType:@encode(NSUInteger) at:&md_flag];
       [coder encodeValueOfObjCType:@encode(NSInteger) at:&md_kind];
       [coder encodeValueOfObjCType:@encode(NSInteger) at:&md_para];
    }
    


    ここで注意しなければいけない点は、UIImageオブジェクトはエンコードしていないことです。今回インスタンス変数のUIImage *md_imageは、UITableViewへ画像サムネイル(小画像)を表示するために用意したものです。しかし、それを一緒にドキュメントへ保存することはしません。ドキュメントをロードした時点で、別の個別ファイルから逐次サムネイルを読み込む仕組みにします。どちらにしろ、UIImageクラスはNSCodingプロトコルに準拠していないので、この方法でUIImageオブジェクトをアーカイブ化することは無理なのです。

    あるクラスがNSCodingプロトコルに準拠しているかどうかを判断するには、そのクラスが定義されているヘッダファイル(UIImage.h)を見てみます。すると、クラス定義の@interface行に、対応しているプロトコル名が列記されていることが分かります。例えば、NSString.hであれば…

    @interface NSString : NSObject 
    


    と記載されています。しかし、UIImage.hの方は以下の様になっています。

    @interface UIImage : NSObject

    つまりNSStringクラスには、NSCopying、NSMutableCopying、NSCodingの3つのプロトコルが実装されていますが、UIImageクラスの方には、対応プロトコルがひとつも無いことを示しています。

    整数(NSIntegerやNSUInteger)や構造体(CGRect)などの非オブジェクトのエンコードには、encodeValueOfObjCType:at:メソッドを使います。メッセージとして渡す@encode()は、エンコードされた内容(種類)をC文字列で返すコンパイラ指示子です。例えば、@encode(NSInteger)なら”i”に、@encode(float)なら”f”となります。構造体の@encode(CGRect)の場合には、”{?=ffff}”(4つの浮動小数点)というC文字列となります。@encodeには、sizeof()演算子の引数として使用できる任意の型を指定できるわけです。

    続いて、デコードのためのinitWithCoder:メソッドです。 こちらも、NSCodingプロトコル準拠のオブジェクト(NSStringなど)については、NSCoderクラスのdecodeObject:メソッドを使います。そうでない整数等は、decodeValueOfObjCType:at:メソッドを使いデコードを実現します。

    - (id)initWithCoder:(NSCoder *)coder
    {
       if( self=[super init] )
       {
           self.md_name=[coder decodeObject];
           self.md_type=[coder decodeObject];
           [coder decodeValueOfObjCType:@encode(CGRect) at:&md_rt];
           [coder decodeValueOfObjCType:@encode(NSUInteger) at:&md_flag];
           [coder decodeValueOfObjCType:@encode(NSInteger) at:&md_kind];
           [coder decodeValueOfObjCType:@encode(NSInteger) at:&md_para];
    
           if( [md_name length] )
           {
               //  ここで画像をサムネイルへ読み込む処理がを行う。
           }
       }
       return self;
    }
    


    この時、デコード順序がエンコード順序と違ってしまうと処理は正しく行われませんので、くれぐれも注意しましょう。ドキュメント読み込み時に同時に実行したい逐次処理は、このルーチン内で行うと便利です(エラー処理は少々難ありですが…)。今回の場合であれば、画像フィルを読み込みサムネイル用のUIImageを作成する処理がそうです。

    今回の方法でドキュメントのセーブとロードを実行すると、後からドキュメントフォーマットを変更するのが難しくなります。そうした事態を考慮し、先んじてModelオブジェクトのインスタンス変数に将来利用しそうなオプションパラメータ(リザーブ)を用意しておくのも手です。また、ドキュメントフォーマットがバージョンアップされることを考慮し、どこか別ファイル(環境設定
    ファイルなど)にドキュメントのバージョン番号も保持しておいた方が良いでしょう。

    ところで、Modelクラスのインスタンス変数はプロパティ宣言されています。プロパティの「属性」が(retain)であるmd_nameとmd_typeのデコード値の代入は、以下の様にselfにドット演算子でつなげて記述します。

    self.md_name=[coder decodeObject];
    self.md_type=[coder decodeObject];
    


    これにより、コンパイラが用意したアクセッサメソッド経由で値を代入したのと同じ意味となります。 これを以下の様にダイレクトに代入してしまうと、得られたNSStringがautoreleaseされますので、ある時点でエラーが発生しアプリケーションが落ちます。この記述の場合には自分でretainすることが必要です。くれぐれも注意いたしましょう!

    md_name=[coder decodeObject];
    md_type=[coder decodeObject];
    


    また、ModelクラスのスーパークラスはNSObjectなので、先んじて以下の様な処理を実行していますが…

     if( self=[super init] )

    もし、このスーパークラスがNSObjectではなくNSCodingプロトコルに準拠した別のクラスであれば、上記の部分は以下のように書き換える必要があります。こちらも注意が必要です。

     if( self=[super initWithCoder:coder] )

    次回は、Modelオブジェクトのドキュメント(ファイル)への書き出しと読み込み処理を実装してみます。また、「しんぶんし 3」で、どのように画像ファイルを取り扱うのかも考えてみたいと思います。

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

    〜 いま敢えて学ぶTerminalのイロハ(10) 〜

    ・お勧め書籍はコレ
     シェルスクリプトの使い方は、前回説明した程度の対症療法的な知識で足りますが、自分で書こうとなると体系的な知識が必要です。Web上にそのようなリソースがあるかもと思い、方々探し回りましたが、見つかるのは書籍の内容のコピーばかりで、量的にも満足できるものは見当たりませんでした。
     こういった場面では、やはり書籍の力に頼らざるをえません。以下に挙げる書籍は、bashの機能およびBシェル(sh/bash)のシェルスクリプトについて、体系的に学習するに十分な内容を持っています。必ずしもMac OS Xをターゲットにしてはいないため、システム関連の話(/etcディレクトリ以下にある設定ファイルの話など)を自力で置き換えられる程度の知識は必要ですが、当て処もなくWebを彷徨うよりは時間の節約になること請け合いです。

    1. UNIXシェルスクリプトコマンドブック
    山下哲典 著
    発売:ソフトバンククリエイティブ
    ISBN:978-4-7973-3063-2
    税込2,310円(税抜2,200円)

     シェルスクリプトのリファレンスとして有用な1冊です。480というページ数もさりながら、項目ごとに豊富なサンプルが掲載されているので、目的の処理にすばやくたどりつくことができます。解説も懇切丁寧、bashよりも「sh」をターゲットにしているため、普遍的なシェルスクリプトの文法/知識が身につきます。この内容とボリュームで税込2,310円は、かなり買い得感があるのではと思います。

    2. bashクックブック
    Carl Albing他著/クイープ 訳
    発売:オライリー・ジャパン、オーム社
    ISBN:978-4-87311-3760
    税込4,410円(税抜4,200円)

     640ページにもわたる大著ですが、実例が豊富に掲載されています。どのようなプログラミング言語でも、他人が書いたサンプルコードというものは参考になるものですが、この書籍も同様に「習うより慣れろ」とでもいわんばかりに、これでもかという量の「レシピ」が掲載されています。「パイプラインでの検索」や「数値のリストの合計」、「多数のファイル名の変更」などのオーソドックスなものから、「データファイルからCSVへの変換」といった実用性の高いものまで、価格に見合う価値はあるのではないでしょうか。

    3. 入門bash 第3版
    Cameron Newham 著/クイープ 訳
    発売:オライリー・ジャパン、オーム社
    ISBN:978-4-87311-254-1
    税込2,940円(税抜2,800円)

     bash解説本の定番「入門bash」の第3版です。bash 3.xのシェルとしての機能、シェルスクリプトインタープリタとしての機能について、体系立って解説されています。今年2月にbash 4.0がリリースされたため、バージョンとしては1つ前になりましたが、Mac OS X Leopardに収録されているbash(v3.2.17)には十分です。基本的な操作方法から各種カスタマイズ、さらにはシェルスクリプトの書き方も1冊でカバーしているという意味で、最初に選ぶ1冊としてはちょうどいいかもしれません。

     それでも書籍の購入に躊躇してしまう場合には、こちらのサイトがお勧めです。どちらも、大学の教材として作成されたドキュメントのようですが、それだけに平易に書かれているため理解しやすいと思います。書籍を購入する前に一読する価値はあるはずです。

    1. /bin/shプログラミング入門
    http://freebooks.info.nara-k.ac.jp/archive/ShellProgramming/index.html

    2. Bシェルのスクリプト
    http://www.wakhok.ac.jp/~maruyama/Unix92/shell2/shell2.html

    ・手始めに「変数」を理解する
     RubyやPythonのようにモダンな機能は備えていませんが、シェルスクリプトは体系立った文法を持つプログラミング言語です。なにか書こうと思い立ったときには、やはり基本構文の理解から始めることが王道でしょう。となると、最初にマスターすべきは「変数」と「ファイル」、「条件式」と「ループ処理」の扱い方になるでしょうか。順を追って話を進めるとして、まずは変数から始めてみます。
     シェルにおける変数は、「シェル変数」と「環境変数」の2種類があります。どちらもシェルおよびシェルスクリプトで設定/参照できますが、シェル上でのタスク(ジョブ)が終了した時点で内容が消えてしまう前者に対し、後者は終了後もシェル上に存在します(その環境変数を定義したプロセスが終了されれば消えます)。ローカル変数とグローバル変数の関係に似ていますが、プログラムが実行されているかどうかにかかわらず内容が保持されるという意味で、環境変数はよりシステムに近い存在といえるでしょう。
     シェル変数を定義する方法ですが、Bシェル(sh/bash)では以下の要領で記述します。たとえば、シェル変数「dummy」に「MOSA」という文字列を代入し、dummyの内容を標準出(ターミナルの画面)へ書き出すスクリプトは以下のとおりです。

    - - - - -
    #!/bin/sh
    dummy="MOSA"
    echo $dummy
    - - - - -

     この場合、シェル変数として定義していますから、シェルスクリプトの終了と同時に「dummy」の内容は失われます。シェルスクリプト実行後に、シェルから直接「echo $dummy」と実行しても、なにも表示されないはずです。

     次回は、今回説明しなかった変数の参照方法と、環境変数の使い方について説明する予定です。

    ◇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)2009 MOSA. All rights reserved.

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

    2009-03-03

    目次

    • りんご味Ruby         第42回  藤本 尚邦
    • 藤本裕之のプログラミング夜話   #155
    • 高橋真人の「プログラミング指南」  第153回

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

    DSL(Domain-Specific Language=ドメイン固有言語)というのは、ある特定の分野(domain)について記述しやすいように設計された言語のことです。Rubyそのものは汎用のプログラミング言語ですが、その上にシームレスにDSLを積み上げ・構築しやすいのがRubyの良いところでもあります(後述する参考リンク先も参照のこと)。

    今回は、Ruby+RubyCocoaを使って「CoreGraphicsによるPDFの描画」を記述するための簡易言語を作ってみることにします。

    Leopard の/Developer/Examples/Ruby/RubyCocoa/Scriptsに、circle.rb というサンプルプログラムが入っています。これは、CoreGraphics を使ってPDFファイルを描画生成するものです。

    -------------------------- circle.rb --
    require 'osx/cocoa'
    include OSX
    
    path = "circle.pdf"
    url = CFURLCreateFromFileSystemRepresentation(nil, path, nil)
    rect = CGRect.new(CGPoint.new(0, 0), CGSize.new(612, 792)) # Landscape
    pdf = CGPDFContextCreateWithURL(url, rect, nil)
    
    CGPDFContextBeginPage(pdf, nil)
    CGContextSetRGBFillColor(pdf, 1.0, 0.0, 0.0, 1.0)
    CGContextAddArc(pdf, 300, 300, 100, 0, 2 * Math::PI, 1)
    CGContextFillPath(pdf)
    CGPDFContextEndPage(pdf)
    CGContextFlush(pdf)
    ----
    


    描画コンテキスト(上記プログラムでは変数pdfに格納)を生成して、そのコンテキストに対して「何かを描画」する、というのがCoreGraphicsによる描画の基本的な流れです。上記のようにPDF描画の場合には、ページの始めと終わりを明示して、その中に「何かを描画」します。この「何かを描画」する以外の部分は、おおよそ定型的な処理になりがちですから、そういうところを隠蔽して「何を描画するか」という点にプログラミングの焦点を絞るためのシンプルなPDF描画言語を作ってみましょう。上の circle.rb を以下のように記述できるようにすることを目標とします。

    require 'pdf_drawer'
    
    PDFDrawer.file "circle.pdf", [0, 0, 612, 792] do |pdf|
     pdf.page do
       pdf.setRGBFillColor(1.0, 0.0, 0.0, 1.0)
       pdf.addArc(300, 300, 100, 0, 2 * Math::PI, 1)
       pdf.fillPath
     end
    end
    


    このDSLでは、CoreGraphicsのコンテキストに対する描画の関数群をコンテキストに対するメソッドの呼出として扱います。元々の関数名の先頭にはレシーバの型を意味する”CGContext”がついていますが、メソッド化するのであれば、これは必要ないので、メソッド名からは取り除きます(例えば、CGContextAddArcに対応するメソッド名を addArc にする)。また、BeginPageとEndPageに挟まれる描画手続き列はブロックで扱うことにします。

    ■ 下準備 — CoreGraphics関数名を抽出する正規表現パターンを考える

    CoreGraphicsの描画関数はたくさんあります。それらひとつひとつを人力でメソッド定義するのは大変ですから、必要な関数名を抽出して、define_methodを使って動的にメソッド定義することにします。まず、このあたりの見当をつけるための下準備として、irb コマンドを使って CoreGraphics の関数名の見つけ方やプログラムによる名前の加工の仕方を調べてみましょう。

    RubyCocoaをロードすると、CoreGraphicsの関数は全てOSXモジュールのメソッドとして組み込まれます。Rubyには、あるオブジェクトが応答できるすべてのメソッド名の配列を返す Object#methods というメソッドがあります。Object#methodsの結果に対して、正規表現によるパターンマッチを使ってCoreGraphicsの関数名を絞り込んでいきます。

     $ irb --simple-prompt
     >> require 'osx/cocoa'
     => true
     >> ary = OSX.methods.grep(/ ACG/)
     => ["CGGetEventTapList", "CGEventSourceButtonState",... 以下略 ]
     >> ary.size
     => 606
    


    Enumerable#grep は、パターンにマッチしたEnumerableの要素を配列で返すメソッドです(ブロック付きの場合は配列化するかわりにブロックが呼ばれます)。

    / ACG/ は、Rubyの正規表現オブジェクトのリテラル表記です。” A”は「文字列の先頭」をあらわしますから、これは「”CGで始まる文字列」にマッチするパターンです。つまり、OSX.methods.grep(/ ACG/) は、「名前の先頭が “CG” で始まるメソッド名」の配列を意味します。どうやら Ruby から呼び出せるCoreGraphicsの関数は606個あるようです。

    では、次にCoreGraphicsの描画コンテキストに対するメソッド的な関数名を抽出してみることにしましょう。これから作る DSL では、PDFコンテキストをレシーバとする関数をメソッド化の対象とするので、関数名が “CGContext” または “CGPDFContext” で始まるものだけを抽出します。

     

    >> funcs = OSX.methods.grep(/ ACG(PDF)?Context/)
     => ["CGContextSetRGBFillColor", ... 以下略 ]
     >> funcs.size
     => 123
    


    ここで、正規表現の中の “(PDF)?” の部分は、”PDF” または “” にマッチします。このパターンにより、CGPDFContext と CGContext 用の関数を抽出します。

    DSL では “CGContextSetRGBFillColor” という関数名からレシーバの型を意味する”CGContext” の部分を取り除き、さらに先頭の文字を小文字に置き換えた、”setRGBFillColor” というような名前のメソッドを定義することになりますが、この名前の変換にも正規表現を使います。ということで次回に続きます。

    ■ DSL参考リンク

    以下はDSLについて参考となるURLです:

    ドメイン特化言語
    http://capsctrl.que.jp/kdmsnr/wiki/bliki/?DomainSpecificLanguage

    DomainSpecificLanghage — 上記URLの原文
    http://martinfowler.com/bliki/DomainSpecificLanguage.html

    ドメイン固有言語
    http://ja.wikipedia.org/wiki/ドメイン固有言語

    「言語内DSL」の概念とRake
    http://www.itmedia.co.jp/enterprise/articles/0703/20/news015.html

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

     てなわけで,1986年の労働者派遣法施行時には,自他ともに……というか,派遣するヒトされるヒト,その派遣をお願いするヒトという三者が等しく「高度で専門的な知識や経験を必要とする職種」と思っており,間違っても「後でその解釈を拡張して派遣できる業種を増やそうというトロイの木馬」としてこれに入れられたものではなかった,ということについてはガッテンしていただけただろうか。

     また実際にもコト「ソフトウエア開発」という職種に限れば,その後「そいつぁちょっとコンプライアンスというか,モラルの観点からどんなもんですかねシャチョー」というような職種の拡大解釈は行われなかったと思う。まぁこれは飽くまでワタシの管見の及ぶ範囲のことだけれどもね。

     問題は,それまでいわゆる「業務請負」という体裁で行われていたソフトウエア技術者の派遣という行為が,この法律の施行によってどう変化したか,である。え,オレも派遣だったが別に変わらなかったって? そりゃ仕事はプログラム組んでデバッグしてデバッグしてデバッグしてデバッグして(中略)デバッグするだけだもの,変わりませんがな。そうではなくて「事業としての派遣業務」の変化のことを言ってるのである。

     なんちうかね,実質的には人材の派遣であっても名目上「業務請負」というカタチであったころは,派遣する人材に関して請負側にまだ「裁量の余地」というものがあった。

     つまり(こういう表現がとっても大雑把なものであることは分かってもらえると思うが)「プログラマを4人,1年間欲しい」という依頼に対し,「人並み以上のプログラマ1人と並のを2人,ずぶの素人(新人)を1人派遣して,その業務をこなしながら新人を育てる」というようなコトが可能だったわけ。

     実際に1984〜5年,オレが「派遣」されていた会社では,Aという会社から5人,Bという会社から5人,Cから2人(このウチの1人がオレだったわけだが)という感じで人が集められており,2人しかいないウチは別として他の会社からのヒトの中には「今年入りましたプログラミングは初めてですけど頑張ります」が1人ずつ混じっていた。

     しかもその5人が全員同じプロジェクトにいるわけぢゃなく,新人のヒトリはオレたちのグループに入ってオレのような他の会社のニンゲンに「教育」されていたんだよね。もちろんオレの方ももっとヴェテランの人たちにいろいろと教えてもらった。派遣先,すなわちクライアント側もそういうのを当然あるべきスガタと認識していた,と思う。

     細かいことを言えば「A社が請け負った仕事はあっちなのになんでそこの新人がC社の請け負ってるこっちの仕事に従事してんだ」ということも言えるわけだけど,誰もそんな文句はつけない。そういう意味では……言葉にしてそんなことを確認し合ったことはないけれども,みんな「どこの会社の社員」というより「プログラマ仲間」としてスキルを高めあい,新人を育てていたんぢゃないかな。

     いいかげんと言えばいいかげんだし,営業のニンゲンに言わせれば同じところに「業務請負」に入ってる3社は「ライバル同士」かも知れなかったが(実際そういうコトを言われたこともある),プログラマ仲間にそんなことを気にするヤツはいなかった。チームを組んで一つのプロダクトを作り上げようというのだ,所属してる会社にこだわるよか,プログラマとしての実力の方が大事に決まってた。

     ところが,派遣法の成立・施行によってそういう状況は一変した。
    (以下次回 2009_02_26)

                          

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

    これから始めようとする人へ(4)

     皆さんこんにちは、高橋真人です。
     さて、前回の連載の載った号の藤本裕之さんの記事に「『高級言語』との訳語は適当でない、と中村正三郎氏に叱られたので…」とありました。私はその中村さんの「電脳騒乱節」(*注)のころからのファンで、彼の言語感覚や技術面でのアドバイスには一目を置いていますから、素直にならうことにします(笑)。
     ちなみに、先日中村さんのブログをチェックしていたら、そのうち紹介しようと思っていた言葉の出ているウォズの本(後掲)について触れられていました。(http://iiyu.asablo.jp/blog/2009/02/28/4144547 余計なお世話ですが、中村さんの語り口は過激で、時に下ネタも遠慮なく織り交ぜられています。ご覧になる場合にはご留意ください(笑)。)

     ついでですので、ここでそれを紹介します。私がこの本で取り上げたかったのは、まだ本の初めの部分である第2章の終わりのところなんですが、以下のようなくだりがあります。

    「アップルをはじめ、いろんなところでいろんな人と仕事をしたけど、途中のやるべきことをすっとばして最終段階だけをなんとかしようとする人をたくさん見た。そんなの、うまくいくはずがないんだ。絶対に無理なんだよ。」※スティーブ・ウォズニアック著、井口耕二訳「アップルを創った怪物」2008年11月 ダイヤモンド社刊 ISBN978-4-478-00479-1

     この言葉に出会った時は嬉しかったですね。私も「硬派のためのプログラミング道場」なる講座をやってきて、基本から確実に積み上げていくことの大切さを強調してきた人間ですが、実際に仕事をしていますと基本を軽く考える「ノウハウのみを求める自称技術者」に出会うことも少なくないのです。われわれMacプログラマの多くが尊敬してやまないウォズの口からこのような言葉が語られたということに、私はとても安心を覚えます。

     さて、前置きが長くなりましたが、続きです。
     前回、「高水準言語は意味的な内容を記述する」と言いましたが、この「意味的」ということがピンと来なかった方もいらしたことでしょう。何を隠そうこの私も、HyperTalk程度は何とか使えていた今から20年弱前に、Cというプログラミング言語の存在を知って「こんなの人間のやれるものじゃない」と感じたことがあったのです。
     ですから、CやPerlの例を見て「意味的」と感じられるにはある程度の慣れが必要だというのも分かります。そこでその代わりと言ってはナンですが、逆に低水準言語というものがどういうものかをお見せすることで、逆に高水準言語の「分かりやすさ」を感じてもらいたいと思います。
     前回、Cで書いたサンプルをお見せしましたが、これをコンパイラが“コンピューターに分かる”ように翻訳したものをお見せします。もっとも既にお話しした通りCPUは数値しか理解しません。ですが、マシン語の数字の羅列を見せられても、人間には、それはただの数字の並びにしか見えませんから(笑)、マシン語に置き換えられる前のアセンブリコードをお見せします。
     以下は、Xcode3.1上でGCCというコンパイラを使って生成したアセンブリコードですが、せっかくですのでIntel用とPowerPC用をお見せします。ただ、GCCの吐き出したものはそのままだといずれも400行以上あり、多くは内部的な情報を表しているだけですから、元のCのプログラムの動作に関係しない部分はざっくりと省略します。さらに、ラベル(コードの位置を示す印)等も取り除いてありますので、このまま動かすことのできるものでないことはあらかじめお断りしておきます。

    《Intel CPU版》

    _main:
       pushl   %ebp
       movl    %esp, %ebp
       pushl   %ebx
       movl    $10, %ebx
       subl    $20, %esp
       movl    %ebx, 4(%esp)
       movl    $LC0, (%esp)
       call    L_printf$stub
       decl    %ebx
       jne L2
    
       addl    $20, %esp
       xorl    %eax, %eax
       popl    %ebx
       leave
       ret
    
    


    《PowerPC版》

    _main:
       mflr r0
       stmw r30,-8(r1)
       lis r30,ha16(LC0)
       li r31,10
       la r30,lo16(LC0)(r30)
       stw r0,8(r1)
       stwu r1,-80(r1)
       mr r4,r31
       mr r3,r30
       bl L_printf$LDBL128$stub
    
       addic. r31,r31,-1
       bne cr0,L2
    
       addi r1,r1,80
       li r3,0
       lwz r0,8(r1)
       lmw r30,-8(r1)
       mtlr r0
       blr
    


     いかがでしょう?
     所々、意味ありげな文字列らしきものも見て取れますが、前回お見せしたCのコードと比べても、というか、比べようがないほどに意味不明なものに見えるのではないでしょうか。
     さらに特徴的なのは、Intel CPU向けとPower PC向けのものに全く同じ部分が存在しないことです。この二つが「同じように動作する」と言われても、なかなか納得できるものではありませんよね。

     このように、実際の低水準言語のコードを見てしまうと、Cのコードはずっと人間に分かりやすく感じられませんか? 何より、Cで書いたコードはコンパイラが対象とするマシンに合わせて変換を行ってくれますから、コードを書く時に「今書いているコードはどちらのマシン向け?」などと意識する必要はほとんどありません。
     このように対象マシンごとに書き方を変える必要のないのが高水準言語の特徴でもあり、これをポータビリティまたは移植性などと言ったりします。

    注記:「電脳騒乱節」
    技術評論社から出ていたパソコン月刊誌「ざべ」(最初はThe BASICという名だったが通称がそのうち正式名称になった)に掲載されていた中村正三郎氏の連載記事。過激な語り口と内容でいろいろと物議を醸したこともある。

    ◇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)2009 MOSA. All rights reserved.