@ledsun blog

Hのキーがhellで、Sのキーがslaveだ、と彼は思った。そしてYのキーがyouだ。

失敗プロジェクトの弔い方

プロジェクトを燃やした経験から、どうすれば有効なふりかえりができるのか考えてみました。

要約

  1. 失敗プロジェクト参加者の信用を回復
  2. 失敗プロジェクトの撤退戦術を共有
  3. 失敗プロジェクトの回避方法を検討

背景

を見て考えました。 外野から見たら、確かにまったくこう見えると思います。 なぜ、傷口を抉るようなことをするなと言いたい「気持ち」になるのでしょうか?

失敗プロジェクトの当事者の立場

外野も嫌がらせや、憎くしみででやってはいません。 わかってはいます。 ただ、原則として、デスマ中は前門の客、後門の同僚、両方から打たれている状態です。 その直後に、罰しないから「失敗ポイントを明確にしてふりかえろう」と言われても、信用できません。

外野の方たちは、本当に辛い場面で後ろから殴ってた人たちです。 ふりかえりに参加している特定個人が本当に殴っていたかはあまり関係ありません。 社内の誰か一人でも殴っていれば、「ふりかえりの参加者も殴りに参加していた」と疑うのが人間の心理です。 一度疑えば、「ふりかえりで殴りネタを探している」と疑うのが人間です。

本当に「ふりかえりで殴りネタを探している」かは問題ではありません。 傷ついていて、疑う心理状態にあるのが問題です。

「そんな傷口を抉るようなことするな」と怒られ

は、こうした背景を意識した反応だったようにも思えます。

ご提案

「失敗」とつけない

最初に「失敗プロジェクト」という認識自体を改めましょう。 なぜ「失敗」とつけたのでしょうか? 外野からでも

  • プロジェクトの進行が、当初聞いていた予定より0.5倍以上伸びている
  • プロジェクト参加者の平均残業時間が長い

といった情報が観測できると思います。 もう少し詳しい情報を知っていれば

  • 売上をコストが超過した
  • メンバーが逃亡した
  • 納品できず、損害賠償請求を受けた

という情報を知っているかもしれません。

これらの現象のどの段階で「失敗」とつけるべきでしょうか?

「失敗」と名付けると、プロジェクトとプロジェクト参加者が批判されます。 批判には「正当な批判」もありますが、誤解に基づく「誤った批判」もあります。 批判にはコントロールが必要です。 コントロールされない批判が増えると、吊るし上げになります。 雑談における批判は、多くの場合コントロールできません。 結果として「誤った批判」が増え、「プロジェクト参加者を吊るし上げてよい」空気が生まれます。

私の観測範囲では、吊るし上げられた人間に、批判と自分を分離する圧倒的メンタルタフネスがない場合は、退職することが多いです。 万が一退職された場合、組織を維持するためには、欠員を埋める分の採用コストと教育コストが必要です。 プロジェクトに「失敗」とつけることには退職者を生むリスクがあります。 現実のコストにつながるリスクです。

「失敗」を禁止すると、別の悪い名前がつきます。 「失敗プロジェクト」には別のポジティブな呼び名をつけましょう。

奇跡の生還プロジェクト

(例えば)「奇跡の生還プロジェクト」と呼びましょう。

「奇跡の生還プロジェクト」のふりかえりでは生還方法を学びましょう。

炎上プロジェクトから生還した人は、少なくとも「困難な状況で逃げない」という特性がひとつ以上の事例で証明されています。 どんな過酷な状況でも生き残る「生還者(リターニングマン)」かもしれません。

この特性は、先天的なものでしょうか? 後天的な要素はないでしょうか? もしあるならば共有する価値があります。

同様の、困難であることがわかっていても、やり遂げなければいけない状況では、使いやすい人材です。 また、開発者には、自身の努力と関係ない部分で「奇跡の生還プロジェクト」に巻き込まれるリスクがあります。

「奇跡の生還プロジェクト」に巻き込まれるリスク

「炎上しはじめたプロジェクトからは全力で逃げる」を貫けると個人の幸せは得られるかもしれません。 ただ、そう強い人間ばかりでもありません。

  • 受注時にリスクを低く見積もっていた
  • 受注後に追加要望が現れた、しかし政治力によって拒否できない
  • すでに炎上しているプロジェクトに助けに入った

のような状況では、多くの人は「奇跡の生還プロジェクト」から逃れるのは難しいでしょう。 「奇跡の生還プロジェクト」に巻き込まれたときに、生還するためのプラクティスを聞いておくのは、いつか役に立ってしまうかもしれません。

奇跡の生還プロジェクトに遭わないようにする

もちろん「奇跡の生還プロジェクト」の芽をみつけ、事前に潰して回るのが至上です。 もしかすると多くの開発の現場では、早すぎる願いなのかもしれません。 残念ながら

デメリット

「奇跡の生還プロジェクト」として扱うことにデメリットはないのでしょうか?

アドレナリンジャンキー問題

当然考えるのが、「奇跡の生還プロジェクト」として褒め称えられなら、最初から炎上させようと考える人間が現れることです。 炎上している時に生きている実感を感じる人間もいます。 そういう人は早めに検出して、「奇跡の生還プロジェクト」の助っ人要員にしましょう。 プロジェクトの立ち上げからは外しましょう。 お互いのためです。

潜在的な問題

ところで「失敗プロジェクト」として吊るし上げられて辞めない人間はどのような人でしょうか?

批判を受けても、ものともしない人間です。 このような人物は、ふりかえりで得た改善案を実践するでしょうか?

また、次の仕事にあてがなければ、なかなか辞められません。

とすると「失敗プロジェクト」などのネガティブな名前付けを放置しておくと 「アドバイスを聞かない頑固者」「つぶしの効かない偏った技術者」を選別して 会社に残すバイアスが働きそうな気がします。

10年後にはどうなっているのでしょうか? 興味深い思考実験です。

おまけコンテンツ

後門から刺される例

外野経験

とは言っても、自分が外野だった時は「いつまでやってんの?早く終わらしてよ」と思っていました。 人間、その立場になってみないとわからないことがあるようです。

IoTゲートウェイのモデリング

用語

  • 機器:HTTP/HTTPSな環境から操作する機器
  • 機器種別:機器の種類。例、エアコン、照明、etc。あるいはエアコンもメーカによって異なる機種種別として扱う必要があるかもしれません。

要件

現在のIoTでは機器種別によって、ネットワークを介した操作方法が異なります。 機器種別によっては直接HTTP/HTTPSの世界と接続できないことがあります。

例えば6LoWPANという規格でつながっているかもしれません。 IoT規格 6LoWPANとは? | IoT

IoT機器を制御するWebアプリケーションを作るには、HTTP/HTTPSの世界につなぐゲートウェイが必要です。 RESTful APIでIoT機器を制御できれば、Webアプリケーションエンジニアにアプリケーション作成環境を提供できるでしょう。

モデリング

IoTゲートウェイでは、原則として、機器種別に応じて変わる情報をロジックで実装します。 機器の設定変更に応じて変える情報はDBに保持します。 大きく次の3つのモデルに分けます。

  • Deviceクラス
  • Profileクラス
  • Clientクラス

これらのクラスはWebMVCの分類では、いずれもModelです。 ここではViewやControllerに関する設計は扱いません。

Device

Deviceは機器操作ロジックを担当します。

  • 対象機器と通信相手のマッチング
  • RESTful APIのパラメータを機器向けのパラメータに変換
  • 複数リクエストが必要なシーケンスの管理

操作したい機器と通信相手が1:1とは限りません。 1つの通信相手が複数の機器を管理していることがあります。 この関係性は静的な情報です。ロジックとして実装します。

機器がJSONでのリクエストを受け入れない場合は、JSON以外の異なるフォーマットに変換する必要があります。 ゲートウェイのRESTful APIは、人間が読めるパラメータが望ましいです。 機器が16進数文字列を要求する場合、変換して送る必要があります。

1つのRESTful APIリクエストに対して、機器に複数のリクエストが送る必要がある場合、 それらのシーケンスはここで実装します。

DeviceはProfileとClientを持ち(に依存し)ます。

Profile

Profileクラスは機器の情報を持ちます。 代表的なものに次があります。

  • 名前
  • 機器種別
  • 位置情報
  • 接続情報

ロジックとしては、検索ロジックを担当します。 ProfileクラスはDBのレコードと対応しています。 Active Recordパターンを使うのに適しています。 Ruby on RailsであればActiveRecordやApplicationRecordを継承したクラスとして実装します。

機器種別ごとの拡張が必要な場合は機種別のSubProfileクラスを作ります。 例えば、機器種別ごとに接続方式が異なる場合は次のように情報を持ち分けます。

  • Profile
    • 名前
    • 位置情報
    • 機種種別
  • SubProfile
    • 接続情報

ProfileクラスとSubProfileクラスには継承関係は持たせません。 DeviceがProfileインスタンスとSubProfileインスタンスを持ち、適宜使い分けます。

想定外の新しい機種種別を追加した際に、Proflieには影響を与えたくありません。 1:1関係のテーブルに分けます。

関連付けにはidを使います。 外部との接続性を重視した場合は、idにUcodeを使うかもしれません。 Ucode | IoT

Client

Clientは機器との通信を担当します。 原則として状態は持ちません。 通信状態は持ちますが、通常はHTTPClientなどの別のクラスに移譲しているでしょう。

機器がHTTP/HTTPSで通信できれば、特に難しいことはありません。 リクエス送信先を整形し、リクエストボディを整形し、リクエストを投げるだけです。 ロジックと言っても、せいぜい通信エラーを例外で抽象化するぐらいです。

Clientを別クラスに分ける最大の効果はユニットテストの書きやすさにあります。 Deviceのテストコードを書く際に、ClientのインターフェースにあわせたMockに置き換えることができます。 Deviceは比較的複雑なロジックを持っているので、ユニットテストで品質を確保します。

IoTではエンドツーエンド試験環境を作るために、機器を用意する必要があります。 機器とゲートウェイの製造が並行している場合は、試験が開発期限ギリギリまで行えないことがあります。 事前にユニットテストでテストしておきたいところです

アプリケーションレベルの分割戦術

エアコンと言ってもメーカごとに接続方法や操作方法が異なります。

ここで扱ったHTTP/HTTPS世界とのゲートウェイの他にもう1つ エアコンを抽象化するゲートウェイを用意すると、分業しやすくなるでしょう。