2010年11月1日月曜日

Agile Tour Osaka(Japan)に参加して来た

ひと事で言えば、アジャイルに対する「愛」を感じた(?)講習会であった。

セッション1.「日本のアジャイル開発の変遷」
日本の開発現場では、ウォーターフォール開発での成功事例が多いため、まだまだアジャイルへの取り組みは遅れているとのことであった。
「ゼネコン式」という言葉が耳慣れなかったが、これは、ソフトウェアは「製造業と同じ」扱いで、知的生産ではないと思われているという意味であった。
ウォーターフォール開発は、外国では、もはや過ぎ去ったものとされているが、日本では完成の域(?)に入ったとかで「エクストリーム・ウォーターフォール」と呼んでいた。
ただ、ウォーターフォールと言えど、テストはしっかりやっているので、日本のソフトウェア品質は9割で、アメリカ7割、中国3割とのことであった。
中国ではATMが落ちなどは日常茶飯事だとか。
日本においてアジャイル開発を推進して行くのに、受託や派遣などの問題、現場のスキルアップなどの教育問題、
ドキュメント中心ではなく、小さな反復や振り返り、顧客同席などの問題点の指摘に改めて感心した。

セッション2.「チケット駆動開発」
バグトラッキングシステムをバグだけでなく、開発の単位にまで使うとアジャイル開発になる。
アジャイル開発になったことで、現場の活力がよみがえり、仕事の効率が上がるなどのメリットがある。
ただし、上手く行かないアンチパターンも紹介して、問題点の解決方法も提言していた。
たとえば、
チケットが溜まりすぎる->チケットの棚卸しを。
イテレーション運用ができていない->ロードマップが空なのでは?リリースが一回と少ない。
平行開発できてない->ソース管理がまずい。ブランチが多すぎて野放図になっている。等々。

セッション3.「アジャイルコンサルタントの秘密」
アジャイルのプロジェクトを推進した事例の紹介。スクラムの利点も同時に説明して、アジャイルの手法によって、
プロジェクトが成功の方向へと導いて行く様がありありとわかる素晴らしいプレゼンテーションであった。
プログラマなんかやめてプロジェクトマネージャに転身した方がかっこいいと思えた。

セッション4.「ユーザ・ストーリー・マッピング」
平たく言えば、横軸に時間にして、横軸の上側には実現すべき機能のブロックが時系列に並び、縦軸は、優先度を表し、
機能ブロックの下側には、優先度順にタスクリストを並べるという(壁か模造紙に付箋を貼る)アナログ的な手法であるが、
プロジェクト全体を俯瞰するのがとても分りやすくなる手法の説明であった。
今までにも色々な図を書いてきたが、この方が圧倒的に分りやすい。人間の記憶は特別な意味づけがない限り、時系列の並ぶし、
時系列と優先度を一別できるというのは、とても理にかなっていると納得。目から鱗が落ちた。

アジャイルに関しては、今年の2月にも「XP祭り関西2010」が催され、そこでアジャイル手法について再認識したところであった。
開発するに当たっても、アジャイル的な手法を使うようにしていたのだたが、実際は使ったり使っていなかったり、まだまだ自分流であった。
特にドキュメントの走査や、振り返りが抜けていた。このため漏れなどの不具合を発生させていたことを猛省して、改めてアジャイル手法に取り組んでいくという意志を強く持てた。

2010年5月7日金曜日

プログラムを速く書くには?

等価交換理論というのがあって、様々な仕組みは交換可能である。
「プログラムを速く書く」という発想を転換して、「車で早く目的地に着く」方法をまず考えてみる。
道の上を移動するなら、移動距離が最短で、移動速度が速ければ速いほど、目的地に早く着く。
しかし、混んでる道では、速く移動することが出来ない。行列になってしまえば、目の前に居る車より速く移動できないからだ。
そういう場合は、他の混んでいない道を利用した方が良さそうだ。
距離が倍もある遠回りの道でも、空いてさえいれば、速く移動することによって、早く着くという目的を達成できる。

この発想をプログラムに戻すと、
「混んでいない」状態は、新規作成プログラムであると言える。
「混んでいる」状態は、既存のプログラムの編集作業であり、用心深く作業しなければならない状況だと言える。

既存のプログラムの改修などは、元のソースには手を入れずに、アダプター・パターンなどのデザインパターンを使って、新規作成で取り組むのが良い。
経験的にも、プログラムは、既存のソースを編集して作成するよりも、新規作成の方が断然速い。
つまり、プロジェクト終盤の仕様変更が一番コストが最も高いと思える。
後から後からチビチビと仕様変更されるのなら、最初にガツンと大量の要件を書いてもらった方が良い。

「移動速度を上げる」には、自分の力をパワーアップすることが必要だが、普段より2倍程度は働けても、3倍、4倍となると難しい。
この場合には、ソフトウェアツールを使うもしくは作るのだ。ソフトウェア開発にもソフトウェアの力を借りるである。

どうしてツールを使えば速くなるのか。それはテキストエディタでタイプするという作業が非常に低速なためだ。
たとえば、次の様なソースを







こういう風に手編集で直していないだろうか?







整然と書いた方がバグを防ぎやすいので、空白やタブ送りをして綺麗に揃えている筈である。
この綺麗にというのに時間がかかる。
自前のツールで、「左揃え」するツールを作っておくと、一瞬である。
カタカタとキーを連打している自分を見つけたら、何かツールを使えないか、なければツールを作った方速いのではと考えた方が断然良い。

つまり、プログラムを速く書くためには、
・新規作成で
・ツールなどを駆使する
のが良い方法であると言える。

2010年4月20日火曜日

ソフト開発への心がけ

  • 目的・目標をはっきり作る。
  • プログラムは小さく、シンプルに、分りやすく書く。
  • コピペしない。
  • 重複コードは書かない。
  • ツールを作る。
  • ツールを使う。
  • プログラムでテストする。
  • テストはもれなくする。
  • プロトタイプでこまめに納品。
  • ミス、失敗は必ず記録して、次回に活用する
  • 詳細に決めない。
  • 作り込まない。
  • 決まっていないことを前倒しで作らない。

2010年4月15日木曜日

逆転の発想

逆転の発想が好きである。
中学生の時には、電子工作が好きで、真空管やトランジスタでラジオを良く作っていた。
「初歩のラジオ」だったかに載っていた記事で、真空管は熱が出るので特性が安定しないという性質を逆手にとって、
金属ケースに真空管を入れて、熱するだけ熱せば良いという記事を読んで、「ああ、面白いこと考えるなあ」と思ったのが最初だと思う。

要するに普通の方法が駄目なら逆の方法も試してみるということである。
江崎ダイオードの江崎博士も当時は、半導体の不純物を少なくする方法を考えるという流れに逆らって、不純物いれちゃえー!みたいなノリで、トンネル効果を発見し、江崎ダイオードができた。
江崎博士そうとうなへそ曲がりだと思う。

プログラミングも常識的な一手を疑うことも大切である。
普通の計算方法なら、非常に時間がかかるが、逆にすればあっという間に計算が終わることもしばしばある。

たとえば、以前、ポリゴンの配列にデータを入れていく時に、既に同じデータがあれば、そのインデックスを参照するようなプログラムを作った。
データが少なければ直ぐに計算が終わるが、これが数十万から数百万頂点になると、何度も最初から配列を調べなくてはならないので計算量は指数的に増大して行く。
しかしインデックスを参照するような頂点データは、そもそも偏っていて、近くにあるものである。
毎回配列の最初から探す理由がない。
配列の最後から探す、たったこれだけで、計算量は極端に少なくなる。
画像処理だってそうである。ある画素に相関のあるのは、その画素の近傍だけである。
データの量が多くても、連続性や偏りなどの局所性に注目すれば良いのである。

2010年4月9日金曜日

コピペコード

自分は、コピペコードは禁止している。
手作業で似たような箇所を3カ所以上修正する場合には、プログラムで発生させることにしている。
プログラムで直すと、最初に手間はかかるけど、次の修正には時間がほとんどかからない。
何故そうしているかは、『修正が何度もあるから』である。
手で直している限りは、必ず同じ分の時間がかかる。
しかも、手作業ではミスが発生しやすい。
そして、コピペコードは間違えた場合に、極めて発見しにくいバグとなる。
たとえば、

ActiveWorkbook.Worksheets("header").Range("EA" & CStr(xlsRow)).Value = .Range("EA" & CStr(csvRow)).Value
ActiveWorkbook.Worksheets("header").Range("EB" & CStr(xlsRow)).Value = .Range("EB" & CStr(csvRow)).Value
ActiveWorkbook.Worksheets("header").Range("EC" & CStr(xlsRow)).Value = .Range("EC" & CStr(csvRow)).Value
ActiveWorkbook.Worksheets("header").Range("ED" & CStr(xlsRow)).Value = .Range("ED" & CStr(csvRow)).Value
ActiveWorkbook.Worksheets("header").Range("EE" & CStr(xlsRow)).Value = .Range("EE" & CStr(csvRow)).Value
ActiveWorkbook.Worksheets("header").Range("EF" & CStr(xlsRow)).Value = .Range("EE" & CStr(csvRow)).Value
ActiveWorkbook.Worksheets("header").Range("EG" & CStr(xlsRow)).Value = .Range("EG" & CStr(csvRow)).Value
ActiveWorkbook.Worksheets("header").Range("EH" & CStr(xlsRow)).Value = .Range("EH" & CStr(csvRow)).Value
ActiveWorkbook.Worksheets("header").Range("EI" & CStr(xlsRow)).Value = .Range("EI" & CStr(csvRow)).Value
ActiveWorkbook.Worksheets("header").Range("EJ" & CStr(xlsRow)).Value = .Range("EJ" & CStr(csvRow)).Value
ActiveWorkbook.Worksheets("header").Range("EK" & CStr(xlsRow)).Value = .Range("EK" & CStr(csvRow)).Value
ActiveWorkbook.Worksheets("header").Range("EL" & CStr(xlsRow)).Value = .Range("EL" & CStr(csvRow)).Value

この間違いが一見して分かるだろうか。
EFとするべきところが、EEになってしまっている。よーく見ても似ている字なのでなかなか見つけにくい。
そもそも連続しているのだから、ループにすれば良いと思う。
だが、エクセルは列は文字列なので、そのままできない。
列名を配列に入れる方法もあるが、ここは列名を数字に相互変換するメソッドを用意した方が色々と計算が簡単になる。

列名加算なるメソッドを追加して、次の様に書く。

Dim ws
Dim column
Set ws = ActiveWorkbook.Worksheets("header")

For i = 0 To 12
column = 列名加算("EA", i );
ws.Range(column & CStr(xlsRow)).Value = .Range(column & CStr(csvRow)).Value
Next

もっともRangeの設定を上手にすれば、そもそもループせんでも良いのでは?などという突っ込みもあるけど。一応参考例として。

2010年2月8日月曜日

XP祭り関西2010に参加して来た

XP祭り関西2010に行ってきました。

結構な人数のプログラマ、エンジニア、リーダーなどの人たちが、アジャイルについて深く体験した日だった。

アジャイルや、チケット開発駆動について、色々な実例を交えて分かりやすく楽しく聞けた。
アジャイルについて知っていても、まだまだ実践しているとは言えなかったので、もっと勉強の必要性を感じた。

その中でも様々な金言が!

  • 製造業では、製品が完成した時点で最高品質でそれ以降は陳腐化する。サービス業は、常に現時点での最高品質。
  • ソフトウェア->オープンソース、ハードウェア->クラウド。もはや何の制約もなくなってきた。
  • 不完全な人間が、間違いを犯さない計算機を相手にしなくてはならない。
  • リーダーは皆の0.5歩先を歩かなくてはならない。
  • チケット駆動開発->バグトラッキングシステムを障害管理ではなく、タスク管理に使う
  • ソフトウェア開発の諸問題は、ソフトウェアで解決。
  • 小さくする(小さな組織。小さなコミュニケーション。ペアプロ。小さくコミット。小さく振り返る。小さなビジネス。小さな変化)

いや-、Dear XP、フォークソングでちょっと切ないところもありますが、感動してしまいました。ラブソングがあるのなら、プログラムプロジェクトのことを歌にしても良い。
楽しくソフトウェア作り。ソフトウェア作るのは好きだけけど、テストは苦しいとか思っていた自分が恥ずかしい。
アジャイル開発が、当たり前にできるように、これからも頑張っていきたい。
カンパ代500円で、セミナーも聞けて、懇親会(4000円)もあり、ビンゴゲームではもれなく本が当たるという、なんだかお得すぎる。

2010年2月1日月曜日

「前へ」と「次へ」のボタン制御

 以前、最初の画像の時には、前へのボタンが無効、前と次の画像に移動できる時は、2つのボタンが有効。最後の画像の時には、次のボタンが無効になるというボタン制御をFLASHでお願いした。


(前へと次へのボタンは、こんな画像)



FLASHプログラマ氏は、「前へ」と「次へ」のボタン制御をActionScriptでこう書いていた。

//ボタンの表示
if (current_page == 0)
{
buttons.btn_prev._visible = false;
buttons.btn_prev_disabled._visible = true;
}
else if (current_page == total - 1)
{
buttons.btn_next._visible = false;
buttons.btn_next_disabled._visible = true;
}
else
{
buttons.btn_prev._visible = true;
buttons.btn_next._visible = true;
buttons.btn_prev_disabled._visible = false;
buttons.btn_next_disabled._visible = false;
}

if文を読み解くと、
1つめのif文には、current_pageが0の時は、一番最初の状態なんだから、「前へ」のボタンは使えないね。
2つめのif文には、最後の状態なんだから、「次へ」のボタンは使えないね。
最後のif文は、それ以外の状態は、「前へ」と「次へ」のボタンは使えるよという意味である。
FLASHのボタンは全部グラフック・シンボルなので、
EnableとDisableのそれぞれのボタンのvisibleプロパティをbool値で制御している。

このプログラム、一見動作しそうなんだけど、動かない。
もし画像が1枚もなかった場合はどうだろう。
current_pageは0、totalは、0なので1つめのif文に行く。ただ、「次へ」のボタンの状態は変更しないので、
もし、「次へ」ボタンが有効になってしまっていたら、そのままの状態を維持することになってしまう。

さらに、もし画像が1枚しかなかった場合は?
current_pageは0の場合には、今度は「前へ」のボタンの状態を更新しない。

それにcurrent_pageにもし、-1が入った場合は?
current_pageにtotalより大きい数字が入った場合は?
その場合には、ボタンは有効になってしまいボタンを押したら、
画像ファイルの配列のサイズの範囲外となりエラーになるだろう(多分)。

こんな短いプログラムでも、条件がもれまくりである。
この場合には、current_pageの前後がどうなのかを考えて、ボタン事にif文を作成しなくてはならない。

// 初期条件。初期状態ではボタンは使えない状態
buttons.btn_prev._visible = false;
buttons.btn_next._visible = false;
buttons.btn_prev_disabled._visible = true;
buttons.btn_next_disabled._visible = true;

// 前のページが0より大きければ、「前へ」のボタンが使用可になる
if( (current_page-1) >= 0 )
{
buttons.btn_prev._visible = true;
buttons.btn_prev_disabled._visible = false;
}

// 次のページが画像の最大数より小さければ「次へ」のボタンが使用可になる
if( (current_page+1) < total )
{
buttons.btn_next._visible = true;
buttons.btn_next_disabled._visible = false;
}

という風に書くのが正しいだろう。