ラベル programmer の投稿を表示しています。 すべての投稿を表示
ラベル programmer の投稿を表示しています。 すべての投稿を表示

2013年1月5日土曜日

2段以上のifを書いたら負け ( ウンコード )

ウンコ確定のコードを勝手にレビューして、勝ったつもりになる企画です。

しかし、ウンコはPHPが多いかと思ったけど、Javaも多いんだなー。
これで、「オレJavaプログラマだから単価高いぜー」とか粋がってる奴が多いんだよな。※主に2chだが

http://unkode-mania.net/view/50a1018a61fd523468000000
これは、完全に「真偽値を返す」が目的になってしまったケース。
小生の数少ないサンプリングでは、16bitの時代からやってる人は、checkって付けたがる。
そして、コメントも「○○をチェックする」とか書いちゃうんですよね。
「真偽値を返す」は手段であって、目的ではありません。

http://unkode-mania.net/view/503cf8bd81ce286163000001
かなりベテランでもこういう多段ifを書く人はいますね。
なんか、「大雑把なエラーケースは、大雑把なifで最初に括りたい」という俺ルールがあるらしい。
それ自体は判らんでもないが。

ただし、これをうまく折りたたむのはかなりコツが要ります。
正直、免許皆伝レベルでしょう。
それが出来る人なら、大抵の要件で、大概美しく書けることでしょう。

小生、「2段以上のifを書いたら負け」っていう独りルールを課して仕事してます。
え、だって、同じ条件式が何度も出てくるって、恥ずかしいでしょう?

出稼ぎ先の皆さんにも課してしまいたい。正直。

http://unkode-mania.net/view/5035b6194525595031000024
これも目的と手段が逆転してるタイプ。
「3日だから」という「手段」しか頭にない。
もしくはネーミングセンスが壊滅的な人。
多分UtilとかMiscとかvalueとかやるに違いない。
「「3日」が何なのか」を変数名にするべき。

http://unkode-mania.net/view/5033834e57c8e41736000004
これはどっちかというと、delete()が失敗した時に、例外を吐くべき。
Javaのお作法なら、そっちのほうが正当だと思うのだが。

http://unkode-mania.net/view/50326320383b806b09000000
怖!

http://unkode-mania.net/view/5060461ea753b5a970000000
一個の関数に処理を全部ねじ込んで、mode=1 とかやりたがる人は結構居ますね。
「処理の違いが、数行だけなんです」というなら、判る。それでも辞めて欲しいけど。

明らかに「複数系統の処理が同居」しちゃってるのは、「カプセル化」が判ってない。
「カプセル化」ってのは、オブジェクト指向云々の話ではありません。処理の粒度の話ね。
えてして、こういうコーディングする人は、非常に改造しにくい実装をやらかすので
仕様変更の毎にゴネます。

2013年1月4日金曜日

ウンココードというらしい

なんでこんなサイト見つけたんだっけ。ああ、「staticおじさん」で検索したらか。

http://unkode-mania.net/view/5017de366ce2e89241000005
http://unkode-mania.net/view/501908d27e19b43a0700000e
なんちゃらutilって名前つけるプログラムは大抵駄目だよね。
何に使うか自分で決定できない。必然、カプセル化失敗。
こういう人がPHPに移ると、幸せになってしまう可能性があります。要注意。

http://unkode-mania.net/view/5017c16b88f62a4864000000
ネーミング自体は悪くないと思う。むしろ賛成。
ただし、TakeCareAboutEscapeToAvoidSQLInjectionするなら、Stringを生で渡すんじゃなくて、new EscapeToAvoidSQLInjection()とかするべきだよね。

http://unkode-mania.net/view/509db1a961fd528e20000009
怖!

http://unkode-mania.net/view/504453931095000c1c000000
初級者に非常に多い。「似たような処理」という認識ができてない。
故に、「似たような処理を集約する」ことが出来ない。
コピペ天国。こういう実装をする人は成長しません。

http://unkode-mania.net/view/50ac2309de7cf25e79000008
http://unkode-mania.net/view/5040f47b9b6066a52e000003
こういう、処理の遷移状態で、解放処理が増減するような場合、結構コツが要ります。
結構なベテランでも、平気でこういう実装をやらかす場合が多いようです。

http://unkode-mania.net/view/50323348383b809649000000

http://unkode-mania.net/view/509b3f94c2a4d15548000001
これはどっちかというと、「パンくずリスト」と訳した人が悪い。
小生も「パンくずリスト」という呼称は嫌いです。
なぜって、一般的実装は「住所」であって「道順」ではないから。ヘンゼルに謝れ。
そう思ってる人は他にもいるらしく、トピックパスとか言うらしい。こっちのが正しいです。

http://unkode-mania.net/view/5030ffd7383b80451c00000a
こういう実装をするひとは、PHPに移ると幸せだろうな。

http://unkode-mania.net/view/50338f6957c8e49774000008
まるで悪いわけでもありません。それぞれ1回しか呼ばない可能性がありますから。
もちろん、DBをsingletonにしたほうが、玄人受けは良いでしょう。

2012年12月14日金曜日

本当にあったredisの怖い話

出稼ぎのとある案件で、redisを使ってますが、色々ヤラれますね。

  • 運用面
    • スキーマ(に相当する概念)を、整数で管理しなければならない
      • 故に、DBを取り違えても、書き込めてしまう。
        • 書き込み先DBを間違えてることに、果たして何時気がつくやら。
      • 端的に言えば、複数のredisインスタンスを使い分けるような運用を想定してないのでしょう。
        • 逆に言えば、そんな使い方するならredisを選択するのが間違ってます。
    • バックアップは、永続ファイル1個をコピーするしかない。
      • 逆にいうと、バックアップが必要になるような運用にredisを選択するのが間違ってます。
    • appendonly=true は永続ファイルを壊す可能性は減るが
      • 実はジャーナルなので、永久に増え続ける。
        • 長期運用するとG単位になるケースもある。そこまで来ると再起動に20分とか掛かる。
  • プログラム面
    • DB全体から「検索」或いは、hashの中身を取得すると、hitした全件を取得するしかない。
      • PHPは、メモリを食いつぶすと、即死するので、非常に相性が悪い。
      • 例えば Set型を使って、タグの運用が楽にできますよー。http://gihyo.jp/dev/feature/01/redis/0004 とか得意気にいってるが
        • 50万件hitしたら、それが$resultにドカーんと送信してくるわけです。
        • ini_set("memory_limit","8000M"); にすりゃいいとかって話でもない。
        • 基本、バッチ実行で使うことを想定してる気がする。
    • expireは、メモリ次第で、期待より早期に消える場合がある
      • キャッシュとしての想定しかないのでしょう。
      • だったらmemcacheでいいじゃねえか。
    • phpredisは https://github.com/nicolasff/phpredis
      • オブジェクト類を、テキトーにシリアライズして保存してはくれるが独自実装なので、他の言語から使うときには互換性がない。
        • そんな想定ないけどね。
      • 本来はsession_handlerに使う程度の想定しかないんじゃねえかと。https://github.com/nicolasff/phpredis#php-session-handler

そんな訳で、それをwebソーシャルゲームのフロントから使ってるオレらが悪いんですけどね。そんなに言うなら使うなって?もちろん使いませんよ。選んだのは小生じゃない。「3ヶ月前から決まってるから、オレの顔に泥を塗るんじゃねえ!」とか言われたら引き下がりますよ。面倒臭いし。こっちは外注の身ですから。

MongoDBでいいんじゃね?と思ってるしね。

2010年12月28日火曜日

仕事で使う言語の条件(1)

似たようなエントリは何度か書いてますが。

出稼ぎでの実装やら、今までの後始末経験を踏まえて、
「仕事」での理想の言語を考えます。

  • 未定義変数をいきなり参照する(代入式の右辺で使う)とエラー(例外)が出なければならない。
    • 極めて当たり前の話の筈が、PHPではNotice
  • 関数の内側から、グローバル変数を使うには、特殊な宣言がなければならない。
    • 勝手に外部スコープを参照しちゃうのは読みにくい。
    • 非オブジェクト指向での実装を助長している気がします。「カプセル化」に逆行する挙動。
  • クラス関数(メソッド)内部で、クラス変数(プロパティ)を使うには、this経由でなければならない。
    • 勝手に外部スコープを参照しちゃうのは読みにくい。
    • グローバル変数への参照と区別が付きにくい。「判るに決まってるだろ!」とか言わないように。
  • mixinのための多重継承。http://ja.wikipedia.org/wiki/Mixin
  • 動的型付け。
  • 関数が第1級オブジェクトでなければならない。http://ja.wikipedia.org/wiki/%E7%AC%AC%E4%B8%80%E7%B4%9A%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88 
    • create_functionとかあり得ない。
  • 関数の可変長の引数の受け渡しを、自然な構文で運用できなければならない。
    • func_get_argsとかva_argsとか駄目だと思うわけですよ。
  • 必要であれば、バイトコードの保存/利用も可能であること。
  • 例外処理のサポート。
  • Unicodeサポート。
    • 機能が使える、だけじゃ無意味。プログラマが意識せずとも、任意バイト文字をそれぞれ同じように扱えないと困る。
      • PHPでは変数の中身をプログラマが区別して運用しなければならない、シングルバイト文字はstrlenで、マルチバイトはmb_strlenで、エンコーディングはmb_languageでとか、テンでバラバラ)
    • 比較的理想に近いのはpythonのstr及びunicodeオブジェクト。両者、同じ操作メソッドを持つし、相互変換も容易。
ハイ、聡明な皆さんならもう判りましたね。pythonの宣伝です。

pythonは所謂スクリプトなので、というわけではないのでしょうが、protected/privateとかが有りません。これらは「カプセル化」って奴で、「オブジェクト指向」で重要ってことになってるファクタです。ただし小生はカプセル化を重要視してません。

2010年12月26日日曜日

mercurialのススメ(2)

筆者は5年ほど前から
バージョン管理はmercurialで統一しました。
http://mercurial.selenic.com/
利用当初は0.6だったと思いますが、今や1.7.2。
あのGoogle Codeですら採用しています。

subversionを使ってる方々は、今すぐgit/mercurialに移行しましょう。

もちろん筆者としてはmercurialを勧める訳ですが

デメリットを先に言っておきましょう。
多分それだけです。
subversionの問題点の殆どが解消します。それがメリット。

  • 「サーバ」が要らない。ってサーバ機能を内包してる。windowsの人はtortoiseHG(http://tortoisehg.bitbucket.org/)で一発インストール。
  • リポジトリ通信が高速。同規模のプロジェクトで、subversionの数倍。
  • リポジトリ同期のプロトコルが豊富。しかも内蔵。httpd, ssh, 
  • ブランチ&マージは半自動的。場合によってはほとんど人手を介さない。
  • 事実上、コンフリクトは起こらない。(マルチプルヘッド扱いになるので先送りできる)
オフィシャルサイトの情報もよくできてますが、
http://mercurial.selenic.com/wiki/JapaneseMercurial
日本語チートシート(アンチョコ)を作ってくれてる人が居たので、これを傍らにおけば、運用は容易でしょう。http://www.textdrop.net/doc/mercurial-cheat-sheet-ja/

bazaarが入ってないのは?
http://bazaar.canonical.com/en/
リポジトリ間同期をするときに、必ずマージをさせるのは
筆者的にはsubversionの反省点ですので。
あと、実際に色々試してみると、激遅い。なんなのコレ。

故に、比較的シンプルなmercurialをお勧めしています。

2010年12月5日日曜日

PHPの本当にあった怖い話(1)

筆者はPHPを仕事で使うようになって5年経ちますが、それは自慢になりません。
何故なら、未だに裏切られます。

結論から言いましょう。


$aaa = range("0","9");
$bbb = range("a","z");
$ccc = array_merge( $aaa, $bbb );
$ddd = array_search( "a", $ccc );


この$dddには何が入るのか?10が入って欲しいですよね?
0です。

この理由がいきなり説明できる人は、PHPの仙人もしくは関係者でしょう。
師匠もしくは、インサイダーと呼ばせてください。

実は最初のrangeが曲者です。
これは"0"と"9"を指定したにも関わらず、intの配列を作ります。
結果、$cccの中身にはintとstringが混在していることになります。

まだ前フリです。

そしてarray_searchで何が起こるのか?

"a"を探せ、って言ってるのに、intval("a")==0 で0番目が一致しちゃってるのです。

ありえなくね?

結論として、前述の例では、rangeとarray_searchの挙動の共犯です。

PHPは、こういった「暗黙の型変換」が大量にあり、warningすら出ません。
http://www.php.net/manual/en/types.comparisons.php

sortについては、これを反映して、「比較「型」の強制」があります。
http://www.php.net/manual/en/function.sort.php

しかし、array_searchには無いわけです。

初心者のうちは助けられることが多いと思いますし、
それを意図しての型変換でしょう。
しかし、中級になったとたん裏切られるのです。

これを期待通りに可動させるには、rangeの結果にstrvalを通す必要があります。


$aaa = array_map( "strval", range("0","9") );
$bbb = range("a","z");
$ccc = array_merge( $aaa, $bbb );
$ddd = array_search( "a", $ccc );


ありえなくね?

2010年12月3日金曜日

ifを書いたら負け

筆者の持論というか、
最近の見解で「条件分岐を書いたら負け」というものがあります。

具体的にはif,for,while,switchです。

プログラムと条件分岐は、切っても切れません。
しかも要件定義者は、プログラムに都合の悪い仕様を考えてくれるので、
馬鹿正直に実装すると、条件分岐で大変な事になります。

何が大変って、デバッグがです。
極論すれば、条件分岐を一つ書くと、バグの可能性が一つ増えることになります。

20年前には、ソースプログラム上のif文の数等を数えて、バグ件数を見積もって、
それに満たなければ「枯れてない」と判断する。そんな昔話もあるらしいです。

面倒な仕様は、実は仕方有りません。
面倒な仕事を面倒なままやるなら、誰にでも出来ます。

困難な問題は分割せよ、と昔の偉い人も言ったらしい。

もう少し具体的な話を書きます。
例えば、非連続値が関わってるタイプの条件分岐は、工夫次第で条件分岐を省けます。

簡単な話では、「「入力値」を幾つかの範囲にグルーピングするもの」。集計ではよくありますね。

perlではフツーに書くと、こんな感じになると思われます。

my @threshold = ( 20,60,100,150,200,500);
sub islevel{
my($value)=@_;
my $level = 0;
foreach my $ii (@threshold){
last if( $ii > $value ) ;
$level = $ii;
}
return $level;
}


#一応デバッグしたから正しい筈

  • 各範囲の閾値のうち、
  • 入力値より大きいもの
  • 直前が、範囲値

直前の値、が曲者で、地味に面倒な処理です。

この手の実装をするときには、大きい方から回した方が、
条件文はスムーズだったかな。

結論からいいましょう。
perlらしく書くとこうです。

my @threshold = ( 20,60,100,150,200,500);
sub islevel{
my $value = shift;
my @levels = grep { $_ <= $value } @threshold; return $levels[$#levels]; }


後者の考え方は実にシンプルです。

  • 各範囲の閾値のうち、
  • 入力値以下のもの全てを、
  • のうち、もっとも大きいものが、範囲値

余り変わってない?そうですね。「直前の値」の解釈を変えただけです。

本稿で論じたいことの肝は、
処理は多めにやっちゃったほうがプログラムはシンプルになる。
というところです。

ループと条件分岐は、grep に任せています。
第2引数に配列、第1引数に条件式を指定すると、
それにマッチした要素を全て抜き出してくれるという便利関数です。
関数型プログラミングの発想らしい?

これがサンプルをperlで書いている理由だったりしますが、
似たような考え方は他の言語でも出来ます。

grepで回せるように、要件を意訳した。と言った方が正しいでしょう。
性能についての議論はややこしくなるから割愛します。

って言うか、grep に相当する機能が無かったら
自分で作るぐらいが本当でしょう。
毎回、前者のループをコピペしまくるんじゃ頭悪すぎます。

2010年11月14日日曜日

mysqlかpostgresqlかNoSQLか

postgresqlとmysqlとどっちを使えば良いかは、
いやっちゅーほど繰り返されてきた議論ですが、
両者とも明確なメリット&デメリットがあり、
極論するなら、消去法で選択するしかありません。

postgresqlの場合

  • insertが比較的早い
  • updateを繰り返すと、性能が落ちてくる。vacuumが必要。
  • vacuumするには、テーブルロックが必要。な場合がある。
  • レプリケーションが未実装。
  • connectは比較的遅い。


mysqlの場合

  • readだけなら早い→そんな案件今時あるの?
  • レプリケーションが比較的簡単&安定→readonlyスレーブ増やして負荷分散、はよくある発想。面倒だが。
  • innodb insert/updateが激遅い。
  • sqlに方言がやたら多い。
  • 複雑なsqlを投入すると、最適化に失敗する。と言うか最適化する気がないっぽい。
  • connectは比較的早い。
  • myisamは結構壊れる。(しかも普通に使っていて)
  • innodbも稀に壊れる。(しかも普通に使っていて)


エンタープライズ業界なら、これの何れか、もしくはOracleでイイヤ、
って話になるでしょうけど、
ソーシャルゲームであると、データ量、時間あたりの処理量が
指数的に増大します。


テーブル分割に対する実装コストも馬鹿になりません。
であれば、NoSQLを使ってしまえ、というのは手です。

NoSQLは数有りますが、近頃実績が増えてるっぽいのが、mongodbでしょう。
http://www.infoq.com/jp/news/2010/10/4square_mongodb_outage
これらのトラブルも、過渡期であるが故です。

それにこのトラブルは、会員数300万人とかのレベルなんで、
仮にmysql/postgresqlで運用していたとしても、
別のトラブルが有ったであろう人数と言えましょう。知らないけど。

シャードの不均一化が原因だって話なんで、
最初から、細かいテーブル(コレクション)に分割してしまえば済む話かも知れません。
メモリ使用的にもその方が有利らしいし。
http://www.mongodb.org/pages/viewpage.action?pageId=18448682

こんな事が出来るのも、スキーマレス、create tableイラズだからです。

2010年11月2日火曜日

金を稼ぐだけが一流か

tumblr経由で、気になる記事を見つけました。

http://d.hatena.ne.jp/yaneurao/20101029

全体的に、収入ベースでの物言いが引っかかります。端的に言えば卑屈。
収入について、何かコンプレックスを持っているのだろうか?

35歳の現場の技術者が「一流の技術者になるには英語と数学を勉強しておきなさい」とか言っても私ならそんな意見にはこれっぽっちも耳を貸さない。35歳なら、もうとっくにセミリタイアしていておかしくない年齢だ。その技術者はもしかしたら本当に一流の技術者かも知れないが、ビジネスマンとしては三流だ。みんなもそういう人が居たら、「英語と数学を勉強してもあんたのようにしかなれないじゃないか!」と言ってやるといい。(そのあとどうなっても知らんけど)

この箇所で自身が述べているとおり「ビジネスマンとして一流」を「技術者として一流」を混同している。
そして、この反論を聞いた相手は、

だからオレのようにならないために忠告してるんだ。

という反論が帰ってくるに違いない。

あと、自分を天才だと思っている若者に向けて一言言っておく。君は本当に天才かも知れん。だけど、もし本当に天才なら30年後なんか見据える必要ねーじゃん。10年ほどで結果を出せるだろ。なにせ、天才なんだからさ。だから見据えるのは10年ぐらいでいいじゃん。君が社会に出てから10年も働いたら2億円ぐらい手元にあるんじゃね?もし、君が本当に天才ならな。

これも穿った見方。

世間は、「天才の扱い方を知らない」。出る杭は打たれる。
ただ社会に出ただけでは金を稼げない。
自明ですよね「金を稼ぐ天才」ではないから。
仮にそうだとすれば、それは詐欺もしくは、それに近い何かでしょう。

技術の「天才」は、世間で活躍しにくいカテゴリだと思われます。
芸能や芸術は、一目見りゃ判る。
しかし、技術系は、判らない人に見せても「魔法」にしか見えません。
#ここで論じてる「天才」ならそのくらい行かなきゃ嘘でしょう。

要するに、「社会に出る」というか「雇用される」線で、
天才が活躍するのは困難だろう。というのが筆者の解釈です。

グーグルとか、外資系なら判らんでもないけど、
それは正しく、英語と数学が必須でしょう。
「一流の技術者」が言っているとおりにね。

真逆のアプローチとしては、
現代はインターネットが普及してるので、

アピール自体は困難ではないどころか簡単です。
一番現実的なのが、iPhoneアプリでも作ってしまうことでしょう。
ものすごい奴をね。それは何かは筆者には判りませんが。

これも英語版は必須でしょう。市場が比べ物にならない。
最近は物理演算の無駄遣いが流行ってるからひょっとしたら数学も要るかもね。

と言っている筆者は、「天才に似てるらしい、天才でない何か」なので、
間違ってるかも知れません。まあ間違ってるでしょう。今貧乏なんで。

2010年10月26日火曜日

app engine 新機能色々

筆者はGoogle app engineを非仕事で常用していますが、
オフィシャルブログ追っかけはやってないので、
結構出遅れます。

一つは remote_shell_api
もう一つは datastore_admin

remote_shell_api

データストアの中身を、直接CSV形式でダウンロードできたりとか、
app.yamlに書いて損無しのremote_apiですが、

- url: /remote_api  script: $PYTHON_LIB/google/appengine/ext/remote_api/handler.p
  login: admin

恐らくその全機能をコマンドラインで試行錯誤しながら叩けるという
刺激的なツールです。

+ python2.5 ../google_appengine/remote_api_shell.py アプリケーション名
No handlers could be found for logger "google.appengine.tools.appengine_rpc"
Email: ########Password: App Engine remote_api shellPython 2.5.4 (r254:67916, Jan 20 2010, 21:44:03)
[GCC 4.4.1]The db, users, urlfetch, and memcache modules are imported.
アプリケーション名>

メッセージがチラっと出てる限り、

  • memcache
  • データストア
  • グーグル認証

等々は使えるようです。
まあデータストアだけでも、ご飯3杯。

直ぐに思いつくのは、データストアに対する、ややこしい操作。
datastore viewで1個づつ書き換えるにはどうよ?という操作。
これをスクリプトで一括処理しちまおう。というのは誰でも考えると思います。
しかしスクリプト書いてデプロイ、を繰り返すのはかなり面倒です。

アプリケーション名> class sitedata(db.Model):...
 pass...
アプリケーション名> sitedata.all().count()
16
アプリケーション名> 

こんな感じで、(感覚的には)直接クラウドの「あっち側」をイジれます。
実際には、remote_apiが、20レコード単位っぽい感じで送受信してるので、
スピードは早くはありません。

筆者はこれで、念願の、データストア一括削除ができました。

しかし、流石のグーグル。もっと良い方法があったという。

Datastore Admin

builtins:
- datastore_admin: on

これを書いておくと、datastore adminのメニューから、
「一括削除機能」が使えます。
しかも内部で、Map/Reduceを使って削除するらしい。

データストアに、

  • _AE_MR_MapreduceState
  • _AE_MR_ShardState

が増えたり
MainのLogsに

  • /_ah/mapreduce/worker_callbak
  • /_ah/mapreduce/controller_callbak

がドンドコ増えたりとか
Map/Reduceの一端が垣間見える体験です。

2010年10月23日土曜日

大規模WEBサービスは、クラウドに倣うべき

日本国内の、主にケータイサイトの裏側は、「apacheとmysqlで構築してます」
なんて話は良く聞きますが、いずれも物理サーバを自前で置いている場合です。

最近ではamazon ec2の利用が増えているであろうと思いますが、
これを、ただ「安価なレンタルサーバ」として使うのは全面的に間違っています。

データが消えても良いことを最初から考慮して、
むしろ2分で新しいインスタンスが立ち上がることを積極的に利用するべき。

「スケーラブル」にしなければならないのに、「インスタンス1台づつ手動で立ち上げて」どうこうするのは無駄。

つまり、物理サーバとは別の運用パラダイムが必要です。
なんて話は、海外のクラウド畑ではあたりまえの話でしょう。
判ってないのは日本国内のお客さんだけ。

筆者が常用している海外のサービスは、最近ではtumblrぐらいですが、
どうも最近不安定。ポスト失敗したり。ダッシュボードが出なかったり。
リブログ主体ですから、画像の取扱いの主体が大変だろうと推測。

似て非なるtwitterは、質的にはリアルタイムチャット、
twitterのトラフィックの異常さは想像に難しくありません。

彼らの努力を見習って、同じ苦労は極力削減するべき。
この不景気、車輪の再生産をする余裕はありません。

運用面の工夫

TwitterがBitTorrentで高速にデプロイしている仕組みについて
http://www.publickey1.jp/blog/10/twitterbittorrent.html

そこでBitTorrentを使ってデプロイする「Murder」というツールを開発をした。Murderは、BitTorrentを包含して内部ネットワーク用にオプティマイズしたもの。これまで約900秒かかっていたデプロイの時間が約12秒になり、75倍も速くなった。


Twitterの大規模システム運用技術、あるいはクジラの腹の中(前編)~ログの科学的な分析と、Twitterの「ダークモード」
http://www.publickey1.jp/blog/10/twittertwitter.html

Twitterのクジラ解剖学、あるいは彼らがいかにサーバの処理能力を向上させたか
http://www.publickey1.jp/blog/10/twitter_4.html
ボトルネック調査

Twitterの大規模システム運用技術、あるいはクジラの腹の中(後編)~Twitterのサブシステム「Unicorn」「Kestrel」「Flock DB」
http://www.publickey1.jp/blog/10/twittertwitterunicornkestrelflock_db.html
ボトルネックの具体的な解消。ミドルウエアの積極的な交換。

kestrel
tiny queue system based on starling, in scala
http://github.com/robey/kestrel
タスクスケジューリングの解法(cronやatには限界があるのは周知)
memcachedの基盤を利用して、大規模分散キューを実現してる。らしい。

ストレージ面

基本的にshardingだけど、アプリケーションが個別に頑張るんじゃなくて、
RDBとの間にアダプタを挟むのが現実的。

Twitterが分散フレームワーク「Gizzard」公開! Scalaで書かれたShardingを実現するミドルウェア
http://www.publickey1.jp/blog/10/twittergizzard_scalasharding.html

GizzardはScalaで書かれたJavaVM上で動作するミドルウェアで、PHPやRubyといったWebアプリケーションからの要求を自動的にデータベースに分散することで、大規模で可用性の高い分散データベースを容易に実現するためのものです。

なんか日本語が変。「ScalaでかかれたJavaVM」に読める。こういう書き方をする人は多いですが。

GizzardはJavaVM上で動作するミドルウェアで、Scalaで書かれてる。Webアプリケーションからの要求を、自動的にデータベースに分散することで、大規模で可用性の高い分散データベースを容易に実現するためのものです。

http://engineering.twitter.com/2010/04/introducing-gizzard-framework-for.html
http://github.com/twitter/gizzard

NoSQLは
思ったより運用実績はないみたいですね。

TwitterとDiggがNoSQLの「Cassandra」を選ぶ理由
http://www.publickey1.jp/blog/10/twitterdiggnosqlcassandra.html

Twitterが、Cassandraの本採用を断念。「いまは切り替えの時期ではない」
http://www.publickey1.jp/blog/10/twittercassandra.html

それにしても、このうちGizzardとKestrelが、Scalaで書いてるらしい。
JVMベースの、「JAVAでない言語」恐るべし。

2010年10月22日金曜日

プログラマは魔法使いである。らしい。

何処かのSF作家の名言で、

http://ja.wikipedia.org/wiki/%E3%82%AF%E3%83%A9%E3%83%BC%E3%82%AF%E3%81%AE%E4%B8%89%E6%B3%95%E5%89%87

充分に発達した科学技術は、魔法と見分けが付かない。
というものがあります。
魔法と科学を区別するには、知識が必要である。そういう事です。
ズブの素人には、現代の技術も、魔法にしか見えないらしい。

http://www.webcreatorbox.com/webinfo/clients-funny-requests/
  • クライアントとレイアウトの変更について話しあっていた時、クライアントが油性ペンで私のMacBookのスクリーンにレイアウトを描き出したことがある。
  • 「サイトを印刷してみたんですが、GIFアニメーションが動きません。」
  • 写真に後ろ向きで写っている人を指さして「Photoshopでこの人を正面に向かせてください。」

流石に嘘くさいです。創作だと思いたい。しかしあり得ない話でもない。

これらのエピソードが示すのは、
素人は、「コンピュータが再現しているモノ」と「現実」の
区別が付いてない事が推測できます。

そして、「パソコン教室」のニーズが普遍であることも。
でも、前述の例の解説をするのは、骨が折れそう。

彼らにとって、「コンピュータが再現している事象」は全て「魔法」なのでしょう。
コンピュータなのだから、プリントアウトが「動く」なんて、簡単なのです。

って言うか、「鏡に驚く猫」レベルじゃね?

2010年9月12日日曜日

PHP5.3の名前空間がイケてない

名前空間の実装は、コンパイラ実装者にとっては悩みの種でしょう。
そういう事にしてください。

散々悩んで、PHP5.3みたいな有様になってしまうケースもままあります。

pythonの厳密には「モジュール」があり、その内側で「名前空間」に近い概念が使えますが、
非常に洗練していて、矛盾がありません。
その根幹は、名前空間ですら「オブジェクト」であるからです。
具体的には、module型。らしい。

  • Pythonのmodule型では
    • 1ファイル中で、名前空間(的なもの)を切り替えることは出来ない。
    • 変数や関数群は、単に実行中のmoduleのプロパティの一つに過ぎない。
    • importは、module型オブジェクトを、同名の変数に取り込む。
    • クラス定義(オブジェクト)とインスタンスは、収録している変数が違う筈なので、混同のしようがない。

javascriptも、これに近い運用ができますね。
端的に言えば、「別の名前をつける筈」なので、「「名前空間名と、クラス静的メソッド等を混同する」ような作り方はしない」

故に、これが、「名前空間専用の、階層区切り文字の設置」の理由にはなりません。
こんな理由が、バックスラッシュの理由で、まかり通っちゃ如何でしょう。
PHP関係者が、如何に他の言語畑とくらべて緩いのか。
言語側から、これを強制できなかったのは、PHP5.3の大失敗の一つでしょう。

PHPの名前空間の区切りがバックスラッシュになったのはそんな理由だったのか

誰かさんの記事ですから、また聞きですが

http://blog.ohgaki.net/php_5_3_namespace

何故このようなエントリを書くかというと、Software Design(技術評論社)の11月号にPHPの最新情報としてα版PHP 5.3を紹介しているからです。入稿後に仕様変更があったので最新号の記事ですが既に内容が古くなってしまいました。
# とは言ってもまだ新しい仕様のPHPは無いですが
α版なので仕様や機能が大きく変更される事もありますが大きな変更がありました。見本誌が刷り上がった頃に名前空間の区切り文字が"::"だと静的にメソッドを呼び出す場合やクラス定数を呼び出す場合に困る場合がある、とPHP開発者のMLで議論になり始めました

マジで?
イヤイヤ、その反論はオカシイデショウ。(リンク先の方に反論している訳ではありません)
という反論は誰かがしているはずだと思いたい。

よく読んでないけど、さらにそれの反論が、これかな。英語なんだよなー。

http://www.sitepoint.com/blogs/2009/08/13/are-php-namespaces-bad/

「静的メソッド&静的クラス変数を呼び出す時に困る。」
そうならないための名前空間じゃないのかと。

もしくは、作り方が下手なんじゃね?
もしくは、「困る」なら、その人にとっては要らない機能なんじゃね?

名前空間とクラスが、どうやら完全に別物だと考えちゃってるのだけど。
pythonを経験すると、決してそうではないということが解る。

やはりそもそもの失敗が、変数と、定数とで、それぞれ構文が違っちゃってるところ。
(まさかその時にも、「○○の時に困る」とか誰か反論したんじゃないでしょうね?!)
コンパイラが継ぎはぎだらけなのは明白です。
さらにそれに、名前空間のために、新しい「継ぎはぎ」を加えたのでしょう。

2010年9月11日土曜日

pike、結構速いぞ?!

結構な昔からありますが、pikeというスクリプト言語があります。マイナーです。
http://pike.ida.liu.se/

そして、これまたマイナーなroxenというwebサーバの、
http://www.roxen.com/products/cms/webserver/
サーバサイドスクリプト言語でもあります。

pikeはC++/Cに似た感じの言語ではあるので、
そういう人々にwebの仕事をしてもらうのに都合が良いかと思っていたのですが、
だいたいそういう方々にはjava/PHPをやってもらっちゃうご時世です。

しかし、PHPは、スクリプト言語としてはどうやら遅い方らしい?

そこで思いだしましたpike。しかしマイナー過ぎて性能情報がありません。
仕方がないので自分で試してみました。

ベンチマークは数ありますが、マンデルブロ集合のものがソース付きだったので、
pikeに移植して、同じ条件で比較してみることに。

オリジナルはここでhttp://www.timestretch.com/FractalBenchmark.html
例によってgistに貼りました。http://gist.github.com/574137http://gist.github.com/574135
結論から言うと、かなり早いです。驚きました。luaに匹敵する性能でした。
http://gist.github.com/raw/574260/f7ad985013a5538921de98a67aafba67b2e781d5/gistfile1.txt
pikeは言語的にはこんな感じなので、
http://gist.github.com/raw/574137/a0d678929dc08cbc034ff9584fb7cebce16c84aa/mandel.pike
C++/Cの人に、PHP/python/luaをやらせるよりは現実的じゃないでしょうか?

http://gist.github.com/raw/574135/48624475858c4cd37fe488c320d7ae5ddaf8bc50/mandel.c
ほうらソックリ。
例によって、全自動スクリプトも作ったので、皆さんも自分の目でお試しを。http://gist.github.com/574260

2010年8月27日金曜日

youtube-dl 日本語版

職業プログラマで、自宅あるいは会社のPCに、
linux入れてます、って変人は少なくないと思います。
いやそういう事にしてください。

linuxであれば、youtubeの動画の保存には、
当然youtube-dlを使ってますよね。
いやそういう事にしてください。
http://bitbucket.org/rg3/youtube-dl/wiki/Home

コマンドラインのダウンローダは数あれど、
ファイル名に、youtubeの動画idを付けてくれるのは意外と少ないです。
#動画のページタイトルからタイトルを作ってくれるのは当たり前。
デフォルトで、というべきか?

ところが、残念なことに、日本語のファイル名を作ってくれません。
日本語部分というか、黄色人種の国の文字がバッサリ落ちます。
まあ作者は英語圏の人っぽいので、まあ読めない文字でファイル作られても楽しくはないでしょう。

仕方がないので、個人的に日本語パッチ当てて使ってましたが、
bitbucketでは、他人のフンドシで相撲がとれる(fork)らしい。

それって。本家の人はどう思うんだろう?
そしたら居るわ居るわ派生バージョン。
http://bitbucket.org/rg3/youtube-dl/descendants

はい、forkさせていただきました。
https://bitbucket.org/kamawanu/youtube-dl-japanesefilename
mercurialだっつーのも活けてますね。
#gist/githubはあっちはあっちで使ってますが、gitには微妙に馴染めません。

と思っていたら、githubに引っ越しちゃってました。

やっぱりforkするわけですが

2010年8月14日土曜日

「速い言語」とは何なのか?

先日、PHPは遅い的なエントリを書いたばかりですが、

プログラミング業界にとっては、
「書きやすく、しかも何を処理しても速い」言語が永遠のテーマです。
実際にはそれほど上手い話はあまり有りません。

多数の言語が存在していることが、
逆にその証明になってるでしょう。

優れた言語であっても、不得意分野が必ずあり、
そのための言語が必ず産まれます。

似て非なる話で、MS Windowsプログラムでは、
古来ではwin32 apiを直接呼んでいたりしてましたが、
ある時から、MFCとか言い出しました。
GUIの「複雑な実装」には「オブジェクト指向」の考え方を取り入れるしかなかったからです。と、筆者は考えていますが。
更にそれでもダメで、C#とか言い出した。まあC#の言語としての評判は悪くなさそうですが。

「何を処理しても速い言語」はどうやって探すのか?

言語の実効速度の比較には、「ベンチマークテスト」がありますが、それをやっているサイトは、多数あります。

http://shootout.alioth.debian.org/u32q/which-programming-languages-are-fastest.php

大抵は、「Cが爆速で、スクリプト言語は激遅」みたいな結論に落ち着きがちです。

その中身は、「エラトスネスの篩」だったりとか。

いや、悪いって言うんじゃなくて、
言語の一部の性能だけを見ているのは確かですね。

例えば、前述のエラトスネスの篩だと、
多回転ループ、長配列の処理ってことになりますが、
果たして、実際の実装で、そういうケースが有るのかどうか?

って言うか、ネエよ!
受注開発で「エラトスネスの篩を作ってください」とかネエよ!

言語の「設計思想ベンチマーク」とでも言うべきものなのかも知れません。

ドコゾの何かのアプリケーションで、ベンチマークモードとかあるとか聞いたような。コンパイラだったかな?

もっと「実際の摘要に即したベンチマークテスト」が必要なのではないでしょうか。

「速い言語」を探して何をするのかというと、
最近ではもう大体webアプリケーションサーバでしょう。
#一昔前はWindows MFC一択でした。いい時代です。

じゃあ何を使えば良いのか?

C/C++で書くのが「速い」のは判りきってる事ですが、
それは低級言語だからであり、コンパイラだからでも有ります。

しかしwebアプリケーションをC/C++で書く、
なんて話は聞いたことがありません。

webアプリケーションの処理は、
文字列を切ったり貼ったりが非常に多く、
それはC/C++では、不得意分野だからです。
所詮は、言語はプログラムの手段、道具なのですから、
適材適所でしかるべきです。

そして、何やら、爆速テンプレートエンジンが有るって言うじゃありませんが。

http://www.kuwata-lab.com/tenjin/
名前からして日本人の作かな?と思いましたが、
英語ページしかありません。

#テンプレートエンジンだから、Tenjin?
#日本人のセンスだよなあ。

テンプレートエンジンの実装として、馬鹿正直に考えると、
大抵は、◯◯クラスを定義して、
テンプレート文字列を切ったり貼ったりする訳ですが、

このTenjinとやらは、そうではないらしい。

内部では、完全な単体スクリプトに変換してしまうらしい。
http://www.kuwata-lab.com/tenjin/phptenjin-examples.html
軽量言語のみサポートしているのもそういう事なのでしょう。

バイトコンパイラの性能頼みですが、実際速いらしい。
http://www.kuwata-lab.com/tenjin/img/fig01.png

比較対象が、不利な実装になってる可能性は否定できませんが、
Tenjin自身がそれだけ速いのなら、使ってみようか、
という気にもなります。

似たようなコンセプトで、JavaにはJSPが有る訳ですが、
残念ながらJSPが遅いのは有名です。
http://d.hatena.ne.jp/kwatch/20100603/1275524286
何故か、を危うく書こうとしてしまいましたが、
知ったかぶりが露呈するので辞めておこう。

2010年8月8日日曜日

mercurialとsubversion file:の実行時間測定

出稼ぎ先で、subversionに悩まされてます。

悩んでいる理由はさて置き、とりあえず「遅い」です。
mercurialに慣れた筆者には、20倍は遅く感じます。

具体的に、どの程度遅いのか、測って見ました。

結論から言うと、subversionはローカルで動かしても、
mercurialの2〜3倍遅い。ということに成りそうです。

Cで書いてある筈のsubversionが
pythonで書いてあるmercurialより遅いってどうよ?

普通にベンチマークすると、真逆になる話ですね。

速度に影響するのは、実装言語じゃない。
データ構造とアルゴリズムであるという。
好例ですね。

/usr/bin/timeで簡単に測ってみると、
subversionは、sysの時間が長めに見えます。
disk IOがネックになってる?

カーネルソースは、バージョン管理の「具」としては、
上品な部類だと思います。
これで、巨大なバイナリやらも詰め込んだらどうなることやら。

linuxカーネル2.6.35のソース 66MB

tarの展開
real 1m2.495s
user 0m43.451s

hg init
hg add
real 0m9.517s
user 0m1.940s

hg commit
real 1m12.223s
user 0m54.771s
#更新数 33316

hg clone
real 0m44.199s
user 0m22.597s

svn import linux-2.6.35 file://*/SVFS -q
real 3m47.385s
user 1m7.488s
sys 0m26.194s

svn co file://$PWD/TEST-SVFS linux-co -q
real 2m13.232s
user 0m47.135s
sys 0m18.765s

2010年4月23日金曜日

pythonにはnew演算子がない

pythonでは、インスタンスの作成で、new演算子を使いません。
というか、「new演算子」という構文が存在しません。

PHPやJavaやらCやらの経験者からすると、
これはやや気持ち悪い。
具体的には小生がそうでした。

ただし、その方法論が腑に落ちると、「new「演算子」」のある言語が「オブジェクト指向言語」に見えなくなってきます。少なくとも小生はそうです。

順番に行きましょう

pythonでは、普通の言語でいうところの「クラス宣言」は有りません。
しかし、同等の機構はあります。クラスオブジェクトの作成です。

http://www.python.jp/doc/2.4/tut/node11.html#SECTION0011320000000000000000

下記の例で言うと、anyclass変数に、クラスオジェクトが入ります。
 class anyclass(object):  pass
インスタンスの作成はどうするかというと、作って有るはずの、クラスオブジェクトをcallしてるわけです。だからnew演算子を付けちゃいけません。「呼んでる」だけだから。
instance_object = anyclass()
これはpython的には、「class宣言は、type型インスタンスを作ってるだけで、それはcallableである」というところです。フツーの言語が、new演算子を起点にして、「コンパイル時」にやってることを、callableを経由して「実行時」にやってる。ここがpythonの肝です。

もちろんこんな空っぽのクラスは何の役にもたちません。とりあえずメソッドを足します。
class hasmethod(object):
 def method1(self): pass

pythonは、言語としては珍しく、メソッドの引数として「自分インスタンスオブジェクト」を第1引数に書かなければなりません。

インスタンスを作ると、クラスメソッドとインスタンスオブジェクトが結びつきます。
instance1 = hasmethod()
instance1.method1()

ここでのポイントは、

instance1.method1() と、hasmethod.method1() は別物である。

ということです。

  • 前者は、インスタンスに結びついたメソッドオブジェクト
  • 後者は、結び付いてないクラスメソッドオブジェクト。
後者は、「結びついてない」ので、
インスタンスオブジェクトをどうにかして渡す必要があります。

それで第1引数 self の出番というわけです。

前者は、「結びついてる」ので、pythonがselfを勝手に足してくれます。故に、インスタンス関数呼び出しでは、self 以外の引数だけを書くわけです。


instance1 == self
とは言え、この調子だと、普通の言語で言うところの、静的メソッドは?このままでは無理です。しかし方法は有ります。

class statichas(object):
 @staticmethod
 def method1(): pass

@staticmethodデコレータを挟むだけです。

フツーの関数宣言は、selfが必要ですが、今度は逆に、selfを入れると怒られます。pythonは、selfを引数に勝手に加えるのを辞めます。staticmethodは、そういうマーキングをやってるらしい。この状態では、method1を直接呼び出すことができます。 http://docs.python.org/c-api/structures.html#METH_STATIC

statichas.method1()

ただしこれでは問題が無くもありません。関数の中からは、クラスもインスタンスも解らないので、クラス内の他のメソッドも使えません。

#逆に、一人完結してます。というアピールに#@staticmethodを使うのは、筆者はアリだと思います。

前述のクラスメソッド表記で呼び出せなくもありませんが、クラスを継承する状況を想定すると、固定で書くのは避けたいですね。

ハイ。そこで出てくるのは、@classmethodデコレータです。フツーの言語の、静的メソッドに相当するのは、むしろコッチでしょう。
class statichas(object):
 @classmethod
 def method1(cls1):pass
引数に必ず1個入ります。わざわざclassmethodと付けたのは意味がもちろんあって、
「「インスタンスオブジェクト」で無いモノ」を付けてね」という意味です。らしい。http://docs.python.org/c-api/structures.html#METH_CLASS 前述のtype型インスタンスなので、歴史的&一般的にselfとは付けません。世間一般にはclsとだけ付けるっぽいですが、小生は3文字変数に辛い思い出があるので、"cls1"にしてます。
statichas.method1()
表面上は、さっきのstaticmethodと同じ使い心地です。しかし、cls1には、statichasクラスオブジェクトが入ってます。classmethod同士を呼び出す分にはこれで行けますね。

statichas == cls1

しかも継承すれば、継承後のクラスオブジェクトがcls1に入っている。

という寸法です。

面白い発想ですね。

具体的には、app engine python-SDKのgoogle.appengine.ext.db.Model.get がlassmethodです。小生は、この辺りの実装を眺めていて、感動すら覚えました。

class「定義」の構文は、フツーの関数定義を「メソッド呼び出しに変換する」処理であると考えれば、腑に落ちると思います。故に、$thisを暗黙で「渡さない」方が何かと都合が良いわけです。

これを利用して、定義済みクラスじゃなくてtypeオブジェクトに、メソッドを後付けできます。「class定義」がコンパイラの仕事じゃないから出きることですね。真の動的言語の何たるかを見た気がします。

そんな訳ですので、フツーのインスタンスメソッドから、classmethodを使うときにはどうするか?構文を区別する必要があります。
self.__class__.method1()
static::method1とか書くより解りやすい気がすると思うのですが、どうでしょう。ダブルコロンとかバックスラッシュとか要らないわけです。オブジェクトだから。

今まで、インスタンス作成、メソッド呼び出し、と色々述べましたが、

表記上の違いはほとんどありませんし、Python内部でのメカニズムの違いも殆どありません。 他の言語でいうところの「クラス定義」は、「タイプ型オブジェクト」でしかないので、「◯◯オブジェクトのメンバ関数を呼ぶ」という機構は統一できてるわけです。


  • インスタンスメソッドを呼び出す場合
    • instace1インスタンスオブジェクトのmethod1メンバをcallする。
    • 特にmethod1にマークは付いてないので、引数の先頭にinstance1を挿入する
  • staticmethodを呼び出す場合
    • class1タイプオブジェクトのmethod1メンバをcallする。
    • staticmethodマークが付いてるので、引数には何も足さない。
  • classmethodを呼び出す場合
    • class1タイプオブジェクトのmethod1メンバをcallする
    • classmethodマークが付いているので、引数の先頭にclass1を挿入する。



呼び出し可能なオブジェクト(特にcallableと呼ぶ)を、呼んでる(call)だけ。

これに付きます。


これが腑に落ちると、途端に「new演算子のあるオブジェクト指向言語」が駄目言語に見えます。

筆者はここまで徹底したオブジェクト指向を他に知りません。
#ご存知の方は、教えてくれなくてもいいです。長くなりそうなんで。

識者が言うところによると、pythonは、広義には関数型言語らしい。
haskelには気絶しそうになりましたが、大分判りやすくて助かります。

2010年4月20日火曜日

関数と戻り値と例外

値を返さなくても、「関数」とはこれ如何に?

ソフトウエアでいう「関数」は値を返さない事もあります。

関数が「値を返す」と言っても、その関数を呼んだ側が、変数に入れなければ、返さないのと同義ではあります。ただし、関数の実装としては、返すのと返さないのとはおお違いです。

perlでは、関数の最後の「式」を返します。なんか過激な実装ですが、何かしら値は戻るでしょう。

pythonとPHPは、return文の式の値が戻ります。しかし、returnを書かなくてもインタプリタは怒りません。更に、関数を呼んだ側でもエラーにはなりません。

変数の中身には?null/Noneが入っています。

これは、ハマる場合がままあります。

実装者の趣味次第だとは思いますが、
  1. 配列を渡して
  2. 何らかの処理をさせて
  3. 出来上がった配列を返す
そういう関数を想定してください。しかし、例によって、プログラマは間違えますので、
変なデータ(上の場合には、空の配列とか)をもらった場合には、何かしら「変でしたよ」って言わなきゃなりません。

変だったなりに処理を続けるか、エラーにするかは悩みどころです。

エラーの場合にはnullを返す。のは割とよく考えると思います。あれ筆者だけ?しかし、returnを忘れてもnullが帰ります。


  • エラーだったのか?
  • return忘れだったのか?


デバッグが面倒臭いことになります。

そこで例外の出番です。

「例外処理」を何故「エラー処理」と命名してないかというと、「エラー」とは限らないからです。より上位の処理で、回復できる&代替できる可能性があるからです。ユーザには、「エラー」と言わないケースもあります。

例えば、営業職の人が、顧客に怒られた。しかし、上司が出張ってくれば、オトナの解決法があるかもしれません。これが例外処理です。

顧客からクレーム系は、まあエラーと言っちゃってもいいかも知れませんが、不可抗力やら外的要因やら、色々あります。

当事者の手に余る自体は、「例外」です。上司に連絡しましょう。

入力間違いなんかは、本来は、「処理関数」に入れるまえに処理すべきでしょう。そういう意味では「処理関数」の手には余ります。「処理関数」の立場では、「エラーだ」とも言えません。

Javaは、例外を馬鹿正直に実装した言語の代表と言えましょう。

関数宣言で、自分が出す予定の例外を列挙しなきゃなりません。さもないと、関数内部で、thrawさせてもらえない。しかも、呼び出す方では、必ずcatchしなければならない。

悪い手ではありませんが、面倒臭くなりがちなので、とにかくcatchを書くけど、何もしない、みたいな形骸化する可能性はあります。面倒臭いからnullを返しちまえ。とか。

とは言え、例外補足を要求しない言語だと、そのまま例外が画面表示まで貫通しちゃって、ようやく思い出すので、どっちもどっち。

って言うかね。
appengine pythonだと、return忘れとか、
例外が画面まで出ちゃったりとか。

とりあえず次回は忘れないようにエントリを書いている次第です。