背景
「脳に収まるコード 13.2.3 何をログに出力するか」に感銘を受けました。
本書からの言葉を引用します
純粋でない操作を記録し、それ以上は記録しない
必要な分だけログ出力できる方法はぜひ理解したいところです。
本書の言う「関数型コア・命令型シェル」のアーキテクチャを支持する理由とは
本書では「Haskellに移行することを期待するわけではない」と断りつつ
コードベースから純粋でない操作を独立させられる。
コードを純粋関数で組み立てると、ログに出力すべきところは減る
とされています。
残すべきログとは
このような純粋関数を意識した構成とすることで
「後から再現できないものを残す」という方法がとれます。
純粋な操作(副作用のないよう構築された業務ロジック)は入力が同じであれば出力は同じです。
つまり出力は再現できるので不要なのです。
具体的なイメージ
抽象的過ぎて難しいので、要点をゴルフ1の例えにまとめます。
ゴルフで例えるログ戦略(導入部)
ゴルフコースに立つ一人のプレイヤー。
その一打には、三つの異なる役割が存在しています。
それは「作戦」「実行」「記録」という、三つの側面です。
プロゴルファーの一打を例に、この構造を紐解きます。
第一の段階:作戦(関数型コア)
プレイヤーは、ボールを打つ前に、キャディと共に思考を巡らせます。
これが「作戦」を立てる段階であり、
ソフトウェアにおける「コアロジック」に相当します。
まず、現状を観察し、情報を集めます。
入力情報
- カップまでの距離は、どのくらいか
- 風向きと、その強さは
- 視界に入るバンカーなど、障害物の位置は
これらの情報から、最善と思われる一手、すなわち「出力」を導き出します。
決定事項
「7番アイアンを選択し、少し右を狙って打つ」
この段階では、まだクラブは握られていません。
これは純粋な思考のプロセスであり、集めた情報だけを基に「何をすべきか」を決定する、計算の時間です。
第二の段階:実行(命令型シェル)
次に、立てた作戦を物理的な行動に移します。
これが「実行」の段階であり、システムの「シェル」が担う役割です。
頭の中で描いた通りのスイングで、ボールを打ちます。
実行時の不確実性
しかし、現実の世界は、常に不確実性を伴います。
- 想定よりも、力が入りすぎてしまった
- インパクトの瞬間に、予期せぬ突風が吹いた
どれほど優れた計画であっても、それを実行する際には、こうした予測不能な事態が介在します。
これが、現実世界との接点を持つことの難しさです。
第三の段階:記録(ログの役割)
そして、優れたプレイヤーは、次の一打、次のラウンドのために、プレイを振り返ります。
そのために不可欠なのが「記録」です。
どのような記録が、未来の自分にとって有用でしょうか。
有用でない記録
「7番と8番、どちらのクラブを使うか、とても悩んだ」
(これは単なる感情の記録であり、次の作戦決定には寄与しません。)
有用な記録
状況(入力): 「カップまで150ヤード。左から、やや強い風。」
結果: 「7番アイアンで打ち、ボールは右手のバンカーへ。」
この記録があれば、後から分析することが可能になります。
「あの状況下で7番アイアンを選択すると、ボールはバンカーに入る傾向がある。
次は、6番アイアンで臨むという作戦を試す価値がありそうだ」
検証・改善のサイクル
このように、「どのような状況(入力)」が「どのような結果」に繋がったかを客観的に記録することで、もとの「作戦(計算)」そのものが妥当であったかを検証し、改善のサイクルを回すことができるのです。
まとめ
ゴルフの一打を、「作戦(頭脳)」、「実行(身体)」、そして「記録(記憶)」という三つの要素に分けて捉える。
この視点を持つことで、一つひとつのプレイを冷静に分析し、次に繋げることができます。
この構造は、ソフトウェアにおける「ログ」のあり方と、本質的に同じものを感じます。
-
残念ながら、筆者はゴルフについて明るくありません。テレビで見る程度の知識です。 ↩