Kengo's blog

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

2024年に読んでよかった本

医療関係

「看護覚え書」ナイチンゲールが書いた本ということで、初心を理解するのに良いかなと思って購入しました。超人ナイチンゲール (シリーズ ケアをひらく)と合わせて、現代看護の成り立ちみたいなものに触れる良い機会になりました。システム実装やドメイン理解の役に立ったかというとNOですが、看護と聞いて自分が連想するものがとても狭いのだということはよく理解できました。

エンジニアリング

「情報セキュリティの敗北史」セキュリティがとても人間のウェットな部分をクローズアップするテーマなんだということを再認識した本です。マイクロソフト社のかつての過ちとか、様々な立場の人間が利益を最大化するために行動した結果として脆弱性が”活用”されているとか、ぱっと見たときに良さそうな選択肢(例えばバグバウンティ)が一歩引いてみるとそうでもないとか。

自分は性善説や理想論で動きがちな人間なので、改めて情報セキュリティめんどくせぇ奥が深いなぁと思いました。今後もちょくちょく振り返って手に取る本になりそうです。

「本質から考え行動する科学技術者倫理」 この春に放送大学の講義を受講しまして、残念ながら単位取得までは行かなかったんですが、この科学技術者倫理について学ぶ良い機会となりました。倫理というと高校の授業でやるやつですが、自分の高校の教師は歳を食ってある程度フラットに物事が見られるようになった今の自分から見ても疑いなくひどかったので、倫理についてはエッセンスも何もキャッチアップできていなかったんですよね。

失敗学の繋がりで回転ドアの話とかチャレンジャー号事件の話とかは知っていたのですが、AI技術の進展を踏まえた議論などは初めて見たので、きちんと学び直したいなと思い放送大学の講義資料とは別にこの教科書を購入しました。スタートアップで社会課題の解決にもがいていると前人未踏の問題領域に踏み込むことは多く、多かれ少なかれ倫理的判断が求められるシーンはきっとあると思うので、情報システムで社会に切り込むスタートアップに在籍しているタイミングでこの本に出会えて良かったと思います。

「一級建築士矩子と考える危ないデザイン」は単行本を購読しているマンガ「一級建築士矩子の設計思考」のスピンオフ?と言いますか、マンガのキャラクタを拝借して危ないデザインを紹介するというものです。元のマンガを購読していなくても楽しめますし、建築関係なくユーザインタフェースの設計・開発をするITエンジニアには広くおすすめです。

個人的には自分の母校のデザインがかなり危なかったのだなぁということに気づき、ちょっと怖くなりました。1階の庇に柵がついてないのに2階から乗ることができたんですよね。当時はそういうものだろうと思っていましたが、改めて考えると悪いデザインだったと思います。日頃の周囲を見る目が変わる1冊でした。

その他

建築好きなのでちょくちょく間取りや設計、建築についての本や雑誌を買っているのですが、今年は商店建築に加えてこちらの「お宿図鑑」を買いました。スケッチがとても美しく細かくて、自分が現地に赴いても発見できないだろうなと確信できる内容盛りだくさんでした。

掲載されているお宿はおおむね子連れで行ける宿というか、いずれ親と行きたい宿という風情ですね。この本を読んで、家族でゆっくりとした時間を楽しめる未来がより楽しみになりました。

Kotlinからお手製Javaライブラリを呼んでる人のためのJSpecify入門

これはKotlin Advent Calendar 20242日目の記事です。前日は id:take7010 さんの「KotlinとOpenAI APIで領収書の情報を抽出する」でした。

先日Kotlin愛好会オンラインでJSpecify入門について話しました。JSpecifyについては3年前のJJUG CCCでも話しましたが、この夏にv1.0.0が出たので改めて知っていただければと思っています。

speakerdeck.com

JSpecifyの何が嬉しいか

Kotlinの世界に閉じた実装を行っていると、JSpecifyのアノテーションを使う機会はほぼないはずです。JSpecifyが嬉しいのはKotlinからJavaを呼ぶ場合です。 Javaライブラリ側の引数や戻り値をJSpecifyアノテーションで修飾しておくと、null-safetyなKotlinの引数や戻り値と同じように扱えます。 今まではKotlinコンパイラが警告を吐くだけでしたが、Kotlin 2.1.0からエラーとして扱われるようになりました。

どこから始めればいいか

nullableな戻り値を @Nullable で修飾するところから始めましょう。ランタイムの NullPointerException を防ぐために最も重要なアノテーションだと思います。

次点が List<T> のようなGenericsだと思いますが、このへんはけっこう複雑なのでドキュメントに目を通しておきましょう。

なおすべてのnullableな型を修飾したと言えるようになったら、パッケージを @NullMarked で修飾しておけば「 @Nullable が無いところは全てnot-null」だということをコンパイラに伝えられます。 nullableな値を持ち回らないようなコードを書いている場合は便利かもしれません。

Java と Kotlin を安全に橋渡ししよう

Kotlinの強みのひとつとして「Javaの資産を活用できる」のが挙げられますが、そのためにはJavaになくてKotlinにある機能をどう扱うかを検討しなければなりません。 null安全はそのうちのひとつですが、JSpecifyのv1.0.0リリースによってある程度標準的な解決策が用意されたと言ってよいでしょう。 KotlinをJavaで書かれたライブラリやフレームワークと組み合わせて使っている方は、ぜひ試してみてください。

Kotlin Advent Calendar 2024の明日の記事は、 id:tsukakei1012 さんの「Exposedについて①」の予定です。

情報処理安全確保支援士になりました

今月より晴れて、情報処理安全確保支援士(登録番号028693)を名乗れるようになりました。昨年取った医療情報技師と合わせて、医療情報システムの情報処理安全についてのプロフェッショナルであることをある程度の説得力を持って説明できるようになったと考えています。

とはいえ資格をとったら急に仕事ができるようになるかというとンなわけないので、より複雑な課題解決ができるように継続して学んでいきます。とりあえず今日は、なぜセキュリティなのかと、今後の抱負をここにまとめておこうと考えた次第です。

なぜ今セキュリティなのか

私はいままでCDワークフロー改善であるとか、ログ管理含めた保守性であるとか、エンタープライズアプリケーションの性能改善であるとか、どちらかと言えばシステム実装に寄った非機能要件を多く見てきました。

一応OSSライセンスの管理やビルドスクリプト改善から発展して、OSS脆弱性への対応も経験してはいるのですが、セキュリティについてはそこまで専門でやってこなかったというのが正直なところです。

 

セキュリティについて学ぶ起点となったのは2021年末、Log4Shellの対応です。GitHubで突如公開されたコミットをもとに修正内容の把握や自社サービスへの影響などを短期間に特定して全社的になんとかする体験をし、セキュリティが「OSSエンジニアとしての経験とベストプラクティスを現場の運用に落とし込むという自身の関心領域とが交差する場」でもあるのだという発見に繋がりました。

そして転職後、医療情報システムの安全管理に関するガイドラインについて学んだり、サイバーセキュリティが医療機関等の管理者に対する義務化されたりして、自然とセキュリティについて学ぶ時間が増えたというのが「なぜセキュリティなのか」への回答というところです。端的に言うと医療業界的にニーズが高いのと、自分のWILLやCANとマッチしたというところですね。

情報処理安全確保の第一歩は相互理解

情報処理安全確保支援士の資格試験では、自分が支援士だと仮定したうえでどう考えて行動すべきかを問う設問が出ます。そしてその場には必ず複数の関係者が出てきます。そもそも情報処理安全確保「支援士」ですから、組織に対して支援を提供してゴールを目指す立ち位置=実行者ではなくハブであり、経営者や情報システム担当に対する助言者だということなのだと私は理解しました。

同様に医療情報技師も関係者との交流を指す「3C」を重視しています

他職種との意思疎通を図るためのコミュニケーション(Communication)、他職種と協力して対応するコラボレーション(Collaboration)、部門間や職種間の調整を行うコーディネーション(Coordination)の3つの能力を必要な資質としています

医療機関で働く医療情報技師は自らの管理下にない部門システムや保守用ネットワークを業務の前提とすることも多く、事業者を含む他職種との協業が絶対必要です。だからこそより安全で患者様や職員のためになるシステム運用を実現するために、協調や調整が重要なのだと私は理解しました。

異なる資格が同様に他者とのコミュニケーションを通じての実行にピンを留めているのは面白いですね。それだけ業務遂行に必要な能力だと考えられているわけで、重要性もまた理解できます。

不安に名前をつけるのが情報処理安全確保支援の初手

さてセキュリティに明るくない方とのコミュニケーションにおいて、その出発点は多くの場合「よく知らないけど、これをしたい」「あれってセキュリティに問題あるって本当?」といった漠然とした不安であることが多いと感じます。そしてわかりやすく一網打尽にできそうな、たとえば閉域網のような選択肢が支持されます。情報技術は目に見えないものを扱うので、気持ちは理解できます。

ここで求められる3Cはその不安を具体的に表すことだと思っています。どのようなゴールを望んでいるのか、どんなリスクがあると考えているのか、保守にどれだけの手間をかけられるのかなど、いろんな視点からあるべき姿を探ります。その結果として不安に名前がつき、この不安にはこう対処する、この不安は当面どうしようもないので受け入れる、という議論ができるようになります。

もちろん相手にはよるものの、多くの場合はこうしたコミュニケーションを通じて不安や心配をリスクマネジメントという経営的な営みに近づけること、なんとなくや人から聞いたからではなくて戦略的に決定を下せるようにすること、その決定に大きな穴が無いようにすることが支援士かつ医療情報技師としてできる貢献なのかなぁ、みたいな。

まとめ

情報処理安全確保支援士になりました。いろんな立場の方との相互理解に努め、ヒアリングを通じて不安に名前をつけ、合理的かつ利便性の高い情報処理安全確保の支援をしていきたいと思います。

そのためには今までやってきたマネジメントやコーチングといった経験が活きるでしょうし、自分のWILLであるベストプラクティスを現場に落とし込むことも役立つはずです。情報セキュリティの知識を常にアップデートしつつ、課題解決に貢献できるエキスパートとして成長していきます。

Gradle用のGitHub Actions勘どころ(2024年夏)

前回に引き続き以下略。

jarファイルのビルドはコンテナの外で行う

ビルドをコンテナの中で行う場合、工夫がなければ毎回はじめからコンテナのビルドが走ります。これはパフォーマンス上好ましくないので、GitHub Actionsのキャッシュ用APIだとかRepository Cacheだとかを使ってビルド性能の改善を図れます:

docs.docker.com

ただGradleプロジェクトの場合はGradle自身が常に同じビルド結果を生成するように動作してくれますので(JVM toolchainとかreproducible buildsとかの話ね)、jarファイルのビルドはコンテナの外でやって Dockerfile では COPY するだけでも良さそうです。この場合は actions/setup-java のキャッシュ機構やRemote Gradle Build Cacheなどを簡単に使えます。

pushとpull_requestで別のワークフローを使う

PR向けのGitHub Actions workflow runが走っているタイミングでPRをマージすると、push時に走るはずのGitHub Actions workflow runが実行されない!という問題があります。ワークフローを分けることで回避できるため push.ymlpull_request.yml とを別に定義してreusable workflowをコールする方法を採ると良さそうです。

# .github/workflows/push.yml
on:
  push:
    branches:
      - main
jobs:
  build:
    uses: ./.github/workflows/reusable-build.yml
    secrets: inherit
  deploy:
    uses: ./.github/workflows/reusable-deploy.yml
    secrets: inherit
    with:
      environment: production
# .github/workflows/reusable-deploy.yml
name: Deploy
run-name: Deploy ${{ github.sha }} to ${{ inputs.environments }}
on:
  workflow_call:
    inputs:
      environment: ...

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: ${{ inputs.environment }}
    permissions: ...
    steps: ...

プロジェクトを増減させやすいtfactionプロジェクトを書きたい

私はTerraformを使うときにtfactionを利用しています。tfactionはGitHub ActionsとS3やGCSのような永続層だけでTerraformをいい感じに管理できるのでオススメです。

suzuki-shunsuke.github.io

ところでプロジェクトの増減はTerraformの難しいところだと思っていて、OIDCで認証するサービスアカウントの作り方とか権限の設定とか、新規に作成したプロジェクトの初期化や設定がなかなかTerraform単体では完結できなかったりします。手順書を作っておいて全部手動でやるのもいいのですが、できるだけTerraformで記述する方法を考えてみました。

前提となるプロジェクト構成

以下、特に断りのない場合、Google Cloudを前提としています。

プロジェクトは環境(staging, productionなど)ごとに1つ作成します。例外としてArtifact RegistryやCloud DNSを管理する共有プロジェクト(shared)がひとつあります。これはstagingやproductionのサービスアカウントがsharedのArtifact Registryに対して読み書きする権限が必要ということで、権限管理のキモのひとつです。

flowchart TD
  staging --> shared
  production --> shared
  shared

GitHub ActionsからのログインにはOIDCを利用します。これはWIP(Workflow Identity Pool)が早い段階で必要になることを意味しています。ブランチ戦略に従ってWIP Providerのattribute conditionを設定する必要があるので、たとえばproductionにはmainブランチからしかデプロイしない、といったルールは先に決めておきます。

プロジェクトの作成フローを定めておく

プロジェクト作成の大まかなフローは次のようになります。moduleはこれらの複数のステップに跨ることがないように作成しておくと良さそうです:

  • プロジェクト作成(scaffold workdir
  • 課金の有効化(手動)
  • 各種サービスの有効化(google_project_service
  • terraform plan用サービスアカウント, terraform apply用サービスアカウント, WIPなど作成(モジュール)
  • terraform plan用サービスアカウントとterraform apply用サービスアカウントがGCSバケットにアクセスできるようにする(同上)
  • terraform plan用サービスアカウントとterraform apply用サービスアカウントの切り替え(workdirのtfaction.yaml更新)

ここまではプロジェクトの作成や他のプロジェクトに属するサービスアカウントの作成ができる、強めの権限を持つサービスアカウントを使います。ここからは他のプロジェクトには影響できないサービスアカウントだけで済むはずです。以下のような手順になります:

  • firebaseプロジェクトの作成(手動)
  • サービスアカウントの作成と権限設定(他プロジェクトにあるArtifact Registryなどを含む)
  • リソースの作成
  • notification channelの作成(手動)

サービスアカウントの作成とリソースの作成は同じmoduleでやって大丈夫ですが、他プロジェクトにあるリソースのIAM設定を考えると分けておいても良さそうです。Cloud RunがArtifact Registryに接続できなくてterraform applyに失敗した、とかはよくやります。

workdirの作り方

workdirは少なくとも3種類を持つようにします。これはわかりやすさはもちろん、 terraform apply 等を実行するサービスアカウントの権限を単純にするためにも有効です:

  • プロジェクトやフォルダを作成・管理するworkdir
    • google_folder
    • google_project
    • google_app_engine_application
    • google_project_service
  • 共有プロジェクト内のリソースを管理するworkdir
    • google_artifact_registry_repository
    • google_storage_bucket
    • google_dns_managed_zone
  • 各プロジェクト内のリソースを管理するworkdir

プロジェクトやフォルダを作成・管理するworkdirは main.tf 内に直接処理を書きますが、他のworkdirは適宜moduleに処理を委譲するような書き方が良さそうです。共有プロジェクト内のリソースを管理するworkdirでは、接続を許可するプロジェクトのIDを locals.tf に定義して使うようにすると、プロジェクト増減時の手順が簡素化されます。

moduleの作り方

「各プロジェクト内のリソースを管理するworkdir」の処理はmoduleとして実装しておくことで、workdirに似たような処理を書いて回る手間がなくなります。tfaction 1.3.0からローカルモジュールの扱いがより便利になったので、ローカルモジュールを使う上でのハードルも下がってます。

suzuki-shunsuke.github.io

「各プロジェクト内のリソースを管理するworkdir」が使うモジュールは先ほど整理した作成フローをもとに、以下の種類に分けられます:

  • 各種サービスの有効化(プロジェクトを作成して課金を有効にした後で行う)
  • terraform-plan用サービスアカウント, terraform-apply用サービスアカウント, WIPなど作成(これは他のworkdirでも使える)
  • リソースの作成

ひとつのモジュールが複数のステップを担っても問題ありませんが、前提ステップが終わるまで後続ステップを進めないことを確実にできるように、リソース間依存やvariableを使う必要はありそうです。

まとめ

サービス運用中はこういった観点を意識できてなかったりして、いざ環境を増やすぞというときに苦労するということが自分は多かったので、しばらく今回まとめたmoduleやworkdirの書き方を意識してみます。

Javaで覚えておくと便利かもしれないクラス・インタフェース7つ

Twitterでこれ↓が流れてきて、あれーあのクラスは無いんだー、まぁ最低限と言われると違うかもなー。と思うのがあったので便乗。

nowokay.hatenablog.com

java.util.Objects

recordの導入で不要になってきたメソッドも多いが、引数の検証などでまだ出番がある。防御的な書き方を簡単にしてくれるのでおすすめ。

java.util.Scanner

標準入力を受け取ってゴニョゴニョするツールを書くのに便利。競技プログラミング御用達。

java.util.concurrent.Executors

スケジュール実行とか、スレッドを立ち上げてなんかするとか、そういうときに役立つ。

java.util.concurrent.CompletableFuture

JavaにPromiseって無いんですか、と言われたらCompletableFuture があるよ!と返してます。

java.time.Instant

時刻を表すのに便利。でもInstant.now() は使わずに Clock#instant() を使うんじゃよ。

java.time.Clock

Instant.now()System.currentTimeMillis() などを使いたくなったら、代わりに Clock をコンストラクタインジェクションして使うようにしよう。テストが書きやすくなるので。

java.lang.AutoCloseable

このインタフェースを実装しておくとtry-with-resourcesでお片付けできるようになる。 状態を持つクラスで、かつ依存先を開放するclose()stop() というメソッドがある場合に便利に使える。

まとめ

java.util パッケージは便利なクラスが多いので眺めておくと良さそう。

docs.oracle.com

組織変革を成功させるために脳科学を理解すると良いという話が面白かった

ハーバード・ビジネス・レビューで紹介されていた「CHANGE 組織はなぜ変われないのか」を読みました。ざっくり言うと、変化の早い時代における脅威と機会に組織として向き合う方法をまとめた本です。理論と実践が程よいバランスで書かれていて、現場のために書かれている本だと感じました。

紙上の空論とは一線を画した、適用可能な解決としてのデュアル・システム

この本は階層型組織は動きが遅いから機会を活かせないのでやめよう!みたいな極端な主張とは一線を画していて、階層型組織の安定性や脅威への対応能力を一定認めたうえで「機会を活かせないのはなぜか?」を脳科学という切り口から解決を検討し、一般化された回答としてのデュアル・システムを提示しているのが良いです。こういう本が読みたいんですよ私は。

もちろんデュアル・システムを動かすうえでの課題はあります。ひとりが2つ以上の組織に所属する難しさはマトリックス組織や兼務でさんざん知られているところですし、そもそも仕事で自発性なんて発揮したくない・発揮できない人もたくさんいます。そしてこうした問題への解決はケース・バイ・ケースですから、この本にはズバリの回答は載っていません。

ただその組織設計の根っこにある「人間の頭脳は脅威と機会に対してどのように反応するか」という知見はおおむね一般的なものだと考えられますし、M&Aや工場閉鎖などの成功事例もいくつか載っていますので「自分のケースだったらどうできるか」を検討する材料はあります。ので人間を束ねる立場の人はとりあえず読んでみて損はないんじゃないでしょうか。オススメです。

経営や組織運営の難度が上がった、というよりは、ゲームが変わってきている

ところで最近の組織論は人間のポテンシャルを引き出すためのコミュニケーションにピンを留めているものが多い、と感じます。ちょうど恐れのない組織両利きの経営を読んだあとだったのでそう感じるだけかもしれませんが、どのindicatorに着目しろとかどんな分析や予測をするべきとかじゃなくて「人間というのはこういうナマモノなのだから、それを織り込んで組織を回していこうぜ」という組織活動を検討するときの根本に揺さぶりをかけるものが多いです。

は?そんなの当然っしょ、んなもん10年以上前からそうだよ。という方も多くいらっしゃると思います。実際私の前職も現職も、人間の多様性とポテンシャルに注目した組織作りをしています。古典であるドラッカーですら、目標管理というコミュニケーションに注目していたわけですし。

ただ、そうでない組織も実際まだまだ多いのです。外の人と話をしていると、社内政治がどうのとか、派閥がどうのとか、リモートワークは誠意がなくてけしからんとか、飲み会や運動会に全員参加をとか、そういう人間の多様性を尊重するよりも会社人・社会人という一様化を適用して扱いやすくすることに心を砕いているところがまだ多数派なんじゃないかと感じさせます*1

そしてそういう組織に限って、いい人が取れないとぶちぶち言ってるんですよね。いや組織づくりを変えればいい人取り放題とは言いませんよ。いつでもどこでも採用は困難です。ただゲームが変わっていることに気づかないまま前時代的な組織づくりや採用をしていても、そりゃ刺さらないよねとしか思わないのも確かです。

良い組織を作ることはお客様によりよい問題解決を届けるだけでなく、自社の採用ひいては事業継続性にも資する行為だと思うので、こういうビジネス書がたくさん出て意思決定層にきちんと届くことはとても重要だろうなぁと思いました。

*1:念の為に書いておくと、飲み会もオフでの繋がりも出社もとても重要だと思っています。だからこそ全員にひとつを求めるのではなく、全員が何らかの形で繋がれるように複数の場を設けることが必要だという主張です。