nunulkのプログラミング徒然日記

毎日暇なのでプログラミングの話題について書きたいことがあれば書いていきます。

『他者と働く──「わかりあえなさ」から始める組織論』を読んだ

はじめに

この記事について

「他者と働く──「わかりあえなさ」から始める組織論」(宇田川元一著)を読んだのでその感想文です。

これまで会社員あるいはフリーランスとして働いてきて思うのは、ソフトウェア開発の仕事においても解決困難な問題は能力起因ではなくほぼ人起因であるということです。人が苦手だからコンピューター相手の仕事に就いたはずなのに、けっきょく人と向き合わないと仕事ができない、というジレンマを感じつつ、フリーランスになることでそういったしがらみから少しでも距離を置きたい、というのがいまの自分のスタイルを形作ったといっても過言ではありません。

かねてより組織に関する本は読んでいたものの、やはり実践の段になるとうまくいかないことがほとんどで、近年は半ば諦めてしまっている領域です。

そういう意味では、この本を読む動機はそれほどなかったんですが、いまの現場でもこの「わかりあえなさ」を感じていて、たまたま X で流れてきたのを見てタイムリーだなと思ったので手に取ってみました。

他者との関係性における私のスタンス

私はこれまでの人生において、対人の問題に対して消極的というか、関係性の構築とか維持とかに執着を持たずに生きてきました。プライベートでも友達と呼べる存在はほぼおらず、唯一バンドのメンバーくらいです。仕事でも、人間関係起因の問題が起きた場合、それが簡単には解決できないと思った場合は、契約を更新しない、という選択を取ってきました。

人起因の問題は、解決するよりも回避するほうが何倍も楽です。とくに私の場合は途中からチームに加わることがほとんどで、出来上がった(てしまった)チームに異物(私)が入ることで不協和音が起こった場合、簡単には取り除けません。自分は意固地な性格ではないので、チームのやり方に合わせることはそれほど苦にしませんし、単にスタイルの問題であれば、これまで色んなスタイルのチームで働いてきたのでそこはぜんぜん問題ないです。

しかし、仕事がうまくいってない/成果を出せていないのに、自分たちが変わろうとしないチームに入ったときが問題で、私はその状況を変えたいと思い提言などするものの、ほとんどのケースではそれは暖簾に腕押し状態になります。

そうしたことが続くと次第に、暖簾を押すのを止めてしまいます。

プライベートでは他人に期待しない、他人を変えようとしない、というスタンスで生きていますが、仕事においては、変わらなければ強くなれないという意識が強く、そのスタンスを適用できていません。

最近はとくに、参画するかどうかを決めるポイントとして、課題解決があります。面談時にマネジャーやリーダーからどんな課題があるか聞いて、自分がそれにバリューを出せそうかどうか、出したいと感じるか、事前にそういったことは話します。なので、課題を認識していて、その課題解決のために私と契約して、いざ実際に現場に入ると話がまったく進まない、みたいなことがあると、なぜなんだ?!と思ってしまいます。

期待値調整がうまくやれてない、というのもあるでしょうし、リクルーティング段階の方便という可能性もあるかもしれないですし、わかっちゃいるけどできない、のかもしれないですが、最終的には「人間は難しい」となって諦めてしまいます。

「他者と働く」概要

さて、前置きが長くなってしまいましたが、本書を簡単に要約すると、

  1. 組織の厄介な問題は合理的に起きている
  2. 厄介な問題のほとんどは、技術的課題ではなく適応課題である
  3. 適応課題の解決には各人のナラティブを理解することが必要である
  4. 他人のナラティブを理解するには対話が必要である
  5. 対話の仕方・ポイント

を順序立てて説明しています。

1. 組織の厄介な問題は合理的に起きている

自分がソフトウェアエンジニアだからか、合理性にこだわってしまう傾向があるのは自覚していて、うまくいかない/成果を出せないのは、合理性が乏しいからだと思いがちです。「理」があればあとはそれに合わせていくだけなので簡単なはず、どうしてそれができないのか、と思っていました。しかし、本書では、そうした状況にも合理性があると説きます。

2. 厄介な問題のほとんどは、技術的課題ではなく適応課題である

「技術的課題」と「適応課題」はもともと Ronald Heifetz さんが定義したものです。それぞれの定義は ChatGPT によると、

「技術的な問題は既存の知識、手続き、または専門知識を用いて解決できる問題です。これらは明確な解決策があり、既知の実践を適用することで、または分野の専門家によって実装できます。一方で、適応課題は、効果的に対処するためには学習、革新、価値観、信念、または行動の変化が必要とされる複雑な問題です。」

とのことです。本書ではさらに加えて、

人と人、組織と組織の「関係性」の中で生じている問題

と定義しています。

技術的課題は、難易度の高低はあれど、比較的入力パラメータの少ないソルバー関数が存在するものである一方、適応課題は、人それぞれの置かれた状況やこれまでの経験、培ってきたマインドなど、膨大な入力パラメータを必要とする、しかもそれが「私」と「あなた」双方に存在するソルバー関数が必要なものである、と解釈しました。

また、技術的課題なのか適応課題なのか一見して区別できなかったり2つが絡み合っていたりこともあり、複合的な場合には、適応課題部分を解いてから技術的課題に取り組まないといけないために、厄介さが増してしまいます。

3. 適応課題の解決には各人のナラティブを理解することが必要である

ナラティブは(またも ChatGPT によると)「人々が自分自身や自分の人生を理解し、意味付けするための枠組み」とのことです。

本書では、

語りを生み出す世界観、解釈の枠組みとしての「物語」

であり、

ナラティヴとは、視点の違いにとどまらず、その人たちが置かれている環境における「一般常識」のようなものなの

としています。

たしかに、なにかの出来事に遭遇したときにそれに対して感じることや行動することが、個人のナラティブによって変化するなら、ナラティブを理解しなければその結果としての感情や行動は理解できない、というのは納得できます。

4. 他人のナラティブを理解するには対話が必要である

対話といってもざっくばらんに話す、とかではなく、準備や予備知識、臨む際の姿勢など、本書が推奨するやり方みたいなのが載っています。

本書では、自分のナラティブ(世界観、解釈の枠組み)と他人のナラティブの間にある溝を、文字どおり溝にたとえ、それに橋をかけることで関係性を変えていくアプローチが紹介されています。

  1. 準備「溝に気づく」
  2. 観察「溝の向こうを眺める」
  3. 解釈「溝を渡り橋を設計する」
  4. 介入「溝に橋をかける」

本書では、この4つの段階をだいたい以下のような感じで説明しています。

まず自分のナラティブを一度棚に置き、相手がどんなナラティブに基づいて動いているのか観察して掴む。それが見えてきたらその相手のナラティブに基づいて自分がどう見えるのかシミュレートし、ようやく最後に行動を起こして関係性を変える、というステップです。

このように急がず順序立ててアプローチしないと、うまくいかないと説きます。

そもそも、関係性が構築されていない段階では、「私とあなた」という関係ではなく「私とそれ」になってしまっていて、道具を使う感覚で他人と接してしまう状態であるので、どうやったら「私とあなた」の関係に相互になれるのか、その辺りが最初の難関なのかな、と思います。

5. 対話の仕方・ポイント

ここからが本書のコアの部分になるわけですが、個別の事例や具体論が続くので、要約が難しく感じたのでスキップします。

一箇所だけ引用しておきます。

しかし、相手との間に橋を架けようと躍起になるあまり、あなたとあなた自身の間に橋がなくなっている状態にあるかもしれないのです。仕事のナラティヴだけになってしまうと、自分自身のその他のナラティヴとの間で乖離が起きてきてしまいます。

「他者と働く」の感想と読んだあとのマインドの変化

フリーランスなので、ぶっちゃけ価値観の合わない組織で働く必要はまったくなく、実際これまでにもときたま良いと感じるチームに出会えていて、その確率はそれほど低くはないと感じています(体感的には半分以下ではありますが)。

自分の理想のチームをここで言語化しておくと、

  1. プロフェッショナルの集まりでそれぞれが自分の専門性を活かして難題に取り組むチーム
  2. 専門性を持ちつつも改善のためなら専門性の壁を乗り越えて一緒に取り組むチーム
  3. 多様な価値観や人間性を持った集団でありながら一体感があり、問題解決に向き合うチーム

過去を振り返ると、20年以上前に参画した某 JTC で結成されたチームに参画したときがもっとも理想に近いチームでした。メンバー数は20-30人くらい、営業、企画、開発、さまざまな部門が2つの隣り合った部屋に集まり、ミーティングはいつも建設的で、ミーティング以外のコミュニケーションも頻繁にあり、田舎(いちおう東京でしたが)にオフィスがあったのでレストランも少なく、たいていはいつも決まった店に行き、結果的にそこでもコミュニケーションが発生する、みたいな、関係性でした。

技術的には、メンバー間でばらつきがややあったものの、開発チームでもそれぞれの役割を果たすことでチームの成果になる、という感じでした。技術的にチャレンジングなこともあり、リーダーがめちゃめちゃ優秀だったので、それに引っ張られるように、みんながそれぞれプロジェクト期間中に成長していった感じもします(もちろん私も含めて)。

自分が上に書いたような理想を追ってしまうのは、そのときの体験(あるいは以降の似たような体験)が、本当にソフトウェア開発者として、充実していて、楽しかったので、またそれを味わいたい、という思いがあるんだろうと思います。

良い/強いチームに入るともれなくその感覚に近いものが得られるんですが、そうでないチームに入るとそのギャップを埋めたくなってしまいます。そしていつも、他人を変えるのは難しいと感じ、そのチームを離れる選択を取ってきました。

本書では、他者との関係性は対話によって変えられる、という希望を少し抱かせてくれたような気がします(単純なので、本を読んだ直後はだいたい洗脳状態になる、という部分は差し引いても、ちょっとやってみようかな、という気にはなっています)。

そもそも、人間絡みでものごとがうまくいかないとき、問題は相手にだけあるのではなく自分にもあるんだろうと思います。自分が友達のほとんどいないEQの低い人間であることもありますし、あまり人間に興味がないこともありますが、それは確信があります。プライベートでは別にそのスタンスで困っていませんが、仕事では(少なくとも契約が残っている間は)そうもいきません。

仕事においては、いつでもどこにいっても、自分の成長がチームの成長に繋がり、結果的に会社の成長に繋がるのを理想にしているので、自分の問題なのであればそれは改めたいですし、成長を阻害するのが適応課題という難題であるならば、それを解いてみたいと思いますし、本書によって「そもそも適応課題は解決が困難な問題である」というのを改めて認識しましたし、いまはもう少し粘ってみようかな、という気持ちです。

あまり関係ないですが、本書を読むちょっと前から、Awarefy というメンタルヘルスアプリを使っています。

www.awarefy.com

AI によるコーチングは正直まだ満足できるレベルではありませんが、自分の感情を吐露できる場として、内省できる場として、いまのところしばらく使ってみようかなと思っています。

まずは自分を見つめ直すところから、自分のナラティブを言語化するところから、じっくり取り組んでいく所存です。

おわりに

Kindle で似たような本をいくつか購入して読んだことがあるので、また読み返そうと思います。

Slack の times チャンネルについて思うこと

はじめに

この記事について

X を見ていたら Slack の times チャンネル(分報)の話題で盛り上がっていて、はてブでも関連記事を読んでブコメしたりしたんですが、いくつか思うところがあったので、記事にしておきます。

times チャンネル(分報)とは

まず前提として、suin さんのこちらの記事が初出と思われるので、リンクを張っておきます。

Slackで簡単に「日報」ならぬ「分報」をチームで実現する3ステップ 〜Problemが10分で解決するチャットを作ろう〜 - 株式会社クラフトマンソフトウェア

課題解決へのアクションが遅れてしまうという日報の弱点を克服するために、僕のチームでは「分報」という独自の取り組みをしている。

つまり、分報は日報のさらにタイムスパンの短いバージョンということです。

分報、ということなら Slack 以外でもやりようはあると思うので、本記事では主に times チャンネルについて書きます。というのは、私は、分報という仕組み(制度?)は素晴らしいと思うものの、それを Slack で運用しようとすると恩恵より弊害が大きいなと感じてやめた経緯があるからです。

分報の目的と効果

前述のとおり、課題解決へのアクションを最短にしよう、というのが分報の目的です。なので、素早く課題解決できる、というのが効果になり、それ以外はおまけだと思っています。

週報は言わずもがな、日報ですらも、課題解決のためのツールとしてはスピードが遅い、というのは個人的には賛同しますが、それでも、忙しいマネジャーであれば、1日の業務の終りにやっと少しのまとまった時間が取れる、みたいなこともあると思うので(そこまで忙しいのはマネジャーの能力としてそれはそれでどうなんだ、という気もしますが)、日報ならまぁいっかと思います。

とはいえ、ソフトウェア開発のチームであれば、朝会(デイリースタンドアップ)をやってるところも多いでしょうし、テキストによる日報の代わりに口頭で報告する形式が一般的かと思います。

たとえばスクラム開発におけるデイリースクラムでは、以下の3つを報告すると定めています。

  1. 昨日何に取り組んだか?
  2. 今日は何に取り組んでいるか?
  3. 障害となっている課題は何か?

デイリースクラムの目的は、チームがスプリント内のタスクを予定どおり終えるための調整で、各メンバーがその日一日にやり遂げることを明確にする、進捗に遅れがあれば遅れの原因を取り除く、ということを日次でやるわけです。

大事なポイントとしては、これは上司と部下のコミュニケーションではなく、チーム全体のコミュニケーションということです。週報や日報は、部下が上司に提出するもの、という扱いになっている組織が多いと思いますが(自分はもう何年もそういう文化の会社では働いていないので現代の一般的なスタイルがどうなっているかはよく分かりませんが)、これだと、情報の流通が制限されるので、仮にメンバーの中に課題解決の策を持っている人がいても、情報を持たないためにそこに関与できないという問題があります。なので、情報はできる限りオープンにして、解決策を持っている人がそれを提供できるようにしなければなりません。

上記3つのようなことをリアルタイムに書く場所があれば、分報は成立します。「Slack 以外でもやりようはある」と書きましたが、現状では Slack などのチャットツールが最適で、タスクに着手するときに「これから◯◯に取り組みます」、完了したら「◯◯を完了しました」、詰まったときに「◯◯のために詰まっています」と書き込むことで、リアルタイムかつ非同期にデイリースタンドアップのようなことができるわけです。

times チャンネルの恩恵と弊害

しかし、冒頭に上げた suin さんの記事に書かれている言葉を借りると、times チャンネルは「個室」です。個人的にはこれが諸悪の根源だと思っていて、人は個室を与えられると悪いことをするものです(主語がでかい)。times チャンネルはタバコ部屋じゃないか、という意見もあります。

タバコ部屋を知らない若い人のためにいちおう解説しておくと、昔は喫煙者が多かったので、会議のあとにみんなタバコを吸いに喫煙所に行くんですが、そこで会議の続きをやり、会議で決めたことをひっくり返すとか、会議で議題に出てないことをそこで決めたりとか、いってみれば非公式に意思決定をしちゃって、非喫煙者(少数派)がその意思決定に加われず、最悪知らされない、みたいな問題があって(こうやって言葉にすると大問題なんですが昔はよくありました笑)、そういう非公式な意思決定に至る議論を「タバコ部屋の議論」と揶揄しているわけです。なんのための会議なんだよ、と。

閑話休題

times チャンネルの使い方は会社や人によって様々で、目的が明文化されていて、それに従っているなら問題ないですし、自由に使ってどうぞ、というポリシーなのであれば、当然問題ないわけですが、それで治安が悪くなってしまうと、やっぱりやめましょうか、という流れになるので、難しいなぁと思うわけです。

times チャンネルがもたらす恩恵としては、

  1. 問題解決を即時に行える
  2. 雑談する場を提供できる
  3. ラバーダッキングできる

あたりだと思っています。

1 は上に書いた分報の目的に合致するのでメインの恩恵です。とくにジュニアの人が、詰まっていることを相談したいけどみんな忙しそうなので躊躇われるが、times チャンネルに書くのであれば心理的障壁が低いので書きやすい、みたいなときに有効かと思います。しかし、それよりももっと大きな恩恵があって、当人は問題と捉えていないが、別の人から見ると問題である、みたいなことがあったときそれに気づけるというのがあります。とくに私はフリーランスなので、業務委託で新しい現場に入ったとき、最初の3ヶ月くらいはどこでもこういう状態になります。プロダクトやチームへの理解度が低いと起こります。もちろん、できるだけはやくキャッチアップするためにドキュメントやソースコードを読むわけですが、それだけでは足りない部分も多く、times チャンネルにだらだらと書いたのを、古参の人に拾ってもらえたりするとめちゃくちゃ助かるわけです。

2 は雑談が職務遂行上必要かどうか人によって価値観が異なるかとも思いますが、やりたい人はやればいいし、やりたくない人はやらなくていいので、ほしい人に提供できるという点ではメリットになるでしょう。

個人的には 3 がいちばん大きくて、もともとのラバーダッキングは声に出して思考を整理する方法ですが、声よりは文字のほうがより効果が高いと感じていて、その点では Slack が最適と感じます。ラバーダッキングだけなら自分宛ての DM とか、最近だと ChatGPT を使うとか、もっというとローカルのテキストファイルでいいわけですが、times チャンネルを使えば、ラバーダッキングをしながら同時に 1 で挙げた「自分は問題と捉えていないが、別の人から見ると問題である」みたいなことに気づけることもあって、恩恵は大きいと感じます。

しかしながら弊害もあって、

  1. 問題解決が半密室で行われるため、times チャンネルにいない人に共有されずに進んでしまう
  2. ノイズの割合が増えてくるとミュートすることになり、恩恵が受けられなくなる
  3. 愚痴を書く人が多くなると治安が悪くなる

1 は、いわゆるタバコ部屋。基本的に times チャンネルは全員が見てなくてもいい前提で設計されていると思うので、問題解決のスピードが上がるメリットよりも情報が閉じることのデメリットが上回ると感じます。

2 は、仕事に関係ないニュース記事のリンクを大量に貼る人や、仕事に関係ないボットで遊んでる人なんかはノイズが多いと感じて、ミュートしてしまいます。無関係なことしか書かない人なら問題ないんですが、たまに仕事のことを書く人が困るんですよね。とくにジュニアの人がそれをすると、恩恵が受けられなくなる恐れがあります。私は、手の空いたときたまに見に行くようにしているので、多少タイムラグは出るものの、課題解決に一役買うことはできるんですが、人によってはそこまでやってられるかって思う人もいるでしょう。

3は、個人的にはこれがいちばん大きいと感じているんですが、組織に問題があるとどうしてもネガティブなことを書きたくなります。もちろん、課題解決を目指して書くわけですが、チームの大半は無関心あるいは現状維持を望んでいて、賛同してくれる少数の人たちだけで議論してしまい、結果的にチーム全体に波及せず、愚痴のような格好になって議論も中途半端、結果も出ない、残ったのは対立だけ、みたいなことがありました。このような組織の課題解決は時間がかかっても同期的に集まってやるほうがいいと思います。

ではどうすればいいか

現時点での個人的な結論なんですが、いまのところは以下のような感じに落ち着いています。

  1. times チャンネルは使わない(用意されても使わない、他の人のは1日2回くらいの頻度で巡回するにとどめる)
  2. 質問があればチームのチャンネルでする
  3. ラバーダッキングは DM でする
  4. 意思決定が times チャンネルで行われているのを見つけたら、チームのチャンネルでやってほしいと伝える

times 文化は好きで、雑談もしたいんですが、タイミングだったり内容だったりが合うことが割合的に高くないので、巡回頻度を落とすとタイムリーに話題についていけなくなり、必然的に雑談ができない状態になります。これはまぁ仕方ないですね。

課題解決については、タイムラグがあっても、もし times に解決できてない問題が放置されていて、それについてなにかコメントできる情報を自分が持っていれば、見に行ったタイミングでコメントすることはしようと思っています。

問題は、課題解決の場がどこにも用意されてない場合で、こちらから頼んで用意してもらえる(または参加させてもらえる)のであればいいんですが、業務委託が社員のグループと隔離され、情報も流れてこなければ意思決定の場に参加もできない、みたいな組織の場合どうしようもないので、間違ってそういうところに入ってしまった場合には諦めて契約更新しない、という選択を取るしかないかな、と思っています。あるていどは参画前の面談などで掴めるものの、入ってみないと実際のところは分からないこともあるので、難しいです。

おわりに

いくつかの組織で times チャンネルを使って、恩恵よりは弊害が大きいと感じたので上のような結論に至ってはいますが、うまくやっている(やれそうな)ところに入ったときにはもしかしたら使うかもしれません、いまのところはあんまりうまくやれるイメージができてないですが。

車の運転でもスピードを上げると比例して操作も難しくなるのと同様、ましてやそれをチームでやるとなると相当のスキルが求められると感じますし、問題解決のスピードと times チャンネルをうまく扱うスキルとのバランスを考えたとき、いまの自分のスキルでは扱えないというのが現時点での結論です。

個人的には、上に書いたようにデイリースタンドアップのような役割を期待してるんですが、それを他人にも求めるのは違うと思いますし、仮にそれができたとしても、タバコ部屋問題みたいなのはどうしても起こるので、ここまで書いてきて改めて難しいなぁと感じました。

理想的には、全員が同じ目的意識を持って、同じような運用方法ができるといいんだけど、と思いつつ、チームが人の集まりである以上、どうしてもブレは生じるので、そこを目指すのではなく、個々人がやりたいようにやってもなおチームの成果が出せるように、試行錯誤を続けるしかないな、という心境です。

小さなチームにおける定例ミーティングの有り様について

はじめに

この記事について

私は、スタートアップあるいは少人数のチームにおいて、定例ミーティングは必要ないと考えていますが、最近は以前ほど拒否感は薄れ、むしろやりたいならやったほうがいいと思うようになったので、その辺りの考え方の変遷も含め、総体としての仕事における定例ミーティングの有り様について言語化しておこうと思います。

定例ミーティングとは

毎週決まった曜日と時間に行われるチームメンバー全員参加のミーティングのことを指します。毎週ではなく毎日、毎月の場合もあるでしょうが、自分の経験の中では定例と名のつくミーティングは週次が多いので、本記事内では週次を対象とします(が、月次でもそんなに変わらないかもしれません)。

定例ミーティングは必要ないと考える理由

まず、定例ミーティングは必要ないと考える理由ですが、すべからくミーティングというのは意思決定のために必要な議論をする場、と捉えていて、その意味でいうと、スタートアップのような小さな組織の意思決定に必要な議論をいつどこでどうやるか、という問題に対する解法として最適ではない、と考えているためです。 まず、そもそも定例ミーティングの目的にはどんなものがあるかというと:

  1. 今週のタスクの進捗確認
  2. 来週のタスクの選定
  3. 意思決定の依頼
  4. 相談事

あたりかと思います。

では、具体的になぜ最適ではないと考えているかというと、それぞれ以下のように対処可能だからです。

  1. 今週のタスクの進捗確認
    1. プロダクトバックログ、デイリースクラム(もしくは日報)で確認できる
  2. 来週のタスクの選定
    1. プロダクトバックログは優先順位付けされてるはずなのでそこから各自取ればいい
  3. 意思決定の依頼
    1. 意思決定権を持つ個人が特定できれば Slack で聞けば解決できる
    2. 複数人での議論が必要なトピックでも Slack で非同期で解決できる
  4. 相談事
    1. 即時で Slack で聞けばいい

進捗管理については、プロダクトバックログのような ITS(Issue Tracking System)はどこでも使っているので(ですよね?)、そこでわかるようにすれば済むことです。日次で進捗が知りたいマネジャーであれば、Slack で毎日報告してもらえばいいです。

意思決定については、1 については言うまでもなく、週次の定例ミーティングを待たずに Slack (および類似のチャットツール、以下同)でサッとお伺いを立てればすぐに解決できます。 2 についても、関係者の多い組織においては調整に必要な人数が多いので、一処に集まって決めるほうが効率的だと思いますが、人数の少ない組織においては、Slack で非同期でもいいので、関係者まとめてひとつのスレッド内でできるだけ早く決めてしまったほうが手っ取り早い、ということです。議論をしましょうといっても、お任せしますっていうスタンスの人もいますし、案外サッと決まることが多いです。定例を待たずに素早く決めちゃいましょう。

相談事も一緒で、詰まったらすぐ聞いてください。定例まで温めておくメリットは何もありません。

多角的な視点がほしいような議題があれば、その都度直近で全員の予定の合う日時に集まって(可能なら即時て)話し合えばいいので、決まった時間である必要はまったくないと考えます。

それでも定例ミーティングをやりたいならやればいいと思うようになった理由

昨今フルリモートの案件ばかりやっているので、顔を合わせる機会がほとんどありません。なので、週に1時間くらいは顔を突き合わせておしゃべりする時間くらいはあってもいいよな、と考えるようになりました。

もともと、ミーティングはコストが高い(参加人数分の時給を計算してみてください、その上でそれに見合うベネフィットが出せていると自信を持って言えるかというと自分は自信ないです)ので、やらないで済むならやらないようにしたい、と思っていましたが、効率を追求する中で失うものもあるわけで、定例ミーティングのもたらす恩恵が、コスパという指標だけで測れないものになったなぁと感じます。

この辺り科学的にどうなのかは分かりませんが、自分の肌感覚としては、ノンバーバルコミュニケーションの影響というのはチームの健康度において重要なファクターだと思うので、軽視できないんですよね。

なので、むしろ、上に挙げた定例ミーティングの目的はいったん脇に置いといて、雑談でもしたほうがよっぽど有意義なのではないか、とさえ思います。中途半端に課題発見・課題解決を定例でやろうとするほうが、スピードが遅い上に下手すると結果も出ない、みたいなことになりやすい気がします。

プロフェッショナルな個人の集まりであれば、心理的にどうあれ、きっちり仕事をこなすし、定例ミーティングはなくてもぜんぜん困らないと思うんですが、週に1時間くらいはみんなで集まってわいわいするのもいいじゃないですか、っていう心境です。

おわりに

チームやマネジャーによって定例ミーティングの位置づけや目的意識は異なるでしょうし、自分が業務委託で入るときにはなるべくそれらを尊重したいという気持ちはありつつも、定例ミーティングでやることが増えたり、そこでの成果を求めすぎたりするのを見ると、原点に立ち戻って、解決したい課題はなんなのか、考えてほしいなと思ってしまいます。もし、今後、定例ミーティングの有り様について相談したいとマネジャーやチームリーダーに言われた場合はこの記事をベースにしつつ、議論してみたいです。

私がプライベートメソッドに対するテストを書く理由

はじめに

この記事について

表題のとおりなんですが、すべて書いているわけではなくて、必要だと思ったときには書いている、というのが正確な表現です。 書くべきか?と問われると No なんですが、書かないべきか?と問われるとそれも No で、書きたければ書く、がいまのところ自分のポリシーです。本文でもう少し深掘りします。

文脈

言語は PHP です。 以下のようなシチュエーションを想定しています。

  1. 長大なパブリックメソッドに対して自動テストが書きにくいため、内部で使われているプライベートメソッドに対して自動テストを書きたいシチュエーション
  2. モジュールの外に公開する必要性がないが、入出力のパターンがそれなりにある

1. 長大なパブリックメソッドに対して自動テストが書きにくいため、内部で使われているプライベートメソッドに対して自動テストを書きたいシチュエーション

単純に実行に時間がかかる、あるいは、モジュール分割がうまくいっておらず、ひとつのメソッドの責務が多すぎる、といった理由で内部のプライベートメソッドに対してまず、自動テストを用意することはあります。

たとえば、バッチコマンドで1ヶ月分のなんらかのデータを作成する必要があるとします。その場合、以下のような構造になることがあります。

<?php

class SomeCommand
{
    public function execute(int $year, int $month): void
    {
        $dateRange = DateRange::fromMonth($year, $month);
        // すべての日付分処理すると時間がかかる
        foreach ($dateRange as $date) {
            // ここに長大な処理がある
        }
    }
}

パブリックメソッドのインターフェースとして年と月を受けて、内部では日付分ループしていて実体のほとんどはこのブロックの中にあるとします。それを以下のようにプライベートメソッドに切り出して、そいつに対してユニットテストを書けば、時間を節約できます。

<?php

class SomeCommand
{
    public function execute(int $year, int $month): void
    {
        $dateRange = DateRange::fromMonth($year, $month);
        foreach ($dateRange as $date) {
            // プライベートメソッドに切り出す
            $this->executeForDate($date);
        }
    }

    // このメソッドに対してテストを書く
    private function executeForDate(Date $date): void {}
}

人によっては、以下のようにクラスを分割してパブリックメソッドにしてからテストを書くようにしているかもしれません。

<?php
class SomeCommand
{
    public function __construct(private readonly DailySomeCommand $dailySomeCommand) {}

    public function execute(int $year, int $month): void
    {
        $dateRange = DateRange::fromMonth($year, $month);
        foreach ($dateRange as $date) {
            // DailySomeCommand::execute() に対してテストを書く
            $this->dailySomeCommand->execute($date);
        }
    }
}

私ならこのケースでは、日別の処理が他で必要ないのであればクラス化はしないですが、似たようなケースで分割することもあります。自分の中の分割基準はありますが、それは今回範囲外なので割愛します。

2. モジュールの外に公開する必要性がないが、入出力のパターンがそれなりにある

ある意味では 1 のパターンと同じですが、外部に公開する必要はないが、そのモジュールの内部処理としてはパターンがそれなりにあるのでテストしておきたい、というシチュエーションです。私はテスト駆動で開発することが多いんですが、そういう場合はまず公開メソッドに対してテストを書くことからスタートします。しかし、書いているうちに、関数化したくなるときがあります。 下記の例では、入力パラメーターから論理値を導出して以降の処理で使用するような関数ですが、最初は公開メソッドにすべての処理を書いていきます(関数抽出もクラス抽出もしません)。

<?php

class SomeClass
{
    public function doSomething(array $args)
    {
        $isHoge = false;
        // パターンを導出する処理を書いていく
        if ($args['hoge'] === 'fuga' && /* ほかにも依存関係がある */) {
            $isHoge = true;
        } elseif (...) {
            // ...
        }
        // ... だんだん複雑になってくる
}

論理値の導出ロジックがそれなりに複雑になってくると専用のテストが書きたくなります。そこで、導出ロジックをプライベートメソッドに切り出して、そのプライベートメソッドに対してテストを書くことになります。

<?php
class SomeClass
{
    public function doSomething(array $args)
    {
        $isHoge = $this->isHoge($args, /* ほかにも依存関係がある */);
    }

    // このメソッドに対してテストを書く
    private function isHoge(array $args, /* ... */): bool
    {
        // パターンを導出する処理
    }
}

これも、1 のパターンと同じで、外部クラスに置くこともあります。とくに enum を使う場合、ファクトリメソッドを用意することが多いので、二値であっても enum にしてファクトリメソッドを使うか、上のケースではもしかすると Specification パターンを使ってそちらに置くかもしれません。しかし、入力パラメーターだけでなく SomeClass 固有の依存関係がいくつも絡んでくるようなケースや複数の変数をまとめて導出するような複雑な処理だと、できるだけ内部に閉じていてほしいのでプライベートメソッドにするかもしれません。その辺は用途範囲だったり、複雑さだったりによって、やり方が変わってきます。

プライベートかどうかと関数にユニットテストがほしいかは別問題

モジュール内の関数の可視性はモジュールの都合であって、複雑性とか保守性とかとは関係ないと思っていて、 上に挙げた例でも、仮にプライベートメソッドが担う処理をまるっとクラスに抽出しパブリックメソッドにしたとすると、当然テストを書きますよね?そうなると公開か非公開かというのはテストを書くか書かないかというのとは関係ないはず、と思います。

テストコミュニティ内で非公開関数を直接テストするべきかについては議論があり、 他の言語では非公開関数をテストするのは困難だったり、不可能だったりします。 あなたがどちらのテストイデオロギーを支持しているかに関わらず、Rustの公開性規則により、 非公開関数をテストすることが確かに可能です。

テストの体系化 - The Rust Programming Language 日本語版

さらっとイデオロギーと書いてありますが、私もプライベートメソッドに関する議論はまさにイデオロギーだと思います。プライベートメソッドにテストを書くべき(あるいは書かないべき)というとき、どういう文脈において、どういう悪影響があるのか、というのが分かっているのであれば問題ないですが、とにかく書くべき(あるいは書かないべき)、というのは思考停止かなと思います。

チーム開発においては、チームの方針としてプライベートメソッドに対してテストを書かないべき、という方針であれば(いままで幸いにもそういう現場に入ったことはないですが)、いちおう上のような話をして、それでもなおその方針でいきます、という反応であればそれに従うようにするつもりです。自分にとっては、そこまでして守りたいポリシーではなく、正直どちらでもいいんですが、べき論によって問題が起こったり複雑化したりする場合は、本当にその方針でいいのか、毎回しつこく確認するようにしたいとは思っています。

おわりに

もうちょっと上手いこと言語化できると思っていましたが、思ったよりもふわっとした内容になってしまいました(実際のコードを使えるともう少し具体性が増すんですけどね…)。

いずれにしても、私はこれからもプライベートメソッドにテストを書くことを厭わない、という意思表明だけしてこのエントリーを終えたいと思います。

日頃からどの文脈においても気をつけていることですが、私はなるべく「〜すべき」ではなく「〜すると〜より良い」という考え方をするようにしています。色んな状況や文脈で取れる解決策を選ぶとき、頭から「〜べき」「〜しないべき」と考えて選択肢の幅を狭めてしまうのはもったいないし、問題と向き合わない態度だと思うので、自分自身のポリシーとしては問題と向き合い、解決のために柔軟な思考を持ち続けていく所存です。

「スタッフエンジニア」の感想

はじめに

この記事について

「Staff Engineer 」Will Larson の日本語訳を読んだのでその感想と、日頃から思っているソフトウェアエンジニアのレベル上げについて言語化しておきたいと思います。

本書が出るまではスタッフエンジニアという役職は聞いたことがなく、日本語でスタッフというと「職員」みたいなニュアンスがあるので、言葉だけではピンときませんでしたが、本書を読んで、ぼんやりと思っていた自分の目指す場所(職位としてのポジションではなく)が明確になったような気もするので、毎度のことながら雑に書いていきます。

スタッフエンジニアとは

このスタッフエンジニアという役職は、そのエンジニアとしてのキャリアの延長線上で、この本はシニアエンジニアを超えた先にどんなキャリアがあるのかを解説している本になります。

logmi.jp

スタッフエンジニアとはただの役割ではない。個人の役割と行動とインパクトの、そしてそれらすべてに対する組織の認識の総体なのである。

Will Larson. スタッフエンジニア マネジメントを超えるリーダーシップ (Japanese Edition) (p. 22). 日経BP. Kindle Edition.

英語が苦手でなければ、下記のサイトで本書に書かれているほぼすべてのコンテンツが読めます。

staffeng.com

ソフトウェアエンジニアの役割と水準

私はフリーランスなので肩書にはまったく興味はないんですが、肩書と役割は重なる部分が多いですし(役割がこなせない、あるいはこなせそうもなければ肩書もつかないし、役割が果たせれば肩書もついてくるものと思っています)、役割の土台にはスキルがあるはずで、そういった意味では、どんな立場であれ、自分の役割(ロール)と水準(レベル)には常に気を配っていたい、という思いがあります。あまり関係ないですが、私はゲームが好きで、RPG もちょくちょくプレイするので、仕事においてもそういう見方(ロールとレベル)をしてしまいがちです。

冒頭に引用した著者の言葉にもあるとおり、スタッフエンジニアはただの役割ではなく、まずそれを求める組織の組織としての有り様があり、行動のインパクトも含むということなら、業務委託のフリーランスであってもスタッフエンジニアらしきものとして振る舞うのは十分可能なのではないかと思っています。もちろん責任や覚悟みたいなのもセットで。

いまの自分の水準としては、個人の成果として期待された仕事をこなすという点であればほぼ100%満足のいく結果が得られ、チームの成果を向上させるという点では短期的にはうまくいくことのほうが多いが、中長期的にメンバーのマインドセットを変えたり、自分が抜けたあとも自律的に発展させていけるような風土づくりとか制度づくりまではできていない、といった感じです。基本的に1年以内、長くても2年の契約がほとんどなので、そんな短い期間でできることは限られるかもしれませんが、少しでもインパクトを出したいとは思っています。

スタッフエンジニアの職務領域と適正

自分にとってフィットするのはソルバー、アーキテクト、テックリードの順かなと思いました。客観的にみて自分は自主性はそこそこあるほうだとは思いますが、人望はないほうだと思うので、3つの中でもっとも人を巻き込む必要のなさそうな課題解決がいちばんフィットしそうです(自分の人望のなさがどこから来るのか、というのはいずれ解明したいと思いつつ、いまはひとまずそれ前提で生きています)。

といっても、この領域になると人を巻き込む必要のない仕事というのはゼロに近くて、そもそも求められることが個人の成果以上にチームの成果になりますから、自分にとっての最大の課題はそこら辺だな、とぼんやり考えています。

幸い25年もソフトウェアエンジニアをやっているせいか、必要最低限は人とのコミュニケーションも昔よりはうまくできるようになってきているようで、アーキテクト、テックリードあたりもなんとかがんばればこなせるんじゃないかという気もします。RPG 的にいうと MP 高め、HP 低めの魔法使い+武闘家+戦士、みたいな感じです1

Microsoft Copilot とスタッフエンジニアについて会話していた中で面白いことを言っていて、以下のコメントがとくに刺さったので抜粋します(余談ですが、ChatGPT や Microsoft Copilot と会話するときは、英語の学習も兼ねてすべて英語でやりとりするようにしています)。

Staff Engineers often thrive when they have the autonomy to shape their work, contribute meaningfully, and drive technical excellence.

自律的に自らの仕事を定義し、インパクトのある貢献をし、技術的な向上を牽引することが鍵になる、ということです。

前述のとおり、私は業務委託として組織の末端に位置することがほとんどなので、第一に求められることはプロダクトを作り上げることであるのは間違いなくて、自分としてもそこは外したくないというか、口だけ出して手を動かさないのは性に合わないので、そこは前提として確保しつつ、ベテランとしての自分に求められることは個人の成果に加えてチームの成果をどれだけ高められるか、というのもあると思いますし、行く先々の現場で、放置されている問題を分析し解決することに対する喜びもあるので、どんな仕事をするにせよ、スタッフであること、スタッフとして認められることは常に目指していきたいです。

レベル上げ

本書にはスタッフエンジニアに必要なスキルや態度についての提言がたくさんありますが、自分にとってポイントになりそうな部分を箇条書きにしておきます。

  1. 成長を促す
  2. 文書化
  3. 上司を決して驚かせない
  4. リードするには従うことも必要
  5. 他人のスペース(余地)を設ける

自分にとっての課題はコミュニケーションで、短期的な成果を求めて、リーダーやメンバーがどのように感じているか疎かにしがちなので、もっと対話する機会はほしいとは思っています。オンラインで働いているのでなかなかそういう時間が取れないのが悩ましいです。立場的には末端兵士なので、トップダウンの手法も使えず、リーダーを立てつつ、さり気なく提案して、うまいことコミュニケーションの機会を増やすような動きができれば、レベル上げへの道が拓けるかもしれません。

避けるべき3つの態度

「第2章 スタッフとしての役割」の中で挙げられていた「前進を阻む一般的な障害」について、自分への戒めも込めて言及しておきます。

  1. スナッキング: 簡単でインパクトの弱いものを選ぶ態度
  2. プリーニング: インパクトが弱く、しかも目立つ仕事をすること
  3. ゴーストチェイシング: 前職での状況というゴーストにとりつかれたまま新しい会社を理解しようとする

3 はちょっと補足が必要かもしれません。

新しくチームに加わったシニアリーダーが冒しがちな間違いとして、入ったばかりなのにこれまでの経験に基づいてそのチームやプロダクトの課題を決めつけ、間違った解決策を早計に適用してしまうことです。主にテックリードやアーキテクトの役割に秀でた人がやりがちかもしれません。

上記3つはどれも回避するのが難しいと感じます。自身を振り返っても、とくに参画した直後は成果を求めがちになるので、簡単かつ目立つ仕事に手を出しがちかもしれません。

ちなみに、「目立つ」とは原文では「high-visibility」となっていて、見た目だけインパクトが大きい、と解釈できそうです。プリーニング(preening)はもともと鳥がくちばしで自身の姿を整えることという意味らしいので、見栄えだけよくて実質が伴わないのはダメですよ、ということだと解釈しました。

個人的には、最初からいきなりインパクトのある成果は出しづらいので、周縁の小さな問題から片付けて、徐々に大きな課題に取り組むのがいいと思っていて、成果を認めてもらい信頼を得ることで、相談してもらえるようになり、相談事を解決することでこちらからも提案できるようになり、さらに大きな成果を上げられる、という良いループに入ることができるんじゃないかと思います(あくまで理想ですが)。

おわりに

本記事で取り上げたもの以外にも示唆に富んだ提言がいくつもあったので、ときどき読み返したい本になりました。

フリーランスである自分にとってキャリアパスというのはほとんど意味がありませんが、組織の中で求められる役割や出せる成果については常に考えているので、こうして新たな道筋が示されるのはありがたいですし、日本のソフトウェア開発組織において昇進や昇給のためにはマネジャーになるしかない、みたいな制度や文化はあまりいいことだとは思っていないので「スタッフエンジニア」が一般的になるといいなと思います。

ソフトウェアの内部品質に対するアプローチについて

はじめに

この記事について

最近 X で「ベテランエンジニアが設計にこだわりすぎてるせいでなかなかリリースできなくて困る」みたいなポスト(当該ポストが見つけられず、正確な表現は間違ってるかもしれません)を見て、思い当たる節があったので、自分の考えをまとめます。自分の中にあるていどの基準は持っているものの、現場ごとに毎回どうアプローチするか悩むこともあるので、そういうときのために自分で参考にしたいです(悩むことは必要なことですが、必要最低限にしたい、ということで)。

文脈

途中から参画したシニアエンジニアが、コードの内部品質を高めようとして、リファクタリングに時間をかけたり、コードレビューを厳しくしたりした結果、リリースまでにかかる時間が長くなってしまった、みたいなシチュエーションを想定しています。 もう少し細かくすると、

  • 既存のメンバーはあまり技術レベルが高くない
  • そのシニアエンジニアは自分が頑張らないとこのプロダクトの内部品質は上がっていかない、というような責任感とリーダーシップを持っている
  • メンバーはそれを好意的に受け取っている人とそうでない人に分かれている
  • ビジネスサイドはあまりいい印象を持っていない

みたいな状況にあると、仮定します。

解決したい問題

ソフトウェアの内部品質を維持あるいは向上させることと、リリースまでにかかる時間を維持あるいは遅延させないことをどうやってバランスすればいいか、一定の基準を定めたい。

前提:ソフトウェアの内部品質とリリース速度のバランス

一般的には「技術的負債」と表現される「内部品質を犠牲にして(借り入れて)リリースし、リリース後にそれが改善(回収)されずに残った状態」1とか、「Done is better than perfect. (多分動くと思うからリリースしようぜ)」というマーク・ザッカーバーグの言葉とか、とかく内部品質とリリース(の速さ)はトレードオフにされがちです。

一方で、内部品質とスピードはトレードオフの関係ではない、という言説もあります。むしろ、内部品質が高まればスピードが上がる関係である、というものです。

speakerdeck.com

私自身も、内部品質が低いとリリースまでにかかる時間が増すと感じていて、主に、ドキュメントがない、自動テストがない、コピペコードが多い、長い関数が多い、などの理由により、修正のコストが上がっていってしまう、というのは事実だろうと思います。

しかし、このスライドにあるとおり、

・内部品質がスピードを生み

・スピードが学びのループを生み

・学びのループが外部品質を生み

(中略)

・競争力が売上を生み

・売上が内部品質を育む

というのが真実だとするとなにも問題はなく、「内部品質第一」がとっくにコンセンサスになっているはずですが、現実に「内部品質を高めようとするとリリース速度が落ちるので困る」と考える人、あるいはそのような現象が中長期的に起きている、というのが事実だとすると、なにか見落としがあるんじゃないかと思うわけです。

いまは「品質と速度はトレードオフ関係である」という認識が「品質は速度に欠かせないパラメーターである」という認識へ移行している時期であり、過渡期である、ということなのかもしれませんが、だとしても、これだけ移行に時間がかかっているのはなぜか、ということです。

以上を前提として、私の認識を書いておくと、「品質と速度がトレードオフになってしまうのはそのように認識してしまう人間の認知バイアスのせい」ということなんじゃないか。だとすると、内部品質向上を目指す前にまずはそれらの認知バイアスをいかに取り除くかということにフォーカスしたほうがいいのではないか、というものです。

認知バイアスのせい?

上記のスライドで引用されている「メンバーの成長とその成長のために必要なフィードバックや学習の時間が秤にかけられているのではないか」という感覚は、私も持っています。

スピード感のために品質を落とすということはチームの成長を諦めるということ - ネットの海の片隅で

この記事の冒頭に書いたような文脈では、「成長や学習」に投資しないあるいはそれらを望まない集団の中に「品質が速度を生む」と考える人が加わることで起こるネガティブな反応が「困る」という感想になってしまうのかな、ということです。

「困る」というのは拒否反応なので、一時的なものかもしれません。そもそもそういう発想(学習や成長)がなかった、ということであれば、状況は徐々に改善していくのかもしれませんが、現状維持バイアスによって成長を拒んだり、確証バイアスによって品質から目を背けてしまったりすると、よりその拒否感が強くまた長引くかもしれません。

学習や成長を無意識にできる人っていうのはそうそういないんじゃないかと思っていて、個人だろうが組織だろうがまず第一に意思が必要ですし、それに加えて意図的に学習や成長ができるような計画なりデザインなりをしていかないと、成果を出すのは難しいものです。なので、学習や成長への拒否感をいかに反対方向へ切り替えていくか、というのが課題になるわけですが、個人的には非常に難しいと感じています。

投資に対する考え方

いままでの話はあくまでもエンジニア組織の話であって、ビジネスサイドは含めてないんですが、ビジネスサイド含めた組織レベルでの内部品質(=つまり学習や成長)に対する認識や態度となると、正直私には分からない部分が多いです。

これまで一緒に働いてきた人は、理解があって協力してくれる人、やんわり拒む人、あからさまに拒む人、などなどバラバラだった気がします。拒絶反応を示した人に対してはそれ以上深掘りしてないので分からないんですが、学習や成長は個人の問題であって、組織的に取り組むものではない、という認識があるのかもしれません。もっというと、エンジニアに比べると非エンジニアの人の組織観として、組織的な学習や成長が重要な要素である、という認識が薄いのかもしれません。

経営層の考えとして、内部品質の向上はいますぐビジネス上の成果として現れないもの、つまり投資であって、必要性は認識しているが、いまはそのときではない、という判断なんだろうと思います。

さらに、投資というのは無駄になってしまうことがある性質のものです。組織的に学習と成長への投資に取り組んだとしても成果を生まない(成果が出るまで時間がかかる)状態に陥ることがあると思います。

個人でも、自分自身への投資をしない人というのはたくさんいるので、それが組織レベルになったら増えるかっていうと増えないだろうな、という気はします。

意図的にせよ、そうでないにせよ、投資に対する考え方はひとつの価値観なので、内部品質にとどまらず、意欲的に投資する経営者(OR マネジャー OR リーダー)なのかどうか、という見極めは必要かもしれません。

内部品質に対するアプローチ

ようやく本題ですが、内部品質向上が全面的に歓迎されているわけではない、という状況において取りうるアプローチは2つ考えられて、

  1. リーダーに内部品質の重要性を説き、一任してもらってから自分の思ったとおりにやる
  2. リーダーの望む範囲内でやる

のどちらかかなと思います。

ここでいう「リーダー」とは、経営者かもしれないし、CTO かもしれないし、部長かもしれないし、テックリードかもしれないですが、要はプロダクトマネジメントに関する意思決定の権限を持っている人のことを指します(さすがに CTO がいる組織で、内部品質が蔑ろにされるってことはないと思いたいですが)。

どんな大きさであれ組織や集団はリーダー次第で、まずはリーダー自身が自分の度量や力量とどう向き合っているか、が鍵になります。意図的に投資を切り捨てているのか、手が回らなくて疎かになってしまっているのか、過去に取り組んだが失敗した経験があって二の足を踏んでいるのか、など、リーダーの考えや経験などをできるだけ理解する必要があるでしょう。

なので、最初は 1 のアプローチで試してみて、これはだめそうってなったら 2 にスイッチするっていうのが基本になるかと思います。が、仮に 2 になったとしても、すぐに状況改善を諦めるんじゃなくて、少しずつゴールをずらすことは可能だと考えています。

ゴールをずらす(内部品質基準を高める)ためには、まずは信頼を勝ち取ることが大事で、「この人が言うなら信じよう」と思ってもらえるかどうか。これまでの(他の現場での)実績は関係なく、あくまでも参画してからの積み上げです。以前のエントリーにも書きましたが、他人のマインドを変えるのは難しいので、時間と労力はかかると思います。ここは私自身のいちばんの課題といってもいいんですが、人間に対する粘り強さがなく、二、三度試してダメなら諦める傾向があります。どこまで粘り強く説得するか、というのは、相手を見てそのつど判断する必要はありますが、「これはダメかもな」と思ってからもう一押し、二押し、くらいは粘ってみようと思います。

あとは、どれだけチームメンバーを巻き込めるか。変更コストが高いことが認識されていれば比較的楽ではありますが、長いことその状態で仕事をしているとそれが当たり前になっていて、現状維持バイアスがあると、頭で分かっていてもどうしても拒絶反応が出てしまう、ということはあるのかな、と思います。

どこから手をつけるか

内部品質向上に投資していきましょうっていう気運になったのであれば、最初からリファクタリングに着手していけばいいでしょうが、そうでない場合、つまり少しずつ信頼を得ながらゴールをずらしていくほかない、となった場合には、信頼の得やすいところから少しずつ施策を広げていくことになります。

本当なら、効果を数字で出せるのがいちばんいいんでしょうけど、スクラム開発を導入してベロシティを測っているならまだしも、そうでない現場では難しいです(そして、往々にして内部品質向上に投資していない組織の場合、そうしたシステムは存在しません)。

なので、いきなり内部品質に手をつけるのではなく、まずはパフォーマンスチューニングから始めるといいのではないかと考えます。内部品質の低いプロダクトはたいてい SQL が非効率だったり、N+1 クエリがあったりしてパフォーマンスが悪い傾向があります。パフォーマンスの向上は外部品質にあたるので効果も見えやすいですし、改善してる感が非エンジニアにも伝わります。

次に、自動テストの整備です。最近は自動テストがない現場に入らないようにはしていますが、すでに導入済みであったとしても実行が遅い、テストケースの漏れが多い、など改善の余地はあるものです。デグレーションが起きているならまずはテストケースを拡充することを優先します。巨大なクラスや関数に対してテストが書けてないのであれば、スプラウトクラスやスプラウトメソッドを導入してテストしたい処理に対してテストを追加していきます。この辺は「リファクタリング」や「レガシーコード改善ガイド」などを読んでおけば、試行錯誤しながらできるようになっていくと思います。内部品質向上の価値が認められたのであれば、社内で勉強会などを開いてもいいかもしれません。

自動テストに関しては、できればテスト駆動開発を取り入れるなどして、リリースする前にリファクタリングを終わらせる文化にしていけるとなおいいです。テストがあれば、大胆に改善できます。もちろん、リファクタリングに時間をかけすぎるのも考えものですが、最初から品質の高いコードを生み出すのは難しいので、最初のうちはあるていど仕方ないでしょう。ペアプログラミングやモブプログラミングも取り入れつつ、スピードアップできるような仕組みも整えたいですね。

テスト駆動開発テストファースト)については以下のエントリも参照してください。

nunulk-blog-to-kill-time.hatenablog.com

そのソフトウェアについての学びを深めるにつれてリファクタリングを行うことで、得られた経験をプログラムに反映していくのです。 Ward Cunningham

https://t-wada.hatenablog.jp/entry/ward-explains-debt-metaphor

コードレビューに関して

個人的にはあまりコードレビューを厳しくしすぎるのはよくないと思っていて、重箱の隅をつつくような指摘はもちろんしませんし、ベターな書き方が仮にあったとしても、内部品質に対してそれほどのインパクトがないと判断できる場合は指摘しないことが多いです。これまでジュニアの人がコードレビューで大量の指摘を受けて凹んでいるのを何度か目にしてきましたが、それで向上する内部品質と、そのジュニアの人が受ける精神的ダメージを天秤にかけると、後者の悪影響のほうを懸念してしまうからです。

それよりはシニアの人がジュニアの人にコードレビューをしてもらう機会を作ることで、自分のコードを参考にしてもらい、次回似たような処理を書くことがあれば真似してもらい、本人が自発的に学習して成長していってもらうほうが、時間はかかりますが、プロダクトの健康とチームの健康のトータルで考えたときにはベネフィットが大きくなると思います。

おわりに

「ソフトウェアの内部品質を維持あるいは向上させることと、リリースまでにかかる時間を維持あるいは遅延させないことをどうやってバランスすればいいか」について考えてみました。品質が高まればスピードも上がる、というのは現実問題としてはなかなかすぐにその因果関係が見えてくるものではないと思っていて、マインドセットの変化や仕組みが伴わないといけないですし、技術の関係するところでもあるので、一定レベルまで引き上げるための時間も必要です。

今後ももしかすると似たような状況のチームに入ることがあるかもしれないので、現時点の方針としては、ここに書いたような考え方やシナリオをもとにして、チームやプロダクトの特性を加味しながら、いいやり方を模索していきたい所存です。


  1. ちなみに、技術的負債についてはまだ誤解している人がそれなりにいそうなので、こちらの記事を貼っておきます。https://t-wada.hatenablog.jp/entry/ward-explains-debt-metaphor

フルスタックエンジニアについて

はじめに

この記事について

前回書いた記事に何気なく以下のように書いたんですが、読み返したところ自分の中で十分に言語化できてなかったなと感じたので、前回の補遺的な位置づけで、「フルスタックエンジニア」とはなにか、自称することへの忌避感はどこから来ているのか、について考えてみます。

自分としてはあまりフルスタックと名乗りたくない、という気持ちはありまして、

nunulk-blog-to-kill-time.hatenablog.com

フルスタックエンジニアとは

前回の記事にも自分で定義を書きましたが、我流でない解釈も載せておくほうがいいと思ったので、Wikipedia にある定義を載せておきます。

A full-stack developer is expected to be able to work in all the layers of the application (front-end and back-end).

Solution stack - Wikipedia

中には勘違いされている方もいるようですが、「スタック」とはアプリケーションを構成するレイヤーのことであって、同階層における技術の種類や幅のことではありません。

フルスタックエンジニアという呼称についての印象

自分がソフトウェアエンジニアになった25年前は(少なくとも自分の周りでは)フルスタックという用語は存在しませんでした。アプリケーションの全レイヤーを担当することがほとんどだったからです(自分自身も、デバイスドライバーから Windows GUI、HTTP サーバーから HTML まですべて書いていました)。

私の印象では、バックエンドとフロントエンドという分業がされはじめたのは HTML5, CSS3 が出てきたあたりで、フロントエンドの技術の幅が広がったためにカバーするのが困難になったのと、主に Flash を使っていた人たちが、HTML5 に乗り換えて動的な(文字どおり動的な)ウェブサイトをバンバン作り始めて、それらのパーツは基本的にはバックエンドと絡まないため、フロントエンドがバックエンドから離れる格好で分離していったんだと解釈しています(それでももう15年近く前の出来事なので記憶が曖昧ですが)。私は Flash の仕事はほとんどしてなかったので、当時の Flasher の仕事の範囲というのはわからないですが、おそらく、ゲームとウェブサイト構築が(システムではなく)主な主戦場だったであろうと思います。

その時代を経て、もともと存在していた「アプリケーションのすべてのレイヤーにおけるコードを書く」(概念上のフルスタック)ソフトウェアエンジニアが、フロントエンドを専任に任せる形で自然とフロントエンドから離れていくパターンと、チームの人数が少ないために依然としてフロントエンドも書かざるを得ずに継続していったパターンとが存在していたんじゃないかと思います。私も所属する会社によっては前者と後者を使い分ける形で従事していました。

最初はウェブサイト制作の文脈でフロントエンド技術の多様化複雑化とともに分業が進み、それが業務システムの文脈まで派生してきた、という印象です。

分業が当たり前の現在、すべてを一人でやることに対してネガティブな印象を持っている方もいるようですが、私自身は昔はそれが当たり前だったというのもあり、ネガティブな印象は持ってないです。当然、昔よりは守備範囲の広さが格段に違うので、一人でやることの大変さというのは分かりますし(実際大変ですし)、分業を否定しているわけではありません。

なぜ「フルスタックエンジニア」を自称したくないのか

積極的に避けたいというよりは、むしろ自分にとってはそれが当たり前なのでなんとなくの気恥ずかしさがある、というのが正確なところだろうと思います。

仮に10年後、(職業としての)料理の世界で分業が進み、一人で料理を作ることがなくなった世界が来たとします。その中にあってなお、あなたが依然として一人で料理を作っているとして、それを「フルスタック料理人」と自称したいと思うか、ということです(喩えとしてあまり上手くないかもしれないですが)。「料理人」は「料理人」であって、そこに修飾語としてなにかを加える必要がない、加えようと思わない、という感じです。

なので、私は「ウェブアプリケーションエンジニア」を自称するようにしていますが、それはやはり過去から引き続いて持っている感覚に基づいているので、20代、30代の方たちとは感じ方が違うでしょうし、平たくいえばみんな好き々々に呼べばいい、という類のものだと思います。

とはいえ、いま現在の潮流がどうなのかはわかりませんが、もし「フルスタック」であることに希少性があるんだとしたら、堂々と「フルスタックエンジニア」を自称すればいいんじゃないかと思います。

実体としてのフルスタックにはこだわりたい

名乗りはしなくとも、自分としてはフルスタックにこだわりたいと思っていて、それは、過去に何人か中小企業の社長からシステム開発の依頼を受けて業務システムを一人で作ってた頃があって、そのときの仕事が楽しかったからです。要件定義から実装まですべて一人でやれるのは圧倒的に楽なのと、自分は自分でなにかを作りたくてこの仕事をしているのではなく、目の前にいる困っている人を助けたい、という動機でやっているので、そうしたビジネスアイデアはあるけど自分では作れない人からの「こういうの作れない?」っていう問いに応えられるかどうかっていうのが、自分の価値になっていると思っています。なので、そういう問いに対して「画面以外は作れます」みたいな回答は基本的にはなしなんですよね。

世の中に、ソフトウェアエンジニアは大量にいて、探せばそれぞれのスタック(レイヤー)で優秀な人材を揃えることはできるでしょうけど、ソフトウェアエンジニアの知り合いが私しかおらず、頼って声をかけてくれたのであれば、それにできるだけ応えたい、という当時の動機がいまでも根底にあるんだと思います。

いまではチーム開発の仕事がほぼ100%ですが、それでも、チーム内にできる(やりたがる)人がいない仕事はどんなことでもやろうと思いますし、できるようになりたいです。

おわりに

今回も勢いで書いたのでとりとめのない感じになってしまいましたが、「フルスタック」についての思いの丈はぶちまけられたんじゃないかと思うので、とくに推敲などせず、このまま公開しちゃいます。