「シリコンバレーのお約束」をことごとく破るアップル

Google's famous catchphrase, "Don't be evil," has become a shorthand mission statement for Silicon Valley, encompassing a variety of ideals that proponents say are good for business and good for the world: Embrace open platforms. Trust decisions to the wisdom of crowds. Treat your employees like gods. It's ironic, then, that one of the Valley's most successful companies ignored all these tenets. 【Breaking the Rules: Apple Succeeds By Defying 5 Core Valley Principles

 シリコンバレーを代表する会社の一つであるアップルが、オープン・ソース、オープン・プラットフォームなどに代表される「独り占めしない」という「シリコンバレーのお約束」をことごとく破っているというWiredの記事だ。

 WebKit関連での動きなどを見ると必ずしもそうではないのだが、iPod+iTunes+iTunes storeというラインでの「囲い込み戦略」はアップルの戦略の要(かなめ)でもあるわけで、当然と言えば当然。それよりも興味深いのが、Mac/iPhoneにおける徹底的な「独自OS戦略」。

 特に後発のiPhoneに関しては、NokiaがしているようにJava+Flashあたりで攻めるのが通常の戦略だが、独自のハードウェアに最適化した独自のOSで真っ向から攻めてくるところが、何ともアップルらしいと言うか。

 しかし、Mac向けのOS Xまでは静観していた私もなぜかiPhone SDKには妙に熱くなってしまっているところがアップルの戦略にハマってしまったというか何と言うか。まあせっかくの縁だからこうなったらiPhone向けに何か本気で作ってみるのも悪くないな、と。


Born to code

大まかな設計図をあたまに浮かべ、おもむろにコードを書き始める

 下回りの部品から順番に、丁寧に積み上げて行く

それでも必ず後から下回りの設計に気に食わない部分が出てくるので、

 苦しくてもそこは躊躇せずに壊しては作り直す

そうして行くうちに、だんだんと下の方から設計がしっかりしたものになってくる

 踏み固められた地面が固くなるように、少しづつ強固なプラットフォームが作られて行く

「今日はここまで実現しよう」と決めたら死にものぐるいでそこまで走る

 でも頭が回らなくなってきたら早く寝る

そうやって愛しい我が子を育てる様にコードを一行一行書いていく

 何百万人、何千万人もの人に使ってもらえる日を夢見ながら

プログラミングという楽しみがある時代に生まれて来ることができた幸せを噛み締めながら


WSSEのセキュリティリスクとその対処法に関する一考察

 引き続きiPhone SDKで遊んでいる私だが、Typepadやはてなが採用しているAtomを使ったiPhoneアプリを作ってみようとしたところで、WSSE認証の仕組みを(Objective-Cで)ゼロから作らなければならないことに気づき挫折しかける。SHA1のライブラリまで自前で用意しなければならないのはちょっと荷が重かったのだが、増井さん(masuidrive)からRFC中のコード(参照)が使えることを教えていただき、それを元に実装(持つべきものは友だ^^)。

 細かな間違いをいくつもしていた上に、WSSEの仕様を少し勘違いして始めたためになかなか動かず、はてなからステータスコード200がもらえたのは夜の10時過ぎ。半日ぐらいで軽く作れると思っていたのに、結局丸一日かかってしまったが、「WSSEとは何ぞや」を何も知らないところから始めたのだから良しとしよう。

 しかし、WSSEの仕様に関して少し心配なのは、生のpasswordテキストをcreationDateとNonceをくっつけてからハッシュを作ってからサーバーに送るという部分。認証のためにはサーバー側で全く同じ計算をしなければならないのだが、そのためにはデータベースに生のpasswordをしまっておかなければならないことを意味する。これはセキュリティ上大きな問題があるように思える(参照)。

 私の知る限り、複数のアカウント間で同じパスワードを使っている人は多い(これはこれで大きな問題だが、そんなユーザーたちを非難するのではなく、ちゃんと守ってあげるのがジェダイ・ナイトのおもてなし)。そんな人たちのパスワードを「万が一のデータ漏れ」から守るには、パスワードをそのままデータベースにしまうのではなく、SHA1などの一方向関数を使ってハッシュ化してからデータベースに格納しておくべき。そうすれば、なんらかの理由(ハックされる、マシンが盗まれる、社員が暴走するなど)で「データ漏れ」が起こってしまった場合にも、被害をそのサービス内だけにとどめることができる。

 という意味では、元々のWSSEのスペックを少し拡張し、passwordをサーバーに送る際には、サービス独自のハッシュをかけたもの(hashedPassword)をcreationDateとNonceとくっつけてからさらにハッシュをかけてからサーバーに送り、サーバー側では生のpasswordではなく、hashedPasswordををデータベースにしまっておき、それを利用して認証するようにすれば良いと思うんだがどうだろう。

 もう少し分かりやすく言うと、

 base64(SHA1(password + creationDate + Nonce))

を送るのではなく、

 base64(SHA1(SHA1(password+"hatena") + creationDate + Nonce))

を送り、サーバー側ではデータベースにしまっておいたhashedPasswordを使って、

 base64(SHA1(hashedPassword + creationDate + Nonce))

を計算して比較することにすれば良いというのが私の提案である。

 WSSEの存在を知ったばかりの私が言うので、何か大きな勘違いをしているかも知れないが、こうやって文章にして公開することにより、より理解を深めようと言ういつもの作戦だ。

 それにしても、暗号の話はこんなふうに一筋縄で行かないところがとても面白い。全体としてどんな技術が何のために作られているかを理解するにはサイモン・シンの暗号解読がおすすめだ。


「作っては壊す」過程があってこそ良いものが作れる

 iPhone用の「はてな人気エントリーリーダー」、そろそろ形になってきたのだが、作ってみていろいろと発見した部分もあったので、全面的にクラス構成を見直し、大幅に書き直した。

 HTTPで通信をしているコードが二カ所に分かれていたので、それをDataOverHTTP/XMLOverHTTPという二つのクラスにまとめ(XMLOverHTTPはDataOverHTTPのサブクラス)、はてな独自のRSSフィードを読んでいるコードから一般的なRSSフィードを扱うコードをくくりだしてRSSFeed/RSSFeedLoaderという二つのクラスにまとめて、あとで別のアプリケーションで再利用することを可能にした。それに加えて、各種ローダーに非同期通信をさせる主体をController(HotEntryViewController)からModel側(HateneHotEntry)に移すことにより、難解になりがちなControllerのコードを大幅に簡略化して読みやすくした。

 この手の「大幅書き直し」をリファクタリングと呼ぶ人もいるが、私にとってはこの手の書き直しはプロジェクトの初期においては日常茶飯事。「これで完璧」と思ったものを次の日にさらに大幅に書き直し、なんてことも良くある。どんなに賢いエンジニアであっても、最初に思いついたアーキテクチャが最適であるなんてことはまずあり得ないので、この「作っては壊す」段階はより良いアーキテクチャに到達するためには必須の工程。焼き上がった壷が気に入らずにたたき割る陶芸師と同じだ。

 この段階で目指すことは、とにかくメンテナンスのしやすいコードを生成すること。プロジェクトも後半になるとどうしても大規模な書き直しはしにくくなるため、その場しのぎのコードでプログラムはどんどんと「きたなく」なって行く。その時に大きく影響してくるのが、プロジェクトの前半で書いたコードの品質。基盤さえしっかりしていれば、「その場しのぎコード」が多少混ざったところでなんとかなる。基盤がぐらぐらしていると、デスマーチあるのみだ。

 NTTの研究所にいた時にかいま見たウォーターフォール型の開発は、上流にいるエンジニアがフローチャートのレベルまでに落とし込んだ詳細設計書を下請けに渡して「コード化」するというものだったが、ここで完全に欠如しているのは、この「作っては壊しながら設計を改良して行く」という工程。

 私の経験から自信を持って言えるのだが、どんなに優秀なエンジニアでも、この「作っては壊す」という過程を経ずには良いソフトウェアは作れない。料理でも陶磁器でも同じだが、ソフトウェアには「作ってみて初めて分かる」ことがたくさんあるので、そこからのフィードバックを主任設計者が自らコードを書いて実感することがとても大切なのだ。

 ソフトウェアを作る上でもっとも難しいのは、顧客や内部からのあいまいな要求を詳細設計書に落とし込む部分であることは誰でも知っている。しかし、意外にちゃんと認識されていないのは、良い詳細設計をするためには、実際に設計者自身が(ここが大切、他人に任せてはいけない)プロジェクト初期段階で、自分が考えた設計をコードに落とし込んで「作っては壊す」という作業を繰り返しながら(コードではなく)設計そのものを「練り上げて行く」過程が必須だということ。

 それはシェフが新しく思いついたレシピに基づいて実際に料理をしながらレシピを改良して行く過程、もしくは陶芸師が焼き上がった壷のできを見ながら製造工程を改良して行く過程と全く同じだ。実際に料理を作らずにおいしい料理のレシピが書けるシェフがいないのと同様に、実際にプログラムを書かずに品質の高い詳細設計書など書けるエンジニアがいるはずがない。


つづいて壁登りロボット

 ついでに見つけた壁登りロボットでもまたまた感動。しかし、日本のロボットと米国のロボットの方向性がかなり違うのが何とも。

  • 日本のロボット研究者が二足歩行にこだわるのはやはりアトムの影響か
  • 米国のロボットが実用性を重視しているのはやはり軍事予算のためか
  • 日本の美少女ロボットはやはり秋葉原の影響か
 

しかし、ソニーがロボットの研究から手を引いたのは痛いな、と。


4足歩行ロボットのビデオを見て思ったこと

 こういう新しいテクノロジーを見た時に感じるものは人それぞれだと思う。私の場合は「どうやって動いているのだろう」よりも「何に応用できるだろう」が常に先に来る。障害者用の歩行椅子とか、ボストンバッグとか。4本足のボストンバックが紐をひっぱるだけで犬のようにピョコピョコと付いて来たら楽しいかも。階段とか楽だし...


iPhone SDKとカリン塔の共通点

Smily  忙しいながらも時間を見つけてぼちぼちとサンプルプログラムを書き直したりして遊んでいるiPhone SDK。まだまだ慣れないところもあるが、すこしづつコツがつかめて来た感のあるObjective-C。今年はJavascriptとAction Scriptを極めようと考えていたのに、なんだか大幅な方向転換をしてしまいそうな予感(ちなみに、右に貼付けた画像は昨日作った「マルチタッチお絵描きソフト」で描いた絵)。

 誰でも無料でダウンロード出来るSDKでありながら、秘密保持契約に同意させるAppleは何をたくらんでいるのか。そのおかげで具体的なAPIの評価やサンプルコードの公開をして良いのかダメなのかが分からないので困る。今年のもう一つの仮題である「英語ブログの継続的な更新」には格好なテーマなのに...。それまでは仕方がないので、非公開の裏ブログでこつこつとサンプルプログラムの解説などを書いておくとするか。そのうち本にして出版するという手もあるし。

 ドキュメントは良く書けているし、サンプルも沢山あるのだが、OS Xで一切プログラミングをしたことの無い私にとっては、天までとどくカリン塔を目の前にした孫悟空の気分。

 「ひぇー、カリン塔ってすっげー高ぇな。でも、オラ、何かワクワクしてきたぞ!」


iPhone SDKとObjective-C:ニートは社会のメモリーリーク?!

 飛行機の中に9時間ほどネットもテレビもない環境に閉じ込められていたおかげでObjective-CとiPhone SDKの勉強もとても良くはかどり、簡単なアニメーションぐらいアプリなら作れる様になったし、Objective-Cでプログラムを書くことにもだんだん違和感がなくなってきた。

 しかし理解が進めば進むほど分かってくるのがiPhoneがいかに他の携帯電話と比べて進化しているかということ。OS Xの不要な部分はばっさりと切り捨てつつ、Objective-Cの拡張性を最大限に利用したとても完成度の高いものとなっている。

 特に良くできているのが、iPhone特有のユーザーインターフェイスを実現するために仕組みと、メモリ消費と電力消費を抑えるための仕組み。特に、バーチャルメモリの仕組み、リードオンリーリソースの扱い、ハードウェアアクセラレータの活用、アプリケーションプロセスの扱いなど、それぞれが徹底的にまでiPhone向けにオプティマイズされている。

 こういう設計を見ると、モバイル端末でWindows Vistaをそのまま動かすことがどのくらい無謀なことかがはっきりと認識できる。よほど大改造をしない限り、電池が持たない。

 ちなみに、iPhone OSはMac OS Xと異なりガベージコレクションをサポートしていないが、autoreleaseという仕組みでC++のスマートポインターと同じような効果を実現しているが。それが妙に気に入ってしまった私。

 具体的には、こんな感じでコードを書く。

    MyView* view = [[[MyView alloc] initWithFrame:frame] autorelease];
    [window addSubview:view];

 少し分解して順番に説明すると、

  1. [MyView alloc] // MyViewクラスのインスタンスを作る
  2. [... initWithFrame:frame] // そのインスタンスを指定した大きさでイニシャライズ
  3. [... autorelease] // そのインスタンスのリファレンスカウントを後で一つ減らすように指示
  4. MyView* view = ... // そのインスタンスへのリファレンスをviewにしまう
  5. [window addSubview:view] // それをwindowの子ウィンドウとして登録する

ということをしているわけだが、重要なのは3番目のautorelease。「アプリケーションがメインループに戻ってからreleaseしてくれ」という意味だが、こうやって新しくオブジェクトを作った後ですぐに誰かにオーナーシップを渡す場合(この場合は親ウィンドウに渡している)、こんな風に「作ってすぐautoreleaseする」ことにより、実質的なリファレンスカウントを持たないローカルリファレンスを持つことができるのだ。

 これは人間で言えば、子供が生まれたとたんに「お前とは親子でもなんでもない。勘当だ。でも大学を卒業するまでだけは家に置いておいてやる」と言うようなもの。生まれてすぐに勘当しておくことにより、大学を卒業してもいつまでも家にゴロゴロしているニートになることを避けているわけである。


iPhone SDK、Objective Cが持つ「進化する能力」の遺伝子

 Objective Cの勉強から始めなければならないiPhone SDKは、いきなりコードを書き始めることが出来ない点が少しもどかしい。しかし、C++に関しては最初の商用コンパイラが出たころからの付き合いだが、Objective Cに関してはまったく付き合いがなかった私としては、結婚20年にして初めて浮気をするかのようなドキドキ感とともにObjective Cとの最初のデートに臨んでいる、という感覚。

 すなおな目でObjective Cを見なければならないのにも関わらず、ついついC++と比べてしまう私。個々のシンタックスの違いに目を奪われつつも、言語仕様の背景にある設計思想を読み取ろうとする行動は、外見だけに捕われず彼女の中身を理解しようとする行動と同じ。

 そんな中でちょっと気にかかったのが、categoryという既存のクラスを拡張する仕組み。言語仕様を見ただけでは、いまいち存在意義が伝わって来ないのだが、ここらあたりにC++とObjective Cを本質的に隔てる「何か」がありそうだが...。

 その予感が的中していたことは、Appleが提供しているUIKit(iPhone用のUIフレームワーク)のチュートリアル・ビデオを見ている最中に判明する。そこに"hello"という文字列変数(型はNSString)を表示するサンプルが出て来るのだが、そのコード、

[hello drawAtPoint:location withFont:font] // C++の hello.drawAtPoint(location, font)に相当

を見て「あれ?」と思った。NSStringは、Mac OSと共通のCocoa Foundationという下位レイヤーで定義されたクラスの一つ。それがなんでiPhoneだけに存在するUIKitという上位のレイヤー向けのメソッド"drawAtPoint"をサポートしているのだろう、と。

 その疑問は、NSStringの定義されているヘッダーファイルを見てすぐに解決した。NSStringというクラスそのものはFoundationで定義・実装されているのだが、drawAtPointというメソッドはUIKitがcategoryの仕組みを使って「追加」しているのだ。これは、RailsがRubyが提供しているシステムクラスを拡張し、jQueryがJavascriptが提供しているシステムクラスを拡張しているのと全く同じ発想だ。

 つまり、Objective Cは、上位のフレームワーク(もしくはサブシステム)で下位のフレームワークが提供しているクラスを拡張することを可能にするcategoryにより、不必要なサブクラス(例えばGraphicsAwareStringクラス)の導入や、スパゲッティコードの元凶である「下のレイヤーから上のレイヤーへの依存」なしにクラスを使う人の利便性を上げることを可能にしているのだ。

 地球上にこれだけバラエティのある動植物が反映しているのは、生物が進化の過程で「進化を容易にする」仕組みを獲得したことによる(雌雄に分かれて遺伝子を交換しあう仕組みなど)が、その意味では、このcategoryはObjective Cの進化を容易にするという意味で重要な役目を果たしているような気がする。

 考えてみれば、90年代にOSの大改造に失敗したAppleはWindows95の成功にあやうく倒産の危機にまで合うことになったが、今度はVistaでOSの大改造の失敗したMicrosoft(Microsoftは当初、すべてのシステムAPIを.Net VM配下のマネージドAPIにしようと計画していた)がAppleに大きく遅れを取っているという点は以外と気がついていない人が多い様に思う。iPhone OSはまさにその成果と言える。


iPhone SDK、第一印象

 iPhone 用のネーティブ・アプリケーションの開発が可能になるSDKがリリースされたので、早速ダウンロードしてみた。そもそもMac OS XのAPIも一切知らず、Objective Cでプログラムを一行も書いたことの無い私には目新しいことばかりだが、私がこれだけ気に入って使っているiPhone向けにアプリケーションを作れるというのに試してみないわけには行かない。 

Uikit

 iPhone SDKをインストールして、サンプルアプリをエミュレータ上で走らせるところまでは簡単にできたのは良いが、読まなければいけないドキュメントが大量にあってちょっと困っている。まずは、Objective Cを理解し、それからOS Xのコア(Cocoa Foundation)を理解しなければならない。それからやっと本題のUIKit(iPhone用のUIフレームワーク、上の図参照)に取りかかれる。

 しかし、ツールにしてもドキュメントにしても、文句の付け用がないぐらいの充実ぶりはさすがソフトウェアで勝負をしているApple。ジョブズが作ったNextからAppleが継承したOSと開発環境が数年間の進化を経てついに実を結んだと言える。

 これだけ充実した開発環境を見るとつくづく思うのは、携帯電話を筆頭にした組み込み・家電の世界にもソフトウェア・プラットフォームの重要性がはっきりと見えて来た、ということ。ここまでソフトウェアが複雑になってくると、開発環境の開発とメンテナンスのコストが膨大になり、個々のハードメーカーが独自の開発環境やOSを作ることがコスト的に見合わなくなって来ている。

 実際、携帯電話の世界を見ても、ネーティブレベルの開発環境を本気で作っているのは、

  • Symbian/UIQ (Nokia/Sony Ericsson)
  • Windows Mobile (Microsoft)
  • iPhone (Apple)
  • BREW (Qualcomm)
  • android (Google) ... ただしまだ実績はなし

ぐらい。トップスリーのMotorolaですらソフトウェア開発コストの高さに悲鳴を上げたことを考えれば、Symbian/UIQを抱えるNokia/Sony Ericsson以外の携帯電話端末メーカーすべてがMotorolaと同じような悩みを抱えていることは容易に想像できる。Appleの携帯電話ビジネスへの参入が他のメーカーにとって脅威なのも当然だ。

 ソフトウェアに関してGoogleやMicrosoftに頼り切った戦略を取ればコモディティ化は避けられず中国・台湾メーカーとのコスト競争に巻き込まれ、ソフトウェアによる差別化をはかろうとするとAppleやSymbian/UIQと同レベルのソフトウェア投資を覚悟しなければならない。臨界点は近いような気がする。

 しかし、今週はMBAのクラスでカンヅメ状態だし、来週は日本出張と(オンラインでの)期末テストが重なるという過酷な状態。そんな最悪なタイミングでiPhone SDKをリリースしたアップルが恨めしいが、こうなったら日本行きの飛行機の中で一気にObjective Cをマスターするしかないか、と。