PHPお手軽スタートキットを作った

先日、色々と調べごとをした結果を踏まえて「よ〜し、いっちょ自分でコード書いて試してみっかな!ライブラリでも作るかい!!」って気分になりまして。
その際に↓みたいなツイートをしていたのです。この辺りの”標準”みたいなのあんま分かってないな〜って。

いちいち「何が必要かな・・?」って考えるの結構ストレスになりそう。CIとかテスト周りとか整えるのも面倒くさくない?
そんな事をボヤボヤと考えている内に「そういえばGitHubにテンプレートプロジェクトって機能があったよね、使ったこと無いな」と思ったので、「ぼくのかんがえる最低限整ったPHPプロジェクトの雛形」を作ってみました。

github.com (コミットがメッセージも切り方も適当すぎてぶん殴られそうですが・・)

「今どきなPHPプロジェクトってどういう感じなんだろ?」っていうのにも興味があり、自分なりに考えて”それっぽいやつ”は入れてみたつもり。

なお、必要なツールを考えるにあたってこのPHP QAツールがすごい!2019を参考にさせていただきました🙌

なにができるの

  • PHPの実行環境としてDockerfileを入れてある
    • IDEから叩くような想定。というかPhpStormのCLI Interpreter
    • 一緒にmysqlも入れた、docker-composeで使う
  • ✅ ↑にXdebugが入れてある
  • PHPUnitをサクッと動かせるようにphpunit.xmlを入れてある
    • 地味に書き方忘れません?
  • PHP_CodeSniffer, PHPStan, Psalmも入れてある
    • 「最初から入ってれば負担も少ないはずだ」と思って、レベルはぎっちぎちにした
    • phpcsはPSR-12とSlevomatCodingStandardベース、PSR-12とぶつかるルールとか一部緩和
    • phpstan-strict-rulesとphpstan-phpunit入れた
    • psalm/plugin-phpunitも入れた
  • GitHub Actionsでphpunit phpcs psalmを叩くようにしてある
  • ✅ ↑を実行した時にreviewdogでコメント飛ばすようにしてある

作ってて思ったこととか

  • とりあえず「最低限」ってレベルならコレでいけそ、って感じにはなった
    • 色々と触りながら育てていく前提
    • lint周りとか色々と気になる部分出てきそう
  • GitHub Actions自分で触ったこと無いんだよな〜〜*1やりたいな〜って気持ちもあったので、少し欲求が満たされた。良かった
    • CIの設定ファイルだけ入れておけばすぐに動くの便利だな、すげーやGitHub Actions
    • 毎回Dockerイメージをbuildしてるからキャッシュとかした方が良いんかな?
  • codecovとかのよく使いそうなSaaSの記述はどうしようかな、と思ったけど一旦入れてない
  • READMEファイル置いてあるけど、このレポジトリの説明どこに置けばいいんだろ?
    • READMEとREADME-exampleみたいなのを分ける必要がありそうだな、紛らわしいし
  • バッヂ類は充実させたいな!
  • composerのcreate-projectも対応させてみよ。やったことないし

他の人の考えたやつも見てみてぇ〜な〜〜

*1:後になって気づいたけどやった事あった・・w https://github.com/Connehito/cake-sentry/pull/35/files

BASE株式会社を退職しました

前にも働いている会社を退職した事があったのですが、この度BASE株式会社を退職しました。 1社目・2社目はそれぞれ4年前後在籍していたので、そこから比べると期間的には短くなりますが、色々なものを初めて見たり学ばせてもらえたんじゃないかな〜と感じています。

続きを読む

やったこと・書いたもの{2020,07}

OSS

github.com ずっと鬱陶しがってたやつ直した。
ぐちゃぐちゃと考えないで、ごくごく単純なやり方で良かったなぁと気づいた・・・・

github.com 以前cake4対応を完了したのをawesome-listに対応してもらったもの。
3.0.1が出てからでいいかなぁ〜とか思ってたけど何もバグ修正や更新が現れないので、そろそろいっか!となり。

勉強会・LT

その他

ウェッブアプリケーションのエラーを無くしていきたいわよねという話

社内に何度か「ね!!エラー減らしてこ!!きっと良いことになるから!!」みたいな話を投稿しておりまして、そのラストに「じゃあ実際どうやって&どう考えて進めていくのかね」という事も認めました。
その内容が「またどっかで使いそう〜」と思ったのでリライトして載っけてみます。

長くなったので記事を分けようかなぁとも思ったのですが・・・

前提: 0次対応というコンセプトについて

エラーはいつ直すか?基本的には「気づいたらすぐ直す」のが最もコストが低いと思っています(なので、そのための土壌を整備しておくべき)。
ソフトウェアがおかしくなるのは、「変更を加えた時」もしくは「変化が生じた時」という事になるはずです。これについては後で改めて言及します。

この「変更を加えた時」において「エラーが起こりやすい」というのは予め認識しているわけですから、「デプロイした直後にはエラーが起きないかをいつもより注視し、発覚したらすぐに修正や回復に取り組む」というのが基本姿勢であると考えています。
これを、インシデント対応の「一次対応/暫定対応」「二次対応/恒久対応」になぞらえて「0次対応/未然対応」という風に個人的には呼称しています。
エラーが既に起こったことが観測された事へのリアクションなのだから「未然」じゃないじゃん、その言い方は詭弁じゃん・・・・と思われるかもしれませんが、「問題が大きくなる前に、ボヤ状態で沈下できた」というイメージです。そのエラーに実際に見舞われてしまったエンドユーザーを思うと重々反省すべきではありますが、もっと大事になってしまうよりかは。。。

ソフトウェア開発において「失敗を恐れない」ことは有効です。また、「まだ起きていないこと」を予測し回避するのは難しいことでもあります。
なので「筋の良い集中力の疎密をデザインする」のは重要です。
逆に、失敗を恐れるあまりに萎縮して、結果として緊張感が過度に高くサイクルを回すのも遅いような状態は望ましいものでもありません。
これらのバランスを取るためのプラクティスとして、「0次対応に力を入れる」という考えに至りました。

「なぜ」やるのか

全ては「サービスの信頼性」の為だと考えています。
前職では、サービスの信頼性について担保できるチームを構築する・スケールしていくために、という観点で「監視の民主化」に取り組んでおりました。

この流れの一環として「アプリケーションのエラーをメチャクチャに減らす」というのに取り組んでいました。
(週単位で、各レポジトリごとのエラー発生箇所数をメトリクスとして「エラーを減らす」に取り組んでいました→後述)

言い換えると、「エラーをゼロにするために、エラーをゼロにしようぜ!」という考え方は当初より持ち合わせておりません。重要なのは、 アプリケーションエラーの管理(アラート)を、モニターとして意味のある状態にできているかどうか というところに絞っています。
「いつも何かエラー通知が飛んできている -> 異変に気づきにくい」よりも「いつもは飛んでないのに、今なんか来た → これは異常が起きてるな?」が良いよね、ということです。
こうした「反応できる」という状態 を作れると、ものすごい価値を生みます。

先述のリンク先記事で触れている資料中では、「対障害のためのアラート」と「対品質のためのアラート」という呼び方をしていました。
前者(変な時にアラート)と後者(すっかりエラーゼロ)だと、前者はある意味で妥協なのですが、しかしコレが出来ればメチャクチャ効果あります。逃げるは恥だが役に立つって言いますしね。

f:id:o0h:20200626183356p:plain

どーゆー流れ

「実際にやっていくとしたらどう進めるか」についてはツラツラと考えている内容でもあるのですが、それを示します

  1. エラー管理ツールの整備
    • 「絶対に使いたい要件」を満たすようにツールの設定をする
  2. 棚卸し: 既存エラーのうち「要らないエラー」を無視できるようにする
    • サービス提供上の問題がないエラーは「ノイズ」とみなし、気にしなくて良いようにする
  3. 残ったエラーを個別に潰していく
    • 発生頻度が高い × 修正難度が低い、の組み合わせが最優先
  4. ここまで行くと「監視に便利」になる :tada:

エラー管理はどういう物が良いかな

適切にツールひいてはエラーと付き合っていくには、 付き合わない相手 を決めることが重要です。
要するに「対処する必要があるやつ」だけ流れてくればOK。
そして、対処する必要があるやつは「すぐ分かるようにしてくれ」という気持ちがあります。

そのためには、以下の内容が適切に扱えるものが望ましいと個人的には考えています。

  1. 「新規エラー」を教えてくれる
  2. 「多頻度で発生しているエラー」を教えてくれる
  3. 「沈静化しているエラー」を考慮してくれる

順を追ってみていきます

新規エラーについて

「今までになかったけど新しいエラーが起きたよ」というのは、アプリケーションエンジニア的には非常に重要な情報です。
サービスで何かしら「異変」が起きるのは、 概ね「変更をした」もしくは「変化があった」とき だと言えます。

  1. 人為的に開発者が変更を加えた時
    • 実装内容の不足・ミス
    • オペレーションのミス
  2. 外発的要因
    • アクセスの急増、負荷上昇
    • 攻撃に起因するもの
    • (クラウドの場合)マネージド領域の異変

もし「何か起きた」のがデプロイ直後なのであれば、コード周りのミスがあるか、データないしインフラ等の不備が考えられるでしょう。

この時に「すぐ気付いてすぐ潰す」ことができれば、利用者に対してのダメージを最小限に抑えらます。それと同時に「なんとなく心当たりがある」ことによって、改修コストも著しく下がります。

なので、 「新規エラー」を教えてくれる ようなツールが良いと考えています。 もちろん、その際に「同じと思われるエラーをグループ化してくれる」のも重要な要素です (例えば、「URLや呼び出し元クラスが違うけど、エラーを引き起こしてるのはモデルクラスの修正ミス」だった場合、stack traceが違っても「同じモデルのエラー」として扱って欲しい)

頻出エラーについて

いわゆる「準正常系」もしくは「runtime的にエラーの完全回避が免れない」ものとは、どうしても出てきます。
例えば「ファイル出力を伴う処理で、リクエストのタイミングによってはalready_file_existsな感じのエラーが起きる」とかそういうやつです。

アプリケーション内部の持つロジックとしてそれを回避できるように整えるのも重要ですが、もし「ユーザーに対しての不利益がない」という確証があれば、そのエラー自体はあまり痛くないかも知れません。
数日に1回はやっぱり起きちゃうよね〜なんて見て見ぬ振りをするのも選択肢の1つです。

が、これがもし「直近30分で100回も発生している」となったらどうでしょうか?
これは「エラー自体はよくあるやつ」で看過できないような、重大な異常のサインとなります。

なので、 「多頻度で発生しているエラー」を教えてくれる とオペレーションフレンドリーな設定が可能になります。
「新規」がopen/closeなフラグによる監視だとしたら、「頻度」はfrequnecyをみるものです。
「あれ、やっぱり変だね」を際立たせる手段は非常に有り難い存在となります。

しきい値として「どのくらいの頻度になったら」は、エラーの質やプロダクトの性質・品質によって変わります。
方針としては、「おかしな量」のしきい値を厳しくすると「けたたましいアラート」になりますので、なるべく緩めにしたいところです。
例えば「10回起きたら異常」と「100回起きたら異常」というのでは全く性質が異なってくる、というのは想像できると思います。他方で、「10回起きたら異常」と「1回でも起きたらヤバい(ユーザーないしデータが被害を被っている)」の違いは何でしょうか?こうした「n回許容できるエラー」については、様々な要素を加味した上での判断が求められます。

定量的に監視したい」ものについては、「そこのコードが悪くないが、他箇所のコードやミドルウェア以下の技術要素等との組み合わせがおかしいもの」とも考えられます。
ここで不安感を過大評価しすぎると「すぐに拾いたい」方向に傾きがちですが、「すぐに拾うべき」ものは極力「1回も発生を許さない」と分類し、実装において解消されるべきだと考えます。
「ユーザ視点での監視」を意識し、「監視のアセスメントを行う」ことで適切な閾値を発見していく・洗練していくことが重要です。

沈静化しているエラーについて

開発を行っていると、そのソフトウェアは日々変化していってるため「いつの間にか何も問題がなくなっている」という事は多々あります。他の箇所の修正で直ったとか、そもそもコードが消されたとかいったものです。

こうした「(明示的に解消を記録してないが)沈静化している」エラーについてはしっかり浄化されていく必要があります。

なので、 「しばらく経ったけどもう大丈夫そう」というエラーはactiveでないと見なしてくれる と日々の運用におけるノイズが減ります。そうすることで、「今起きていること」についてだけ知ることが出来るわけです。本質的なこと、本当にやるべきことにフォーカスしましょう。
設定したインターバル中に1回も起きなかったら自然消滅する、みたいなのが良いですね。

「どのくらいのインターバルをおけばいいか」は、対象となるPJのリリース頻度やチームとしてエラーの解消をどの位こまめに行えているかに依りそうです。

自分が過去にいたチームで行った設定を例に取ると、「3日間なにもなかったら自動でクローズ」です。
これは比較的短い単位で「またアラートが飛んでくるようになる」という事を意味します。一見すると「問題が解決したとみなすハードルが低い」ので「運用をゆるふわにする」ような印象を持つかも知れませんが、体感としては逆の事態が起ることになります。
これをもし、1週間や10日というインターバルにしたのであれば、「(エラー管理ツール上はactiveなままだけど)再発のアラートはあんまり飛んでこない」という事になります。

どうやって気づくか: push通知(アラート)と組み合わせて考える

アラートは「何かが起きた時に気付かせてくれる」ようにしたいです。
ここまでに整理した3点について要件を纏めると、

  1. 「新しいエラー」が起きたら通知してくれる
  2. 既存エラーを「明らかにおかしな量」検知したら教えてくれる
  3. 解決済みのエラーが「再発」したら教えてくれる

といった条件が浮かんできます。
これらをSlackに飛ばせると良さそう。

また、「頻出」エラーについては、その他のトリガーよりも少し警戒レベルを上げて発報する・・・という手段を検討して見る価値はあるかも知れませんね。(発報先のチャンネルを変える、メンションの対象範囲を変えるなど)

あるいは、しきい値を複数用意してnotice/warnを出し分けるのも良いアイディアです。
もし利用しているツール単体ではそうした繊細な管理が難しそうであれば、CloudWatchのカスタムログにoutgoingしてCloudWatch Alarmに管理させる〜なんて手もあると思います。もしくは、インシデント管理全体のデザインから見直して「ツールを組み合わせる」ことも考えられます。個人的なオススメはPagerDutyです。

これらの「1,3: 発発生したらアウト(要対応)」のものを「定性的なエラー: 内容に対する監視を行っている」、「2: 頻度を見て通常の状態から逸脱が見られる」ものを「定量的なエラー: 動向について監視を行っている」とみなすことも出来るかと思います。

「定性的な監視対象のものが、定量的な観点でも異常と言える」ものは緊急事態が発生している可能性が高いです。
例えば「データベース接続エラー(めったに起きるものではない!)が1分で100回も起きる」のは緊急度が高いですし、これはインフラに対してアプリケーション観点で統合的に監視していると考えることも出来ます。アプリの範疇を超えたモニタリングの責任を負わせるのか?と捉えると違和感を覚えるかも知れません。が、気づくキッカケはどこでも良いのです、とにかくヤバいことだけ伝われば後は人が対処できる・・・
あるいは、もっと単純に「未定義変数の呼び出しが行われている」といった「そこまで緊急的なものではないかも」というものでも、「3分で500回も起きた」ならば、それはユーザーの利用頻度が高い・リクエストが集まっている箇所でのダメージが考えられるので、対応すべき確率が高くなるはずです。

蛇足: アラートは少ないほうが良い

「FYIの通知」と「誰かを叩き起こすためのアラート」という考え方は基調に据えるべき重要な指摘だと思っています。
それにしたって、「要対応レベルではあるけど即死級ではなさそう」なものであっても「1週間に1個だけ飛んでくる」という話であれば、きっと真面目に対応することも可能になるでしょう。これが「毎日100個」となると大変です。

「そもそもアラートが鳴らないようにする」ことを徹底しておけば、「たまに飛んできたエラーにじっくり向き合う」ことも現実的になるはずで、自ずと「Informationの質が上がる」ことに繋がるのではないかと考えています。

「要らないエラー」を捨てる = 情報を断舎離する

「ユーザーの操作が前提条件を満たしていない」「想定の範囲内ではあるが(=正しく制御された結果として)、内部的にuncaught exceptionを使ってユーザーの操作を停止させている」みたいな場合に、実装的にはエラーじゃないが表現として例外になり、エラー管理ツール上に登録される みたいなものが発生してくると思います。

「既にエラー管理ツールに可視化されている内容を金輪際シカトする!!」のは、割とドキドキする作業ですが、経験上、ここを徹底できると物凄く捗るな〜というのを個人的には心得ています。

例えばcakephp/app では、「PageNotFound Unauthorized などの例外はガッツリ管理する必要はない」といった設定を示しています。
https://github.com/cakephp/app/blob/3d543a0a9ae03ac299bc2b1c222fe08570a9bf7f/config/app.php#L174

これらの例外は、確かに「ユーザーの要求通りの結果を返答していない」という点でエラーではありますが、実装者側ではなくユーザーの操作に起因するところも大きいですし、「どーしようもないじゃ〜ん!」って感じです。
なので、「ログ(=エラー管理ツールへの登録)は要らない」というのは納得しやすいのではないでしょうか。

ただし、これらもうまく付き合えば異常を顕すシグナルとして利用できます。「めっちゃ変な動きをしているね!」を拾える工夫は可能でしょうか?
そのために別のツールで「定量的に監視する」というアイディアが生まれます。

例えば「ユーザーの送信データがバリデーションに引っかかってエラーになった」というのは、単発であれば「ユーザーの入力ミス」で済ませるのが自然です。

しかし、これが「1分間に100回発生した」らどうでしょうか。もしくは「新しいコードをリリースした途端に10%増えた」だと、看過する訳には行きません。
こうした場合、 「validation ruleが間違っている」かも知れません。もしくは「バージョン管理をclient側との上手く協調できていなかった」という事も考えられます。「UIが著しく使いにくくなった」という事もあります。

あるいは、HTTP Responseコードをインプットにしたモニタリングも効果があると思います。
Cloud WatchだとデフォルトではELBのステータスコードの内訳がざっくりしている(4xx/5xx)ので、別途ログを集計する手立てが必要になるかも知れません。少なくとも、400/401/403/406/413/500/502/503/504辺りは欲しいかも。

何にせよユーザー体験の悪化が発生しているシグナルになるので、ここでちゃんと対応していくのがサービス信頼性につながります。
ということで、「別観点」を組み合わせた監視をすることは個人的におすすめです。

また、そういった「セーフティネット」を敷くことによって、「大胆に削ぎ落とせる」ようになるのも狙いの1つです。
もし「単純に無視するようにするだけ」だと、「何も気づけ無いのは怖い」という不安がつきまとってしまいます。ここで踏み込めないでいると、結局「エラー管理ツールにノイズが増える」状態や「恒常的に発生し続けて、activeなままのエラーが増える」ことになります。
これは、「今すぐ対応すべきものが列挙されている」という理想状態に対して大きな妨げになります。
そうならないよう、「無視させる、が、拾うことも出来る」という手段を用意しておくのは重要です。

定量監視どーやってたん?

定量監視とはいうものの、「1発なら無視できるものの頻発したら退っ引きならねぇ」みたいな類なので、「どこで」「どうして」というのが極めて重要になります。
そこで、「何か起きた」時に「ちゃんと内容をドリルダウンして観察できる」のも重要です。

ということで、

  1. エラーの「記録」に2系統を用意する
    • 定性的に見たいものはアプリケーションエラー管理ツール(※利用していたのはSentry)に飛ばす
    • 定量的に見るだけでいいものはログツール(※利用していたのはPapertrail)に飛ばす
  2. アラートも2系統になる
    • エラー管理ツールに入ってきたものはそこから通知する
    • ログツールに飛ばしたものはCloudWatch(カスタムメトリクス)経由でAlarmを使う

みたいな使い分けをして、監視に柔軟性をもたせて、「なにを見たいかな」ベースで適所適材!どっかで網羅!!という事が実現できれば良いかなと思っています。

具体的には、

  1. 割と細かい粒度に独自例外クラスを定義して
    • 抽象クラス(ないしInterface等)で「定量監視用」というのを分かるようにして
  2. 「普通の例外」「定量的に追えば良い例外」に応じたエラーハンドリングを用意して
    • 後者はPapertrail(->CloudWatch)にだけ記録される
    • Papertrailでは、例外クラス名ごとに個別にsearchを保存して、CloudWatchに毎分exportしていました
  3. CloudWatch上で、例外クラス名ごとにカスタムメトリクスを設置
  4. CloudWatch Alarmで個別にしきい値を設定し、Slack等に通知可能にする

という方法で実現しています。
エラー内容やStacktraceなどは、Papertrail上で確認することになります。

あとは地道に対処していくよ

ここまで進めると、残っているのは「サービスの提供品質上、潰して行く必要がある」ものです。なので、とにかく片っ端から潰していきましょう。
重要度(もたらすダメージ)が大きい × 頻度の高いもの × 簡単に直せそうなもの、という掛け算で優先順位を付けていくのが良いと思います

実際どこまでやるんよ?

さて「恒久的にエラーを0にするぜ!!」というのはもしかしたら難しい目標かも知れません。
それでは、何をモチベーションにエラー潰しをやっていけばいいでしょうか?これは、「良い感じにやる気の出るしコミットしたら跳ね返ってくるKPIを設ける」という他ありません。

私がいたチームの場合は、 週次の定点観測を行い、レポジトリ×領域(backend or frontend)ごとにactive状態のままのエラーの数(種類数)を追う というようにメトリクスを決めました。1
※ 「種類数」 = 「unique error数」みたいな感じです

以下のような理由からです。

  1. 1週間のエラーの「発生件数」については、コントロールがしにくい
    • 「1リクエストだけで複数回起る」ものがあると一気に失点が増えます
    • ループの中でnotice起きてる、とか
  2. 1週間のエラーの「発生種類数」については、開発者に負のモチベーションを与えかねない
    • 実現したいのは「信頼できるサービス」であり、これには「しっかりと改修・改善され続ける」という性質も含まれるはずです
    • なので「リリース恐怖症」を誘発してしまうのは、本望ではありません
    • もし「エラーが起きたらアウト」にすると、罰がおもすぎるのです
  3. 1週間のエラーの「アクティブな種類数」なら、エラーを直すことにもモチベーションを与える
    • ごめん!バグった!→すぐ直したわ!!→よ〜〜し、ならOK!
    • また「発生件数は多いが、重要度が低い」というものに対して、誤った優先順設定を行ってしまうリスクを下げる意図もあります

こうしたトラッキングを行いながら、「着実に一歩ずつ進めていく」ような流れを作る事ができました。
・・・「一歩ずつ」とはいうものの、要らないエラーを捨てたときには一晩にして目覚ましくエラーが減ったりしますが 👻

安心感のある開発、いいですよね〜〜!

ということで、こうやって「エラーを綺麗にしていく」ことが叶うと嬉しくなっちゃいますよね〜〜と個人的には考えています。
ココに上げた「エラー管理ツールの要件」は比較的ミニマムな要求だと思っていて、他にも「コメントがしやすい/markdown等の記法が使える」「ソース管理ツール(GitHub)との連携が高機能」「エラーの検索が使いやすい」「簡易的な統計が使える」「アラートの管理が柔軟(一時的なsuspend、指定条件による自動的なunsuspendなど)」などなど、使い心地に直結する要素は多々あると思います。また、「提供されているSDKがしっかりしている、もしくはSDKに頼らずとも使いこなせるくらいシンプルで柔軟である」などの観点も欠かせません・・・

個人的にはSentryがこの辺りの要求を満たしてくれていたと感じているので、結構オススメできるサービスです。
「どういう風にエラーを管理していくか(平常時のボトムラインをどう設定するか、どのくらいエラーに向き合い対処するか)」「エラー対処のためのワークフローをどう組むか」といった、 チームでどう動くか/どういう意識合わせをするか 次第です。
別に「いつもエラー垂れ流しでも構わんよ」というのであれば、あまりエラー管理ツールに拘らなくてもも良いでしょう。実査に、基本姿勢は「何かあったら対応しよう」に過ぎないはずで、この「何かあったら」の基準について色々な考え方があるよね〜という感じです。

実態に即した・身の丈にあった・それでいて理想を掲げてアプローチできるような!!そんな「あるべき姿勢」というものを、まず定義してみよ〜というのが全てのスタートになるのかな、と思います。


  1. コレ自体はGASのスケジュールトリガでSentry API叩けば容易に実現できたし、票&折れ線グラフで示せて快適だった

リーダーが主人公の組織

ということで、下書き放出です。

最近なにかと、チームってなんじゃらほいとかいった事を考えている。
・・・かつて自分と一緒に働いたことのある人からしてみたら、「お前が何を」「どの口で」と思われそうだけど。膝に矢を受けてしまうことは誰にでもある。

主人公とは、例えば漫画や小説でいうところの「内面や心理の描写が行われる」みたいな存在か。*1
そして「物語を進める」という役割でもあると思う。もちろん、外的な要因や周囲の人物に巻き込まれ、触発され、転がり落ちるように進んでいく事も多いが。が、「傍観者」や「モブ」とは異なり、仮に主体性がそこに内在しなくても、世界は彼(女)を中心に進むーといったような。

では、現実的なビジネス等の場面で、チームにおける「主人公である」とはどんな状態なのか?
まず最初に「その人物が何を思い、どういう動機で動いているのか」というのは意識される必要があるなと感じる。
漫画なら回想シーンが入ったりする。人は原体験に突き動かされる生き物だ。なので、過去にどんな事があって今に至っているのか・・・というのが見えてくると、途端に「憎めなく」なったりもする。そして、それと合わせて現在進行系の理想や「もっとこうなりたいんだ・・!」という覚醒の語りが描かれるのである。
こうして、サブキャラや脇役が、これまでのただの演出上の装置から 物語を突き動かす側 へと変わる。 彼/彼女が何かを言った時に、以後は「意味のある発言」になるだろう。共感すら得られるかもしれない。
無味乾燥な、形式的な「いま何を考えているか」から何歩も踏み込んだ「なぜそういう考えに至るのか」という次元で協調をしてけるとチームというのは有機的につながり活発な主体となると思っている。そのために、主人公的な独白は意味のあるものなのではないか、と。

さて掲題。
自分としては「リーダーが主人公になる」といいうのはアンチパターンなのでは、という考えも持っている。必要なことだし、そのポジションに至るに足る理由があってそうなっていると思うので、おかしな話ではあるのだが・・・
そもそも「権威」がある時点で、その人の一挙手一投足、発言の一言一言に「存在感」が出てしまうと思う。それに対峙しなければいけないのはチームメンバーである。
また、実際に「的を得ている」「正しい」ような発言が多いのだろう。

だからこそ、リーダーこそ「主人公」であってはいけないのではないか?と思うのだ。
例えば、外から見て「あのチームって最近なにしてるの?リーダーの○○さんが頑張っているのは知っているけど」「へぇ、あっちのチームはそんな新機能だしたんだ!流石だねぇ、○○(リーダー)さん!」となっている状態・・これは不健全なのでは、と。

何でそんな風に考えるんだろう、って思うと「1番自分が頑張るタイプのリーダー」の姿を見たからかなぁ。。
確かに広く深い知識を持っている。現状の課題を認識している。その人が、「徹夜して抜本的な改善を成し遂げました」というのを何度も見ていたら・・?
スタンドプレー、とまで言うと言葉が強いが、やっぱり「他の人は何をしているのかな」というのが見えづらい気がする。
まぁ、コレは「傍から見ていて」の話なのだけど。実際に輪の中にいたら状況は違って、「頼れる兄貴」な側面のほうが強いのかも知れない。

しかし、「全部をその人が決めている」ような雰囲気を(勝手ながら)感じてしまい、「他のメンバーは『チーム』という一人格に対して与すことが出来ているのだろうか」などと思った。
課題を見つける、方針を決める、成果も上げる。 コレが一箇所に集中した場合、経験も機会も自主性もその人に集まってしまうと思う。
そうすると、自ずと得られる体験にはどんどん乖離が生じる。
そして、自分も過去に「やっちまった」側での心当たりがあるのだが、そういう場合は往々にして

「だって、他の人が誰もやらないじゃん。こんなに課題はあるし、やって良い自由もあるのに」

と思っている事が多いのではないか。
そうした”中心人物”を周りから見ると、「自由がるのは分かる、課題も感じる、でも自分は○○さんほど上手く出来ない」とかって精神的に怯んでしまうような状況になってしまいそうで。。

ここに矛盾があるのだ。
そのリーダーも、メンバーの成長を望んでいると思う。その方が自分のためにもなる。単に実務量や負荷分散という物理的な面もあるが、それ以上に「対等にやり合える仲間」が居るのは楽しい。自分のためにもなる。
しかし、その「成長」の可能性を、ともすれば自分で奪ってしまっている・・・・

「できる」から「機会」があり、そこでようやく「自分が主人公」になれる。理想的な流れ。
しかし実際は、「先に主人公になってもらう」ことが必要なのではないか。
チームをリードしている自分が、チーム全体の成長性に対するブロッカーになってしまっている・・・という可能性はないか。

そんな訳で、誰もを「主人公」にするチームが、信頼とそれを糧にした再成長を望めるのではないか?なんて事をモヤモヤと考えたのでdump。

自分としては、

  • やっぱり「皆が主人公」になって、物語を紡いで、そこから共感を得たりキャラクターを理解できた方が楽しく働けそう
  • 自身に対しては、「強権」をいつのまにか持っちゃっていないか・・?は意識していきたい

という感じ。

*1:必ずしも作品の主人公とイコールの関係ではないけど、いわゆる「○○回」というものにおいて、その瞬間の主人公はサブキャラクターにまで移る。山王戦いいよね・・

「依存性逆転の原則」は人間にも適用できないか、という思考実験

SOLID原則のD、「Dependency inversion principle」だが個人的にはClean Architectureを読んで理解が深まったように感じている。単体のクラス設計にとどまらず、パッケージ単位で見たらどうなる?という話も含まれるが、「どのくらいズームイン/ズームアウトしようと、依存の流れをどうしたいかという意思は同じだろう」と思う。

ざっくりいうと「お前がどう使われたいかはお前自身がハッキリ定めておけよ!!」という。 これは「組織」というパッケージだったり、「個人」という単体コンポーネントだったりにも適用できるのではないか?などと思った。

表面的に考えると、「人は組織に所属する」ということで、これは集約ないしコンポジットと考える。所有もしくは部分と言う関係だ。「人: 組織の一部」。 また、「組織は人に依存する」ということになる。
組織全体での期待が、具体的には「他の個人」からの依存という形で現れたり、単に「組織-役割-個人」という関係性の中に規定されていたりする。

パッケージの外部に「私はこういう約束を満たします」というのをInterfaceとして定義して、外の奴らはそのInterface=取り決めに従ってメッセージを送りあえ、というのがClean Architectureで語られている「良いやり方」だった。これによって、処理の流れと依存の方向性が逆転する = 依存性逆転を実現できる。
結果として、「不要不急の変更に(内部構造まで)振り回されることがない」、抽象度を高めた状態になれる。
多くの人と関わったり背負う責務の幅が広くなるほど、被依存が生じる = 安定度が高くなる。・・・「安定度が高くなる」と言うが、要するに「安定していなければ困るという度合いが高まる」、"不安定" "多動的"であってくれるなよという祈りが捧げられる。安定度が高いなら抽象度を同じくらいにまで高めなければならない。抽象度を高めるには、「意味のある」「明確な」Interfaceの設置だ。それが正に外部との接触面となり、他人とのやり取りの「出入り口」となる。

組織と個人の間では、責任と期待によってメッセージングされるものだと思っている。組織は人に責任を与えることで語りかけ、人は組織に期待を持って語りかける。「対組織とのやりとり」はそのまま「対・組織にいる誰か他の個人とのやりとり」と置き換えることも出来る。 往々にして、自分の属する組織≒環境に対しては「こうあって欲しい」という期待を抱くものだ。そして、その期待が満たされて嬉しかったり、不足があれば「裏切られた!!」とすら感じたりする。・・・これは、ひじょ〜〜に不安定である。
全てが上手くいけばいいのだが、「裏切られるかも」というリスクがある以上は、これをどうにか避けるための戦略が必要になると考えている。そうすることで、自身の存在を安定させられる。

ここで、掲題の通り「では、俺が依存するのではなくて、俺にどう依存するかはコチラの表明によって決定させてしまえばいい」と考える。これにより「使役先の振る舞いから自分の存在を保護できる」というものである。
依存性をどうコントロールするか?というと、インターフェイスの設置 = 「約束事」「取り決め」の公開だ。
「自分はこういう存在である、こういう事ができる、こういう風にしたいと思っているしその役割を果たさせてくれ」という「こう期待されたい」の期待値を、十分にexportしていく・・・・という取り組みは、「依存性の逆転」をもたらすことができないか?

環境による「裏切り」は、ひとたび起きてしまうと重大なダメージなると感じていて、自身の選択を嘆き続けるような日々をもたらす。
それを避けるために、なるべくコントローラブルにしていきたいものだ。
単純な話、積極的に「自分はこういう風にやっていくぞ、頼んだ!!」という合意をとっていくことで、他者との関わり方をしなやかにしていきたいと考える。