2009-03-17
目次
りんご味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回
皆さんこんにちは、高橋真人です。
前回まで、「マシン語から始めて徐々に高いレベルに向かって」ということでお話をしてきました。
しかし、高水準言語の説明に入ってすぐに言うのもナンなのですが、この先も「少しずつ高いレベルに向かって」というのは、あまりうまいやり方ではありません。何故なら、低水準言語は基本的にマシン語に準ずるものであって、これらは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からのお知らせと編集後記は割愛します◇