omoが書いたよ
Making bad design look bad
by
omo
2008-01-10 19:27
会社で blog を書いてみる。
どうもはじめまして omo といいます。プログラマです。 同僚の Web 担当の子が blog 書けー! と圧力をかけてきました。 書いてもいいよ、じゃなくて書けー! なのが面白い。
私はふだん 別のところ でウェブ日記を書いているのですが、 仕事中に blog を書くのはさぼっているような後めたさがあります。 世間の会社員 blogger がどんな気分で書いているのかは気になるところです。
それはいいとして、何か書いたものか考えてみます。 CE ではプロジェクト管理だけでなく社内の雑多な文書置き場に Trac を使っています。私もそこにちまちま書きためた文章があるので、 しばらくはそれを抜粋してお茶をにごすことにしました。
最初のねたは "Making Bad Design Look Bad". 同僚の日報メールをねたに 思いついたバッドノウハウです。(実名の伏せ字は特に意味なし。)
Making Bad Design Look Bad
xxx の日報に反応を書いたがねたとしてそれなりに面白い気がしたので Wiki へ.
XXX です。
* gen
* 文章書き: Application ってクラス名は具体性が無くて良くなかった。
「なんとかManager」っぽいダメさがある。
Application とかなんとか Manager は、名前以前に 設計がまずいことが多いです。(なんとか Context も同じ。) 依存関係の整理をさぼり、とりあえずなんでもつっこんでおく オブジェクトをつくってしまっている可能性があります。 そういうのは役割分担を考え直し、 オブジェクトやインターフェイスを分割するのが筋です。
逆に、まずい場所にまずい名前をつけておくのは悪いことではありません。 ソフトウェアの規模が小さく部分的にさぼってもインパクトが少ないなら、 そういう手抜きはトレードオフとしてありえます。
そんなときに「すまんがここはさぼった」というマークとしてまずい名前は有効です。 「間違ったコードは間違って見えるようにする」のバリエーションで、 「まずい設計はまずく見えるようにする」というかんじです。
もとねた
別に同僚を dis たりして日々を過ごしているわけではありません。 これはたまたまです。いやほんとに。 ちなみに当人からは 「ダメなとろには FIXME: マークをつける方がオシャレ」 と反応がありあした。そうかも。
表題のもとねたは Joel on Software の Making Wrong Code Look Wrong から。
Rule Of Three (Part 1)
by
omo
2008-01-18 19:06
コードの再利用っていいの?
どうも森田です。こんにちは。 週に一回くらいは投稿をしようと思ってましたが、早速挫折しかかっています。 今日は会社の宴会です。出発まで中途半端にあまった時間を使い、何か書いてみることにしました。
最近、社内の Wiki に「受託開発でもコードの再利用は意識した方がよくない?」 という話がありました。Community Engine はミドルウェアを売って商売をしていますから、 売り物を増やす努力をするのは悪いことではありません。 受託開発でも、顧客との契約が OK なら再利用可能なものをつくるのは一つのアイデアです。
面白いのはその続きです。 その書き手は、「経験によると、再利用を意識した方が最終的にも工期は短くてすむよ?」と主張するのです。 これは驚きの事実です。というのは、 私はこれまで再利用を意識したとおぼしきフレームワークやライブラリに何度も苦しめられてきたからです。 (そのうちのいくつかが自分製なのは公然の秘密です...)
再利用可能なソフトウェアを作るのはそれなりに大変です。 変化に強く、汎用的なつくりにする必要があります。 どんなプログラマも、自分のプロジェクトでおこりそうな変化には備えます。 でも再利用を可能にするなら、転用先の状況を見越さなければなりません。 しかも多くの場合、複数のプロジェクトを同時にサポートする必要があります。 ミドルウェアとして売りたいならなおさらです。
再利用可能なソフトウェアは使うもの大変です。 再利用性を高めるために用意されたカスタマイズの穴を埋めなければなりません。 設定ファイルを書く、ホットスポットを実装する... 自分のプロジェクトだけで使うのコードなら必要に応じてソースを書き換えるだけで済むところを 外部化する必要があります。これは再利用に伴う主要な複雑さのひとつです。 (だからこそ世の中には "インテグレータ" という仕事があるんですね。)
こうした問題を乗り越え再利用ができるようにと作っても、それが使われるとは限りません。 必要にならないかもしれないし、利用者の都合にうまく一致しないかもしれません。 なんとか使おうと調整を繰り返すより、一から書くほうが早いかもしれません。
では再利用可能なソフトウェアを作るべきではないのでしょうか? そんなはずはないですよね。私達は普段から様々なライブラリを再利用していますし、 そもそも Community Engine はミドルウェアを売っています。 ダメという結論では私の立つ瀬がありません。
それなら、どんな時に再利用可能なソフトウェアを作るべきなのでしょうか。 冒頭の書き手と私の経験の食い違いはどこから来るのでしょうか。
と...ここからが本題だというのに宴会の時間になってしまいました。 気がむいたら続く。
Rule Of Three (Part 2)
by
omo
2008-01-25 20:20
前回のつづき
しまった金曜だ。森田です。こんにちは。 先週 つづく と書いたままなのを思いだし慌ててかきます。
あらすじ。再利用再利用っていうけど 再利用できるコードを書くのは大変でしくじりがちだし、 再利用できるはずのコードなのに使うのが大変だったりするよね。 どうしよう? <- 今ここ
さてつづき。 再利用が難しい理由はいくつかあります。 その一つは、再利用を意図してコードを書くのが 本質的に投機的な面を持つからでしょう。 投機という言葉に抵抗があるなら投資と呼んでもいいけれど、 とにかく不確実な未来を相手にしています。
インターフェイスをつくるのは投機です。 あとから別の実装を作る未来に bet しています。 パラメタを外部化するのは投機です。 あとから調整する未来に bet しています。 同じコードをまとめることにすら投機的な面があります。 コピーせず一つにまとめる DRY 原則は、 コードをあとから変更する未来に bet しているのです。(他の目的もあるけどね。)
投機/投資をする以上、リターンの期待値を大きくしたいのが人情です。 そのための戦略は多く知られています。 玉石ある手口の中から、 そのなかの一つ "Rule Of Three" を紹介したいと思います。 ようやく本題です。前置きが長くて済みません。
Rule Of Three
Wikipedia には様々な Rule Of Three が紹介されています。 プログラミングにおける rule of three は こう です: 「同じコードを 3 回コピペしたらコードを関数にまとめろ」。 書籍 リファクタリング にも同じことが書いてありました。 もう少し一般化すると、 「同じようなコードを 3 回書いたら再利用に備えろ」と 言うことができそうです。
以前、私は別のところで似たような話を読んだことがあります。 フレームワークの改変戦略を議論した Evolving Frameworks という記事で、 著者らは「いつフレームワークを作るべきか」の指針として "Three Example" パターンを示しました。
Develop three applications that you believe that the framework should help you build. These applications should pay for their own development.
まず三度アプリを作れ、というわけです。 三度似たようなアプリケーションをつくるなかで、 ホットスポットと再利用可能な箇所の区別がついてきます。 再利用先があるという自信も持てます。 一回や二回ではそれがわからないということでしょう。
私も身に覚えがあります。 学生の時分、 自称「グラフィクスエンジン」の OpenGL/DirectX ラッパを何度書いたことでしょう。 ベクトルや行列を実装した回数や数えきれません。 空で逆行列計算のコードが書けるくらいです。(というのはブラフでかけ算くらいかな...)
はじめてウェブの仕事をした頃も、 自称 「J2EE コンテナ」の servlet ラッパを書き散らしてバイト先に多大な迷惑をかけました。(時効です。)
Rule of three に従うなら、酷いコードでもまずゲームやウェブサイトを作るべきだったのです。 そうすれば、半透明のポリゴンやフレームを含む HTML を正しく扱えない 役立たずの「フレームワーク」を実装する無駄な労力を避けられたことでしょう。
ふりだしに戻ると?
前回の話に戻ります。 再利用の成功体験を語る同僚と、 再利用の失敗体験に苦しむ私の違いは何だったのでしょうか。
話によれば、 その同僚が再利用を志したのは度重なるコードの繰り返しに飽きたからでした。 これは先の "Rule Of Three" を満たしている気がします。 二回じゃ飽きないですからね。 逆に私が苦しんだフレームワークはアプリケーションに先立って書かれたものでした。 (テストすら通っていないものもありました...)
Community Engine のミドルウェアはどうでしょうか。(ここからは宣伝なので適当に眉唾してね:D) VCE の初期バージョンは、ボスがゲーム開発をするの中でちまちま作ったものだそうです。 WS の売り文句には 「これまでにコミュニティーエンジンで培ってきたネットワークゲーム開発の知恵がこめられています」 とあります。ノウハウ培う過程で似たようなコードを書いたことでしょう。 これらも Rule Of Three を満たしていそうです。 つまり良いフレームワークなのだといえます。おひとついかがですか?
...会社 blog っぽいオチをつけてみました。ではまた。
Small and Orthogonal
by
omo
2008-02-04 17:05
バラバラコード事件
森田です。こんにちは。 週に一本の誓い(?)は早くも破れてしまいました。 ちょっとたてこんでおりまして... 先週なんてボスのコメントがついてるのにスルーしてます。 我ながら社員としてはいかがなものか。 そんなわけで今日の話もちょっとです。次回に続いたりはしません、たぶん。(追記: しなかった。)
社内で、ミドルウェアの共通コードを別のライブラリに抜き出そう、という話がありました。 基本的に一方のミドルウェア(WS)は下位のミドルウェア(VCE)に依存しているので、 VCE が共通部分になっています。しかし諸事情からちょっとだけ重複する部分があり、 それをなんとかしようとしている様子。 社内 dis 担当の私としては、さっそくつっこまねばなりません。 つっこみました。「バージョン管理とかリリースはどうするの?」 すると「ファイル単位でバラバラに使えればいいんじゃない?」とのこと。 なるほど。感心しました。なかなか名案です。
重複しているのは、一部の移植層や簡単な文字列/バイト列操作のルーチン群です。 素直に考えれば、こういうのは一つのパッケージとしてリリースするのが定石でしょう。 世の中にも移植層+a のライブラリは多く、 APR, NSPR, GDK, APL など枚挙に暇がありません。 しかし、この手のライブラリには張り切りすぎてしまう悪い癖があります。 正しくビルドされ、正しくパッケージされ、正しくリリースされてきます。 ところが正しくビルドするのは部外者(特に windows ユーザ)には面倒だったりするのです。
対照的に、ファイル単体(または数個のファイル)でぽつりとリリースされる素朴なコードもあります。 たとえば、ruby で使われている Peter Moore の ハッシュ表, senna で使っている Mini-Scheme, sqlite 内蔵のパーサジェネレータ lemon, VCE で使っている NTT の camellia などがそうです。 これらのライブラリには大抵ろくにドキュメントがなく、 公式のリリースパッケージがないこともあり、 ビルドは適当に書かれた Makefile がついてくるだけだったりします。 しかし、みな有用なのも事実です。
そもそもリリースが適当なのはなぜでしょう?大抵は枯れているからです。 ドキュメントがないのは?小さいコードは読めばわかるからです。 Makefile がしょぼいのは? 適当につっこんでもビルドできるからです。 逆に autoconf なんかにされてしまうと windows やコンソール機への 移植ではかえって迷惑です。巨大なコードはレポジトリでかさばります。(かさばる例: boost)
枯れた部分を小さく切り出す。そんな再利用の形態があります。 どんなソフトウェアでもそう区切れるわけではありませんが、 このあいだ社内で話題になったのはそういう部類のものでした。 ぜひバラせるコードを切りだしてほしいものです。
もちろん、バラせるコードにはトレードオフもあります。 たとえば定義から、バラ部品の間でコードは共有できません。 似たような構造体や typedef を複数つくる羽目になるかもしれません。 それが少しならいいですが、大量に必要なようなら バラバラ作戦は諦めねばならないでしょう。
しかし、それでも小さなコード片というアイデアは魅力的です。 そこには自己完結した小さく有益なコードという、儚い憧れがあります。 現実のソフトウェアは、複雑で大きなコードベースによって、 ようやく少しばかりの仕事をなしとげるのもの。 私(たち)は、小さなソフトウェアに自分の夢を映し出しているのかもしれません。
ではまた。
Futon Bootstrap Problem
by
omo
2008-02-08 12:12
布団ブートストラップ問題
こんにちは。森田です。寒いです。 ここ数日早起きに挑戦しています。 でも寒さがひどくでまったく布団から出られません。 目覚しにせっつかれて照明と暖房に火を入れるまではいいのですが、 部屋があたたかくなるのを待ちながら二度寝してしまい、 気がつくともう(自主規制)時、という日々です。
これは「布団ブートストラップ問題」として広く知られ、 様々な解決策が提案されています。 その一つが「朝ゲーム」です。私も今朝からはじめました。 布団のなか DS でゲームをさわりながら、暖房の起動を待つのです。
「ゲームは交感神経を刺激するので睡眠に良くない」などと 叩かれることがあります。 これは逆に言うと、眠気を防ぐのにゲームはもってこいということです。 今朝はプレイ開始後 5 分くらいで意識がはっきりしているのに気付きました。 こりゃいいわ。ゲームは朝やれ、といいたい。
ただ一つだけ問題があります。 部屋が暖まったあとも、 セーブポイントに着くまではプレイを続けないといけないんですよね。 今やっているゲームの中で 「セーブって何?」「...宇宙の愛。」という会話がありました。 たしかに、宇宙の愛がそうそうあるはずはありません。的確です。 でも朝ゲーマーとしては、15 分に一回くらいセーブできるといいなあ。 DS 向けタイトルを作られている皆様には、 朝ゲーマーの存在も忘れないでいて頂きたいところです。
ではまた。こんなどうでもいい話を書くつもりじゃなかったのになあ...
Brown Bag Lunch
by
omo
2008-02-15 17:06
茶袋の会
こんにちは。森田です。今週も blog の時間がやってまいりました。
今年に入ってから、社内では 「茶袋の会」という 勉強会のようなものが開催されています。 三日坊主で終わると悲しいのでここには書きませんでしたが、 気がつくと開催が 5 回を超えていました。三日坊主回避ばんざい! 記念に (じゃないけど) 同僚がロゴをつくってくれました。
茶袋の会は 毎週水曜、昼休みに開催しています。 時間がくると、弁当を持った参加者が休憩室にあつまります。 発表するひとは一回あたり二、三人。 ひとり 15 分くらいづつ喋ってもらいます。 ギャラリーは 10-15 人くらいかな。 弁当をつつきながら話を聞き、時につっこみを入れたりもします。
勉強会「のようなもの」というのは、一般にいう勉強会ほど 気張ったものではないからです。 発表の中身も技術寄りのものとは限りません。 C++ の悪口やロボット・プログラミングの話がある一方で、 鶏肉の話や紳助竜介の話があります。みな好き勝手に話しています。 いいかんじにグダグダです。
開催の様子はなぜか ustream で 配信 されています。 グダグダぶりに興味のあるかたはご覧ください。 基本的に毎週水曜 13 時スタートです。(ただし開始時間も若干グダグダ。)
茶袋の会で話された具体的な内容については、 折をみて(=書くねたが尽きたら)ここでも紹介していければと思っています。 話した本人が書いてくれるのがいいかもしれませんね 。 (と、誰となく圧力をかけておく。)
名前の由来など
茶袋の会の元ねたには、"Brown Bag Lunch" と呼ばれているものがあります。 昼飯時に集まってグダグダ(とは限りませんが)何かやることをこう呼ぶそうです。 私は アジャイルプラクティス という本で知りました。 brown bag は昼の弁当を入れる袋を指すそうな。 (Google で "brown bag" と 画像検索してみてね 。)
残念なことに、弊社の近所で brown bag に弁当を入れてくれるのは Subway くらい。 毎週 Subway を食べるのも面倒なせいか、コンビニその他の Plastic Bag Lunch が大半。 初台近辺で茶袋をくれる、おしゃれなパン屋をご存知の方は一報ください。
Fall The Bar
茶袋の会には各人がさまざまな野心を持って臨んでいます。 (野心の例: ustream でメジャーデビュー) 私個人は、会社で思いつきや興味を話す敷居を下げられればいいなと思っています。 もちろん社内には Wiki も ML もあって、雑談をする場所が無いわけではありません。 一方で、文章を書くのはそれなりにかったるい作業です。 反応するのも面倒で、やりとりが殺伐になりがちです。 誰もが私のように図太いわけではないですから、 そうした殺伐は書き手の敷居を高めてしまうことがあります。
たとえばロボットの話や見た DVD の紹介なんてのは 画面や実物を見ながら口頭で話す方が文章を書くよりずっと簡単に説明できます。 また話の中に説明不足があっても、その場に当人がいれば会話で補うことができます。
そしてなにより、茶袋の会はグダグダです。 なにしろ聞き手はみな弁当を食べています。 会に興味のない人が画面の前を通ってコーヒーを淹れてます。 唐揚げを床に落とした悲痛な叫びが上がります。 そういう雰囲気なら、多少アホで不完全な話をしても良い気がするものです。
そうやって発言の bar を下げると、 「もう少し整理してから話そう」とか「まとめて書こう」とか 「面白い気がするけど他の人には当たり前かな」などと 思ったまま死蔵されていた知識やアイデアに 日の目を見せることができるかもしれません。 グダグダには、そんな発掘の意図がなくもないのです。
それらしい建前を書いてみました。 洋画の再放送をみながら弁当を食うのには飽きたから おまいら何か話してよ、という本音は公然の秘密です。
ではまた。
Asynchronous Programmer
by
omo
2008-03-07 15:50
非同期プログラマ(の貢献)
こんばんは。森田です。一週間すっぽかしてしまいました。 事情は挨拶からお察しください:D
さて、私は非同期プログラマ(自称)です。 ブロッキングが苦手で、他からのコールバックに主導されて働く プログラマのことをいいます。 たとえばミーティングからは極力逃げて、後から参加者に中身を聞く。 書類や仕事はせっつかれてから出す。 難しいバグに出会ったら画面の前でブロックせず散歩にブレークする。 そんな働き方を非同期プログラマといいます。
本人の快適さとは裏腹に、非同期プログラマの評判はあまり良くありません。 どうも世の中は同期型で動いているらしく、いつも肩身の狭い思いをしています。 たまには「非同期プログラマも役にたつんだぜ?」というところをアピールし、 居場所をつくっておかねばなりません。今日はそんな話です。
複数プロセスのデバッグ
このごろ、いわゆるネットゲーのようなものを作る仕事をしています。 ネットゲーなのでクライアントとサーバがいます。 開発中は、両方を同時に動かすことになります。
開発環境は Visual Stduio です。 Visual Studio の UI は単一のプロセス相手にデバッグする前提で設計されています。 「実行」の F5 キーで起動できるプロセスは一つだけです。 クラとサバのいるネットゲーづくりには向きません。 今まではクライアントの初期化中にバッチファイルを呼び出し、サーバを起動していました。 これだと起動は自動化されますが、サーバにデバッガがアタッチされません。 (つまりステップ実行できません。) 今日は面倒なバグを追う必要があり、仕方なくクラとサバの両方にアタッチする方法を調べてみました。
で、さすがは Microsoft。 Visual Studio には複数プロセスにアタッチできる機能がありました。 「ソリューションエクスプローラ」の GUI でコンテクストメニューからプロセスを起動すればいいんですね。 ただ GUI はいまいちです。自動化したい。 そして GUI からできる操作はほとんど自動化できるのも Visual Studio のいいところです。 さっそく操作をマクロに録音、再生してみました。
... が、なぜかダメです。マクロのコードはこんなかんじ。
' 改行とコメントは森田による
Public Module RecordingModule
Sub TemporaryMacro()
' サーバのプロジェクトにフォーカスをあわせる
DTE.Windows.Item(Constants.vsWindowKindSolutionExplorer).Activate()
DTE.ActiveWindow.Object.GetItem("xxx\servers\game_server") \\
.Select(vsUISelectionType.vsUISelectionTypeSelect)
' "新しいインスタンスをスタート"
DTE.ExecuteCommand("ClassViewContextMenus.ClassViewProject.Debug.Startnewinstance")
' 同じことをクライアントにも
DTE.ActiveWindow.Object.GetItem("xxx\client").Select(vsUISelectionType.vsUISelectionTypeSelect)
DTE.ExecuteCommand("ClassViewContextMenus.ClassViewProject.Debug.Startnewinstance")
End Sub
End Module
どうも "ClassViewContextMenus.ClassViewProject.Debug.Startnewinstance" コマンドは 遅延され、マクロのコードが動いた「後」に実行されるようです。 そのためか、二回続けて呼び出すとエラーになってしまいます。 最初は実行が終わる前に処理が戻るのかと思い、Sleep() してみましたが、それでもダメ。 困りました。
さて、私は非同期プログラマ(自称)です。このトラブルは非同期の臭いがします。 スクリプトが終わるまで処理が遅延されるなら、更にその「後」まで実行を遅らせたらどうなるの?
Visual Studio (2005) のマクロは .NET のランタイム上で実行されます。 .NET の機能がフルに使えるなら、処理の遅延なんてチョチョイと書けるはず。
書いてみました。
Public Module XxxDevelopment
Sub TemporaryMacro()
' 1 秒後にサーバを起動するタイマーをセット
Dim aTimer1 As System.Timers.Timer = New System.Timers.Timer(1000)
aTimer1.Enabled = True
aTimer1.AutoReset = False
AddHandler aTimer1.Elapsed, AddressOf StartGameServer
' 2 秒後にクライアントを起動するタイマーをセット
Dim aTimer2 As System.Timers.Timer = New System.Timers.Timer(2000)
aTimer2.Enabled = True
aTimer2.AutoReset = False
AddHandler aTimer2.Elapsed, AddressOf StartClient
End Sub
Private Sub StartGameServer(ByVal source As Object, ByVal e As Timers.ElapsedEventArgs)
DTE.Windows.Item(Constants.vsWindowKindSolutionExplorer).Activate()
DTE.ActiveWindow.Object.GetItem("xxx\servers\game_server").Select(vsUISelectionType.vsUISelectionTypeSelect)
DTE.ExecuteCommand("ClassViewContextMenus.ClassViewProject.Debug.Startnewinstance")
End Sub
Private Sub StartClient(ByVal source As Object, ByVal e As Timers.ElapsedEventArgs)
DTE.Windows.Item(Constants.vsWindowKindSolutionExplorer).Activate()
DTE.ActiveWindow.Object.GetItem("xx\client").Select(vsUISelectionType.vsUISelectionTypeSelect)
DTE.ExecuteCommand("ClassViewContextMenus.ClassViewProject.Debug.Startnewinstance")
End Sub
End Module
動いた! マクロ実行コンテクストが終わったあとも、 ランタイム自体は生きてるんですね。Visual Studio エライ。
というわけで、非同期プログラマもたまには世間の役に立つというお話でした。 ではまた。
あ。実行前にビルドが走るケースはうまく動かない・・・。 それはまた気が向いたら直すことにして、当面はだましだましやることにします。
追記:
慣れないとかったるい非同期プログラミングですが、 最近は (これも実行環境に制限の多い) クライアントサイドのウェブ開発で 見直されているようです。 興味のある方は for文をsetTimeoutに変換する などの記事が楽しく読めるかもしれません。
最近、あるゲーム会社の人から、「ツール作りの主導をするエンジニアは、8年の経験を求めることにしている。」と聞きました。
PlayStation以降のゲームでは、ゲーム開発に1年半から2年ぐらいかけることは普通です。3つを2年かけてつくると6年なので、8年の経験があれば、ツールづくりのために十分な経験を積んでいると言える。 という経験則があるのかもしれません。このときは、Rule of Threeの話は出てこなかったけど。
なんと、ファミコンと同時に発売されたゲームは3つだった! 「マリオブラザース」「ドンキーコング」「クルクルランド」