MOSA Developer News[MOSADeN=モサ伝]第299号
2008-05-27
目次
- りんご味Ruby 第25回 藤本 尚邦
- 藤本裕之のプログラミング夜話 #138
- 高橋真人の「プログラミング指南」 第136回
- 開発ツールよもやま話 Sharkの概要
りんご味Ruby 第25回 藤本 尚邦
前回、プログラムが期待通りに動作しているか確認するのためのテストを書きました。ということで、今回はYahooHonyaku#translateの実装にとりかかることにします。人がYahoo!翻訳を使うときには:
(1) WebブラウザでYahoo!翻訳のページを開く
(2) 何語から何語へ変換するか指定する
(3) 翻訳したいテキストを入力する
(4) 翻訳ボタンをクリック
(5) 結果が表示される
(6) 翻訳されたテキストを読む
(7) 続けて使う場合は(2)から繰り返す
というような手順を繰り返すことになるでしょう。Webブラウザは、(1)でHTTPのGETメソッドでYahoo!翻訳のトップページを取得します。(4)でHTTP のPOSTメソッドで翻訳を実行します。(5)でHTMLをパースして翻訳されたテキストを含めたデータ構造(HTML構文木)を作っているはずです。
YahooHonyaku#translateメソッドの実装もこれと同じような流れで書くことにします(注:前回までに示していたtranslateの実装から変更しました)。
def translate(mode, text)
open_top_page unless top_page_opened?
html = post_text(mode, text)
parse_result(html)
end
・ページが開かれていなければ、開く (1行目)
・変換モードを指定して翻訳したいテキストをポストする (2行目)
・結果のHTMLをパースして翻訳されたテキストを取り出す (3行目)
1行目では、unless の後置記法を使って書いています。これについては後述します。
YahooHonyaku#translateの中で使っている4つのプライベートメソッド、open_top_page, top_page_opened?, post_text, parse_result の中身はあとで実装するとして、現時点での yahoo-honyaku.rb のコードは以下のようになります:
--------------------------------------------- yahoo-honyaku.rb
class YahooHonyaku
def self.translate(mode, text)
new.translate(mode, text)
end
def translate(mode, text)
open_top_page unless top_page_opened?
html = post_text(mode, text)
parse_result(html)
end
private
def open_top_page
raise NotImplementedError, "まだ実装してねぇ、誰か書いてくれ!"
end
def top_page_opened?
raise NotImplementedError, "まだ実装してねぇ、誰か書いてくれ!"
end
def post_text(mode, text)
raise NotImplementedError, "まだ実装してねぇ、誰か書いてくれ!"
end
def parse_result(html)
raise NotImplementedError, "まだ実装してねぇ、誰か書いてくれ!"
end
end
---------------------------------------------
private 宣言以降の部分はプライベートメソッドの定義になります。ここで前回書いたテストを実行すると:
$ ruby test-yahoo-honyaku.rb
(中略)
1) Error:
test_s_translate(TestYahooHonyaku):
NotImplementedError: まだ実装してねぇ、誰か書いてくれ!
./yahoo-honyaku.rb:19:in `top_page_opened?'
(中略)
2 tests, 0 assertions, 0 failures, 2 errors
となりました。top_page_opened? を実装してくれということなので、次回はそこから取りかかることにします。
■ (おまけ) if と unless について
今回示したYahooHonyaku#translate の1行目は、unless の後置記法を使って書いています。Rubyでは、ifやunlessの(Perlにあるような)後置記法を使うことができます。
AAA if BBB # if BBB then AAA end と同じ意味
AAA unless BBB # unless BBB then AAA end と同じ意味
AAA if not BBB # if not BBB then AAA end と同じ意味
好みの問題もありますが、AAA や BBB の部分がシンプルで短いときには読みやすくなります。AAA や BBB の部分が長めだったり複雑な場合には、むしろ読みにくくなるので、普通に if式を使って:
if BBB
AAA
end
と書いた方が良いでしょう。if式で、条件節とTHEN節の間を改行する場合は、両者を挟むthenを省略可能です。ifやunlessの後置記法、もしくはif式やunless式において、else節が省略されて居る場合、条件にマッチしなければ結果は nil になります。
irb(main):001:0> 123 if true
123
irb(main):002:0> 123 if false
nil
irb(main):003:0> 123 unless true
nil
irb(main):004:0> 123 unless false
123
CやJavaのif文が文であって値を返さないのに対して、Rubyのifやunlessは式として、THEN節またはELSE節のどちらかを評価した値を返します。CやJavaでいうと三項演算子の?に近いかもしれません。
藤本裕之のプログラミング夜話 #138
承前……というか、またちょっとモノの見方を変えてみたい。前回「かつてワタシは(いやワタシだけでなく多くのプログラマは)、ユーザがソフトウエアをハードウエアのおまけだと思っていることについて憤っていた」と書いた。いや、このままの表現ではなかったかも知れないがそういう意味のことを書いたんですよ。で、今回はユーザだけでなく誰が見ても「ハードウエアのおまけ」である「バンドルソフト」というものについて考えてみたい。
およそパッケージ・ソフトを制作、販売しているものにとって、それがターゲットとするマシンに自分のソフトがバンドルされるというのは実にうれしくおいしい話である。……あ、ちょっとこの辺の事情というかカラクリについて知らない人がいるといけないので解説しておくか。あれ、バンドルしてもハードメーカーから入る金は微々たるもんすよ。オレの見聞した話だと、だいたい小売りで1万円くらいのソフトをバンドルして、1台につき数百円の利益があればおいしいくらいのもんだったと思う。……数十円かな? いやとにかく聞いたときびっくり仰天したことは覚えているのだ。
そんなんでナニが実利やねんロックンロールショーと思うかも知れないが、つうかオレも当時はそう思ったのだが、そういう人はソフトウエア・パッケージ商売についての理解がまだまだ浅いのね。
そもそもソフトウエアというのはバイナリ商品だから、メーカー出荷時にハードディスクにコピーして貰うだけなら原価(開発費は別ね)はゼロ、メディアと印刷したマニュアルをつけたところで知れている。少々旧い数字で申し訳ないが、オレが以前いた会社で制作・販売してたパッケージ、メディアとマニュアルだけなら300円はかからなかった。メディアはフロッピーで歩留まり悪かったから、CDを使える今はもっと安く済むだろうし…だいたい、今のバンドルソフトってマニュアルもpdfでいいし自前のメディアも要らないよね。つまりバンドルしてもらうための「持ち出し」というのはほぼゼロ。そしておいしいのは「とにかくユーザの目に触れる、一度くらいは使ってみてもらえるかも知れない」ことなのだ。
なんだかどんどん筆が……キーがかな? あらぬ方向に滑っていくような気がするが、アプリケーション・パッケージ商売で最も難しいのはソフトの開発でもバグフィックスでもない。そのソフトの存在をユーザに知ってもらうことなのである。もちろん、資金潤沢で莫大な広告費をかけられるならコトは簡単だ。だけど普通そんな金はないし、ワタシを含めてプログラマという論理的な
種族はそもそもそんな金があったら働かない。しかも困ったことにソフトウエアって、斬新で画期的なものほどコトバだけでナニをするものか、ナニが便利か、ナニが楽しいかを理解してもらうのが難しいモンなのね。
「こう升目に数字を入れてですね、自動的に合計とか平均とかが出せるわけです」
「そりゃできるでしょ、計算機なんだから。……電卓でだってできるよ」
「いやその、つまり表を作ってですね」
「ああ、表組みができるワードプロセッサなの?」
「そうではなくて……」
80年代始めに「Visicalc」(AppleII 向けに開発された最初の表計算ソフト)がどんなソフトであるかコトバだけで人に伝えるのはとんでもなく難しかったはずだ。そう言えば当時石田晴久センセが書いた本に「これからはBASICよりもVisicalcだ」てな文言があって、しばらくの間オレはVisicalcのことをプログラミング言語だと思っていたんだよな。
閑話休題。とにかくハードにバンドルされれば多くの人に「一度は」使ってみてもらえる。そして彼らの……例えば数%の人がそれを日常的に使うようになってくれれば、そこに「バージョンアップ」という大きなチャンスが得られるのだ。これまた知らない人には意外な話かも知れないが、アプリケーション・パッケージ商売で最も楽で効率がいいのはバージョンアップなのである。
流通マージンが無いうえ、外装も簡略でいい。しかも料金回収を振り込みやクレジットカードにすれば、ほとんど現金商売なのである。バンドルソフトってのはバージョンアップのための「撒き餌」だと言ってもいいくらいなのである。
と、斯様にいいことずくめにみえた「バンドルソフト」だが、広い目、長い目で見るとそう喜んでばかりもいられないシクミだった。次回はその「弊害」……てのは言い過ぎか。「功罪」の「罪」のほうの話をしてみたい。
(以下次回 2008_05_24)
高橋真人の「プログラミング指南」第136回
プログラマのためのオブジェクト指向再入門(42)
〜XcodeによるPowerPlant X入門(25)〜
こんにちは、高橋真人です。
さて早速続きですが、「なぜビューのアクティブ状態によって、枠とコントロールの前後関係が入れ替わってしまうのか?」という疑問についてでした。最初に言ってしまうと、この「前後関係が入れ替わる」という私の認識は誤りでした。その辺も含めて、今回は私の考えていった過程をお話しします。
前回の最後で、私が「コントロールはどこで描かれているのでしょう?」と書いた時に頭の中で考えていたのは、MyViewがPushButtonを経由して生成するボタンコントロールは、便宜上はHIViewとして扱われているが、もともとはControl Managerにおけるコントロールとして実装されていたものなので、プログラムのどこか(Carbonイベントの処理の流れとは)別のところで描かれているのではないか、ということです。
Control ManagerがControlを描く場合、Draw1Control()というAPIが使われます。このAPIの引数に描画したいコントロールを渡すことでコントロールが描かれるというわけです。そこで、MyViewが内部で利用しているボタンコントロールの場合、HIViewのCarbonイベントによる描画の仕組みが内部的にどこかでこのControl Managerの仕組みを呼び出しているのではないかと私は推理したわけです。
それでは、この“内部的に”呼び出す部分はいつ呼び出されるのでしょうか? “別のところ”とは言え、呼び出しがMyViewの描画と別のタイミングで行われたらMyViewとの連携が取れません。MyViewに対して描画要求が来たら(当然、これはCarbonイベントの流れでやってきます)、それと連動してボタンコントロールの描画が行われる必要があるわけです。
そうなると、次に考えるのは、「DoControlDraw()の呼ばれる前なのか、後なのか?」ということです。これは、描画における“前後関係”の話になってきます。後から描かれるものが手前に来るのは自明の理なので、MyViewがアクティブな時にはボタンコントロールは装飾部(MyViewのDoControlDraw()内で描画されている内容を指します)よりも後に描かれるはずですし、逆にアクティブでない時にはボタンコントロールは先に描画されるために、装飾部が手前に来るという理屈になるわけです。
ボタンコントロールが先(つまり、装飾部よりも下)に描かれる場合、前々回で触れた「イベントの流れを止める」ことを意図してDoControlDraw()でnoErrを返しても、それ以前に描画が完了していれば影響は出ないでしょうから、「MyViewがアクティブでない時には、noErrを返してもボタンは見えるはず」と推理して、早速実験をしてみたわけです。
実験の結果は私の予想を覆すものでした。MyViewがアクティブでない時にもボタンコントロールは全く表れなかったのです。
さて、これは一体どうしたものかとしばし考えてみて、ある仮説を思い付きました。それは、そもそも前後関係が入れ替わっているわけではなく、単にボタンが透き通っているために、後ろにある装飾部分が見えているだけなのではないのか? ということです。
そこで早速実験をしてみました。具体的には、DoControlDraw()の
::CGContextStrokeRect(inContext, frame);
の前に以下のコードを追加してみたのです。
::CGContextSetRGBStrokeColor(inContext, .95, .85, .3, 1.0);
::CGContextSetLineWidth(inContext, 5.0);
この状態でプログラムを走らせてみると予想通りでした。MyViewがアクティブでなくなったときにも、ボタンコントロールの中央にあるタイトル部の“Button”という文字は黄色い斜線に隠されることなく見えています。さらに、黄色い部分のうちボタンコントロールと重なっている部分が、そうでない部分に比べて薄く見えることも、よぉーく観察してみると分かります。黄色い線の透明度はゼロにしてありますから、黄色が見えるということはボタンコントロールが透き通っていることを示しているわけです。
というわけで、MyViewのアクティブ状態によってボタンコントロール部と装飾部の前後関係が入れ替わっているように見えたのは錯覚で、単にボタンの透明度が上がっていただけのことだったのです。
もっとも、私が予想していたように「アクティブ状態によって描画順が変わってしまう」などということになっていたら、もっと複雑な表示をしたい場合には相当厄介な話になってしまいそうです。ですから、今回判明した事実の方がずっと処理もラクですし、何より筋も通ります。
ボタンがアクティブでない時に透明になるということを既にご存知だった方にとっては、「何を今さら」という内容だったと思いますが、実は私はこの描画順序が変わるという“事実”に基づいて、今後の連載の進めて行く内容を考えていたために、正直、少なからぬショックを受けております(笑)
次回からは、気を取り直して、今回得た結果を元にボタンの周囲だけでなく前面にも装飾をする方法を考えて行きたいと思います。
開発ツールよもやま話 Sharkの概要 高橋 政明
開発に欠かせないツールはXcodeだけではありません。前回ご紹介したMallocDebugのようなパフォーマンスツールも重要です。
Mac OS Xはパブリックベータから10.5まで起動速度など性能(パフォーマンス)が目に見えて改善されてきました。もちろんMac本体のハードウェアも高性能になっていますが、少し古い機種でもMac OSをバージョンアップすると起動が早くなったことを体験されたことと思います。
処理速度の改善ではボトルネックを見つけて、そこを集中的に改善するのが最も効果的です。ボトルネックは計測して見つけ出す事が肝心と言われています。今回ご紹介するsharkはコードのパフォーマンス問題を発見するために利用可能な最も強力なツールのひとつです。
sharkの公式ドキュメントは次の4つありました。
Optimizing Your Application with System Trace in Shark 4 2006-01-30
http://developer.apple.com/tools/performance/optimizingwithsystemtrace.html
Optimizing Your Application with Shark 4 2004-11-08
http://developer.apple.com/tools/sharkoptimize.html
Optimizing with Shark: Big Payoff, Small Effort 2004-01-19
http://developer.apple.com/tools/shark_optimize.html
Performance Overview/Doing an Initial Performance Evaluation/
Using Shark 2006-10-03
http://developer.apple.com/documentation/Performance/Conceptual/PerformanceOverview/InitialEvaluation/chapter_5_section_5.html
また、日本語の資料としてはCocoa勉強会の「Cocoa Life」Vol.2に関根延篤氏の「Sharkを使ってみよう」があります。
どの資料からもsharkが強力で多機能な最適化ツールである事がわかります。
■sharkのインストール
かつてはCHUD Toolsと分類されていましたが10.5のXcode ToolsのインストーラではDeveloper Toolsシステムコンポーネントにチェックをするとインストールされます。
インストール先は/Developer/Applications/Performance Tools/Shark.appです。サメアイコンなのですぐにわかります。
■なぜ「サメ」?
sharkを起動しHelpメニューからShark Helpを開くと304ページもあるpdf書類「Shark User Guide」が開きます。(ページ数に圧倒されますね)
最初に『なぜサメなのか?』が書かれていました。
sharkはパフォーマンスを理解と最適化のためのツールである。
なぜサメと呼ばれるのか?
パフォーマンスの最適化はハンターの精神を必要とし、サメ程純粋に獲物を探索する動物はほかにない。
サメは目的のためにすべての潜在的資源を使う専門家でもある。
サメという名前は、あなたがコードをチューニングする時に持たなければならない精神と感情を表す。…だそうです。
sharkの解析機能を使うとコードのどこにパフォーマンスの問題があるのかを明らかにすることができます。結果的に開発者は最も効率よくパフォーマンスを改善できるのです。下手な訳で恐縮ですがOverviewの続きもご紹介します。(Yahoo!翻訳に手伝ってもらいました〔^_^;〕)
あなたのコードのパフォーマンスを分析するのを助けるため、sharkはシステム全体(アプリケーションと同様にカーネルとドライバ)のプロファイルを可能にする。
最もシンプルな水準ではsharkはあなたのコードが動作する間、時間がどこで費やされているかプロファイルする。
ハードウェアとソフトウェアのパフォーマンスイベント例えばキャッシュのミス、仮想メモリの活動、メモリアロケーション、ファンクションコール、インストラクション依存の失速などのプロファイルをつくる。
この情報はあなたのコードやシステムのどの部分がボトルネックであるかを見るパフォーマンス調整努力の貴重な一歩だ。加えてどこで時間が費やされているかをあなたに示すことに加えて、
sharkはどうやってコードを改善するかをアドバイスできる。
sharkは多くの一般的なパフォーマンスの落とし穴を確認でき、視覚的に問題のコストを示す。
プログラムのどの部分で時間を費やしているのかを明確に示してくれる重要なツールで高性能ですが、コマンドラインでの操作ではなく通常のMacのアプリケーションである点が助かります。
CPUのキャッシュやバーチャルメモリや機械語レベルの話になるとかなり高度となります。使い手のレベルでより効果を発揮するツールであることもまたまちがいないですね。
sharkは普段目にする事のないような高度な内容を含む膨大な情報を収集してくれます。その情報をもとに、どこに改善の余地がひそんでいるのかを見つけるのは他でもないプログラマです。
都合により開発ツールよもやま話は今後不定期の掲載とさせていただきます。
◇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.