Ad Network

Sponsored Links


あわせて読みたい

  • あわせて読みたい

「戦略的OS」の開発がことごとく失敗している点に関する一考察

 90年代にIBM、Microsoft、Apple各社が巨額の開発費を投じて作っていた「戦略的OS」がすべて失敗してしまったことを皆さんはご存知だろうか?

 IBMが作っていたのはOS/2。元々はMicrosoftとの共同開発だったが、途中で仲違いをしてしまい、最後はIBMだけが細々とサポートしていたことすら覚えていない人が多いとは思うが、Windows95の成功であっというまに市場から消えてしまったのがOS/2。具体的な数値は公開されていないので分からないが、両社が数百人体制で数年間開発していたので、少なく見積もっても日本円で数百億円は投じられたことは間違いない。

 しかし、OS/2は少なくともリリースまで結びついたから良い方だ。悲惨なのは、Microsoftが開発していたCairoとAppleが開発していたTaligent (=pink)。

 Cairoの方は私自身が初期のころにいたこともあるし、最終的には「Chicago(Windows95のプロジェクト名) vs. Cairo」の戦いの最前線にいた私としては知りすぎている点も多いのだが、一つだけ確かなのは、プロジェクトとして最初からトップクラスのエンジニアを集めすぎて「船頭多くて船進まず」の状況になってしまった点。それに対して、「Cairoまでの場つなぎ」的な存在だったChicagoが少人数で経営陣の注目を浴びずにもの作りに集中できたのはラッキー以外の何ものではない。

 TaligentはMac OSに続く「次世代OS」としてAppleが'88年から開発しはじめ、途中でIBMとのジョイントベンチャーとしてスピンアウトしながらも空中分解してしまった幻のOS。開発はかなりの難産だったようで、'96年にNeXTを買収せざるを得なかったのはこのプロジェクトが失敗したことに加えてその後のOS(Copland)の開発までもが難航してしまったから、というのは有名な話。そのNeXTがOS Xという形で世の中に出たのは5年後の'01年のこと。MicrosoftがWindows95+WindowsNTで大攻勢をかけた90年代の後半にApple側のOSの進化が止まっていたというのは、Windowsがなぜあれほど成功できたかを説明する上でも歴史上の重要な事実。

 そして今のOSの市場を見ると、Linus Tolvaldsという個人がが作ったLinuxと、Steve JobsがAppleを追い出されて作ったNeXTを元にしたOS Xと、Cairoまでの場つなぎに過ぎなかったWindowsと、企業の中核戦略からはかけ離れたところで作られたものばかりが使われている、というのがなかなか面白いところ。

 「日の丸OS」だったはずのB-Tronもどこかに行ってしまったし、そもそも「戦略的OS」を意図的に作るってことにかなり無理があるんじゃないかと思える。結局のところ、ソフトウェア作りはアートに近くて、大企業が資金力にまかせて優秀なエンジニアを集めても無理があって、少人数で作ったものが市場原理で自然淘汰されてこそ良いものができると思うんだがどうだろう。


 

iPhoneのJailbreakの危険性に関してひと言

 iPhoneをハックして、Appleが認めている以上のカスタマイズを可能にしたり、Apple公認のApp Store以外からのソフトをインストール可能にしたり、することをJailbreak(=脱獄)と言うのだが、PhotoShareでの会話とかを見ていると、その危険性をちゃんと理解せずにJailbreakしている人たちがたくさんいるようなので、ひとこと警告しておく。

 まず最初に考慮しておくべきことは、iPhoneはNintendo DSやSony PSPと違い、携帯電話でありメールマシンであり、インターネットマシンであり、住所録やらメールやらウェブサイトのパスワードなどの個人情報を思いっきりやりとりする、ある意味パソコン以上にプライバシー管理が大切なマシンであること。当然、ウィルスに感染したり、セキュリティホールからハッカーに情報を盗まれたりしないようにすることがものすごく大切。

 パソコンの場合は、元々がセキュリティホールだらけのオープンすぎるアーキテクチャであるがために、市販のアンチウィルス・ソフトやファイヤーウォールなどをわざわざ入れておく必要があるのは、多くの人の知るところ。

 iPhoneの場合は、「アンチウィルス・ソフトなんかよりずっと効果的な方法」として、開発者の認証コードが付いたApple公認のアプリケーションしかインストールできない、という制限を加えることによりユーザーをその手の危険から守るという方法をAppleが選択している。

 この仕組みおかげで、iPhoneを持つユーザーは、市販のアンチウィルス・ソフトなど面倒なものを導入せずに、安心してさまざまなアプリケーションを楽しめる、という仕掛けになっている。この面に関しては、後手後手のMicrosoftやNokiaよりもずっと高く評価できる。

 Jailbreakをするということは、せっかくAppleが提供してくれているこの「セキュリティの枠組み」を外すことである。そのため、ウィルスに感染してしまう可能性もあれば、予想もしないセキィリティホールから個人情報を盗まれてしまう危険に自分をさらすことになる。もちろん、jailbreakしたiPhone向けのアンチウィルス・ソフトなどを本気で作る会社もない。

 つまり、jailbreakしたiPhoneで電話をかけたり、メールをしたり、パスワード付きのウェブサイトにアクセスすることは、セキュリティホールだらけの少し前のWindowsマシンをアンチウィルス・ソフトなしで走らせるのと同じぐらい、もう少し分かりやすく言えば、新宿歌舞伎町のマンションの1階の部屋で窓を開けっ放しで女性が一人で眠る、ぐらい危険なのである。

 ということで、そんなリスクを理解した上でJailbreakをしている人たちにお願いがある。技術のことに詳しくない人たちから「jailbreakって僕もして大丈夫かなあ?」とたずねられた時に、「アップルからの保証が受けられなくなるけど、それでよかったら」とか「ちゃんと勉強してリスクを理解した上で自己責任でやると良いよ」などと不親切・無責任なことを言わずに、「ウィルスとかに感染するのがいやだったら絶対に辞めた方がいいよ」と言っていただきたい。

 もしあなた自身が、すでにjailbreakしてしまっており、jailbreakのリスクはアップルから保証を受けられなることぐらいなどと大きな誤解をしているとしたら、なんとかしてすぐに元に戻した方が良い。悪意を持ったハッカーにとって、jailbreakされたiPhoneほど簡単に個人情報を盗めるデバイスはないのだから。iPhoneが壊れてもたかだか2〜3万円の被害だが、銀行口座に不正アクセスされたら被害はそんなものでは済まない。

スケーラビリティとユーザービリティの話

 先日のPhotoShareのスケーラビリティのエントリーに関しては、さまざまなご意見をいただき、とても良い勉強になっている。ただし、少し分かりにくかった部分があると思うのでそこに関して補足しておく。

 サーバーのスケーラビリティに関してはすでに色々なところに書かれているが、今回の私が注目しているのは、どうやってサーバーのキャパシティを増やすか、という話ではなく、サーバーのキャパシティを超えたトラフィックが来てしまった際にどんな挙動をするように設計しておくのが良いか、という話である。

 限られた資源を使って数万人・数十万人の人たちにサービスを提供するかぎり、予想外の急激なトラフィック増加でサーバーに過負荷がかかったりすることはどうしてもあるわけで、そこで問題となるのは、その手の過負荷をどうさばくか。

 たとえば写真に付いたコメントを表示させる場合、「最新の情報をすぐに」表示するのが良いのが当たり前だが、それが過負荷のためにどうしても不可能になった場合に、

・表示するまで15秒かかる
・表示はすぐにするが、それは15秒前の状態(投稿されたコメントが反映されるまで15秒かかる)

のどちらがユーザーから見てストレスが少ないか、どちらの状況になるように設計しておくべきか、という部分が私は重要だと考えている。

 また、通常ピーク時に3秒で処理出来ているところに、通常の倍のトラフィックが来てしまった時に、それを倍の6秒で処理出来るように作ってあるか、倍以上の9秒かかってしまうように設計してあるか、というのが「リニアにスケールするかどうか」という部分である。HTTP Requestに対するレスポンスが遅くなると、それに応じて同時アクセス数が増えてしまい、ペンディング中のスレッドが増えてしまう、そのためにさらにレスポンスタイムが遅くなる、という悪循環は、マルチスレッド型のHTTPを使ったアーキテクチャの根本的な弱点。安易にマルチスレッドに頼ったプログラミングは良くない理由はこの辺りにもある。

 そしてもちろん、もっとも大切なのは、トラフィックがキャパシティを超えて来てしまった時に、サーバーが落ちてしまうのか、単に処理速度がそれに応じて遅くなるだけなのか、という点。

 これらの点を考慮した上で、PhotoShareのようなCGMサービスの場合、「トラフィックがキャパシティを超えて増えてしまうとレスポンスが幾何級数的に遅くなり、しまいにはサーバーが落ちてしまう」という同期型のアーキテクチャではなく、「トラフィックがキャパシティを超えて増えてしまっても、レスポンス時間は常に一定で、単にユーザーの変更がサーバーに反映される時間がリニアに遅くなるだけで、サーバーが落ちることもない」という非同期型のアーキテクチャの方が適しているのではないか、というのが今回の話である。

マルチスレッド・プログラミングの落とし穴、その2

 ずいぶん前に、「マルチスレッド・プログラミングの落とし穴、その1(かもしれない)」というエントリーを書いたが、今回はPhotoShareサーバーを運営していて、まさにこのあたりの深い考察が必要になって来たので、良い機会なので続編エントリー。

 PhotoShareのバックエンドのようにCRUD(Create/Read/Update/Delete)のAPIをサポートするバックエンドを作る場合、Create/Update/Deleteのリクエストに対してはクライアントからのAPIコール時にすぐに(HTTP Requestに返事をする前に)データベースに変更を加え、Readの際にも(キャッシュを使う・使わないを別にして)データベースの最新の状況を反映するデータを返すように設計するのが普通である。

 このアーキテクチャの問題は、ユーザーのアクティビティが増えた時に、データベースやI/Oがボトルネックとなり、アクセス量に応じてレスポンスタイムが伸びるため、同時に処理しなければならないHTTP Requestの数が増え、さらにレスポンスタイムが遅くなり、結果的にはレスポンスタイムはリニアにでなく、幾何級数的(exponential)に増えていく。そのため、あるしきい値を超えたアクセスが来ると急激にレスポンスが遅くなり、しまいにはサーバーが落ちてしまう。

 アクセス数が増える→HTTP Requestへのレスポンスタイムが遅くなる→同時アクセス数が増える→しまいにはサーバーが落ちる、という悪循環に陥るのだ。

 通常、その場合はキャッシュを導入したり、スレッド・プロセス・CPUを増やしたり、データベースを多重化したり対処するのが普通だが、私はPhotoShareのようなCGMサービスに限って言えば、まず最初に、そもそものアーキテクチャを非同期なものにする必要があると考えている。

 PhotoShareのように、大勢の人が写真やコメントを投稿してコミュニケーションをとるサービスの場合、オンラインバンキングのように「常に最新のデータを見せなければ大問題が起こる」サービスとは根本的に違う性質がある。具体的には、「この写真に付いたコメントを読みたい」というシナリオではすばやいレスポンスが要求されるが、自分が投稿した写真やコメントが他の人のアプリに反映されるまでの時間はそれほど重要ではない。新しい写真やコメントに関するNotificationも、最終的に届きさえすれば良い訳で、秒単位でのリアルタイム性は必要ない。

 そう考えると、私にはCreate/Update/Deleteのリクエストに対して、クライアントを待たせながら(つまり、HTTP Requestの処理に必要なスレッド・プロセスを保持したまま)データベースに変更をかけることが根本的に間違っているように思える。

 そうではなくて、Create/Update/Deleteのリクエストに関しては、そのリクエストをキューにしまい、クライアントにはすぐにレスポンスを返した上で(つまり、HTTP Requestの処理に必要なスレッド・プロセスはすぐに解放して)、別プロセス(それもシングルプロセス)でキューにたまったリクエストを順繰りに非同期で処理すべきだ。

 アクセス数が上がると、ユーザーがした投稿がデータベースに反映されるまでの時間がかかるようになるが、それが直接的におもてなしの低下に繋がることはない(ユーザーから見ると、単にコメントのレスが遅くなったように見える)。

 結果的には、先の悪循環が解消し、アクセス数が増える→ユーザーの投稿が反映されるまでの時間がかかる→ユーザー間のコミュケーションの速度が落ちる→ユーザーによる投稿数が自然に減る、というより自然なスケーラビリティを持った「より落ちにくい」サービスとして提供することが可能になる。

 それに加えて、キャッシュの生成もオンデマンドで行うのではなく、Create/Update/Deleteのリクエストをキューから取り出してデータベースに変更を加えるときに行えば、Readは基本的に静的ファイルを返すだけになるので、データベースへのアクセスを極端に減らすことができて、WriteよりもReadの方が多いというCGMサービスに適した設計となる(MTとかはすでにそんな設計になっている)。

 Twitterがスケーラビリティで苦しんでいるのをみると、同じ過ちは絶対に犯したくないので、ユーザー数の少ない今のうちに、根本的な設計でスケーラビリティを上げて置くべきだとつくづく思う。富豪プログラミングの時代とは言え、このあたりの設計を誤ると、いくらサーバーの台数を増やしたところで追いつかないので。

 このあたりの設計に関しては、私よりももっと多くの経験を積んだ方がいると思うので、ぜひともコメントやトラックバックを通じた議論・ご教授をお願いしたい。

Google Chromeに関してひとこと

 今回Googleが発表したウェブ・ブラウザー、Google Chromeは、ひと言で言えば、「安定度・安全度を高めるために、それぞれのタブを別プロセスで走らせるタブ・ブラウザー」である。

 95年にIE3.0を設計した時には、タブのコンセプトも存在せず、セキュリティの問題もそれほど強く意識していなかったので、ウィンドウごとに1スレッドを割り当てたマルチ・スレッドを選択した訳だが、ここまでウェブ・アプリケーションが重要になってくると、マルチ・プロセスに移行するのは当然。特定のページ上でのJavaScriptの挙動がおかしくなったからと言って、ブラウザーすべてが落ちてしまう今までの設計が異常。

 一つのウィンドウ下で管理させるそれぞれのタブにプロセスを割り当てる、一般的に一つのウィンドウに一つのプロセスやスレッドを割り当てる通常のGUIアプリケーションとは異なるが、ユーザー・モデルとリソース管理は別物ということを意識すれば、当然との流れ言えば当然、典型的な「コロンブスの卵(=誰かがやれば当たり前のことになる)」とも言える(注:IE8はすでにそうしている、という指摘あり)。

 せっかくここまでやるのであれば、同じタブ内でドメインを移動した時にもプロセスを切り替えるべきだと思うんだが、いかがだろうか。クロスドメインのセキュリティを徹底的に強化した先はそこだと思うんだが。

 URLバーをタブの下に持ってくるというのも、ユーザーモデルをUIにキチンと反映させることを考えれば当然と言えば当然。既存のブラウザーがインクリメンタルに進化した結果たどりついたタブ・ブラウザーという形を、ユーザーモデルからキチンと見直した上でURLバーをタブの下に持って来た点は評価できる(注:Operaはすでにそうだ、という指摘あり)。

 Googleがレンダリング・エンジンにWebKitを採用する・独自の高速JavaScriptエンジンを作っているらしい、という話は以前から業界の人々には知られていたので、目新しい話ではないが、コンパチビリティで一番苦労する作業をAppleと協力して、比較的純粋なエンジニアリングで勝負できるJavaScript VMは自分で作るあたりが、GoogleらしいといえばGoogleらしい。

 ターゲットユーザーを考えれば、短期的にマーケットシェアを失うのは、IEではなくFirefoxだろう。私の場合は、すでにWebkitベースのSafariをメインで使っているので、OS-X版さえ出してくれれば乗り換えは簡単だ。当然、長期的にはIEにも影響を及ぼすだろうけど、結局は「最初から入っていたブラウザー」を使う人が多いことを考えれば、Googleがすべきことは、Dellなどのパソコンメーカーを説得して、デフォールトのブラウザーにしてもらうこと。

 Googleにとって、戦略的にもっとも大きな意味を持つのは、これによりGearsの普及が大きく進むこと。Gearsの普及が進むことがGoogleにとってどうして重要なのかに関しては、長くなるので別の機会に。

スティーブ・ジョブズが一度アップルを追い出されてNeXTを作ったからこそ存在するiPhone OS

117pxnext_logo

 ここのところブログの更新がさっぱりなのは、iPhone向けのアプリの開発で大忙しだから。4月15日にApple Desng Awardの件がアナウンスされてから二週間、ようやくAward向けのアプリも形になって来たので一息つける。締め切りの5月12日まではまだ少し余裕があるが、締め切り寸前にプログラムを変更するのが大嫌いな性分の私はこのくらいの段階で「今日出そうと思えば出せる」ぐらいのクオリティに仕上げておかないと気が済まないのだ。後は徹底的なテストと、見た目の微調整。「ベータ版」としては十分のできだ。

 iPhone SDKもbeta4になり、ようやくチューニング用のinstrumentsも安定して動き始めたので、今日はメモリー・リークの徹底的なチェック。非同期通信だらけなのと、Objective-C覚えたての時に書いたコードが混ざっているため、予想通りリークだらけだったが、このツールのおかげて順調にリークを直すことができた。ガベージ・コレクションのないiPhone OSの場合、自分でリファレンスカウントの管理をちゃんとする必要があるが、非同期通信をきちんとサポートするためには、Model-View-Controllerのアーキテクチャ徹底した上で、それぞれのライフサイクルをきちんと考え抜いてノーティフィケーションのメカニズムを作らないと安定しては動いてくれない。このあたりのノウハウに関しては、一度ちゃんとまとめて書いてみたいが、少なくともiPhone SDKのNDAの呪縛が解けてからのことだ。

 ちなみに、3月からはじめたObjective-Cにもすっかり慣れたが、これはすばらしい言語である。スクリプト言語なみの自由度を持ちながら、必要なところはstrong-data-typeな部分を活用して「つまらない人的ミス」を減らすことができる。C++やJavaよりは明らかに開発効率が良く、JavaScriptやActionScriptよりも遥かに自由度と完成度が高い点が私としてはたまらなくうれしい。

 しかし何と言ってもすごいのが、iPhone OSと開発環境の充実度。Interface Builderまでもがきちんと動くので、「組み込み系の開発環境」としてはブッチギリでNo.1だ。数年前からこの分野でプラットフォームを提供している、Sun Microsystems、Microsoft、Qualcomm、Symbianがここまであっさりと抜かれると誰が予想できただろう。まあ、それもこれも、スティーブ・ジョブズが一度アップルを追い出され、NeXTを作ったからこそiPhone OSが存在するというのは何と言うドラマだろう。

 

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

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

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

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

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