勧めたいプロジェクトの進め方

どうも、最近本を読むのにはまっている人です

今までは割と技術的な本を読むことが多かったのですが、最近はもっと抽象的な本を読む方向に進んでますｗ
そこで、いろいろな本から学んだ手法をまとめてみました

詳細について知りたい方は下記の本を参考にしてください
[アジャイルサムライ−達人開発者への道−](https://www.amazon.co.jp/gp/product/4274068560/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1)
[テスト駆動開発](https://www.amazon.co.jp/gp/product/4274217884/ref=ppx_yo_dt_b_asin_title_o02_s00?ie=UTF8&psc=1)
[エクストリームプログラミング](https://www.amazon.co.jp/gp/product/4274217620/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1)

#これまで考えていた最強の方法
未だにウォーターフォールで進むプロジェクトが多いと思います
特にソフトウェア開発ではない(物理的な構築が中心となる)案件ではウォーターフォールで進めても問題なかったりするので、同じノリでソフトウェア開発をしてしまっているプロジェクトを多く見かけます(というか、それしか見たことない…)

このような場合、以下のようなプロジェクトの進め方になります

![無題のプレゼンテーション.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529608/0c5927ff-6c15-54ec-ed6f-0bf091b35fd0.png)

ネットワークの設計・構築やサーバーの設計・構築の仕事をしていたときはこの手法でプロジェクトは成功していました
小規模なものでも大規模なものでも基本的には数が増えているだけなので、手を動かす人さえいれば問題ありませんでした
要件自体もシンプルなことが多く、構築自体も短期間で行えるものが多かったです
成功の要因として、ヒアリングの段階でリスクの高いプロジェクトは捨てていることも挙げられると思います

上記の理由もありウォーターフォールは一定の支持を得ていますが、ソフトウェア開発だとうまくいかないことが多々あります
まずは、僕が初めて経験したソフトウェア開発プロジェクトのお話をしようと思います

#最強の方法のはずが…
そこではエンドユーザー向けの業務ソフトウェアの開発をウォーターフォールを使って行っていました
単体テストは終わっており、結合テストからの参画、ということでした
先ほどの図で言うと下から2番目、運用の直前となるフェーズです

テストチームのメンバーの一員として参加した僕は、リーダーから振られたタスクを順調に消化しており、テストスケジュールも想定通り…になっていると思っていました
ですが、うまくいきませんでした

何故うまくいかなかったのか、下記のようなことが起こっていました

- **そもそもスケジュールなんてもんは無い！**

タスクの洗い出しをし、スケジュールに線は引いてありましたが全く役に立っていませんでした

第一に、タスクの洗い出しの漏れが発生していたこと
第二に、タスクを全て消化できるほど人的リソースがなかったこと
第三に、スケジュールに現実味がなかったこと

これらが積み重なった結果、スケジュール表は捨てられることになりました
スケジュールが手間のかかるドキュメント扱いになったためです

- **単体テスト？終わってる訳ないだろ！**

勘の良い人は気付いているかもしれませんが、このプロジェクトではAチーム、Bチームに分けられており、Aチームは設計とテスト(ITa以降)を、Bチームは開発とテスト(単体テスト)を責務としていました
プロジェクト参画時に聞いていた話では単体テストまで終わっているはずでしたが、Bチームの遅れにより単体テストが終わっていませんでした
こう言うとBチームが一方的に悪いように聞こえますが、正確にはAチームの設計が遅れており、その結果開発が遅くなっていました
というか、僕が順調にこなしていたタスクは実はテストではなく、設計書類の編集が主でした
設計が終わっていないため、当然開発も遅れ、テストもできていない状態でした
(後々聞いた話ですが、Bチームは設計書無しで開発をしていたようです)

- **データの不整合？よく知らないけどそれって何か問題あるの？**

DBの設計がとんでもないことになっていました
データの不整合が起こると、本来あるはずのデータが無いように見えたり、無いはずのデータがあるように見えたりしてしまいます
RDBではこれを防ぐ機能が搭載されているのですが、使っていませんでした
更に、時間が無いという理由でデータの不整合は見逃されることになりました(全く意味がわからないですが、このDBを見ても何も思わないような人しかいなかったので、開発ほぼ未経験の人間に何を言われても何も思わなかったのだと思います)



上記以外にも書ききれないほど問題がありましたが、簡単に言うとうまく行っている部分がひとつもありませんでした

最終的にはプロジェクトの納期を無理やり引き延ばしたものの、プロジェクトの予算がなくなっていたため契約は終了しプロジェクト離脱となりました
数か月はこのプロジェクトに関わっていたのですが、結局まともにテストが通ることはありませんでした(毎月40時間近く残業したにも関わらず…)

このプロジェクトはどうすれば良かったのでしょうか(そもそもの設計スキル不足の問題はありますが…)

#まだマシな方法
では、どうすればもう少しマシになるのか考えてみましょう
先ほどこのような問題が発生していました

>第一に、タスクの洗い出しの漏れが発生していたこと
>第二に、タスクを全て消化できるほど人的リソースがなかったこと
>第三に、スケジュールに現実味がなかったこと

これはやり方だけで解決できます
ひとつづつ見ていきましょう

>第一に、タスクの洗い出しの漏れが発生していたこと

漏れは必ず発生します
手を動かしていく内に設計の間違いに気付き手戻りが発生することは許容できていなければなりません
そもそも漏れが発生する前提で物事を考えていれば、他の問題を起こさずに済んだかもしれません

>第二に、タスクを全て消化できるほど人的リソースがなかったこと

人が足りない！っていうのはよくあることです
今回の問題の原因は「人手不足」ではなく、「タスク過多」でした
簡単に言うと、タスクの精査ができていませんでした
優先順位は付けていたのですが、要/不要の切り分けは行っていませんでした
そのため本来必要のないタスクに人が割かれてしまい、実際に使える人的リソースが元々の半分以下になっていたのです

>第三に、スケジュールに現実味がなかったこと

タスク過多な状態のため、勿論まともに線を引いていったらスケジュールは成立しなくなります
チームリーダーはそれを回避するため、現実味の無いスケジュールを引いてしまいました
現実味の無いスケジュールにどれだけ価値があるかは理解できませんが、少なくともそのチームリーダーは価値がある、と思ったようです
スケジュールは実行可能な状態にしてください

なるほど、これらを気を付ければもう少しマシな結末を迎えられたかもしれません
でも、これだけで十分でしょうか？

#最強の方法
いくつかの本を読んでみたところ、共通点が浮かび上がってきました

- **一人より二人**

ペアプログラミングというやり方があります
一人でコードを書くのではなく、一つのコンピューターの前で**二人で**コードを書きます
これをすると生産性が半分になるのではないか？という反論があるようですが、実際には違います
プログラマーはより良い設計を考えながらコードを書きます
タイピングの速度競争ではありません

二人分の情報を使えるため、より品質の高いコードが書けます
何かの問題にぶち当たったとしても、一人でやるよりもはるかに素早く、正しく問題に対処できます

ソフトウェア開発で問題になるのは、個人間の情報の差です
情報量が少ないと、情報量が多い人に比べて誤った判断をしてしまう可能性がグンと上がります
複数人で協力して仕事をする、というのは情報を共有し、正しい判断ができるように促すことだと思っています

- **一番頭の良いお金の使い方を**

「明日のお金よりも、今日のお金のほうが価値がある」という考え方があるそうです
この考え方でくと、素早く稼いでゆっくり使っていくのが頭が良いお金の使い方と言えます

- **小さいステップ**

複雑な問題をいっぺんに解決しようとするのではなく、複雑な問題を分割して簡単な問題にしてから解決したほうが良い、ということです
そのほうが確実に問題に対処できますし、どのくらいの期間が必要なのかも予測しやすくなります

これらの考え方を元に、より良いやり方を考えてみましょう

###ウォーターフォールからの脱却
まずは、ウォーターフォールから抜け出さなければなりません
ウォーターフォールでは最初から全てのことを把握した上で設計することが前提となっていますが、ソフトウェア開発では非現実的です
他の方法を用いる必要があります

それがアジャイルと呼ばれる方法です
アジャイル開発にはいくつかのやり方があり、厳密に言うと正しいやり方はありません
自分らで考えて！という風になっているからです
まずは下記の図を見てみてください

![優れたやり方.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529608/45e024d7-20d6-c008-2458-f8f4a7d34c6c.png)




これが僕が学んだ最強の方法です
テストめっちゃ多いですよねｗ
順に説明していこうと思います

- **要求(ストーリー)**

まず、顧客が求めているものをストーリーとして書き出します
そのストーリーに優先順位を付けてもらい、優先順位が高い順から手を付けていきます
※基本的には顧客が付けた優先順位ですが、技術的な問題がある場合は優先順位を入れ替えても良いです
ここで重要なのは作業工程単位ではなく顧客の価値(フィーチャー)単位で扱う、ということです

- **テスト**

手を付けるストーリーが決まったら、まずは受入テストを書きます
Cucumberが有名ですが、顧客と合意が取れるのであればなんでも良いと思います
合意、と言いましたが、可能であれば顧客に書いてもらいましょう
チームはそれをサポートしてあげてください

- **設計**

顧客を交えてドメインをモデリングしてください
これが基礎となります
が、最初から最強の設計を行うことはできません
逐一設計を見直し、問題無いかどうかを確認する必要があります
必要があれば設計を変更してください

- **テスト**

実装の前にテストを書きます(テストファーストと呼ばれている)
ここで注意したいのは、全てのテストを書いてから実装に移るのではなく、ひとつテストを書いたらひとつ実装を書く、というのを徹底してください
最初にテストコードを書き、とりあえず成功する実装を書き、その後実装をリファクタリングしてください
※TDDと呼ばれる手法。レッド、グリーン、リファクタリングを繰り返す

- **実装**

TDDにのっとり、最初はテストが成功するためだけの最小限の実装をしてください
滅茶苦茶な意味のないコードになりますが、それで問題ありません
テストが成功したら、その中身を書き換えていってください
このタイミングで実装をきれいにしていきます
コードをいじる度にこまめにテストを実行してください

- **テスト**

実装と重複しますが、コードを書き換える度にテストを実行してください
最終的に納得のいくコードができたらそこで終了です
次のテストを書くか、設計に問題があるようであれば設計を変えてください(これには実装のタイミングで気付くかもしれません)

- **テスト**

全ての実装が終わり、テストも通ったのであれば受入テストを実行してみてください
それが通り、本番環境に統合した後もテストが成功するのであればそこでストーリー完了です
次のストーリーに取り掛かってください


ストーリーは上記の方法で実施していきます
バーンダウンチャート(もしくはバーンアップチャート)を用いることによってあとどれくらいでストーリーを全て消化できるのかの予測をかなり正確に立てることができます
是非使ってください

###注意点
少し前にTwitterで話題になりましたが、納品期日を守るのが仕事ではありません
<font color="red">**どのくらいの期間が掛かるのか、嘘をつかずに誠実に伝えることが仕事です**</font>
無理なことを隠してプロジェクトを進めることは誰にとっても良いことはありません

見積もりの精度はそのプロジェクトに関わる期間が長ければ長いほど正確になる傾向があります
全然知らないプロジェクトの見積もりをなんとなくやっただけでは精度の良い見積もりはできません
この条件をクリアするために、契約は細かく分けて結ぶ、というやり方もあるようです
これによって精度の高い見積もりを提示できるようになります(勿論最初からは無理ですが…)

#役割分担は必要？
アジャイルでは同じ人が顧客と話し、設計も実装もテストもやります
役割分担は必要なのでしょうか？
結論を言うと、役割分担が必要な時もあれば必要無い時もあります

役割分担をしなくても勝手に仕事をしてくれるチームを作ることが目標ですが、最初からそうはできません
プロジェクト当初や、新人が入ってくるタイミングではある程度役割分担があったほうがうまくいきます
しかし、この役割分担というのは完全に「担当者」になるのではありません
テスト担当者が設計をすることもあるし、デザイナーがテストすることもあるかもしれません
それを全員が理解している必要があります

チームが仕事の進め方に慣れてきたら役割分担が足枷に感じるようになります
その時には役割分担を無くしてしまいましょう

意味のあることはやって無駄なことはやらない、というのがアジャイルです

#何が悪かったのか
先ほどのプロジェクトの話に戻ります
このプロジェクトでは、大きなスコープを一度の契約で結んでいました
この時点で一つリスクを抱えていたことになります
プロジェクト内では複数の段階でリリースしていましたが、契約自体はひとつでした

人数も異常に多く、複数の拠点でプロジェクトを進めていました
コミュニケーションに掛かるコストを無視しており、コミュニケーションがスムーズになるような取り組みを何も行っていませんでした

各チームリーダーはタスクを割り振ることしか考えていませんでした
<font color = "red">**タスクは引き受けるものです**</font>
割り振ることはできません
<font color = "red">**責任が移動する場合は、同時に権限も移動しなければなりません**</font>
このプロジェクトではそれを無視していました

このプロジェクトでは実装をしてからフィードバックを貰うまでの期間が異常に長かったです
顧客もプロジェクトに参加しておらず、受入テストも書いていませんでした

ペアプログラミングも行っておらず、それどころかコードレビューも100%は行っていませんでした
コメントも1行ごとに書いており、品質の低いコードを時間を掛けて書いていました

設計と言いながらメソッドごとにきれいなフローチャートを一生懸命書いていました
実装は常に変わっていくので、ドキュメントを編集するコストが異常に高くなっていました
変に詳細な設計書を最初から完璧に作ろうとしていたので、複数人で設計書編集をしても結局追い付きませんでした

勿論まともにテストは通ることはなく、プロジェクトは赤字になりました(何もしないほうが稼げたｗ)

ここにある全ての問題は最強の方法を使えばもう少しまともになったかもしれません
ただ、一番問題だったのは良いソフトウェアを作ろうとしている人がいませんでした
単に技術的なスキルが低い、ということもありますが、それ以上にやる気が全くありませんでした
朝早く来て夜遅く帰ることを仕事だと思っている人たちだったので、ソフトウェア開発がうまくいく訳がないですよねｗ
ここまでひどいと、優秀なコンサルに頼んで組織改革までやってもらわないと立て直せないと思います
結局、一番重要なのはやる気のある人間がいるかどうかなんです

#まとめ
いくつかの本を読んできた感想みたいなものを簡単に書いてみましたが、もっと詳細なやり方も載っていましたので詳しく知りたい方は是非本を買ってみてください

[アジャイルサムライ−達人開発者への道−](https://www.amazon.co.jp/gp/product/4274068560/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1)
[テスト駆動開発](https://www.amazon.co.jp/gp/product/4274217884/ref=ppx_yo_dt_b_asin_title_o02_s00?ie=UTF8&psc=1)
[エクストリームプログラミング](https://www.amazon.co.jp/gp/product/4274217620/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1)