Kengo's blog

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

「誰が書いたコードか当てまShow!!」出題者による解説

勤務先のブログで紹介されていますが、Kotlin Fest 2025で出題したクイズに向けてKotlinコードを書いていました。本記事では自分で自分のコードを解説してみます。企画のネタバレを含みますので、先に企画紹介記事を読んでいただければ幸いです。

ヒントは「メソッドチェーン」「Kotlinのプロ、じゃない」

まず自分のコードを再掲します。パッと見でメソッドチェーン風だということがわかり、リアクティブプログラミングの経験があるひとにはAっぽいなと伝わる雰囲気を醸し出しています。

fun solve(input: String): String {
    var prevScore: Int? = null
    var prevRank = 1
    return input.split("\n")
        .map { it.split(" ") }
        .groupBy({ it[0] }, { it[1].toInt() })
        .mapValues { it.value.sum() }
        .toList()
        .sortedWith(compareByDescending<Pair<String, Int>> { it.second }.thenBy { it.first })
        .mapIndexed { index, (name, score) ->
            val rank = if (prevScore == null || prevScore > score) {
                index + 1
            } else {
                prevRank
            }

            (rank to "$name $score").also {
                prevScore = score
                prevRank = rank
            }
        }.takeWhile { it.first <= 3 }
        .joinToString("\n") {
            "${it.first}. ${it.second}"
        }
}

ひとつずつ見ていきましょう。まず目につくのが変数名です:

fun solve(input: String): String {
    var prevScore: Int? = null
    var prevRank = 1

prev は previous の短縮形です。このくらいなら短縮せずに previousScore としたほうが良いかもしれませんね。このくらいの変数なら特にコメントで意図を説明する必要はないかなと思って、ドキュメンテーションコメントは何も書いていませんでした。

なおBのコードでは previous ではなく last が使われており、どちらが良い命名なのかを議論するのも面白そうです。

さて次の行が大きなヒントになっています:

    return input.split("\n")

これとてもJavaっぽい書き方で、実際他の方の回答だと lineSequence() が使われているんですよね。ここで少なくとも「AはKotlinのプロであるタケハタのコードじゃないな」とバレるようになっています。なぜ lineSequence() を使わなかったのかって?だって、知 ら な い そ ん な 函 数!勉強になりました。

なおここで「OSがCRLFのような他の改行コードで動いてたらどうするんだ」ってツッコミは可能なんですが、この手の出題でそこが問題になることはないだろうと判断しました。厳密には System.lineSeparator() あたりを参照したほうが良いですね。

ちなみにJavaで似たような問題を解くと必ずと言っていいほど Scanner が出てくるんですが、さすがKotlin、流れるように処理を書き下せました。便利。

さて次のコードです:

        .map { it.split(" ") }
        .groupBy({ it[0] }, { it[1].toInt() })
        .mapValues { it.value.sum() }
        .toList()
        .sortedWith(compareByDescending<Pair<String, Int>> { it.second }.thenBy { it.first })

ここはまぁ、普通ですね。 Pair を引き回すと可読性が落ちるので、Dのようにクラスを定義して使うのも良さそうですが、今回はまぁいいでしょという気持ちになりました。今見返すと、 .groupBy({ it[0] }, { it[1].toInt() }) がだいぶ厳しいか。

あと compareByDescending() については、3分くらい「GuavaならOrderingなんだけどな〜」って検索してました。無事に便利函数が見つかって良かったです。

さて次は誰からも突っ込まれなかったコードです:

            (rank to "$name $score").also {
                prevScore = score
                prevRank = rank
            }

この also の使い方、だいぶ独特な感じに仕上げたつもりなんですが、見事にスルーされました。クリーンアップ処理を他のコードと違う場所にまとめて書ける、かつ finally と比較したときに例外の発生を想定してないことを伝えられる、ということでわりと悪くない書き方だと思うんですけどね。

最後はこのコードです:

        }.takeWhile { it.first <= 3 }
        .joinToString("\n") {
            "${it.first}. ${it.second}"
        }
}

お題を見たときに takeWhile() が出てくることは決めていました。一番最初に書けたコードだとも言えますね。あとは特に変わったところはなく、普通に joinToString() して終わりです。

他の人のコードへのツッコミどころ

ということで、以上で出題者による解説でした。楽しんでいただけたでしょうか。

なお他の人のコードにもツッコミどころというか、個性を感じるところは多々あります。ぜひ皆さんも考えてみてください。私が思ったのは次のような感じでしたが、人によって意見は異なると思いますので、ご参考まで:

  • 名前つき引数、いい。わかりやすい。IDEAで書いてるとなかなか気付けない気配りポイント。印刷前提だったので、自分も書いたほうが良かった。
  • String.split(String) は正規表現のコンパイルが走る可能性があるので、ループ内では呼ばないクセをつけたほうが良いかも
  • return@foobar は可読性が落ちるので、個人的には避けたい
  • tailrec すごくいい
  • コメントがいちいち意味ない!(たぶんツッコミ待ちなんだけど気になる)
  • is-a と has-a は違うんですよ!(たぶんツッコミ待ちなんだけど気になる)
  • 函数の引数の型はできるだけ抽象に寄せたいなぁ、なんで HashMap なんだっけ……(たぶんツッコミ待ちなんだけど気になる)

エンジニアに必要な「根拠のない自信」と、挑戦を支えるマネジメント

自分は以前、意思決定というのは「腹をくくる」「清水の舞台から飛び降りる」のように不可逆的かつ一定のダメージを覚悟する・リスクを負う行為だと思っていました。そして意思決定が関わる戦略が長期的であればあるほど、情報を集めても考えを深めても不確実性を下げることはほぼできませんから、意思決定の難度も高くなっていきます。この長期的な意思決定の代表例が企業の経営戦略でありスタートアップの企業理念なので、自分は企業経営に対して強い苦手意識を持っています。不可逆なリスクを負うには覚悟が必要で、その覚悟はどっから持ってくるんだ?というのが未解決問題だったわけです。

ただ最近、不可逆的にリスクを取りに行くだけが経営ではないというか、もうちょっと違う解釈への投影もできるんだなと思ったので、ちょっと書いておきます。

ビジョンは未来予測じゃない

我々はどのような企業になる、弊社の製品はどのような課題を解決する……といったビジョンの策定と発信はマネジメントの大きな仕事です。個人的には創業経営者の仕事はほとんどこれだと思っています。ビジョンに共感する人材を集めて目標をつっこむとアウトカムが生産される、それがスタートアップというやつでしょう。

このビジョンはもちろん想像可能・達成可能なものである必要はありますが、別にそれは「腹をくくる」ようなものである必要はない……というと語弊があるんですよね。当人は腹をくくって強いリーダーシップを発揮するべきですし、考え抜かれたメッセージと行動を通じて課題を実際に個人として組織として解決しなければなりませんので、腹はくくるべきです。投資家が投資先を選ぶうえで必ず見るものとして創業経営者の人柄が挙げられるようですが、それには腹をくくれるか、ビジョンを誰よりも信じて実行に突っ込める人物かを見ている側面は間違いなくあるでしょう。

自分が言いたいのは、この意思決定を100%実現可能だと信じることは重要だが、この意思決定した内容が100%実現されることはそんなに問題ではないということです。自分はここを混同していたのですが、世の中を見るとこうしたビジョンを途中で変えたり、実現する前に退場したりという結果に至った経営は多数あります。 わかりやすいところではGoogleのビジョンでは2000年代に one-click という単語を使っていましたが、今は使っていません。実際音声入力やマルチタッチスクリーンが当たり前になってきた現在において one-click と言っていたら、違和感が強いでしょう(当時もキーボードで全部やる人はいましたが、ここではクリックしない調べ物がより一般ユーザに浸透したと考えます)。しかしこのビジョンの変更について、one-clickだと言っていたじゃないか!と怒るような人は投資家にもいないんじゃないかと思うんですよね*1。クリックが主要なインタラクションではなくなる未来を読めなかったことや、20年使えるビジョンを提示できなかったことは問題ではないわけです。

結局重要なのはビジョンを出して実行することを通じて、従業員や顧客、市場といったものを動かしていくことです。one-clickという言葉を通じて強いシンプルさへのこだわりだとかユーザインタフェースの削ぎ落としだとか、そういったものの重要性を強く示して世界に働きかけることが重要だったわけです。だから今までの自分が「one-clickでできると思うけど、万が一できなかったらどうしよう」みたいな心配をして苦手意識を持っていたのはちょっとズレていたなと思います。

根拠のない自信の効用

自分が打ち立てたビジョンを信じられるのは、決して楽観的だからではないと思っています。まぁそういう人もいるでしょうが、どちらかというとまぁなんとかできるやろ的な根拠のない自信が多いんじゃないかと思うんですよね。そして根拠のない自信を持つことはシニアエンジニア、というか人を巻き込んで動いていく開発者には結構大事なんだなと思います。

根拠のない自信というと深く考えないことや痛みを気にしないことのような「鈍感力」のイメージもあると思いますが、自分が今回考えているのは「全く同じじゃないけど、似たようなことは経験してきた」「失敗しそうなポイントをざっと洗って、あらかじめ対処を考えられた」という、確実ではないけど一定の工夫はした、でも根拠と言うには薄くないか?みたいなそういうやつです。経験者の肌感とか、職人の感覚とか、そういうやつです。テスト駆動開発がすべてのバグを防ぐわけじゃないけど、前に進む自信をくれるのと似ているでしょうか。

一応テクニックとして「失敗してもダメージを許容できるようにする」、つまり撤退条件をあらかじめ定めるなどのコンティンジェンシープランの検討は使えます。使えるし、使うんですが、コンティンジェンシープランは次善の策であって本丸の確度を上げるものではないので、自分で打ち立てたビジョンを頭から信じる根拠にはならないと思うんですよね。のでテクニックとしてつくるコンティンジェンシープランの向こう側に、マインドとしての「まぁなんとかできるやろ」的な根拠のない自信は一定必要になるはずです。そして「根拠がない」ことを気にしすぎないでまず一歩踏み出すことが必要なんだと思います。

生存バイアスを作ればいいんだよ、というアドバイスをしないために

この根拠のない自信は理詰めでは身につきません。ではどうするのか?一番シンプルな答えは「とりあえずやってみて、転んだらそこから学べばいい」というものです。確かにこれは短期的には有効で、コードを書いて壊して直して覚えるような開発者の学び方とも相性がいい。

ただ、この考え方には落とし穴があります。生き残った人だけが「転んで学んだ」と語れるのであって、再起不能になるケースも多いのです。これがいわゆる生存バイアスというやつですが、ビジネスや組織運営では持続可能な方法が求められることから、「千尋の谷に突き落とす」ようなコミュニケーションは避けるべきです。

levtech.jp

だからこそ大事なのは、「安全に転べる環境を用意する」ことです。歴史から学ぶのが理想ですが、それが難しいときには上司や仲間とのコミュニケーションでセーフティネットを作る。例えば「まず1週間自由にやってみて、うまくいかなければこのプランに切り替える」といった撤退条件を決める。「失敗したら一緒に謝りに行こう」と保証する。そうすることで挑戦のリスクを許容でき、持続可能に第一歩を踏み出せるのだと思います。

blog.kengo-toda.jp

こうしたセーフティネットと合わせてもうひとつ大切なのが、周囲からのフィードバックによる“外付けの自信”です。根拠のない自信を持たない部下は、新しい一歩を踏み出しにくい状況にあるかもしれません。その場合は「君ならできると思うよ、だってあのときもああやって解決できたじゃん」などと、普段見ているからこそできるフィードバックを通じて背中を押しましょう。

根拠のない自信が自分で作れないなら、まぁアイツが言ってたからやってみるか……という外付けの自信を持たせてあげる。それで第一歩を踏み出せたらしめたものでしょう。

まとめ:リスクはゼロにできないから、根拠のない自信をうまく使う

リスクをゼロにすることは必要は多くの場合不可能ですし、不要です。企業経営のような難しい意思決定であっても、リスクをゼロにすることではなく行動を通じて課題解決を個人として組織として前に進めることが求められます。これは楽観的になってリスクを軽視しろという意味ではなく、自分ならなんとかできるだろうという根拠のない自信をうまく使うことが大切だという意味です。

もちろんリスクを管理するために、コンティンジェンシープランを定めたりダメージコントロールしたりすることは必要です。これらが自分でできない部下に対しては、上司としてこれを助けることが欠かせないでしょう。加えて根拠のない自信を外付けで持たせてあげることで、リスクを伴う挑戦に一歩踏み出せるように支援できると理想的だなと思いました。

*1:don't be evil の方は知らん

医療向け基幹システムを提供するスタートアップに入社して3年経った

医療向け基幹システムを提供するスタートアップに入社して丸3年経ちました。入社した目的はどの程度達成されたのか、今後どうしていくのかをまとめておきます。

入社した目的の振り返り

入社エントリに書いてるのですが、今回の入社には大きく分けて3つの目的がありました:

  1. 顧客と開発現場から学び、製品とチームを継続的に改善する
  2. 製品を通じて社会の課題を解決する
  3. ドメインの課題を解決する手段とプロセスを理解する

リーンに社会課題を解決するワザを研ぎ澄ませること、新しい技術で新しいアプローチを実現することで難しい社会的課題を解決すること、ドメインの課題を噛み砕いて実行可能な計画に落とし込むことがだいたいの理由というところです。そして前職の先輩方からさんざん聞いていた創業時のカオスを楽しみたかった、というのも大きかったですね。

リーンに社会課題を解決するという点で期待以上の動きができている

これは直近の記事でも公共政策について触れていましたが、リーンに社会課題を解決するための動きは当初の期待を超えた広がりを見せてくれています。スクラムをちゃんとやる、組織を大きくする、社会課題に真正面から取り組むといった機会が山のようにあります*1

医療という社会課題を選んだのも結果的に良かったと感じます。課題の大きさや市場としての複雑さはもちろんですが、2040年という節目を国が挙げていることもあり*2ここから15年間に何が問題になるかが考えやすく、少なくともマクロでは傾向や課題は掴みやすい領域です(と思っていたんだけどそうではない領域がたくさんある、という話が今読んでる本に書かれているようなので楽しみ)。

お金と生命を預かるシステムなので難しさは当然あるのですが、そこは前職から変わらずです。ただ要配慮個人情報を扱う一方で医療機関側に専門家が少ないという業界の課題については、事業での解決は難しいなと思っています。

ドメインの課題を解決する手段とプロセスに驚きはない

過去記事「組織という仕組みで解決することの難しさ、あるいはマネジメントに超人を求めるのは間違っているだろうか」で書いたことほぼそのままです。ドメインの課題を解決する手段にも、それを適用するプロセスにも、大きな驚きはありません。たぶんどこに行ってもこれは変わらないんだろうと思いますし、生成AI時代でも使えるスキルというのはこういうものを指すのかもしれません。

結局これをどこまで泥臭く、丁寧に、飽きずに情熱を持って徹底できるかどうかで課題が解決されるか決まります。内発的動機づけが重要な理由はだいたいこれだと思ってますし、創業経営者が重要な理由もだいたいこれだと思ってますし、社会課題解決の現場にしばしば継続可能性が怪しい活動が出てくるのもこれだと思ってます。だからこそ信念を持って継続できる、興味と関心を保ち続けられる社会課題を探すことが大切だと思いますし、中間管理職としては理想と継続可能性の両方に目を配らなければなりません。ロイヤリティとかエンゲージメントとかの横文字が出てくるのも、この複雑さに起因するのでしょう。

結論、やりたいことはだいたいできてる

連結ウン千人のメガベンチャーで社員番号1000番台だった3年前と比べて、100数人のスタートアップで社員番号20番台をやってる今のほうが事業と社会課題解決にまっすぐ向き合えている感覚があります。前職の先輩からさんざん聞かされていた体験をいままさにできていて、良かったと思います。

もちろん全て理想的に事が運んでいるわけではなく、色々とやりきれてない部分はまだ多々あるのですが、ひとつずつ解決していきます。

*1:具体的な内容については個人ブログの範囲を超えるので、勤務先のカンパニーデックに譲ります

*2:最近公開された医療提供体制等についてという資料がわかりやすい

ガバクラにおけるモダン化の定義について考えたこと

Twitter (X) でデジタル庁が出したnoteについての議論があり、様々な立場からの意見が集まっています。自分が感じたこと考えたことを残しておくと私自身の勉強になりそうなので、このブログでもちょっとまとめてみます。

一応コンテキストとして書いておくと、私はオンプレミスパッケージ製品の開発運用経験がある、クラウドネイティブSaaSのSRE 兼 セキュリティ担当です。

文脈

この情報の初出は今年の2月で、そういう意味では新しい情報ではないでしょう。ガバクラのコストの高さなどに注目が集まったタイミングで拡散しやすいnoteに情報が載った、という文脈が今回の注目量の背景にあると思います。

xtech.nikkei.com

note.com

最近の流れを汲めていない内容になっているのは、2月に決まっていた内容をほぼそのまま載せたから、と考えられそうです。

この定義の着眼点

モダン化に限らず情報システムの評価においては、様々な着眼点というか切り口が存在します。私はこの定義を見て、サービス運用者の目線で書かれているなと思いました。モダンではないサービスの運用現場で何が起こっているかと言うと、私の知る限りでは:

  • シングルテナントであり、テナント(顧客)ごとに環境が必要になる
  • テナントごとに環境が複数存在する(SAPで言う3-system landscape)
  • 環境ごとにサービスのバージョンが異なる
  • 更新にサービス停止が必要で、サービスを止められるタイミングは各テナントの都合で決まる
  • 環境(サーバ、クライアント共に)のスペックやOSは各テナントの都合で決まる
  • 実行ファイル(クライアント)がDBに直接接続しているので、DBスキーマ変更には全クライアントの停止と一括更新が必要になりがち
  • 複数のシステムが連携しており、ひとつの失敗が複数のシステムや業務に容易に波及する
  • ストレージやメモリなどの増設には顧客の対応と出費が必要で難度が高い
  • サーバが状態を持っており水平スケール(スケールアウト)できないので、垂直スケール(スケールアップ)が必要で高スペックマシンが必要になりがち
  • サーバは必ずしも設備が整ったサーバ室で実行されているわけではない
  • サーバのハードウェアは必ずしも冗長化や管理が行われてはいない
  • サービスの実行環境は顧客のものであり、アクセスや変更の手順が重い

たとえば100テナントそれぞれが3環境持っていたらそれだけ300環境になります。それらの環境には少なくても5年前のOSやハードウェアが含まれ、最新のライブラリやフレームワークが使えないことが前提になってきます。またサポートコストを減らすなどの理由から最古のメジャーバージョンのメンテナンスを停止する場合、100以上ある環境それぞれに対してマイグレーション手法やスケジュールを提案し、それぞれに対してオペレーションを適用する必要が出てきます。そんなコストはなかなか払えないので破壊的変更を入れる頻度を下げざるを得ず、魅力的な実装を届けるハードルが上がり、魅力のないマイナーバージョン更新は顧客を惹きつけないので最新のマイナーバージョンを使ってもらえず、在野に放たれるマイナーバージョンが更に増えていきます。

そんな状況でLog4Shellのような緊急度の高い脆弱性が報告されたらどうなるか。サポートしているすべてのマイナーバージョンに対してパッチをあてて動作確認をし、全環境に適用する……というコストが突発的に発生します。スモークテストやリグレッションテストは当然手動ですから、数日から数週間は非常に厳しい状況に陥るでしょう。このような想定があるため、サービスのサポート体制はどうしても厚くせざるを得ません。サポート体制が厚いということは、人件費が高いということです。自動化や効率化のためのITシステムなのに、その維持には人手が必要だという自己矛盾に陥りがちだと言えるでしょう。

ところでデジタル庁のnoteで挙げられているモダン化の利点は、先程挙げた運用現場の課題にそれぞれ対応しているように思われます:

現行のシステム モダン化されたシステム
ひとつのシステムの失敗が複数のシステムや業務に容易に波及する 複数のシステムが互いの処理完了を待たずに、それぞれが独立して処理を進める
クライアントがDBに直接接続しているので、DBスキーマ変更には全クライアントの停止と一括更新が必要になりがち フロントエンドとバックエンドを疎結合化することで、開発やデプロイを独立して実施
サーバが状態を持っているため高スペックマシンが必要になりがち ステートレスなアーキテクチャ&オートスケールを活用する
サービスの実行環境は顧客のものであり、アクセスや変更の手順が重い コンテナを活用する
人件費が高い 定型作業は手順書ではなくコード化する。コード化することで、自動化も容易になる。
サーバ実行環境の貧弱さ マネージドサービスの活用

これが私が「サービス運用者の目線によるモダン化」について書かれていると感じる理由です。noteではアーキテクチャと運用のモダン化だとしていますが、アーキテクチャも実行性能やランニングコストではなく「サービス運用の容易性」で選ばれているように感じます(後述しますが、夜間バッチを逐次処理に置き換えるとクラウドでもコストは高くなるため)。この理屈でいうとマルチテナントやclear change processについても言及があってしかるべきではありますが、さすがにすべてがマルチテナントになるべきとはまだ言いにくい*1のかもしれません。

この定義があると誰がどう嬉しいのか

デジタル庁によってこうした定義が提示されると、誰がどう嬉しいのでしょうか。もちろんサービス運用者には溜飲の下がる人が多いかもしれませんが、サービス運用者の意見だけでサービスの実態が変わることはまずありません。サービスのオーナーである企業経営者や、サービスを求める発注者にとっての利点があって、はじめてモダン化の重要性が認められモダン化が進むと思われます。

私はこのモダン化の定義によって、サービスの「モダン化度」を測るチェックリストを作れることが嬉しいのかなと思いました。いまサービスを運営している人が「モダン化にあたり、いまの課題はどこなのか」を専門家である第三者に教えてもらえる、モダン化のためのロードマップが引ける、そして顧客にその必要性を説明できるための素材になるのではないかなと。特にアーキテクチャの具体についてある程度触れることで、工数見積をやりやすくしているのではないかと思います。

これについては色々思うことも無いではないのですが、大号令によって市場を形成してITシステム開発の大勢を変えていく手段としてはアリなのかもしれません。私も情報セキュリティの専門家であることをお客様に伝えるとき、Log4Shell対応などで縦横無尽に活躍したかを語るよりはただひとこと「国家資格持ちです」と言う方が効果的だということを身にしみていますので、やっぱり「難しいのは重々承知してますが、デジタル庁が言ってますんで」のひとことが言えるだけで助かる現場があるんだろうなとは想像するところです。

個別の要素について

ここまで来ると個別の技術的記載に突っ込むのは野暮な気がしてきますが、自分自身他の方々のご意見を拝見してとても勉強になったので、気になったところをいくつか書いておきます。

非同期APIについて

要件について説明が不足していると感じます。このAPIは少なくとも次のような構成要素を持つはずです:

  1. APIを提供し、リクエストパラメータをジョブキューに積むサービス(FaaSっぽいがそれに限られない)
  2. ジョブキューから情報を取り出し、その内容を処理する冪等なサービス
  3. リクエストした内容がどこまで処理されたかを確認するためのAPIや画面

1つめはAPIの可用性を上げるために重要です。このAPIはリトライすればなんとかなる程度の短いMTTRを実現する必要があるため、できるだけマネージドサービスに寄せて実装を薄くすることが求められます。採番ルールなんて気にせず、粛々とUUIDを返すAPIであるべきです。またファイルや巨大なペイロードを処理するAPIの場合は、ファイルをアップロードする別のAPIが必要でしょう。

2つめは処理の本体です。冪等に実装する必要があり、多くの場合は既存コードの流用は難しいでしょう。モダン化のハードルのひとつだと言えそうです。

またAPIを使った人はその進捗や結果を確認したいことがほとんどなので、3つめも必要になります。数10分かかるとわかっている処理であれば、その進捗度を知りたいというニーズもあるでしょう。1と3はほとんどのサービスで共通の構造になりますが、2の持つ入力や出力の仕様が染み出してくるところがあるため、必ずしも共通基盤として括り出せるかはわかりません。

さてこのように構成要素を整理したうえで、モダン化システムはかならず非同期APIを使うべきか?と問えば、まぁNOでしょう。業務要件によっては同期的なAPIも必要になるからです。

単純に情報を取得するAPI、ファイルをアップロードするAPI、ロックを取得するAPI、ログインやログアウトをするAPIなどはイメージしやすいでしょうか。他にもリクエストパラメータが間違っていることを最初にvalidateして返したいAPIなんかは、システム間連携でも同期APIにしたいかもしれません。非同期APIの使い所として帳票を生成したり複数のシステムを活用するAPIなんかは思いつきましたが、すべてのAPIがそうあるべきとは思いませんでした。

フロントエンド・バックエンドアーキテクチャ

これ自分は「UIもビジネスロジックもひとつの実行ファイルで動かしているパターン」、まぁDelphiなんですけど、を想定して読みました。ので責務を分けるという言葉が単なるプログラミング言語的な意味での開発速度向上ではなく、サーバとクライアントとを独立して保守・更新できるという意味での開発速度向上だと理解しました。

ただ私とは異なる理解をしている方も多かったようなので、仮に私の理解が正しいのであれば、バックエンドが互換性の維持に気を使ったAPIを提供することの重要性や、現在のシステムとして想定しているものが何かをもう少し書くと良かったのかもしれません。

イベントドリブン処理

このあたりの話は、みずほ銀行さんの一件を思い出しますね。結論としては、夜間バッチでも良いと思います。

xtech.nikkei.com

オンライン処理、というか逐次処理にしてしまうと、単純に計算回数が増加します。たとえば勤怠管理のための打刻処理を考えます。その人の勤務時間は退勤時に計算できますので、オンライン処理の場合は退勤時に計算することになります。しかし運用によっては休憩時に退勤手続きを行うこともありますし、無事に退勤したがオンコールで呼び出されてしまった場合などは複数回の出勤・退勤を記録することになりますから、退勤時に走る勤務時間計算処理も2回3回と実行されます。オンライン処理よりも計算回数が増えるわけですね。

また非同期処理のためにメッセージキューやらDBのトリガーやらCloud Tasksやらを導入しますから、構成要素が増えて可用性が下がることも想像できます。たしかに夜間バッチには処理を相対的に計算機資源が空いている夜間にシフトするという物理資源節約の側面もあるのですが、コストや運用の観点からも合理的なことがあるわけです。

オートスケール

オートスケールが嬉しいかどうかは業界というかシステムによりそうです。どちらかといえばローリングアップデートができることの方が、clear change processやコンテナの活用などを念頭に置くと一般的に重要なように思われます。ただランニングコストを下げるという錦の御旗を考えると、スケールダウンできるように作りましょうと言いたいのは理解します。

定型作業を自動化する

これも要件というか「定型作業」の具体が読み手によって異なるために、混乱を生んでいるように思います。年1回しかデプロイしない想定ならデプロイ作業を自動化する意味は薄いですし、1次対応を外注している想定なら自動化によるコストダウンや確実さは重要でしょう。

おわりに

デジタル庁のモダン化の定義は運用現場の課題を解決する道筋を示すチェックリストとしての価値があるのではと感じました。一方で、同期API vs 非同期API、夜間バッチ vs イベントドリブンといった検討は、必ずしも全サービスにそのまま当てはまるわけではありません。各組織や案件ごとに業務要件やリスク許容度を見極め、バランスを取る必要がありそうです。そのバランスが難しいから、ひとまず道を示しているのかもしれませんが……。

今回の議論は私にとって、普段とは違うシステム構成について検討し、私達の今後のシステム開発を考える良いきっかけになりました。業務の効率化はITシステムの開発・保守・活用すべての局面において求められています。私としては、それぞれバランスよく検討できるだけの知恵と経験をつけていきたいです。

*1:厚生労働省は医療情報システムについてマルチテナントに踏み込んで発言をしているので、ドメイン固有の問題が知られている業界を念頭に置いているのだろうと思います

システムで世界を変えるにはシステムだけでは足りない話

現職でPodcastの放送が始まりまして、私と id:Songmu さんで開発しているプロダクトや開発技術や開発体制、課題などの開発の現状について話しました。

本ブログ読者の方には「音声よりも活字だぜ!」という私みたいな方も多いのではと思います。先日文字起こしも出ましたので、お好きな方をご覧いただけば幸いです。

システムでは手が届かない部分と、システムエンジニアのレゾンデートル

さてこのポッドキャストでもちょっと触れたんですが、ITシステムを通じたイノベーションに取り組んでいると「ITシステムでは手が届かない部分」がどうしても出てきます。というか届かない部分がほとんどです。

たとえば育児休業や児童手当の申請手続。こうした制度はそもそも設計が複雑で、自治体ごとにフォーマットが違ったり、必要書類がバラバラだったりと、利用者の立場からすれば非常に“遠い”存在でした。マイナポータルのようなオンライン窓口は以前からありましたが、書類は郵送、申請は窓口、必要情報は自分で調べてね、という状況が長く続いていました。情報システムの力があっても、制度や慣習という「壁の向こう側」に手が届かない例のひとつだと言えます。

もちろんITシステムが手を出せる領域はセンサーや自然言語処理といった技術革新によって徐々に増えてきていますし、まさに生成AIによるブレークスルーが激しいフィールドではあります。それでも人間社会の課題はまだまだシステムだけでは解決できない問題が数多く残ることは確信できます。我々がやりたいのはデータをこねくり回すことではなく、未だ社会に横たわる課題をぶっ壊すことなので、情報技術をどう使うと人間をより幸せに近づけられるかという「解決ではないモノを解決を生むために使う」ための工夫が必要です。そしてその工夫は「人間の不完全さ」にも「ITシステムの融通利かなさ」にも歩み寄れる、またITシステムでは手が届かない「壁の向こう側」に飛び込める、我々システムエンジニアから今後も出ていくことでしょう。

公共政策という粘り強い根本解決

で、最近感じているのはただ「壁の向こう側」に飛び込むだけではなく、壁を壊す、壁を作り直すといった「壁を動かす」アプローチがけっこう有効なのかもしれないということです。もちろん人間を完全な存在にするとかシステムに融通を利かせるとかそういう話ではなく、業界の慣習や人間社会の在り方といった活動を通じて壁に働きかけるという話です。

たとえば先ほどの例では、マイナポータルを通じて育児や介護に関する各種申請がオンラインで完結できる仕組みが整いつつあります。これは単に「ITシステムを作った」ではなく、各自治体が提出書式や確認プロセスをすり合わせ、法制度も見直されたからこそ成り立っているものです。技術は以前から存在していたけれど、それが“届く範囲”は制度設計によって大きく左右されます。これはまさに「壁を動かす」ような話です。

どの業界にもまず間違いなく、長い歴史と積み重ねられたシステムがあります。中には血で書かれたものもあり、軽い気持ちで変えるべきものではないことは明らかです。一方で情報技術や社会の変遷についてこれていないものも少なからずあり、それが「壁の向こう側」を作っている現実もあります。

そして個人的には意外だったこととして、国や関係機関はその問題を認めて行動しようとしています。前述の例もそうですし、医療関係で言えば省庁が医療情報システム向けに出しているガイドラインもシステムの流行り廃りを踏まえて更新されています。そして企業はデータや実際の運用を握っていますから、改善のモチベーションを持っている国や関係機関とのコミュニケーションを間違えなければ互助関係を構築できるはずなのです。前職でも国や大学とのコラボレーションはやっていましたが、今回より高い解像度で公共政策を見ることができて、とても勉強になっています。

人がソリューション、ITシステムはテコ

まとめると、壁の手前側にしか影響できないITシステムで壁の向こう側を巻き込んだ課題解決をすることはもともと困難ですが、イノベーションによる社会課題の解決にはこれが不可欠です。このときに壁を所与の条件として扱うのではなく解決可能なものとして捉えて協調することで、どのような業界でもより良い課題解決に繋がるのではと感じます。

そして壁を動かすのも壁の向こう側に飛び込むのも人なので、ITシステムはいかにそういった人を助けるかとか、壁を動かしたあとのワークフローをきちんと自動化するとか、そういう人間の在り方や能力を拡張する補助的な存在になっていくべきなんだろうなと思います。私もやはり仕様や機能について議論しがちなんですが、ITシステムが運用された結果として人がどう嬉しくなるのか、に改めて着目してITシステムの開発と運用に関わっていければと思います。

とあるアラフォーが感じるITエンジニアのキャリアについて

ITエンジニアのキャリアアップについて徒然と話していて、こういう考えのスナップショットを残しておくとあとで役立ちそうだと思ったので書いてみます。人間は自分が見てきたことしか書けないので、このブログも汎用性のある内容ではないことはあらかじめ断っておきます。

自分の価値観と技術的関心のコアを見つける

大前提として、誰にでも適用できるキャリアという概念ないしキャリア論というものは存在しません。これは断言して良いと思います。もちろん多くのITエンジニアに共通して言える概念、たとえば市場であるとか技術トレンドなんかはあるのですが、それを踏まえてもその前提で何を優先するかは個々人の価値観や環境によるでしょう。

卑近な例として私はCOBOLが読めるという市場価値が相対的に低い技術を持っていますが、これにはシステム連携の電文フォーマットであるとか、古いシステムの保守体制の裏事情をある程度推察できるというシステム開発エンジニアとして得難い利点があります。では市場評価が間違っていて全ITエンジニアはCOBOLを学ぶべきなのかというと、そうではないでしょう。

では価値観や環境を前提としてどのようなキャリアを積むべきか。これを考えるには、まず自分の価値観を見つけなければなりません。そのためには何でもまずはやってみることです。WEBシステム開発を生業としているのであれば、既存コードの読み込みや参考書の写経だけでなく、一見関係のなさそうな競技プログラミング, コードゴルフ, 他言語, 組み込みなんかも広く浅くやったほうが良いですし、環境が許すならお客様先や他社にも足を運んで色々見ると良いです。もちろん書籍やインターネットで情報を得るのも良いですが、実際に時間を使って手と頭を動かしたほうがより得るものも多いでしょう。というかどこかに書いてある情報は今後生成AIで手軽に引っ張ってこれるようになるので、今後は今まで以上に経験の重要性が上がるはずです。

私の場合は新卒で入社した会社で数度の異動をしたことで、COBOLやcshからTypeScriptやGroovy, RDBMSからCassandra, シングルテナントオンプレからマルチテナントクラウドなどと幅広い経験を得られました。チームリーダーやマネジメントも経験しました。また趣味開発でバイトコードやビルドスクリプトなどを触っていますし、学生時代にFortranや高速フーリエ変換のようなアルゴリズムを学んでもいます。

こうして数をこなすと、食指が動かない技術も出てきます。自分の場合はRDBMSやJVMはコードを書いてみようと思えましたが、OSは本を読んだだけで止まっています。家にサーバーを飼おうとベアメタルサーバを部品から組み上げたこともありましたが、さらにネットワーク機器やサーバを追加してクラスタを組もうという気にはなれませんでした。ロックフリーとかPaxosのようなアルゴリズムをスゲェと思ったり、 CompareAndSwapConcurrentHashMap などのコードを読んだりはしましたが、Topcoder SRMは青で止まりました。

そして長続きする技術や関心領域が見えてきます。自分の場合はGitHub ActionsやGradleなどのCI/CDワークフローの保守性や実行性能、ビジネスロジックの実行性能、そしてドメインの課題をシステムとチームやその周辺領域で解決することでした。そこから派生してサイバーセキュリティやDDD、クラウドにおけるアプリケーションアーキテクチャなんかも関心領域ではあるのですが、究極は「ユーザとチームが喜んでいるところが見える」ことが自分の価値観のコアでした。この価値観はマネジメントをやったからこそ発見できた側面も大きいので、趣味だけでなく仕事の場でも「まずはなんでもやってみる」を続けた価値があったと考えています。

加えて、技術的関心のコアについても自負するところがあると良いと思います。自分の場合は「CIでくるくるビルドとテストを回して目に見えた改善と維持ができる」ことです。作って数カ月後に成果がわかるのではやっていけないし、数カ月寝かせたプロジェクトのキャッチアップに数日かかるようでもだめです。これがわかったからこそクラウドでマルチテナントSaaSを開発する会社を転職先に選びましたし、コードに”血が通い続ける”ことに異常に執着していますし、事業ドメインが違ってもまぁやっていけるだろうなという自信にもなっています。

20-30代で磨いておいて良かった能力、もっと磨きたかった能力

間違いなく言えるのは国語力です。これはWorking Out Loudを実行するフットワークや、自分の考えをテキストに落とし込む言語化能力もコミです。他の人がなかなか言語化できていないことをヒアリングしてグラフにしたり, 異なる立場の人を集めて問題構造をひとつの文書に落としたり, 技術広報に役立ったりと、様々な恩恵を受けてきたので読書やブログをやっててほんとに良かったと思います。抽象と具象とを行き来することを生業とするITエンジニアであれば必ず恩恵に預かれる能力だと思うので、個人的にはおすすめです。

反面、海外赴任をしたのでまぁ仕方ないと思いつつ、業界での横のつながりはもっと作っておくべきだったと思っています。転職回数も少ないので、何か困ったときに社外に助けを求める選択肢があまり無いという問題が顕著になってきています。最近になって情報処理安全確保支援士会などの場に顔を出すようになったのは、この危機感の表れでもあります。

年齢とキャリア

このブログを書いたもともとのきっかけは、40歳になってからのキャリアアップに関する議論でした。個人的には年齢によるキャリアへの影響はあると思っています。というか、年齢が上がるにつれて転職ではなく社内評価によるキャリア変革の割合が大きくなっていくんじゃないかと感じています。

年齢が上がるということは経験を持っているということで、やはり技術的・ドメイン的・業界的な理解を期待されます。またスタッフエンジニアやCクラスになると影響する従業員や事業領域も大きくなるので、目で見た実績がないとなかなか未経験者を引き上げるというリスクが冒せないんじゃないかという気持ちもあります。一般的な話としてはComplicated Subsystemとしてコンサル的に活躍する道はあるとは思うんですが、自分の価値観のコアとしてはそれを本業にするイメージはないのと、やはり生成AIなどが取って代わるリスクが高すぎるように思うので、リファラルで釣ってもらえるだけの人脈と実績がなければやはり社内評価によるキャリア変革の重要性は高まるんじゃないでしょうか。

なお、ある程度年齢を食っているので、社内評価の機会を獲りに行くだけでなくて"若者"の邪魔にならないようにするという観点もまた重要なんですが、それすなわち黙っていることではないとも思ってます。このへんは別の機会に掘り下げます。

見えるアウトプットを作っておく

これは他の人に説明するときに役立つというのもそうなんですが、転職して社内資源にアクセスできなくなったあとも役に立つので、ITエンジニアはちゃんとアウトプットをインターネット上に残しておくとよいです。これは登壇でもいいですし、ブログでもいいでしょう。自分は前職で書いた技術ブログが海の藻屑と消えたので、リスク分散の観点から個人の登壇やブログ, 技術書執筆も視野に入れるといいんじゃないかとは思います。

原資を確保する

ITエンジニアとして新たな領域を開拓するということは、本を買うとかサーバを買うとかクラウドを使うとか懇親会に参加するとかのお金がかかります。ので原資の確保が重要です。キャリアのはじめこそ、所得はきちんと確保したほうがいいです。家族を持つときがきた場合にも、その判断は役に立つはずです。

自分は単純に運で乗り切ったため、そのためにどうするべきかは語れないんですが、価値観のコアが許せば景気の良い業界に目を向けるというのは一助になるかもしれません。自分はNetbeansなんかの凋落を遠目に見てきたので、IT技術は金があってはじめて維持できるものだという実感があります。また所得の高い会社はそれだけ同僚や先輩の質も期待できるので、選考プロセスを通して自分の目で判断することは必須ですが、就職時の足切りとしてはかなり大切な観点だとも思っています。

まとめ

キャリア論なんてものはないので、自分がどう生きたいかを問い続けるしかないと思っています。その問いの中心には、価値観と技術的関心のコアがあるはずです。まずはそれを見つけたい。

ITエンジニアでも、ITエンジニアだからこそ、国語力や人とのつながりが重要です。そうしたものを作る下積みや習慣は早めに工数をかけたほうが良さそうです。そして新たなつながりを作るきっかけになるアウトプットは、インターネットにきちんと残しておきましょう。

ビジネスとは問題解決のフラクタル構造でしょ的な割り切りの話

「戦略の要諦」を読みました。この本が語っている「戦略」は戦略の一部であり狭義の存在なので、あまり「戦略」という言葉を使ってほしくなかったなぁというのが第一印象でした。戦略論の世界的権威に何言ってるんだとは自分でも思いますが。。。

広義の戦略について理解していると、狭義の戦略を理解する助けになる

もう少し掘り下げて説明すると、自分の中では「戦略とは現状を理想に近づけるための実現可能なアプローチのこと」だという理解ができていて、実際に著者が言っている戦略はその「広義の戦略」のサブセットとして説明できると感じました。著者は組織的課題を克服するための戦略について話していて、その過程で出てくる「良い戦略」「良い目標」そして「戦略ファウンドリー」はすべて他の戦略でも適用できます。

graph TD
  理想的状態 
  眼前の現状
  組織の理想
  組織の現状

  眼前の現状 --->|広義の戦略| 理想的状態
  理想的状態 <-.->|問題(理想と現実の差分)| 眼前の現状

  組織の現状 --->|本書の戦略| 組織の理想
  組織の理想 <-.->|問題(理想と現実の差分)| 組織の現状

中でも「戦略ファウンドリー」は、アジャイルで頻出の概念やスクラムマスターの心得を別の角度から言い換えたものが多く含まれています:

  • 判断の先送り→アイスボックス
  • タイムトラベラーになってみる→プレモーテム
  • 組織の問題に目を向ける、なぜ困難なのかを考える、反省的思考を行う→レトロスペクティブ
  • 現実的に取り組み可能な戦略課題を見つける、近い目標に集中する、期間を設定する、即席戦略を考える→スコープの管理
  • 宣誓式、課題から始める→プランニング

のでこの本は組織的課題克服の実践を学ぶうえでは良書だと思いますし、自分も多くを学びましたが、問題解決というフレームワークの運用に自信があるならばそこまで収穫はないかもしれないと感じました。ただ改めて問題解決フレームワークの重要性に気づけたため、ここを掘り下げて考えてみたいと思います。

ビジネスにおいて問題とは同じ構造が入れ子になっているもの

「戦略の要諦」が組織課題の解決に問題解決フレームワークを適用したように、事業課題や製品課題、顧客課題の解決にも問題解決フレームワークが適用できます。組織や個人、製品といった異なる主体が抱える課題にも適用できます。

さらにちょっとデカめの問題解決をすると、問題解決のための戦略がさらに問題を内包していることに気づくと思います。複数の問題が循環参照を持っていることも少なくありません。だから因果関係をツリー状に整理して、真の問題・ボトルネックを特定するフレームワークである現状問題構造ツリー(CRT、ザ・ゴール2に掲載)*1などによって問題の間に横たわる関係性を描いて、真に解くべき問題を洗い出して優先度をつけることになります。

ここから学ぶべきことは、自分が直面している問題の外側にも問題があるということです。自分が認知していないだけで「外側」に問題があると意識するだけで、相談するべき人や想定すべき影響、自分が意識できてない視点などを見つける手がかりになります。

Findyさんのとこid:Soudai さんが使っていらっしゃるこの図がわかりやすいので引用すると、問題の外側(図で言う視野外の事実)があることに自覚的になると、視座を上げるための行動を取りやすいということですね。

図1 問題解決が入れ子になっていると意識すると視座を上げて新たな視点を得る助けになる

ビジネスにおいて問題は複数の関心に投影される

問題解決は外と内という視座の違いで入れ子構造を作るだけでなく、同じ視座でも異なる視点に投影できるという特徴もあります。たとえば「納期が守れない」という問題を解決する戦略を営業と製造の観点から作成すると、全く異なる戦略が出てくるでしょう。

図2 投影という概念の例示(TensorFlowのロゴ)

ここで重要なのは、営業と製造の双方の戦略をよしなにマージしないと真の問題解決にはならないということです。実際は営業と製造だけではなく、経理や調達をはじめとした多角的な視点からの検討が必要でしょう。もちろん自分にとってControllableな範囲でぱぱっと解決を作ることも重要なんですが、広範な視点を統合すること、すなわち関係者のモチベーションを高めて巻き込んではじめて「チームで問題解決ができる」ので。わざわざ法人というチームを作って問題解決にあたるビジネスにおいては必須だと言って良いでしょう。

これは視座を上げても通用します。たとえば最近地方独立行政法人 岡山県精神科医療センターのランサムウェア事案調査報告書を読んだのですが、多くの人がこれを読んでまず出てくる感想は「医療情報システムと医療機器のベンダーがクソだな」じゃないかと思います。実際私もそうですが、では今ある医療情報システムと医療機器のベンダーを全部潰したらこの事例は良くなるのか?業界の問題は解決するのか?と考えるとそれは違うとも思います*2。徳島・大阪・岡山と大きな事例が続いていることを考えても、病院という仕組み、ひいては医療業界全体になにか問題があると考えるべきでしょう。

わかりやすい悪に飛びつかず中長期的な視点をもとに息の長い社会課題解決ビジネスを行うためにも、問題解決が入れ子構造であることや複数の視点に投影できることに意識的になっておきたいと思いました。

まとめ

理想と現実のギャップに向き合い解決するという問題解決フレームワークを紹介しました。また問題解決は同じような構造が視座や視点を変えても繰り返し現れるフラクタル構造であるとも述べました。これを意識することで異なる視座や視点への想像力が生まれ、より広範な専門家の協力を得て問題解決に臨めるようになるため、息の長い社会課題解決ビジネスを行ううえで重要な発想であると考えました。

*1:問題がMECEに分解できるならロジックツリーだけど、漏れなくはともかくダブりなく分解することはあんま現実的じゃないと思っている

*2:注意点として、筆者は破壊的イノベーションを行う医療情報システムのベンダーに勤めています