スタッフエンジニア マネジメントを超えるリーダーシップ

先日原著の感想文を書きましたが、日経BPさんから増井雄一郎さんの監修・解説で日本語版が発売されました。実物を見るまで半信半疑でしたが私のインタビューも掲載いただいています。

オンラインでも書籍に連動した記事が掲載されています。

bookplus.nikkei.com

type.jp

また、原著の紹介でも書いた通り、本書の後半部分は各社のエンジニアのインタビューになっているのですが、一部のインタビューの内容を抜粋したものが日経クロステックさんに掲載されています。どんな内容か気になっている方はまずはこちらを参照されるとよいのではないかと思います。

xtech.nikkei.com

このような素晴らしい書籍に私のインタビューを掲載いただくなど恐れ多いことですが、少しでもどなたかの参考になりましたら幸いです。自分自身もこれまでのキャリアの振り返りと今後の身の振り方について改めて考える良い機会になりました。大変貴重な機会をいただきありがとうございました。

Staff Engineer: Leadership beyond the management track

近々日本語版も発売されるこちらの書籍ですが、現職での自分のタイトルが(今年の3月までは)スタッフエンジニアだったということもあり、以下の記事にも出ている通り、本書の日本語版に収録するためのインタビューをしていただいたのですが、インタビューを受けるにあたって原著の内容を把握しておいた方がいいだろうということでざっと目を通してみていました。

bookplus.nikkei.com

前半はスタッフエンジニアについての解説、後半は海外の有名テック企業のスタッフエンジニアたちのインタビューという構成になっています。日本だとスタッフエンジニアという呼称はあまり一般的ではないと思いますが、要はソフトウェアエンジニアの上級職で、本書でも言及されているように一言でスタッフエンジニアと言ってもいくつかのタイプに分類されます。アーキテクトやテックリードはもちろんですが、チームリーダーやプロジェクトリーダーといった役割で働いているソフトウェアエンジニアの方もこの書籍で扱っているスタッフエンジニアの範囲に含まれるのではないかと思います。

前半部分は割とあっさりめではあるのですが、そもそもスタッフエンジニアとは何なのか、スタッフエンジニアとして働く際のアドバイス、スタッフエンジニアになるにはどうすればよいのか?といった内容で、自分自身もスタッフエンジニアの役割について認識を整理することができましたし、現実的な(身も蓋もない)アドバイスもあったりで面白かったです。

後半のインタビュー部分に関しては、当然のことながら会社やその方の状況によって言っていることは様々なのですが(同じような立場の方は同じようなことを言っていたりもします)、多くのインタビューが掲載されておりインタビュイーのバリエーションも豊富なので、特定の意見に偏らずバランスが取れているのではないかと思います。自分の立場に重なるインタビューもあれば、自分とは全く状況が異なる方のインタビューを読むのも参考になるでしょう。

結局のところ、スタッフエンジニアとして働くということは「一定以上に成長した企業のエンジニア組織の中で働く選択をする」ということを意味するわけですが、ソフトウェアエンジニアとしての将来のキャリアパスについて考えている方、すでにスタッフエンジニアもしくはタイトルは違えど同等の役割で働いている方にとっては何らかのヒントが得られる書籍なのではないかと思います。また、逆にある程度以上の規模のエンジニア組織を運用する側の立場の方も上級エンジニアの必要性や使い所を学ぶことができるのではないかと思います。

日本語版は5月発売だそうです。こちらには日本人の原著の内容に加えて日本人スタッフエンジニアのインタビューも収録されているとのことですが、まだ実物を見ていないので本当に私のインタビューが収録されているのかどうかはわかりません!

GitBucket 4.39.0をリリースしました

Scalaで実装されたオープンソースのGitサーバ、GitBucket 4.39.0をリリースしました。

https://github.com/takezoe/gitbucket/releases/tag/4.39.0

カスタムフィールドでenum型をサポート

イシュー、プルリクエストのカスタムフィールドで複数の選択肢から値を選択可能なenum型をサポートしました。

カンマ区切りで選択肢を登録しておくとイシュー、プルリクエストの作成、編集時にプルダウンリストから値を選択できます。

巨大なdiffはデフォルトでは非表示に

差分が巨大な場合、画面表示に時間がかかるという問題を解消するため、1000行以上の差分があるファイルはデフォルトではdiffを表示しないようにしました。必要に応じてShow diffリンクをクリックすることでdiffを表示できます。

複数台構成で動作させるためのオプションを追加

GitBucketを複数台構成で動作させる場合に必要な以下のオプションを実験的に追加しました。

  • --disable_news_feed
  • --disable_cache

詳細については以下の記事も参照してください。

takezoe.hatenablog.com

ただし、これらのオプションは実験的なものであり、GitBucketが正式に複数台構成での動作をサポートしたわけではないという点にご注意ください。

今回のバージョンではこの他にもWeb APIを中心に様々なバグフィックスを行っています。詳細についてはIssueの一覧をご覧ください。

AirSpecのテストケースをIntelliJ上で実行するプラグインを作った

仕事でAirSpecというScala用のテスティングフレームワークを使っているのですが、特定のテストケースをIntelliJ上で実行できないのが不便だなーと前々から思っていたのでプラグインを作ってみました。IntelliJScalaプラグインやZIOプラグインのテストサポートを参考にしました。

github.com

JetBrainsのプラグインリポジトリにはpublishしていませんが、GitHubのリリースページからアーカイブをダウンロードしてインストールできます。

github.com

インストールするとこんな感じでテストケースにマーカーが表示されるようになり…

クリックすると実行できます。

テスト結果のビューからテストケースにジャンプする機能は実装できていません。テストケースのソースコード上の位置を取得する必要があるのですが、良い方法が思いつかず…。

IntelliJ上でテストを実行するとテストランナー上でテストが実行されるのですが、IntelliJはテストランナーが標準出力に出力したTeamCityのサービスメッセージ形式のテキストから情報を取得しているようです。今回作成したプラグインでは若干アドホックな方法でAirSpec自体に含まれているテストランナーを流用しつつメッセージを出力する機能を追加しています。

www.jetbrains.com

いくつか細かい問題はあるものの、ひとまず自分で使うには十分なものができたので満足です。

ScalaでIntelliJプラグインを作ってみる

IntelliJプラグインを作りたいなと思うものがあったのですが、Scala開発用のものだし、JetBrainsからScalaプラグインを開発するためのsbt-idea-pluginというsbtプラグインも提供されているようなので折角なのでScalaIntelliJプラグインを作る方法を調べてみました。

github.com

上記のsbtプラグインのREADMEに書かれているのですが、GitHub上でこのsbtプラグインを使用したサンプルプロジェクトのテンプレートが公開されています。

github.com

このテンプレートリポジトリからリポジトリを作成し、cloneしてきてIntelliJで開くとプラグインの開発を行うことができます。

が、このテンプレートリポジトリはあまりメンテされていないようで、sbtやIntelliJのバージョンなど色々古かったのでアップグレードするためのプルリクエストを出してみました。以降はこの修正を取り込んだものとして話を進めます。

github.com

プラグインの動作を確認するには sbt runIDE を実行します。すると以下のようにサンプルプラグインがインストールされたIntelliJが起動します。

このサンプルプラグインはToolsメニューに「Action Basics Plugin: Pop Dialog Action」というメニューアイテムを追加しており、クリックすると以下のようなダイアログが表示されます。

プラグインの配布用アーカイブを作成するには sbt packageArtifactZip を実行します。するとtargetディレクトリにMyAwesomeFramework-0.0.1-SNAPSHOT.zipというファイルが作成されますので、プラグインマネージャで「Install Plugin from Disk」を選択し、このファイルを選択することでプラグインをインストールできます。

sbt-idea-pluginはこの他にも作成したプラグインをJetBrainsのプラグインレジストリにpublishするためのタスクなど様々なタスクを提供しています。

プロジェクトの構造ですが、src/main/resources/META-INFにplugin.xmlというファイルがあり、このファイルでプラグインの拡張ポイントに対して拡張を宣言し、指定したクラスを実装していくという感じのようです。

<idea-plugin>
    <id>me.and.co.my.awesome.framework</id>
    <name>My Awesome Framework</name>
    <version>0.0.1-SNAPSHOT</version>
    <vendor>Me and Co</vendor>

    <description>A new plugin for IntelliJ platform written in Scala and built with SBT</description>

    <idea-version since-build="203.0"/>

    <depends>com.intellij.modules.platform</depends>
    <depends>com.intellij.properties</depends>

    <resource-bundle>messages.SamplePluginBundle</resource-bundle>

    <actions>
        <action id="org.jetbrains.scala.samples.actions.PopupDialogAction"
                class="org.jetbrains.scala.samples.actions.PopupDialogAction">
            <add-to-group group-id="ToolsMenu" anchor="first"/>
        </action>
    </actions>

    <applicationListeners>
        <listener class="org.jetbrains.scala.samples.listeners.FileOpenedListener" topic="com.intellij.openapi.fileEditor.FileEditorManagerListener"/>
    </applicationListeners>

    <extensions defaultExtensionNs="com.intellij">
        <notificationGroup displayType="BALLOON" id="My Plugin Notification" />
        <toolWindow factoryClass="org.jetbrains.scala.samples.ui.MyToolWindowFactory" id="MyToolWindow" anchor="bottom"/>
        <completion.contributor implementationClass="org.jetbrains.scala.samples.completion.SimpleCompletionContributor" language="Properties"/>
    </extensions>

</idea-plugin>

ScalaでのIntelliJプラグインの開発については英語でもあまり情報がありませんが、IntelliJScalaプラグインが参考になります。

github.com

また、ZIOでIntelliJプラグインを開発しており、こちらも参考になるかもしれません。

github.com

GitBucketを複数台構成で動かす方法を考えてみる

GitBucketはもともと学習用途やスモールチーム用と割り切っていたことと、またGitの絡みでRDBだけでなくファイルシステムが切っても切り離せないこともあり、これまで複数台構成で動かすことは想定していなかったのですが、Giteaでは共有ファイルシステムを使って複数台での稼働を一応サポートしているようなのでGitBucketでもできないかなと思い試してみました。

github.com

具体的に障害になりそうなのは

それぞれ具体的に見ていきます。

RDB

GitBucketはデフォルトでは組み込みモードのH2を使用しますが、外部DBとしてMySQL/MariaDBPostgreSQLをサポートしていますので、各GitBucketインスタンスを外部DBに接続するよう設定すればOKです。

ただし、GitBucketはアップグレード時に自動でDBのマイグレーションを行う機能があるため、この点だけは留意が必要です。多くのケースでは普通に各インスタンスをローリングで更新し、最初に更新したインスタンスにDBマイグレーションを行わせるでうまくいくと思うのですが、場合によってはスキーマの不一致によって未アップデートのインスタンスでエラーになってしまう可能性があります。安全を考えるといったんサービスを停止した状態でアップグレードした方がよさそうです。

HTTPセッション

GitBucketはServletのHTTPセッションを使用していますので、複数台構成にする際はアプリケーションサーバ側でセッションをレプリケーションするように設定しておく必要があります。ここは各アプリケーションサーバに依存する部分ですが、GitBucketのスタンドアロンモードであれば --save_sessions というオプションでセッション情報をディスクにシリアライズすることができますので、このディレクトリを共有することで複数サーバでセッションを共有できます。

ただ、将来的にはHTTPセッションに依存しないようにした方がよいのかもしれません。

キャッシュ

GitBucketは取得するのに重い処理が必要な一部のGitリポジトリ関連の情報をメモリ上にキャッシュしています。このキャッシュの中にはgit pushされた際に破棄する必要があるものも含まれているのですが、複数台構成にするとリクエストを受け付けたサーバ以外ではキャッシュが破棄されず古い情報を返し続けてしまいます。

とりあえず --disable_cache というオプションを追加してキャッシュ自体を使わないようにできるようにしてみましたが、将来的にはmemcachedに対応してもよいかもしれません。

ローカルファイル

GitBucketはGitリポジトリや添付ファイルなどをローカルファイルシステムに保存しています。ここはGiteaを倣って共有ファイルシステムを使います。以下のディレクトリ(要するにpluginsディレクトリ以外)を共有すれば大丈夫だと思います。

  • <GITBUCKET_HOME>/repositories
  • <GITBUCKET_HOME>/data
  • <GITBUCKET_HOME>/sessions
  • <GITBUCKET_HOME>/tmp

JGitはS3をサポートしているので、将来的にはローカルファイルシステムの代わりにS3を使えるようにするのもありかもしれませんが、GitBucketをイントラで立てるようなケースだとAWSなどは使えない可能性もあると思うのでユースケースに合うかは微妙な気もしています。

また、GitBucketにはもう1つローカルファイルシステムに依存する機能として、ダッシュボードにアクティビティログを表示するという機能があります。アクティビティログは<GITBUCKET_HOME>/activity.logに書かれており、このログを加工してダッシュボードに表示しているのですが、当然各サーバは自分でリクエストを受け付けた分のログしか持っていません。そこでひとまずダッシュボードにアクティビティログを表示しないようにする --disable_news_feed というオプションを追加しました。

もともとアクティビティログはRDBに入れていたものをサイズが大きくなりすぎるのでファイルに移行したという経緯があるのですが、それが裏目に出てしまいました。将来的にはログは各サーバに書きつつ、表示に必要な分のデータだけRDBに入れるといった工夫が必要かもしれません。

プラグイン

複数台構成での動作を想定していない一部のプラグイン(CIプラグインなど)は正しく動作しません。これはもう仕方ないところです。

また、使用するプラグインによっては追加で共有しないといけないディレクトリがあります。たとえばGistプラグイン<GITBUCKET_HOME>/gistを使用しますのでこのディレクトリも共有する必要があります。

まとめ

こんな感じでやっつけ感はあるものの、やろうと思えば複数台構成にすることはできそうです。ただ、実際の運用を考えるとバージョンアップ時のデータベースのマイグレーションは問題がありそうです。

また、やはりGitリポジトリを共有ファイルシステムに置くとなるとそこがスケールの限界になります。スケールアウトを考えるとGitリポジトリのシャーディングは必須になるかと思いますが、GitBucketは小規模での利用を想定しているという点については変わりありませんので、まあそこまでは頑張らなくてもいいかなというところです。

2022年の振り返り

年末なので今年も毎年恒例の振り返りをしてみました。

仕事関係

前半は去年からやっていたPrestoのバージョンアップを主にやっていました。入念な準備と万全の移行計画のおかげで切り戻しが必要になるようなトラブルもなく非常にスムーズな移行でした。この移行の経験はDBTestというVLDB併催のカンファレンスで発表をさせていただきました。COVIDの状況も鑑みてリモートでの発表とさせていただいたのですがとても貴重な経験をさせていただきました。

takezoe.hatenablog.com

その他ではPrestoのバージョンアップと並行してData Lineage関連の実装をしていたり、後半はPrestoのリソース管理周りの修正などをやっていたのですが、最後の最後で突如予想外の状況に追い込まれてしまい色々なことを考えさせられる年の瀬になりました。

OSS関連

今年もOSS活動はあまり活発にはできなかったです。

仕事の絡みでTrinoにいくつかPRを投げて取り込んでもらったり、TDのScalaアプリケーションで使用しているAirframeの改善をしたりはしていましたが、それ以外だとGitBucketでイシューやプルリクエストでのカスタム属性のサポートや複数担当者をアサインできるようにするなどの機能追加をしたり、ScalatraのScala3対応版をリリースしたり、個人で作っているScalaライブラリをScala3に対応させたりしていたくらいで新しいものを作ったりとかはできなかったです。

takezoe.hatenablog.com

takezoe.hatenablog.com

ScalatraのScala3対応はThis week in Scalaで取り上げてもらったり、いろいろ反応貰えてよかったですね。

medium.com

英語学習

社で受けていたオンライン英会話の受講資格を喪失してしまったので、以前個人で受講していたDMM英会話を再開しました。すでに英語学習というよりは仕事以外のことを話す気分転換みたいなところがありますが…。日によっては仕事で英語を喋らない日もあるので毎日短時間でも話す時間を作っておいた方がいいかなということで。

今年は英語での読書はあまりできなかったです。スコット・ギャロウェイさんのPost Coronaを読んだのと、オライリーのData Governance: The Definitive Guideを読んだくらいでしょうか。ちょこちょこと論文を読んだりはしていましたが…。

takezoe.hatenablog.com

takezoe.hatenablog.com

それと、3年ぶりくらいにTOEICを受けてみました。リスニングが全然わからんかったり、リーディングも今回も最後までいかなかったのでダメダメだったなーと思ってたんですが、結果は前回とまったく同じ点数だったのでこれが現在の自分の英語力ということなのでしょう。なんだかんだ言ってもTOEICよくできてるなと思いました。

生活周り

夏場にエアコンが水漏れしまくったのが厳しかったです。去年も水漏れして設置時の業者さんに断熱をやり直してもらったのですが、今年も水漏れしてきたり、さらに去年は大丈夫だった別の部屋のエアコン(こちらは引越し後に買い増したので別の業者さんに設置してもらった)からも水漏れしてきたりで複数の業者さんを何度も呼んで見てもらう羽目になったのですが、結局直ったのが確認できる前に夏が終わってしまったので来年に持ち越しに…。来年は大丈夫だろうか…。

家電周りでは8年半使った自宅のMacBook ProをついにM2 MacBook Airに買い換えました。予算の関係でスペックは妥協してAirにしたのですが、それでも以前のマシンと比べてめちゃくちゃ快適になりました。MacBook Proは14インチでも結構大きくて持ち運びが大変そうですし、自分の用途ではこのスペックのAirで十分だったかなと思います。

takezoe.hatenablog.com

MacBook以外にも昨年引っ越した際に揃えていなかった家具を買い足したり、家電を買い替えたりなどで去年から引き続きかなりマネーを失ってしまった一年でした。

まとめ

リモートワークで全然運動してないからというのもあると思いますが、今年は特に後半あたりからずっと体調が悪い状態が続いている感じで加齢を感じる一年でした。ここ数年、毎年言ってる気がしますがさすがに今年はヤバさを感じてきたので来年は少し真面目に体を動かすようにしようと思います。そして15年ぶりにプレミアリーグでクリスマスを首位で向かえたアーセナルには19年ぶりの優勝目指して頑張って欲しいです。