Kengo's blog

Technical articles about original projects, JVM, Static Analysis and TypeScript.

自分のなかにあったリーダーシップに関する固定概念

自分のなかにあったマネジメントに関する固定概念の続き。リーダーシップに関する固定概念を棚卸しして自覚的になるためにまとめます。

リーダーシップとマネジメントの違い

自分の中ではこれはかなり明確です。私はVisionary Leadership and Strategic Managementという言葉を多用していますが、マネジメントが戦略的に地盤を作ってリーダーシップがその上でreactiveに問題解決に動くイメージ。例えば文化を醸成してガードレールを用意するSREはマネジメント的だと言えます。

他の観点から言うと、私が言うマネジメントはドラッカーが提唱するものを指していて、ほぼほぼ経営のことです。顧客の創造に必要なことは全部やる。しかし「やる」というのは直接手を下すことではなく、権限委譲や組織文化づくり、つまり「自分より強い人に気持ちよく働いてもらう」ことを指しています。だからこそのビジネスモデル、だからこその目標設定です。なお自分のマーケティング側の解像度がイノベーション側のそれよりも粗いのが、個人的には課題だと思っていますがここでは割愛。

そしてリーダーシップは現職で田中聡先生が勉強会を開いてくださった、チームワーキング本の定義がわかりやすいです。私の解釈ではリーダーシップとは知的労働者みんなが持つべき「働き方」「新常識」であり、それが目標を握り続けるなどのチームの行動原理を通じて働く上での共通言語として機能します。

だからこそ知的労働者が勤める企業においては、少なくともMVVのうちValueはリーダーシップを内包するものになるでしょう。現職の行動指針はまさにそんな感じですし、前職の「問題解決の核になる」もまさにリーダシップのレゾンデートルを表しています。

で、なんでこの「リーダーシップとマネジメントの違い」を一番最初に持ってきたかと言うと、同僚とまずここをすり合わせないと会話が成立しないからなんですね。例えばこちらは同僚が書いたnoteなんですが、このnoteで語られるリーダーは戦略的に組織機能を設計する役割を担っていて、私の定義ではマネジメントに踏み込んでいます。リーダーシップという概念的な話ではなくチームリーダーという具体的な役割について議論しているのだと私は理解しましたが、この理解を敷かずに「それリーダーじゃなくない?」と突っ込むのは違うわけです。ので「リーダーシップとマネジメントの違い」を自分の中できちんと持っておいて、相手の提示した概念とのマッピングを構築しながら議論することが必要です。

リーダーシップとは必ずしも情熱を持っていたりヒエラルキーの頂点に立っていたりするとは限らない

リーダーシップとは熱い情熱を持って部下を引っ張ることではありません。もちろん理想や目標を掲げるのは立派なリーダーシップですし、引っ張ることはリーダーシップの形のひとつではあります。ここで言いたいのは「リーダーが全員そうである必要はない」ということです。むしろ熱い想いを語り続けるあまりに周囲の声や自発性を拾えないようであれば、リーダー失格とすら言えます。情熱型であることはリーダーシップの発現の形のひとつでしかなく、必要条件でも十分条件でもないわけです。

ではヒエラルキーの頂点に立つことはリーダーシップかというと、これも違います。肩書がリーダー業務を楽にしてくれる部分はもちろんあるのですが、リーダーシップとはむしろ顧客や課題に直接接する人間こそが発揮するべきものであり、頂点に立つ人にはそれを邪魔しないことが求められます。よってどちらかといえばマネジメント側の存在だと言えるでしょう。

周囲に影響をめっちゃ及ぼしている方がリーダー適性がないという自己評価を持っている場合、だいたいこのあたりのかみ合わせがズレていたりします。ので、いやいやめっちゃエナジャイズしてますやん、巻き込み力高いじゃん、と思った場合は「リーダーっていろんなやり方があるんですよ〜」みたいな話ができます。

リーダーの言うことは常に同じだが、目標やアプローチはコロコロ変わる

リーダーの言動は常に一致しなければなりません。リーダーが顧客が第一だと言うならば、それは常にそうである必要があります。昨日までは顧客が第一だったけど、今日からは株主を優先します!という人はリーダーではありません。いかに顧客が重要で、そのために我々がどうしたいかを手を変え品を変えて力説する人こそが良いリーダーです。

一方で、良いリーダーが取るアプローチはコロコロ変わります。それは理想(TO-BE)が変わらずとも現実(AS-IS)が変化するためであり、仮説検証を通じた学習が頻繁に行われているためでもあります。先月と今月では見ている指標が変わるでしょうし、昨日と今日では最優先のEpicが変化しているでしょう。だからこそチームは目標を握り続ける必要があります。

ここはリーダーシップの理解がズレると言うか、働き方についての理想像がズレがちなところかなと思っていて、マネージャが働き方の理想像を継続的に発信していく必要がありそうです。

リーダーシップは良いマネジメントに依存している

アプローチや目標がコロコロ変わる必要があるということは、それが可能な勤務体系や評価制度が必要です。例えばプロダクトバックログの順番を変えると混乱をきたすようなコミュニケーションが行われてはいけませんし、半年前に設定した目標の達成度合いで評価されるようでは良いリーダシップは発揮できないということですね。ここはマネージャがリーダーのために心を砕いて戦略的に整備するべきところです。

これは組織内に閉じた話ではありません。目標やその優先度を変えるということは、顧客に提供する価値の内容や順番が変化することを意味します。ですから顧客の理解を得るためのコミュニケーションをすることや、過多なコミットメントを避けることもまたマネジメントには必要です。情報システムで言うならば顧客にビジョンへの共感を持っていただき、具体的な価値を提供し、継続的にブランドを作ることで、UIや機能の変化をポジティブに受け止めていただけるだけの関係性を構築するということです。これはマーケティングであり明確にマネジメントの領域です。

ですからマネージャはリーダシップを理解し、良きリーダーに寄り添えるようにしなければなりません。マネージャの払う工数の大多数はここに突っ込まれるべきなのではと思うことも多いです。

まとめ

マネジメントが「全部自分でやれ」ならリーダシップは「皆を巻き込め」です。ひとりでできない問題解決をするためにビジョンを掲げて人を巻きこむことを指します。 リーダーシップは今日の知的労働者が持つべき新常識であり、その点で採用の時点で考慮するべきものです。MVVや行動指針に組み込むのが一番わかりやすいでしょう。 またリーダーシップとマネジメントは両立します。問題の核となる能力と問題解決に向けた戦略を考えることは、問題解決の両輪であって排他的なものではありません。

という3点が噛み合わないと話がどこまでも発散するので、リーダーやリーダシップについて話すときはその言葉の意味するところや議論の目的を見極めるところから入る必要がありそうです。

自分のなかにあったマネジメントに関する固定概念

固定概念、自分の行動を爆速にしていくうえでは非常に有効なバフなんですが、ナチュラルに「あれ?僕またなんかやっちゃいました?」を生産する機会にもなるのできちんと棚卸しして自覚的になっておきたいため、まとめました。

「ちゃんとやる」コストを自分で払う

ソフトウェアエンジニアリング業あるあるだと信じているのですが、この仕事はベスト・プラクティスが積み上がっていて目指すべき働き方が明確なだけに、「ちゃんとやる」ことがとても難しいという問題があります。たとえばRedmineのようなものでチケットを積み上げてガントチャートを消化していくようなプロジェクトであれば、チケットの管理だけでも以下のようなことを「ちゃんとやる」ことが理想です:

  1. チケットは最長でも3日でデフォルトブランチにマージできる大きさを保つ
  2. 新しく発生したタスクはチケットに落とし込み、DONEの定義についてチームで合意を取る
  3. チケットにはチケットを解決するうえで判明した事実やブロッカーを書く
  4. 朝会までに変更をpushし、着手していたチケットを更新し、経過を共有できるようにしておく
  5. チケットやチャットで判明した事実のうち、ストックするべきと思われた事実はWikiやドキュメンテーションコメントにする
  6. チケットは他のチケットやPull Request、デプロイとの紐づけを行い、あとから関係性を追跡できるようにしておく

さて、これをチーム全員ができているプロジェクトはどのくらいあるのでしょうか。無いでしょというのが自分の意見です。これは新卒採用がメインで「走りながら教える」必要があった自分の経験から来ている考え方ではありますが、ベテランが集うプロジェクトでも大差ないだろうと感じています。

ではやっていない人を吊るし上げればいいのか、やれない人に根気よく教えるべきかというと、そうではありません。中途半端なコードの共有に抵抗のある方、状況や考えをテキストにダンプすることが苦手な方、コードを書くときは集中しており終わったら疲れ果てているのでチケットを更新する時間が捻出できない方、他のことに挑戦していてチケット管理の優先度が低い方など、「ちゃんとやれない」背景には様々な事情・個性があります。特に気質や価値観、健康に根ざしている場合は「やれ」と言うこと自体がリスクなわけです。

少し抽象化した表現をすると、自分は企業文化・行動規範以外に「チーム全員に画一的な素質・行動を求める」のは失敗パターンだと思っています。そりゃ面倒をみる側からすればチーム全員がちゃんとチケットを管理してくれれば大助かりです。実際に教えればできるようになるケースも多数あるでしょう。しかししばらく声をかけてみてダメだったり、ヒアリングや観察の結果「いまは難しそうだな」と思ったら、諦めも肝心です。あまりにも致命的で協力関係が築けない場合は除くとして、基本的には自分が「ちゃんとやれる」範囲で手助けするほうが良いでしょう:

  1. 新規に作成されたチケットの粒度を確認し、大きすぎると思ったら分割を提案する
  2. チケットのDONEの定義が明確ではない場合、チームで話し合いの機会を持つ
  3. 考えをテキストに落とせていない場合、朝会でヒアリングしてその場でチケットに書いていく
  4. 変更をpushできていない場合、朝会の前後で座席に行って画面を見せてもらう
  5. wikiやドキュメンテーションコメントを更新できていない、自分で変更を提案する
  6. 紐付けられていないチケットがあれば、自分で紐付けるか、自動化を用意するか、デプロイやレトロスペクティブのタイミングで一緒に紐付ける機会を持つ

こんな考えだからマネジメントに超人性を求めてしまうのだとはわかっていますが、チームワークを円滑に回して組織としてのアウトカムをコミットするのがマネージャである以上、必要なことだとも思います。

実際、こうやって「ちゃんとやる」フォローに回ることで一番メリットを享受できるのは、マネージャである自分自身なんですよね。組織がアウトプットを作れていてアウトカムの実現に近づいているかという、そのプロセスの透明性を見たいですよね。ので「ちゃんと見せろ」と他力本願するよりは、「ちゃんと見に行く」ほうがControllableだし育成の方向性も見えてくるし建設的なはず。

なおマイクロマネジメントとの線引きは自分の中では明確で、「ちゃんと設計できてないから自分で設計する」「ちゃんとテスト書くのが大変だから書いてあげる」「ちゃんと機能追加するのが難しそうだから代わりにやってあげる」あたりはマイクロマネジメント寄りかなと思います。

この判断基準については、最近同僚が「相手のプロフェッショナルに踏み込む」という表現をしていていいなと思いました。相手がプロフェッショナルとしてやるべきところ、やりたいと思っているところには触れない。スクラム回すからには透明性を上げるのもプロフェッショナルの範囲だろうと言う考え方はできるかもしれませんが、そこは先程の「チーム全員に画一的な素質・行動を求める」のは避けるを適用します。

まぁこれ、たぶん真のcross-functional teamをマネジメントしてるとあんまり問題にならないんでは無いかなと思います。そもそもチームメイトと自分のプロフェッショナルがぜんぜん違うんで、代わりにやってあげるという選択肢がそもそも取れない。ので自分がcross-functional teamの経験が浅いことの裏返しなのかなとは思う。

最後まで自分で追いかける

先の例(チケット管理)だと、マネージャじゃなくてスクラムマスターがやればいいのでは?という疑問があるかと思います。もちろんスクラムマスターに委譲するなど、仕組みや委譲で解決できればその方が良いことも多々あります。

それでもそのスクラムマスターがちゃんとやっているか?は自分で見る必要があります。チームメイトの1on1を通じて、スクラムマスターに目指してほしいチームづくりができているか、できていないなら何を変えるべきかを考えていくわけです。またこの姿勢は相手と一緒にDONEの定義を考え、適切な問題空間を設定することに繋がります。チームメイトにとって難しすぎる問題設定を避けるとともに、あとあとで「期待とぜんぜん違うアウトプットが出てくる」リスクに対する対策にもなるため、チームマネジメントにおける重要な姿勢だと言えます。

これはスクラムマスター以外のプロフェッショナルについても同様で、新しいデザインや機能が顧客の課題を解決したのか、新しく導入した品質管理手法はどう作用したのか、作成したドキュメントやツールが現場で使われているのか、実装の最適化でランニングコストやレイテンシは改善されたのか……などをプロフェッショナルと一緒に最後まで追いかけることが必要です。昔の上司が「信頼はするけど信用はしない」と言っていましたが、プロフェッショナルを信頼することとそのアウトプットを確かめもしないことは別なのです。

もちろん他のチームやお客様に対しても同様の姿勢が必要です。依頼したタスクが終わったのか、その効果が出ているのか、やるべきことを忘れていないか……などを追跡することで、組織的な課題がチームの間にこぼれ落ちたり、顧客が必要としていないことにコストを掛けたりといった問題を早期に発見できます。

ここは意外と多くのマネージャが「そこまで私の仕事なの?」と言いがちなところで、まぁ実際マネージャのマネージャや経営がしっかりしてたらマネージャがそこまでやらなくていいよねとか、給料に入ってるんだっけこれという思いも無いわけではないのですが、結論、やったほうがいいですね。チケットのDONEの定義をクリアしたらオッケーなのはチームメイトにとっての話で、マネージャの仕事である「チームとしてアウトカムをデリバリーする(横文字多いな)」はチケットの積み上げからは見えないラストワンマイルがあったりするので、ほぼ例外なくデリバリー先を見に行くことが必要です。そしてこれをやるためにも日頃からのチーム内外との関係性構築が大切で、このためにもマネージャはWorking Loud Outしておくと良いと思います。

developers.freee.co.jp

が、すべてのマネージャがこの考えを持っているかというとそうではないので、あくまでも自分の固定概念だということに自覚的になっておきたいと思いました。

なお、これはマネジメントもそうだけど、リーダーシップを発揮するうえでも必要な姿勢かもしれません。リーダーシップについても近々考えをまとめておきたいです。→まとめました

マネージャは暇してるべき

自分でやれ、最後までやれと来て、最後がこれか?とは自分でも思います。思いますが、チームの前に立ちはだかる障害を即座に解決してチームをトップスピードに保つためにはやはり必要です。経験的には毎日勤務時間の4割に空きがあって、いつでも1on1や対応工数を積めるくらいの暇さがあったほうがいいです。どんなに定期1on1や朝会などの仕組みを整えてもイレギュラーは発生するので、即対応できる時間はいつでもつかえるようにしておくべきです。

べきですが、ここは自分の考えに柔軟性がなかったなと反省するところで。大企業ならチームの役割も比較的明確なのでこれで回るのですが、そもそも市場を探している段階だったり1人で3つも4つも役割を兼任しないといけない場合だったりすると、そんな暇を抱えてるわけにはいかないのも事実でした。本来マネージャに兼務はご法度なんですが(むしろ兼務自体が滅べばいいとすら思っている)、マネージャをやるということは集まる情報が増えるということなので、その人が複数の役割を持つことは展開としてまぁナシじゃないなという。

この場合、即応するのはマネージャではなくチームメイト同士が有機的に行うことになるはずで、お互いに即助けに入れるくらいチームメイトの仕事と状況を理解していないといけません。cross-functional teamであれば一時的に自分の専門外のことに着手することもあるでしょう。そういう空気や関係性を醸成することのほうが、マネジメントにとっては優先度の高い営みなのかもしれません。

まとめ

自分のなかにあったマネジメントに関する固定概念を一言でいうと「全部自分でやれ」なんですよね。もちろん組織としてのアウトカムをコミットするのがマネージャである以上、マネージャが口にする主語は常にweなんですが、weという存在を円滑に動かす機能の最後の砦がマネジメントなのは疑いないので、文化情勢や仕組みでの解決では漏れてしまうところは常にマネージャが拾い続ける必要があると思っています。

何でもかんでも自分でやる姿勢、一歩踏み外すとマイクロマネジメントや部下の成果をぶんどる系上司になりがちなのはあると思います。自分でやるのか、コーチングするのか、根気よく教えるのか、それとも諦めて別の手段を取るのかという判断基準は「相手のプロフェッショナルに踏み込む」を基本にしつつも相手に依って調整が必要なため、今後も手探りになりそうです。

エコシステムにビルドツールがたくさんあるのは悪いことではない

JavaやNodeJSには多数のビルドツールがあります。ものによってはビルドツールではなくタスクランナーとかワークフローとか名前が付いてるかもしれませんが些細なことです、ここでは以下のようなツールのことをまとめてビルドツールと呼びます:

一方で言語公式のビルドツールを用意している言語もあります。これによってプロジェクトごとに異なる技術を学ぶ必要性が減りますし、一貫性のある開発体験を得ることができます。javac javadoc のような単純なコマンドしか提供しないJavaとは異なる方針を言語として持っていることは明らかでしょう。

では言語のエコシステムにビルドツールがたくさんあることはモダンではなく不便なのでしょうか?そんなことはないだろうというのが自分の考えです。もちろん欠点がないとは言いませんが、以下に私見を述べます:

プロジェクトによってビルドツールに求められる役割は異なるため、きめ細かな選択肢を選べる

例えばプログラマが若干名のプロジェクトでは、コンパイルやテストが一箇所にまとまっていてフットワーク良く改善を回せていけることが望ましいでしょう。複数リポジトリやサブプロジェクトを作る必要性もまだ薄いでしょうし、そこまで統制について考えることもありません。自分なら開発が活発でパフォーマンスも良いGradleを選択することになると思います。

一方で何百人ものプログラマが関与するプロジェクトでは、ビルドツールやワークフローについても統制を考えるケースが出てきます。 mvn test を実行したらテスト実行結果が必ずJUnitのXML形式で target/surefire-reports/TEST-*.xml に吐き出されなければならないとか、Reproducible Buildsに準拠するとか、developブランチにマージしたらSonarQubeを実行せよとか、ビルドするにはJava 8を使わなければならないとか、そういったベースとなる要求をすべてのプロジェクトに守らせることでリポジトリ横断的な品質改善に役立てたりするわけです。

今だとこういった要求もGradleで満たせそうですが、7年くらい前?に自分が似た状況にあったときは、Mavenのparent projectによる制約の中央管理とバージョン管理が非常にマッチしました。DSLがないので自由度が低く、統制側としては考慮すべきことが減るというのもあります。中央管理する以上は各リポジトリの困りごとをきちんと拾い上げる姿勢は必要になりますが、その工数を考慮してもMavenに軍配が上がることはあるでしょう。

ビルドツールの思想に種類があることを学べる

そもそもこうした違いはどこから生じるのでしょうか。モダンな技術を使って開発された新しいビルドツールは常にレガシーなものよりも優れているべきではないのでしょうか?実はそうではなく、むしろ最もレガシーなApache Antと最もモダンなGradleはかなり近い特徴があります。

Apache AntとGradleはタスクを繋いで有向非巡回グラフ(DAG)を作るという発想で作られています。テストはテストケースのコンパイルに依存し、テストケースのコンパイルは実装のコンパイルに依存し、実装のコンパイルはアノテーションを使ったコード生成に依存する……といったタスクの間の依存関係を明示することで、タスクを並列実行したり不要なタスクの準備を省いたりして高速化ができるのです:

graph LR;
  annotation-processing --> compile --> testCompile --> test --> check --> build;
  compile --> jar --> assemble --> build;

特定のタスクだけ実行する・特定のタスクだけ除外するといった操作も簡単に行なえます。プロジェクト固有のタスクや概念を導入することも容易ですが、一方でタスク実行時に必要な入力がすでに生成されているかどうかを管理するため、タスクの入出力を宣言したり、タスクが依存するタスクを明記する必要があります。DAGをメンテナンスする責任をユーザが負い、それを前提にタスクの内部実装を気にせずに済むようになっています。

Mavenはビルドライフサイクルという概念があり、すべてのプロジェクトはこのライフサイクルに従うことを期待されています。ビルドライフサイクルをゼロから作ることも可能ですが、かなり重い作業です。

ビルドライフサイクルにはフェーズが定義されており、このフェーズにプラグインのゴールを紐付けることで、どのようなプロジェクトでも同じビルドライフサイクルで臨んだ結果を得られるようにしています:

graph LR;
  subgraph compile
    compiler:compile
  end
  subgraph test-compile
    compiler:testCompile
  end
  subgraph test
    surefire:test
  end
  subgraph package
    jar:jar
  end
  compile --> test-compile --> test --> package

そのフェーズに入った時点で以前のフェーズはすべて完了していると信じられるため、ゴールの入力がすでに生成されているかを気にする必要は比較的薄いでしょう。フェーズ内で実行する処理に依存関係がある場合、 compiler:compile ゴールがアノテーションプロセッシングとコンパイルの両方を行うように、ひとつのゴールにまとめてしまうことで単純化します。

一方でやはり柔軟性には欠けます。ライフサイクルの一部だけ実行したい場合、例えばテストを再実行してレポートを生成する場合など、必要なプラグインのゴールを特定してそれを直接実行しなければなりません。逆にテスト以外のすべてを実行する場合も、プラグインの実装を理解して -DskipTests オプションを指定するといったことも必要です。依存先のゴールを自動的に推定・実行することもないためゴールの入力が不正になることも多く、昔は「とにかく mvn clean してやりなおす」ということもよくやっていました。おそらく多くのMavenプロジェクトでは、開発時の混乱を避けるためにREADME.mdCONTRIBUTING.mdにこういうときはこうするというコマンド一覧が載っていると思います。

長くなりましたが、すべての状況にマッチするツールが存在しないのは、ツールの根底にある思想によって適した現場がそれぞれ異なるからだと考えられます。これらの思想そのものは20年以上変化していない時代の荒波に揉まれたものですので、一長一短はあれど使い所が合えば価値の高いものだと言えます。ビルドツールの多様性は、それすなわち言語の活用幅の広さだということなのでしょう。

単に歴史が長いのでビルドツールが数多く生まれてきた

特にJavaは言語としての歴史が長いので、多くのビルドツールが作成され検討されてきたという側面はあると思います。例えばApache Antを使っているfb-contribは2005年からあります。当時からJavaのビルドツールが成長せず、Antだけでここまで来れたかというと、ちょっと考えられませんね。最近(と言っても8年前ですが)Java Moduleにネイティブで対応するビルドツールも提案されていたりして、今でも新しい形が模索されています。

それで言うと今はひとつしかビルドツールを備えていない言語も、もしかしたら今後はビルドツールが2つ3つと増えてくるかもしれませんね。どんなニーズにもひとつのツールチェインで応えようとすると収集つかないこともありそうなので。

とはいえ新しいツールに乗り換えたほうがいいこともある

古いビルドツールをずっと使い続けると技術革新の恩恵を得にくいみたいなところはありますので、ビルドツールをモダンなものに変えていく努力はしたほうが良いことはあります。これからも活発に変更を入れていくプロジェクトであれば特に、更新が活発なビルドツールに移行したほうが良いでしょう、私もFindBugsをSpotBugsにforkするときはAntとMavenを使っていたプロジェクトをGradleで書き換えるという経験をしました

異なる思想を持つツールに移行する場合は両方のツールに詳しくないと思わぬところで失敗するなんてこともあるので、一時的に有識者に手伝ってもらうことも検討しましょう。私もビルドツール移行の副業を受け付けております(唐突な宣伝):

youtrust.jp

まとめ

エコシステムにビルドツールがたくさんあることは悪いことではありません。キャッチアップが大変とか、コミュニティの知見が分散してしまうとかはもちろんあるのですが、コミュニティの抱えるプロジェクトの多様性を担保し、歴史あるプロジェクトと新鋭気鋭なプロジェクトとが同居する上でとても重要な貢献をしています。

キャッチアップコストが気になる場合はREADMEを整備するとか情報の多い新しめのツールに乗り換えるとか、自衛策を取ることもできます。最初からビルドツールがひとつだったら払わなくて済むコストでは確かにあるのですが、言語の歴史と実績に思いを馳せていただければと思います。

組織という仕組みで解決することの難しさ、あるいはマネジメントに超人を求めるのは間違っているだろうか

そりゃ間違ってるんだけど、ではどうするべきなのかが見えてないなぁという話です。

事業が大きくなると組織という仕組みの重要性が上がる

同僚が何千人といたメガベンチャーから社員数20数人のスタートアップに転職してから1.5年経ちました。ここまでに自分が貢献した内容にはSREや医療情報技師としてのものも当然あるのですが、マネジメント経験のあるIndividual Contributorという立場から組織の成長や組織における連携について補足や関連情報を提供するということも意外とありました。例えば社内ブログや社内勉強会で触れたものには以下のようなものがあります:

こうした知識や観点を個々人が持つことは、ボトムアップと呼ばれる自発的な行動を支援する意味では大きな意味があります。そして少ない人数で尖った成果を出すことが求められるスタートアップ立ち上げ時には、これで充分でもあると思います。

一方で事業と組織が急成長していくフェーズでは、これでは足りないというのも事実です。もちろん個人の知識や観点を伸ばしていくことは引き続き大切ですが、人数が増えたことによるコミュニケーションの混乱や事業拡大による着眼点の増大についていくためには、底上げ的な施策や目標の明確化、すなわち組織をマネジメントするための動きが必要になります。トップダウンが必要だということではなく、ボトムアップを続けるためには最も情報を多く持つトップがきちんと情報や要求を棚卸しして、従業員に共有し続けなければならないということです。

事業目標の明示と共有に、トップの演説。
燃え尽き症候群対策に、ピープルマネジメント。
従業員の成長支援に、教育とコーチング。
従業員エンゲージメントの向上に、定期的な面談や人事施策などの実施と評価。
従業員の常識を合わせるための、定期的な従業員教育や統制。

このような「組織をマネジメントするための動き」をトップがやっていたら事業成長に時間を使えなくなりますし、専門家を採用して任せようということになります。こうしてスタートアップは組織化され、専門家が進み、より質の高い課題解決をお客様に提供できるようになっていきます。

組織化はチームマネジメントの負担を高める

しかし人事部があればそれでオッケーかというと、そういうことにはなりません。各部署やチームごとに働き方や求められる専門性、扱う情報などは異なりますし、職場に求めるものは個人レベルで異なります。そうした異なるニーズに対して人事部がケアしきることは事実上不可能です。

この問題に対する解決策でよくあるのが、人事部はルールやツールの整備をし、実行の多くをチームマネジメントが担う方式です。つまり部長や課長に相当する中間管理職に対して、その部下への「組織をマネジメントするための動き」を期待する方式です。部長や課長であればそのチームがどのような働き方をしているのか把握していますし、部下それぞれの個性もわかっていますし、面談を通じてコーチングすることもできます。よってチームマネジメントが「組織をマネジメントをする動き」をすることは合理的であり、組織としてスケーラブルな施策であるとも言えます。

しかし待ってください、チームマネジメントにはもともと他の役割を期待していなかったでしょうか。それはプロダクトマネジメントかもしれないですし、プロジェクトマネジメントかもしれないですし、コードレビューや渉外かもしれないですが、とにかくチームを結成してここに代表者を置いた時点で何らかの機能を持たせていたはずです。チームマネジメントはその道の専門家であって、ピープルマネジメントだ従業員エンゲージメントだ統制だとあとから役割を増やすことにはいくつかの問題があります:

  1. その人には「組織をマネジメントするための動き」に対する知識や関心がないかもしれない。チームを率いるものとして組織に全く関心がないということはないかもしれませんが、そんなの人事でやってくれという声を聞くことは珍しくないのでは。
  2. その人の「組織をマネジメントするための動き」を評価してフィードバックすることが難しい。前提の整理やゴール設定を中央管理的にできないからチームマネジメントにお鉢が回ってきているわけで、そのチームマネジメントがきちんとできているかを外部から評価することは意外と難しい。

言い換えるならば、組織化はチームマネジメントに対して多彩な要件をつきつけます。経営者が経営に必要なすべてを担い、スクラムマスターがスクラムの運用に必要なすべてを担うように、組織化はチームマネジメントにチームが機能するために必要な全てを背負わせます。そして事業の成長とともにチームとそのメンバーに対する期待値も高まり、チームマネジメントへの負担も向上します。

これは組織を運営する我々が、チームマネジメントに超人であることを求めていると言えないでしょうか。チームにおける単一障害点(SPOF)であるチームマネジメントにここまで高い負荷をかけることは、組織運営上正しいことなのでしょうか。

求められるのは「組織をマネジメントする動き」の専門家か、それとも「組織をマネジメントするための動き」のコモディティ化か

浮上した課題に対して組織化によって対応したこと自体は、大きな間違いではないと思います。two pizza teamを作ってこれをまとめることで事業と組織を大きくすることは、今やシステム開発におけるベストプラクティスのひとつだと言っていいでしょう。となると「中央管理を諦める」か「分散実施をチームマネジメントによって実現する」のどちらかに課題があると思われます。

ただ中央管理にこだわるのは、事業成長のどこかで破綻するのではないかと考えています。もちろん人事部はミッション・ビジョン・バリュー(MVV)を整理して全従業員が共通言語で話しあい評価しあう組織を志向するべきですし、そのレベルでは中央管理もするべきです。しかし前述のとおり、チームや従業員ごとの個性に対する配慮なしには「組織をマネジメントするための動き」は実現できないため、どこかで破綻するだろうというのが自分の考えです。

よって解決は「分散実施をチームマネジメント以外の仕組みで実現する」になるでしょう。しかし、具体的にはどうすればいいのでしょう?

ひとつのアイデアは組織をマネジメントする動きを提供する専門のチームを作ることです。部下からは専門性(チーム)の上長と、人事的メンタル的な上長を持つ形になります。 これはちょっと難しいかなと思っていて、というのも専門性の上長と人事的メンタル的な上長の間のパワーバランスってどうなるんだろうという。メンター制度によってある程度はメンタルのケアや教育の実施を上長から外すことを実現できている事例は聞くのですが、完全な代替にはなっていなさそうです。

もうひとつのアイデアはチームマネジメントだけではなく従業員全員が「組織をマネジメントする動き」をすることです。上長によるトップダウンではなく、チーム内での相互作用によって組織をマネジメントしていくことです。 これはある意味で理想的なんですが、事業成長において必要な(比較的に)大量の人材を採用するときのハードルとなってしまいます。「組織をマネジメントする動き」には合う合わないもありますし、単純に習熟と時間を必要とするからです。それこそ新卒採用なんて無理じゃねって感じですね。またこの手のアプローチには再現性がまだなさそうだなと思っているということは、「ティール組織わからん、を掘り下げる」にもまとめています。

組織という仕組みで解決することの難しさ、あるいはマネジメントに超人を求めるのは間違っているだろうか

事業拡大における組織化の重要性と、その際にチームマネジメントの負荷向上という問題について書いてきました。組織化は重要だけど組織という「仕組みで解決」する過程でどうしても個人に依存しちゃうねという。正直まだいい解決は見つかっていないと思っていて、チームマネジメントに高い負荷をかける今までのやり方をチームマネジメントの様子を見ながらやっていくのが現実解かなぁと思っています。その点で、人事部が真にやるべきなのはチームマネジメントに対する教育とコーチングなんでしょう。

現職はまだこういう悩みとは無関係なのですが、自分が統制をかけていく側のロールなのでうまいやり方を見つけていきたいんですよね。このへん読むといいよって感じの推薦図書とか講演動画とか、もしあればTwitterやはてブ、本記事へのコメントなどで教えていただけると嬉しいです。

オープンソースソフトウェアのユーザに知っておいてほしいひとつのこと

あけましておめでとうございます。新年早々オープンソースソフトウェア関係でやねうら王さんの記事が流れてきました。同じオープンソースソフトウェアを手掛ける開発者として記載内容の大部分には賛同できないのですが、枝葉は置いといて主幹だと私が思う主張については共感する部分があり、それについて書いてみます。

yaneuraou.yaneu.com

ユーザには無償であること以上に、オープンであることに着目してほしい

さて、そのような経緯でやねうら王はOSSとして公開してきました。やねうら王は、「無償でいいからどうか使ってくれ」ではないのです。まして、「俺はプロ棋士のファンだからプロの先生に使ってもらえたらとても嬉しい」でもないのです。(そういう考えの開発者の方も確かにいらっしゃいます。私はそうではないというだけです。)

繰り返しになりますが、OSSとは、単なる無料のソフトウェア以上の意味を持ちます。

この件については、ちょっとした補助線となるストーリーがあるので紹介します。私が学生だった頃は、この手のソフトウェアをフリーソフトウェアと呼んでいました。例えば当時のフリーソフトウェア配布場所最大手のひとつであるベクターさんでも、オープンソースソフトウェアではなくてフリーソフトウェアという形で説明しています:

www.vector.co.jp

このフリー(Free)には自由という意味を持たせていました。ところがフリーには無償という意味もあり、ソフトウェアの自由を保証すること以上に、無償で手に入るソフトウェアだということが前面に出る使われ方をされるようになります。そりゃそうですよね、命名が良くない。

そこで自由であることを強調するために*1、Free/Libre and Open Source Software(FLOSS)であるとか、単にOpen Source Software(OSS)などと呼ぶようになりました。こうした経緯、すなわち無償ソフトウェア扱いされてきた体験があって、オープンソースソフトウェアを開発・公開している人は「無償ではないんだ」ということを大切にしている人が一定数いらっしゃると私は考えています。

このあたりが気になる方は、詳しいサイトがあるのでこちらの一読をおすすめします:

www.kogures.com

のでオープンソースソフトウェアを使う場合は、無償であることよりも公開されていることや始めやすいことを特徴として捉えていただけると良いかなとは思います。

オープンソースソフトウェアにはだいたい「動作の保証はしないよ」と書いてある

私は、将棋ファンに向けて「将棋ソフトを無料で公開するから是非将棋ファンの皆さん、遊んでください」と考えているような篤志家などではなく、どちらかと言えばOSSの開発にコミットメントしてくれない人たちは、 (引用者略) 有償ならともかく無償ではそういう人たちのサポートをしたくありません。

このあとに書かれているように、大抵のオープンソースソフトウェアはサポートにも手厚い傾向は実際あります。ただすべてのプロジェクトがそうではなく、そうしたプロジェクトはサポートを手厚くすることで貢献のハードルを下げるとかシェアを奪うとかの狙いがあるからそうしている、あるいは成功体験があって無意識にそうしている場合が多いはずです。ですからオープンソースソフトウェア開発者ならユーザを大切にせよというのは、少なくとも違うと思います。

これはオープンソースソフトウェアには必ず含まれている文書にも明記されています。オープンソースソフトウェアはOSSライセンスによって利用者に対してライセンスされますが、このライセンスにはだいたい、以下のような表記を頒布物に含めることを求めています:

このプログラムは有用であることを願って頒布されますが、全くの無保証 です。商業可能性の保証や特定の目的への適合性は、言外に示されたものも含め全く存在しません。詳しくはGNU 一般公衆利用許諾契約書をご覧ください。

GNU 一般公衆利用許諾契約書バージョン2でライセンスされるソフトウェアに同梱される文書


適用される法律または書面での同意によって命じられない限り、本ライセンスに基づいて頒布されるソフトウェアは、明示黙示を問わず、いかなる保証も条件もなしに「現状のまま」頒布されます。

Apache License v2でライセンスされるソフトウェアに同梱される文書


本ソフトウェアは、著作権者およびコントリビューターによって「現状のまま」提供されており、明示黙示を問わず、商業的な使用可能性、および特定の目的に対する適合性に関する暗黙の保証も含め、またそれに限定されない、いかなる保証もありません。

3条項BSDライセンスでライセンスされるソフトウェアに同梱される文書

英語で記載されていることもありますが、内容は一緒です。保証はないので自己責任で使ってくださいということです。オープンソースソフトウェアだけど保証がほしいなという場合は、サポートを提供してくれるベンダーを探すことになるかなと思います。

オープンソースソフトウェアを開発している開発者に求めるのは、間違いではないかもしれませんが機能しないことがあることは念頭に置いていただければと思います。このへんは本当にプロジェクトによる感じです。

配布されている無償ソフトウェアがオープンソースかどうかわからなくても、同梱資料を読めばオッケー

ここまで読んだ方は、なんだオープンソースソフトウェアってなんかめんどくさいんだな、とお考えかもしれません。でも実際ユーザが使うときは、ソフトウェアがオープンソースソフトウェアかどうかなんて気にしていないことがほとんどですよね。そこで、使おうとしているのが"めんどくさい"ソフトウェアであることに気づき、扱いを間違えないためのコツをお教えしましょう。それは、配布物に同梱された資料に目を通すことです。

あなたが入手したソフトウェアには十中八九、READMEとかLICENSEとかNOTICEとか、あるいはライセンス通知やエンドユーザーライセンス契約(EULA)などと名前のついたファイルが同梱されているはずです。インストーラが表示してくれる場合もあるかもしれませんね。

これらのファイルにはソフトウェアを利用する上で何に合意する必要があるか、このソフトウェアを利用するということは何を作者に許諾する必要があるか、などが書かれています。ユーザサポートについてはもちろん、商用利用時の可否についても書かれています。仮にオープンソースソフトウェアではなかったとしても、作者があなたの端末からどのような情報を得るか(!)などが書かれていることもありますので、目を通すに越したことはありません。

本当はオープンソースソフトウェアは決してめんどくさいソフトウェアではなく、ソフトウェアの自由と発展を考えて作られてきた運用であり文化だというのも伝えたいことではありますが、それは別の機会に譲ります。

まとめ

オープンソースソフトウェアのユーザには、とりあえず同梱の資料には目を通しましょうということを知っていただきたいです。そこにはユーザが知るべきこと、作者が伝えたいこと、双方の権利を守るための重要な通知が含まれています。

また無償であることを前面に出すことは、ソフトウェアの自由と発展を考えて作られてきたオープンソースソフトウェアの歴史、あるいは開発者個人の経験から、オープンソースソフトウェア作者にはあまり良い印象がないかもしれません。公開されていることや始めやすいことに感謝し、ブログで紹介するとか感想を伝えるとかの形で貢献(還元)することもご検討いただければと思います。

とはいえオープンソースソフトウェアとひとくくりに議論するには、この世のプロジェクトは多すぎます。つまり、私が書いたことを気にしない、あるいは他のことを大切にしている開発者も多くいるでしょう。ソフトウェアの向こう側にはその作者やメンテナーがいるのだとご理解いただき、その人がどんな人かに関心を持っていただくことが、そのソフトウェアを真の意味で大切にする行為なのかもしれません。

*1:コピーレフトの件もあるけど割愛

はたらく人には自己成長と健康のためにコーチングがおすすめ

人の一生は重荷を負うて遠き道を行くがごとし、とは徳川家康の言葉らしいですね。この記事では人生という旅路を振り返ること無く歩んでしまうと自己成長と健康に良くないので、ちょいちょい振り返りをするといいですよ、そのためにはコーチングというものを知っておくと捗りますよ。という話をします。

エンジニアにとって振り返りというとポストモーテムのイメージがあるかもしれませんが、今回対象にしているのは個人の活動に対する組織的な振り返りのことで、人材育成の文脈でフィードバックと呼ばれるものです。目標管理(MBO-S)とかOKRとかもこれに含まれます。

読み手としてはマネジメントも想定しますが、どちらかと言えば新社会人ないし組織運営の観点を補強したい方に向けています。コーチングは「コーチングのしかた」という技法も重要ですが「コーチングというものがあるのだ」という認知もまた自己成長と健康に役立つと考えています。よってコーチングを受ける側の新社会人の方にも役立つでしょう。

フィードバックとは教えることと答えを出す助けをすること

まずフィードバックを定義しましょう。私は中原先生の定義が好きでよく使っています。「Feedback = Teaching + Coaching」というもので、明確な答えがあることを教えるティーチングと、自ら答えを見出すことを助けるコーチングをあわせてフィードバックと呼ぶわけです。

ティーチングは学習機会を提供することで、例えば業務や事業領域についての知識を伝えることを指します。例えばJavaの書き方とか、サイバーセキュリティ教育とか、PRレビューのやり方とか、社史であるとか、こうした学習機会の提供は多くの職場でやっていると思います。特にオンボーディング(入社時教育)で頻出のイメージがあります。ティーチングは答えがあるものを扱うため、理解度を試験で確認することができます。

コーチングは逆に、答えのないものを扱います。前述の書籍から説明を引用します:

コーチングを最も簡潔に要約してしまえば「他者の目的達成を支援する技術」です。それは、育成する相手に「現状」と「めざすべきゴール」のギャップを、第三者からの「問いかけ」によって意識化させ、振り返り(リフレクション/内省)を促し、「今後、何を為していくべきか」の行動指針や行動計画をともに作っていく技術です。

(フィードバック入門 耳の痛いことを伝えて部下と職場を立て直す技術 第一章)

問いかけを受けて足を止め後ろを振り返ることが、旅路には有効に作用することも多いんですね。これ単体でも掘り下げて話せるような深い話題ですが、今回は話に具体性を持たせるため、メジャーなコーチングの場である1on1に絞って話していきます。すなわち職場において部下が、上司や同僚による「現状と目指すべきゴールのギャップ」についての問いかけを受けて振り返りを行い、今後の行動指針や行動計画をともに作っていく場面を想定します。目標管理やOKRの現場ではよくある姿ですね。

1on1の真の価値、あるいはなぜ1on1に準備が必要なのか

皆さんは1on1を定期的に開催していますでしょうか?筆者としては、月1度でいいのでぜひ定期的に1on1をしてほしいと思っています。相手としては自分のロールやフィールドに詳しい人がベストですが、そうでなくとも傾聴ができて問題解決プロセスにある程度明るい方であれば良いと思います。周りに適当な方が見つからない場合は、フィードバックに興味がある同僚を見つけて相互にフィードバックしあう形が始めやすいかもしれません。

1on1のよくある失敗パターンは、進捗共有と雑談だけして終わるパターンと、「今日は話すことがないのでスキップします!」パターンです。1on1をコーチングの場として、すなわち「自分で見つけなければならない答えを見出すヒントを得るための場」として見たときに、まず必要なのが「答えのない問い」です。事前に問いを用意して失敗パターンを回避しましょう。すでに心のなかにあるならそれを持っていけばいいですが、ぱっと思いつかない場合は次のように自問自答してみます:

  • 自分の働き方や貢献に満足できていないことはあるか?
  • どのようになりたい、何をもって覚えられたいという想いに反した現状が目の前に横たわっているか?
  • 3ヶ月前、6ヶ月前、1年前の自分といまの自分を比べたときに、胸を張って成長したと言えるか?

問いが見つかればこれを分解し、自分で解決できることを除いていきます。例えば自分の貢献が足りないなと気づいて分析した結果、睡眠が足りないので朝会に遅刻することが多いという問題を見つけたとしましょう。このとき「早寝早起きする」のがすでに実行可能なのであれば、相談は必要ないでしょう。しかし「夜遅くまで業務が入ってしまう」「ストレスでなかなか寝付けない」などの事実があるなら、これは1on1に持っていく価値がありそうです。

自分で解決できない問いをいくつか用意したら、1on1が始まる前にこれを議事録に書いて相手に共有しましょう。相手は相談の内容に応じて準備するでしょうし、自分もなにが邪魔して「自分で解決できない問い」になっているのかを考える時間ができます。こうした準備がコーチングにおける傾聴と振り返りを可能にします。

コーチングが健康に効く理由

まずコーチングには承認と呼ばれる、あなたの挑戦やできていることを認めるプロセスがあります。これが自己肯定感の醸成につながるため、新しいことに挑戦していてまとまった成果が出にくい時期には特に、コーチングを受ける側のメンタルを守るすべとして期待ができます。ある程度経験を積んでいい意味で鈍感になれば、このようなフィードバックがなくても自尊心を維持できることもあるとは思いますが、特に新卒採用をするときには組織的にコーチングを行う体制が必要になるでしょう。

次に、これは人によるとは思いますが、少なくとも自分は身体の過負荷に対するサインって普通に生活してたらけっこう見逃すんですよ。ので「最近どう?元気?」と聞かれて「いやー全然ダメですね」と答えることはあまりありません。サインに自分で気づいたころにはもう戻れないところまで来ていたりします。

つまり「あっ、このまま行くとヤバいな」と気づくには才能や経験が必要なんですね。よって朝会や飲み会のような「最近どう?」ではなく、1on1という問題を意識的に俎上に載せる場が同僚の健康を守ることに繋がると考えています。

コーチングする側への手引き

もしあなたがコーチングをする側なら、ひとつルールを定めましょう。それは「進捗共有はするな!」です。進捗共有は朝会のようなチームに開かれた定例で充分に行われるべきだからです。不純物は取り除きましょう。

また1on1は業務上の問題を相談する場でもないので、「1on1が開催されるまで問題をしまっておく」ような動きが見えた場合もこれをやめてもらう必要があります。業務上の問題はリアルタイムにチーム内あるいはエスカレーションをもって相談するべきです。マネジメントが忙しそうだとなかなか報連相できない、という方は一定数いらっしゃるものなので、口を酸っぱくして「いつでも来てね!」というスタンスを伝えていく必要があります。自分は以下のルールをオフィスのキュービクルに貼っていました(とあるネットスラングの改変です)。

1. Your boss always has time to talk with you.
2. If your boss seems busy and hard to talk with, see the rule number 1. 

そして自分では解決できない問いだけが1on1の場に残ったとき、はじめて傾聴や質問、承認といったコーチングを行えるようになります。その問いはおそらくコーチングをする側であるあなたにも答えられないものでしょう。もしティーチングが有効そうならコーチングからさっと切り替えてしまってもいいですが、まずは傾聴することを勧めます。

まとめ

コーチングは自己成長と健康のために活用できるテクニックです。受ける側としてもする側としても、きっと学べることがあると思うので挑戦してみてください。特に準備の有無で体験が大きく変わりますので、1on1にマンネリを感じている方もテコ入れの一環としてコーチングを取り入れてみてほしいです。1on1をやっていないという方は、これを機に取り入れてみてはいかがでしょうか。

JVMにおけるServiceLoaderとjavaagent

本エントリーはJava Advent Calendarシリーズ2の19日目です。

qiita.com

OpenTelemetryの自動計装機能を調べていたら、 ServiceLoader とjavaagentを活用した実装になっていました。これ前知識がないと魔法に見えるやつだなって思ったのですが、 ServiceLoader はともかくjavaagentなんてなかなか使わないだろうなぁと思ったので簡単な説明を書いてみます。

ServiceLoaderはJVM標準のDI技術

ServiceLoader とはJava 1.6から提供されている仕組みです。ので現代で使われているJVMでは必ず使える機能のひとつですね。

サービスとは、既知のインタフェースおよびクラス(通常は抽象クラス)のセットです。サービス・プロバイダとは、特定のサービスの実装です。通常、プロバイダのクラスによって、サービス自体に定義されているクラスのインタフェースとサブクラスが実装されます。 https://docs.oracle.com/javase/jp/8/docs/api/java/util/ServiceLoader.html

ServiceLoader を端的に説明すると、Javaプログラマに通りのいい表現としては、DIのようなものです。このインタフェースを実装してるクラスの実装がほしいよ〜、というコードを書いておくと、それをCLASSPATHから探して渡してくれるんです。

class よくあるDI {
  @Inject
  よくあるDI(Collection<適当なインタフェース> 引数) {
    // 指定したインタフェースの実装をコンストラクタに渡してくれる
  }
}
class ServiceLoader動作イメージ {
  void method() {
    ServiceLoader serviceLoader = ServiceLoader.load(適当なインタフェース.class)
    serviceLoader.iterator() // 指定したインタフェースの実装をイテレートするIteratorを返してくれる
  }
}

なお実装のインスタンスはデフォルトコンストラクタによって作成されます。このため複雑なインスタンスを作ることはできませんが、特定の処理を開始する起点としては充分なことが多いです。

例えばログファサードライブラリであるSLF4Jでは、この機能を使ってバインディングと呼ばれるインタフェースの実装を探しています。SLF4JはLog4j2やLogbackなどのロギングライブラリに処理を委譲しますが、このときに「Log4j2が使えるのか、Logbackが使えるのか?」を判断するのにService Loaderを使っているわけです。

OpenTelemetryでは InstrumentationModule の実装を探すのに ServiceLoader を使っています。何からデータを集めたいのか(RDB、gRPC、HTTPサーバなどなど)に応じたライブラリをCLASSPATHに入れておけば、起動時に ServiceLoader がよしなに必要なコードを拾い集めて初期化してくれる、そういうコードが簡単に書けるわけです。業務ロジック側では、それらのライブラリの存在すら認識する必要はありません。

ちなみに ServiceLoader でインスタンス化される側のコードを書く場合、ほぼセットで利用するのがGoogleのAuto Serviceです。Service Loaderでインスタンス化される側のコードを書く際に「Service Loaderに実装の居場所を教えるためのファイル」を作成する必要があるのですが、これをアノテーションから自動的に生成してくれます。便利ですね。

main関数以前の処理を実現するjavaagent

次にjavaagentの話をします。皆さんがJavaプログラマであれば、 public static void main(String[] args) な関数を一度は書いたことがあるでしょう。え? public static なんて今ドキ書かないって?2023年ですね。

ところでJVMはこの main 関数を実行する前、何をしているのでしょうか。メモリの確保とか、GCの準備とか、 ClassLoader の作成とか、プロセス引数から String[] を作るとか、色々やってそうですよね。そこで自分のコードを動かせたら最高じゃないですか?例えば ClassLoader 作成に一枚噛めるということは、これは事実上JVMが利用するほぼすべてのクラスのロードに介入して改変できることを意味しています。実際OpenTelemetryではメソッドの実装に介入してメソッド実行時に引数を差し替えるなんて芸当をしています。

実際こういう実装の差し替えとかやりはじめると、考慮することが結構あって大変なんですけどね。bytecode manipilationと呼ばれる分野で、筆者の好物のひとつでもあります。

さてjavaagentの話に戻ります。javaagentは java.lang.instrument パッケージに説明があります。javaagentにはそのままズバリの premain という関数を実装すればよさそうです。なるほど、 main 関数の前に呼び出されそうな名前ですね。さらにクラス定義を差し替えるためのメソッドなども提供されていて、いかにもJVMをハックするためのAPIという感じです。

のでひとつ注意点があって、javaagentは使うとどうしてもJVM起動速度にペナルティがかかります。迅速に起動を終わらせてリクエストを受け付けられるようにしたいんだという場合、javaagentの利用を避けて手で各種初期化を行うことも検討せざるを得ない……ということもあるでしょう。

以上でざっくりした説明を終わります。OpenTelemetryは ServiceLoader とjavaagentの合わせ技で、javaagentのCLASSPATHに入っているインタフェースの実装を main 関数実行前に使うことで、 ClassLoader に手を加えて計測対象モジュールに対して自動的に初期化を行っていました。一見便利ですがjavaagentの持つ速度的なペナルティや、javaagentのCLASSPATHが大きくなりがちという問題も潜んでいます。ご利用は計画的に。