MOSA Developer News[MOSADeN=モサ伝]第325号
2008-12-24
目次
- りんご味Ruby 第38回 藤本 尚邦
- 藤本裕之のプログラミング夜話 #151
- 高橋真人の「プログラミング指南」 第149回
- mosa entranceだより 第3回 大野 亮一郎
り
んご味Ruby 第38回 藤本 尚邦
前回は、オープンクラスによる疑似的な構文糖衣の実装として、Moduleクラスに直接、アクセッサ宣言のための attr_predicate を定義するコードを示しました。
--------------------------------------- attr_predicate.rb ---
Module.class_eval do
def attr_predicate(*names)
names.each do |name|
define_method("#{name}?") do
instance_variable_get("@#{name}") ? true : false
end
end
end
private :attr_predicate
end
----
この attr_predicate の定義の中身について、これまでほとんど触れていなかったので、ここで、オープンクラスの定義で登場した class_eval も含めて説明をします。
■ class_eval (module_eval の別名)
class_eval は、既存のモジュールやクラス(=Moduleクラスのインスタンスオブジェクト)に対して、新しい定義を追加したり、既存の定義を変更するときに呼び出すための Moduleクラスのインスタンスメソッドです。Rubyのマニュアル流に表現すると Module#class_eval ということになります。
Moduleクラスには Module#module_eval というメソッドがあって、実のところclass_eval は module_eval の単純な別名として定義されています。おそらく、メソッドを呼び出すとき、レシーバがクラスならば class_eval、レシーバがモジュールならば module_eval、というように使い分けるために別名があるのでしょう。以下、「クラスはモジュールの一種である」ということを前提に話を進めます。
class_eval (または module_eval)を呼び出すときには、追加・変更したい定義を、ブロック構文:
レシーバ.class_eval { ... }
レシーバ.class_eval do ... end
または文字列:
レシーバ.class_eval(プログラム文字列)
レシーバ.class_eval(プログラム文字列, ファイル名)
レシーバ.class_eval(プログラム文字列, ファイル名, 行番号)
で与えることができます。定義プログラムを文字列で与える場合には、適切なファイル名や行番号を実引数として与えることにより、プログラム文字列のパース・実行でエラーが発生したときに、エラー情報にエラー発生箇所のヒントを含めることができるようになります。
上の attr_predicate.rb の定義と同じように、定義をブロックで与える場合には、class_eval ではなく、通常のクラス(あるいはモジュール)の定義構文:
class クラス名
...
end
を使って、追加・変更したい定義を書くこともできます。
一見、どちらでもあまり違いがないよう気がしますが、実はひとつ大きな違いがあります。前者(class_evalを使う場合)では、もしレシーバが存在しなければエラーが発生します。一方、後者(classまたはmodule定義構文)では、そのクラス(またはモジュール)が存在する場合には定義の追加・変更を意味するし、存在しない場合には新しいクラス(またはモジュール)の生成と定義を意味します。
今は既存のクラスに定義を追加・変更するのが目的なので、クラスが「既存」でなければエラーが発生する class_eval を使って定義するのが妥当といえるでしょう(余談 — 1年くらい前に指摘されるまで、私自身もこの大きな違いを意識していませんでした。ちゃんと使い分けるべきでしょう)。
もうひとつの違いとして、class_evalは、構文ではなくメソッド呼出なので、
メソッド呼出できるところならどこでも、例えばメソッド定義の中でも、使うことができるというものがあります。ここでその詳細に立ち入ることは避けますが、実はこれも重大な違い(環境、変数などのスコープに関して)になることがあります。
■ private 宣言
def構文による attr_predicate の定義の次に:
private :attr_predicate
という行があります。これは(直前に定義した)attr_predicateメソッドをprivate なメソッドとして設定します。attr_predicate は、クラス定義時に使うための疑似構文にしたいわけですが、private宣言しないままだと、プログラム中のどこか(つまりクラス定義の外でも)以下のように:
TodoItem.attr_predicate :foo, :bar
使うことができてしまいます。private宣言することにより、attr_predicate宣言をクラス定義でしか記述できないように制限することができます。
Ruby においてメソッドを private 指定することは、そのメソッドをレシーバを省略した形式でしか呼び出すことができなくする、つまり、プログラム実行(評価)時に、そのときどきのselfに対してしか呼び出すことができなくするということを意味します。プログラム実行時に、クラス自身(Classクラスのインスタンスオブジェクト)が self になるのはクラス定義のときだけなので、
private宣言することにより、attr_predicate をクラス定義でしか使うことが出来なくなるわけです。
(注: Ruby の private は、C++ や Java の private とかなり意味が違います。強いて言えば、派生クラスの定義でも使えるという点で、 C++ や Java のprotected にやや近いかもしれません)
藤本裕之のプログラミング夜話 #151
今回の話は、もしかしてあなたが現在学生だったり学生でないまでも20代前半とか、オマケして20代後半から、かろうじて「アラウンド・サーティ」だったりする場合、あんまり当てはまらないと思う。最初にそんだけ言い訳させといてください。では……。ところでモサにそんな若いヒト、いるの?
承前、前回ワレワレ(ちうかオレ一人だが)が検討したところによれば、たった一人で粉骨砕身努力に努力を重ねてコンピュータゲームを作ることは不可能ではない。だが、時代はそうしたものを商品価値のあるゲームと認めていたところからはるかに遠くイスカンダルのあたりまで来てしまっており、それを射程に入れるにはヤマト総員の気持ちが一つになることが必要なのである……ぢゃなかった、制作チームというか団体戦になってしまう。
で、オレはそれでもいい、コンピュータゲームの制作チームの一員、そこのプログラマとして働いて食って行きたい、とあなたは言うかもしれない。しかしである。実際のところ、オレもそうだがこれを読んでいるアプリケーション・プログラマのあらかたが、おそらくそういうチームに入れては貰えないだろうという現実がある。
年寄りは受け付けないってこと? それもある。今をさること25年前、オレがこの業界で仕事を始めた頃には「プログラマ30歳定年説」というのがあってね、「コンピュータの進歩はとっても早いから、だいたい30歳くらいで新しい技術についていけなくなる」なんて言われていた。
で、オレ達の世代はこれが論理的にまったくスジが通らないばかげた説であることを文字通り体(頭か)で証明してきたんだが、いまだに経営側方面の偉いヒトってのは「若い人=頭が柔軟=新しいことをすぐ覚える=だから最新のテクノロジーについていける」なんて馬鹿なことを信じていて、ただ若いというだけのヒトをヤミクモにプログラマにしようとする傾向がある。
実際には「コンピュータの進歩はとっても早いから、現在最先端のことを理解するための前提となる知識が短い期間で膨大になってしまい、これからコンピュータのエンジニアになるひとがワレワレのようなある程度のオールラウンダーになれる可能性はとても低い」というほうが正解だよね。でも社会的にはそうぢゃない。
したがって実力的には申し分ないのに、いやはっきり言えばどんぴしゃの適任の場合が多いのに、年齢が行ってるプログラマはゲームのチームに入れてもらえない。まぁゲームの場合、他のスタッフには文科系、あるいは芸術系が多いので感性として若い(年齢的に顧客に近い)ほうが、という考え方もあるし、そうなるとチームの人間は同世代のほうが……と日本のメーカーは考えがちなんだよね。
そう、年齢が第一の問題。
第二の問題は……まぁこれも上のことに絡むんだけど、ゲーム・プロダクション全体の中でのプログラマの重要性が相対的に下がった(他の分野も重要だからね)ため、プログラマに割かれる人件費というものが、プログラマ的(というのはつまりオレ達の常識ということです)に「それはねぇだろ」という水準まで下げられているというのがある。
実際ゲーム・プロダクションで最もお金を取るのは、ゲームのコンセプトや企画をひねくりだす「ゲームデザイナ」とか「クリエータ」のヒトたちで、プログラマは3Dモデラーとかと共になんつか「工員」レベルの扱いのところが多い。ブーメランのように上の話に戻るけど、スキル不足の若い人を雇うのも、仕事の出来栄えが評価できない以上「安く使える」ということがそのまま「価
値」になるからである。
……と、まるでそれがゲーム業界特有のことのように書いてしまったけど、これは多かれ少なかれ日本におけるソフトウエア・エンジニア、プログラマが共通して直面している問題なんだよね。ここで年を改めて、この、プログラマの仕事に対する世間的評価という話を来年は展開して行きたい。みなさんよいお年を、とは言いにくい状況ではあるが、ワタシもがんばるので皆さんもがんばってくだされ。
(以下次回 2008_12_19)
高橋真人の「プログラミング指南」第149回
プログラマのためのオブジェクト指向再入門(55)
〜XcodeによるPowerPlant X入門(38)〜
こんにちは、高橋真人です。
前々回から、PPxにおけるEventHandlerUPPの作成・保存・破棄をテーマに解説をしていますが、前回の説明ではC++におけるstatic変数の特徴のお話をしました。このことがどのようにUPPの作成・保存・破棄につながっていくのかということですが、そのためにはシングルトンというものに馴染んでいただく必要があります。
シングルトンというのは、GoF(*1)の「デザインパターン」(*2)にも含まれるポピュラーなパターンのうちの一つで、一言で言えば「一つのクラスからインスタンスが一つしか生成されないように設計する仕組み」です。
シングルトンが必要になることは、普通のアプリケーションにおいても所々にあります。中でも一般的と思われるものに初期設定があります。アプリケーションの各種設定内容をまとめて管理するクラスを作ったとして、それを利用する度に新規にインスタンスを生成してしまうと、設定内容にダブりが出たり複数のインスタンス間で内容にズレが出てきたりするなどの問題が起こりますので、初期設定のクラスをシングルトンパターンで実装することは一つの解決策です。
記事末尾に挙げた参考書籍で例示されているシングルトンパターンのC++での実装例は以下のようになります。(書籍の掲載例を説明に合わせて改変)
class Singleton {
public:
static Singleton* Instance() {
if (_instance == NULL) {
_instance = new Singleton;
}
return _instance;
}
protected:
Singleton();
private:
static Singleton *_instance;
};
まず、このSingletonクラスのパブリックインターフェースはInstance()です。staticメンバ関数ですから、Singletonクラスのインスタンスが生成されていない状態でも呼び出せます。
上記コードでは明示していませんが、唯一のメンバ変数である_instanceはプログラムの起動時にNULLに初期化されます。従って、最初にこのメンバ関数が呼び出された時には条件判断が真になり、インスタンスが1つ作られて_instanceに格納されます。
2回目以降のInstance()の呼び出し時には、既に_instanceに保持されているインスタンスがそのまま返されるだけとなります。
このクラスはコンストラクタがprotectedに指定されているため、外部からインスタンス生成することができません。privateではなくprotectedなのは、このクラスがサブクラス化して使われることが想定されているからです。
さて、このGoFのデザインパターンにおけるSingletonの実装には問題点がいくつかあります。それは、一度作成されたSingletonのインスタンスが決して破棄されることがない、ということです(「破棄できない」ではありせん)。
C++においてはnewしたものはdeleteして終えるのが作法です。その意味でこのクラスのインスタンスも最終的にdeleteされるべきであるのはその通りなのですが、deleteしなかったからと言って、メモリーリークが起きるわけではありません。
何故なら、元々シングルトンパターンでは、生成されたインスタンスはプログラムが終了するまで存在することを前提にしていますので、プログラムの終了時にはあえてdeleteを呼ばなくても、メモリの後始末はちゃんと行われます。
しかし、メモリのリークはないとしても、別のリークが起こる場合があるのです。それはリソースリークです。
C++では、インスタンスが生成される際に、そのインスタンスの居場所となるメモリの確保を行いますが、同時に、そのインスタンスが必要とする資源の準備をいくつかする場合があります。
簡単な例では、インスタンスの生成時にファイルをオープンし、インスタンスが破棄される時にファイルをクローズするなどというのが挙げられます。先ほど挙げた初期設定のクラスの場合、最初にインスタンスが生成される際に設定内容をシステムから読み込んでおいて、それをずっとメモリ上に保持しておく。プログラムの終了時、つまりインスタンスの破棄時に、もし設定内容に変更が加えられていたらシステム側の設定内容を更新する、などといったやり方が考えられます。
このような設計にしておいた場合、上記のGoFのシングルトンの実装例では、システム上の設定内容が更新されることが起こらない、ということになってしまうのです。(破棄時の動作はデストラクタに実装されるが、インスタンスが明示的に破棄されないとデストラクタが呼び出されない)
そこで、PPxでも使用されているstatic変数を利用したシングルトンパターンの実装方法の登場です。次回はそれを解説します。
【注記】
*1 GoF ギャング・オブ・フォーの略で、オブジェクト指向界ではErich Gamma、Richard Helm、Ralph Johnson、John Vlissidesの4人を指す。彼らの書籍(下記)により、デザインパターンという用語がソフトウエアの世界で定着した。
*2 デザインパターン 技術者が新たなソフトウエアの製作に取り組む際に、過去の経験や知識の中から類似のケースを抽象的に応用することがあるが、これを体系的にかつ一定の規則に基づいてまとめたものをパターンカタログと言う。元々は建築の世界で生まれた考え方であるが、これをSmalltalk界隈のソフトウエア技術者が中心になってソフトウエア界に紹介した。デザインパターンはパターンの中でもデザイン、つまり設計にかかわる部分についてのパターンをカタログ化したもので、「GoFのデザインパターン」と呼ばれる下記書籍にまとめられた23のデザインパターンカタログが最も有名。
参考書籍:オブジェクト指向における再利用のためのデザインパターンソフトバンク刊 1995年
mosa entranceだより 第3回 大野 亮一郎
皆様こんにちは。mosa entranceを主催しております大野と申します。今回は年内最後のモサ伝ですので、今年のmosa entranceを振り返ってお伝えさせて戴きます。
7月に始まったmosa entranceですが、毎回十数人の皆様にご参加戴いています。回を重ねる度に人数が増え、11月には19名を数えるに至りました。ちょうどiPhoneのSDKが出始めた頃で話題が豊富だったこともあり、iPhoneを目的にMOSAに入会してそのままお越し戴いた方も少なくありませんでした。iPhoneの開発経験は少なくても、MacOSや別環境ではご経験を積んでいらっしゃる方も多かったように思います。mosa entranceのモットーは、初心者と悩めるMacプログラマーに愛の手を!
なのですが(笑)、実際には私が考えているよりも猛者にお集り戴いている印象です。もちろん私のような初学者の方もいらっしゃいますが、皆様とても控えめで、非常に幅広い初心者の集いとなりました。
そんなmosa entranceですが、当初は本当に開催できるのか、一人も来なかったら哀しすぎる…等と不安も多かったものの、無事に回を重ね年末を迎えることができたようです。毎回お茶とお菓子を中心に、MacOSの話、iPhoneについて、またWebアプリケーションについてあーでもないこーでもないと、たくさんのお話をすることができました。高度な話題も少なくなかったのですが、これから腕を磨こうと考えている皆様には、他では得られない有意義な時間になったのではないでしょうか。ひとえに参加戴いた皆様、ご参加は難しくとも応援して下さった皆様のお陰です。
正直なところ、本当に初心者や悩んでいる皆様のお役に立てる「場」になっているのか自信がありません。試行錯誤しながら進めていますので、ご迷惑をおかけしていることも多いと思います。来年はmosa entranceをよりよい場とするために、ご一緒に道筋のない発展を楽しんで行ければと考えております。ご興味をお持ちの方、どうぞほんの少しだけでも清泉女子大学までお越し下さい。お時間の都合がつかなければ夕食だけのご一緒でも構いません。参加しようか迷っている初心者の皆さん! 思い切って一歩を踏み出してみて下さい!きっとmosa entrnaceで何か新しいものに触れることができると思います。
改めまして、皆様に今後ともmosa entnraceをご活用戴けます様よろしくお願い申し上げます。
Merry Christmas and a happy new year!
どうぞ来年も良い年でありますように!
◇MOSAからのお知らせと編集後記は割愛します◇
配信停止 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.