TadaoYamaokaの開発日記

個人開発しているスマホアプリや将棋AIの開発ネタを中心に書いていきます。

【読書ノート】SCRUMMASTER THE BOOK 優れたスクラムマスターになるための極意――メタスキル、学習、心理、リーダーシップ

書籍「SCRUMMASTER THE BOOK 優れたスクラムマスターになるための極意――メタスキル、学習、心理、リーダーシップ」を読んだので内容をまとめる。
以下の内容は、ほとんどClaude3 Opusを使用して作成している。

要約

CHAPTER1 スクラムマスターの役割と責務

スクラムマスターは、自己組織化したチームを作り、ハイパフォーマンスなチームへと導くことが使命である。秘書のような仕事ではなく、チームの改善活動において欠かせない存在であり、アジャイルスクラムのエキスパートである。スクラムマスターは、チームの自己組織化を促進し、障害を取り除き、透明性を高めることで、チームが最高のパフォーマンスを発揮できるようにサポートする。そのため、スクラムマスターにはサーバントリーダーシップが求められ、観察力や傾聴力、共感力などが必要不可欠である。

重要なポイント
理解度確認のための質問

1. スクラムマスターの最終目標は何か?
2. スクラムマスターに求められるリーダーシップのスタイルは何か?
3. スクラムマスターに必要な3つのスキルを挙げよ。

CHAPTER2 心理状態モデル

スクラムマスターは、チームの状況に合わせて適切なアプローチを使い分ける必要がある。その手段となるのが、スクラムマスターの心理状態モデルである。これは、ティーチング・メンタリング、障害物の除去、ファシリテーションコーチングの4つのアプローチから成る。スクラムマスターは、チームの成熟度や置かれた状況を見極め、最適なアプローチを選択する。ただし、どのアプローチを取る前にも「観察」が重要であり、チームの状態を注意深く見守ることが肝要である。

重要なポイント
  • スクラムマスターは状況に応じて適切なアプローチを選択する必要がある
  • 心理状態モデルは4つのアプローチ(ティーチング・メンタリング、障害物の除去、ファシリテーションコーチング)から成る
  • チームの成熟度や状況に合わせてアプローチを使い分けることが重要である
  • どのアプローチを取る前にも「観察」が重要である
理解度確認のための質問

1. スクラムマスターの心理状態モデルを構成する4つのアプローチは何か?
2. スクラムマスターがアプローチを選択する際に考慮すべき点は何か?
3. 心理状態モデルにおいて、アプローチを選択する前に重要な活動は何か?

CHAPTER3 #スクラムマスター道

#スクラムマスター道は、スクラムマスターの成長段階を表す3つのレベル(私のチーム、関係性、システム全体)から成るモデルである。最初のレベルでは、スクラムマスターは自分の担当チームに注力する。次のレベルでは、チームを取り巻くステークホルダーとの関係性にも目を向ける。最終的には組織全体の改善を目指し、システム思考でアプローチする。各レベルで必要なスキルや心構えは異なるが、下位のレベルの課題をクリアしてから次のレベルに進むことが重要である。また、スクラムマスター同士が自己組織化したチームを作ることが、組織全体の変革において効果的である。

重要なポイント
  • #スクラムマスター道は3つのレベル(私のチーム、関係性、システム全体)から成る
  • 各レベルでスクラムマスターに求められる役割は異なる
  • 下位のレベルの課題をクリアしてから次のレベルに進むことが肝要である
  • スクラムマスター同士の自己組織化したチームが組織変革の鍵を握る
理解度確認のための質問

1. #スクラムマスター道を構成する3つのレベルは何か?
2. スクラムマスターが次のレベルに進む際の留意点は何か?
3. 組織全体の変革において、スクラムマスター同士が果たすべき役割は何か?

CHAPTER4 メタスキルとコンピタンス

スクラムマスターに必要なメタスキル(ある状況において意図的に取る態度、考え方、スタンス)には、ティーチング、傾聴、好奇心、尊敬、遊び心、忍耐などがある。これらは、状況に応じて使い分けることが大切である。また、コンピタンス(能力)としては、アジャイルの理解、説明と経験の共有、ファシリテーションコーチング、そしてビジネス知識、チェンジマネジメント、技術知識を兼ね備えている必要がある。スクラムマスターは自己研鑽を怠らず、これらのメタスキルとコンピタンスを高めていくことが求められる。

重要なポイント
  • スクラムマスターに必要なメタスキルには、ティーチング、傾聴、好奇心、尊敬、遊び心、忍耐などがある
  • メタスキルは状況に応じて使い分けることが重要である
  • スクラムマスターに求められるコンピタンスは、アジャイルの理解、説明と経験の共有、ファシリテーションコーチング、ビジネス知識、チェンジマネジメント、技術知識である
  • スクラムマスターは自己研鑽を怠らず、メタスキルとコンピタンスを高めていく必要がある
理解度確認のための質問

1. スクラムマスターに必要な代表的なメタスキルを3つ挙げよ。
2. スクラムマスターがメタスキルを扱う上で大切なことは何か?
3. スクラムマスターに求められるコンピタンスを3つ挙げよ。

CHAPTER5 チームを構築する

チーム作りは、スクラムマスターにとって最重要のコンピタンスである。本章では、チーム構築のためのモデルやフレームワークが紹介されている。タックマンの集団発達モデルは、チームがたどる成長段階(形成期、混乱期、統一期、機能期)を理解するのに役立つ。レンシオーニの5つの機能不全は、チームの抱える問題を特定し、解決に導くためのヒントを与えてくれる。また、非難、防衛、壁、侮辱の4つの毒には注意が必要である。優れたスクラムマスターは、これらのモデルを使いこなし、チームを次のステージへと導いていく。

重要なポイント
  • チーム構築はスクラムマスターの最重要コンピタンスである
  • タックマンの集団発達モデルは、チームの成長段階を理解するのに役立つ
  • レンシオーニの5つの機能不全は、チームの問題特定と解決に有効である
  • 非難、防衛、壁、侮辱の4つの毒に注意が必要である
  • スクラムマスターはこれらのモデルを使いこなし、チームを導く必要がある
理解度確認のための質問

1. タックマンの集団発達モデルにおける4つの段階を順に挙げよ。
2. レンシオーニの5つの機能不全とは何か?
3. チームの議論の中で注意すべき4つの毒とは何か?

CHAPTER6 変化を実装する

スクラムマスターは変化のガイド役として、チームや組織が新しい道を歩み出すための支援をする。まずは、変化を必要としている正しい理由を見出すことが不可欠である。そのためにアジャイルの車輪を使い、現状把握と未来への期待値を共有する。その上で、人々の行動が変わるように促していく。変化を成功させるためのコッターの8ステップ(危機意識、ガイディングチーム、ビジョンの創造、ビジョンの共有、行動の促進、短期的成果、さらなる変化、新しい文化の定着)も有効なフレームワークとなる。スクラムマスターは人々の抵抗に寄り添いつつ、しっかりとした理由と高いモチベーションを持って変化を推進していくことが求められる。

重要なポイント
  • スクラムマスターは変化のガイド役である
  • 変化にはしっかりとした理由と高いモチベーションが必要である
  • アジャイルの車輪で現状と期待値を可視化する
  • 人々の行動が変わるように働きかけることが重要である
  • 変化には抵抗がつきもの。スクラムマスターは寄り添いつつ推進する
理解度確認のための質問

1. 組織が変化を始める前に明確にしておくべきことは何か?
2. 変化を成功に導くためのコッターの8ステップを3つ挙げよ。
3. 変化を推進する上で、スクラムマスターはどのような姿勢で臨むべきか?

CHAPTER7 スクラムマスターの道具箱

本章では、スクラムマスターがチームや組織の改善のために活用できる手法やフレームワークが数多く紹介されている。守破離モデルは、プラクティスの習熟度合いを理解するのに役立つ。ポジティブな言動は、チームを健全に保つために重要である。根本原因分析やインパクマッピングは、問題や戦略をより深く理解する手段になる。大規模スクラム(LeSS)は、スクラムをスケールするフレームワークである。このように、スクラムマスターが使える手法は多岐にわたる。状況に応じて適切な手法を取捨選択し、チームやステークホルダーとともに実践していくことが、スクラムマスターに求められる。

重要なポイント
理解度確認のための質問

1. 守破離モデルにおける3つの段階とその意味を説明せよ。
2. ポジティブとネガティブの健全なバランスはどの程度か?
3. 根本原因分析の代表的な手法を2つ挙げよ。

CHAPTER8 私は信じています

著者は、誰もが偉大なスクラムマスターになれると信じている。そのためには現在の役割や地位にとらわれることなく、アジャイルコーチングという未知の世界に飛び込む勇気が必要である。偉大なスクラムマスターを有する企業は、ダイナミックで創造的な学習型組織へと変革できる。スクラムマスターの仕事はチームを越えて組織全体にも影響を及ぼすものであり、企業の成功に不可欠な存在である。本章では、著者のスクラム支援サービスとともに、アジャイルスクラムに取り組む様々な企業に向けたメッセージが綴られている。

重要なポイント
  • 誰もが偉大なスクラムマスターになれる
  • そのためには勇気を持って新しい世界に飛び込む必要がある
  • 偉大なスクラムマスターを有する企業は変革へのアドバンテージを持つ
  • スクラムマスターの仕事は企業の成功に不可欠である
  • 著者は企業のスクラム実践を支援している
理解度確認のための質問

1. 著者が信じている「誰もが偉大なスクラムマスターになれる」ために必要なことは何か?
2. スクラムマスターはチームだけでなく、組織全体に対してどのような影響を及ぼすか?
3. 著者はどのようなサービスを通じて、企業のスクラム実践を支援しているか?

日本語版付録 10分でスクラム

スクラムシリコンバレーのチーム文化や日本の製造業の製品開発プロセスを参考に考案された、不確実性の高い環境下でのソフトウェア開発フレームワークである。自己組織化したチームを信頼し、彼らが透明性や検査、適応を通じて成果を出していくことを重視している。スクラムを構成する主な要素は、スクラムマスター、プロダクトオーナー、開発チームという3つの役割と、スプリント、デイリースクラム、スプリントレビュー、レトロスペクティブなどのイベントである。プロダクトオーナーは優先順位をつけたプロダクトバックログを作成し、開発チームはスプリントごとに動作するインクリメントを完成の定義に従って構築する。スクラムではプロジェクトごとにチームを解散するのではなく、長期間安定したチームを前提とすることで、学習と改善を継続的に行っていく。

重要なポイント
  • スクラムシリコンバレーと日本の製造業の知見を参考に生まれた
  • 自己組織化したチームを信頼し、透明性・検査・適応を重視する
  • 主な要素は、3つの役割(スクラムマスター、プロダクトオーナー、開発チーム)とイベントである
  • プロダクトオーナーはプロダクトバックログを作成し、優先順位をつける
  • 開発チームはスプリントごとに動作するインクリメントを完成の定義に従って構築する
  • 長期安定したチームを前提に、学習と改善を継続的に行う
理解度確認のための質問

1. スクラムが参考にしたとされる2つの異なる文化・知見は何か?
2. スクラムを構成する3つの役割を挙げよ。
3. スクラムではチームの解散をどのように捉えているか?

よく使われる重要な概念の解説

  • 自己組織化:チームが自律的に仕事の進め方を決め、外部からの指示をできる限り減らすこと。メンバーが主体的に考えて行動し、チームの価値を高めていく。
  • タックマンモデル:チームが辿る成長段階(形成期、混乱期、統一期、機能期)を示したモデル。各ステージでの課題を理解し、適切なアプローチでチームの発展を支援する。
  • サーバントリーダーシップ:メンバーに奉仕することでリーダーシップを発揮するスタイル。指示命令ではなく、メンバーの成長を後押しし、主体性を引き出す。
  • 心理状態モデル:スクラムマスターがチームに対して取るべき4つのアプローチ(ティーチング・メンタリング、障害の除去、ファシリテーションコーチング)を示したモデル。状況に応じて適切なアプローチを選択する。
  • メタスキル:特定の状況で意図的に発揮する態度や心構え。スクラムマスターに求められるメタスキルには、傾聴、好奇心、忍耐などがある。
  • 5つの機能不全:信頼の欠如、衝突の回避、コミットメントの欠如、説明責任の回避、結果への無関心という、チームの機能不全を引き起こす5つの要因。これらを特定し、改善することがチーム構築に不可欠である。
  • 根本原因分析:問題の表面的な症状ではなく、その根本的な原因を探ること。フィッシュボーンダイアグラムやなぜなぜ分析などの手法を用いて、問題の本質に迫る。
  • インパクマッピング:プロダクト開発や組織変革において、ゴールとそれを達成するための具体的なアクションを可視化する手法。ゴール、アクター、インパクト、デリバリーの4つの階層で構成される。
  • 守破離:型を守り、型を破り、型から離れるという3つのステージを踏むことで、プラクティスを習得し、自在に使いこなせるようになるという考え方。スクラムマスターの成長過程にも当てはめられる。
  • アジャイルコーチ:チームや組織にアジャイルな考え方や手法を導入し、定着させるための支援を行う専門家。スクラムマスターの役割を組織全体に拡張したものと捉えることができる。

書評

本書は、スクラムマスターという役割に焦点を当てつつ、アジャイルスクラムの本質を理解し、チームと組織を改善するためのヒントに満ちている。単なるプロセスやイベントの facilitator ではなく、自己組織化したチームを育て、組織の文化を変革するリーダーとしてのスクラムマスターの姿が描かれている。
特に印象的なのは、スクラムマスター自身の成長段階を示した #スクラムマスター道の概念である。チームのためだけでなく、組織全体のために自らの役割を拡張していく道のりは、スクラムマスターにとって励みになるであろう。
また、チームを導くためのモデルやフレームワークが数多く紹介されている点も本書の魅力である。タックマンモデルや5つの機能不全、システム思考などは、チームの状態を分析し、改善アクションにつなげる上で強力な武器になる。
一方で、スクラムマスターに求められるスキルやマインドセットは多岐にわたり、習得にはある程度の時間を要すると感じた。本書で提示された守破離の概念を念頭に、まずは基本を身につけつつ、reflectと学び続ける姿勢が大切だと思う。
本書はスクラムマスターの役割を、チームと組織の成功を支えるサーバントリーダーとして再定義している。アジャイルの理念を組織の随所に働きかけ、変革を導いていく存在として、スクラムマスターの真の価値を見出せる1冊だと感じた。スクラムマスターを目指す人だけでなく、チームを率いるリーダーや、組織開発に携わる方々にもおすすめしたい良書である。

【読書ノート】科学的根拠に基づく最高の勉強法

書籍「科学的根拠に基づく最高の勉強法」を読んだので内容をまとめる。
以下の内容は、ほとんどClaude3 Opusを使用して作成している。

要約

はじめに

本書は、科学的に根拠のある効果の高い勉強法について、心理学や脳科学の研究によって得られた客観的な証拠に基づいて紹介している。単なる個人の経験や伝統的な方法ではなく、科学的根拠に基づく勉強法を知り、実践することで、読者がより良い人生を過ごせることを願って書かれた一冊である。「勉強する」という行為には人によって大きな違いがあり、効果的な勉強プロセスとそうでないものがあることを示唆している。本書では、誰でも実践でき、科学的に効果が確認された勉強法を具体的に説明していく。

重要なポイント
  • 本書は科学的根拠に基づく効果的な勉強法を紹介している
  • 勉強のプロセスには人によって違いがあり、効果的なものとそうでないものがある
  • 本書で紹介する勉強法は誰でも実践可能で、科学的に効果が確認されたものである
理解度確認のための質問文
  • 本書で紹介されている勉強法の特徴は何ですか?
  • なぜ著者は本書を執筆したのですか?
  • 効果的な勉強プロセスとそうでないものの違いは何ですか?

CHAPTER1 科学的に効果が高くない勉強法

科学的に効果があまり高くないとされている勉強法として、繰り返し読む(再読)、ノートに書き写す・まとめる、ハイライトや下線を引く、好みの学習スタイルに合わせることが紹介されている。これらの方法は、多くの学習者が実践しているものの、記憶の定着や理解度の向上に有効ではないことが複数の研究で示されている。時間をかけていても成績が伸びない場合、勉強法を見直すことが重要だと著者は指摘する。

重要なポイント
  • 再読、書き写し・まとめ、ハイライト・下線、学習スタイルの選択は効果が低い
  • これらの方法は多くの学習者が実践しているが、記憶の定着や理解度向上に有効ではない
  • 時間をかけても成績が伸びない場合は勉強法の見直しが必要
理解度確認のための質問文
  • 再読、書き写し・まとめ、ハイライト・下線、学習スタイルの選択の問題点は何ですか?
  • これらの方法が効果的でないことを示す研究結果はありますか?
  • 勉強に時間をかけているのに成績が伸びない場合、何をすべきですか?

今日から実践したい!こんな勉強法 科学的に効果が高い勉強法1 アクティブリコール

記憶するためには、学習内容を積極的に思い出す作業や、脳から能動的に引き出す作業が決定的に重要であることが明らかになっている。この「アクティブリコール」は、ただ繰り返し読むよりも記憶の定着に効果的であり、直接聞く問題だけでなく、推論など深い理解が必要な応用問題に対しても有効である。著者自身が実践している「白紙勉強法」を例に、アクティブリコールの具体的な方法が紹介されている。

重要なポイント
  • 学習内容を積極的に思い出す、脳から能動的に引き出すことが重要
  • アクティブリコールは記憶の定着に効果的で、応用問題にも有効
  • 著者の実践する「白紙勉強法」は、アクティブリコールの具体例
理解度確認のための質問文
  • アクティブリコールとはどのような勉強法ですか?
  • アクティブリコールが記憶の定着に効果的な理由は何ですか?
  • 著者が実践している「白紙勉強法」とはどのようなものですか?

今日から実践したい!こんな勉強法 科学的に効果が高い勉強法2 分散学習

一度にまとめて勉強するよりも、時間を分散して勉強するほうが長期的な記憶の定着が良いことが知られている。この「分散学習」の効果は、幅広い分野の勉強において確認されており、学習の間隔を長くあけるほうがより長く記憶に定着することも示されている。アクティブリコールと分散学習を組み合わせた「連続的再学習」は、現代の学習の科学的根拠に基づく、誰でも実践可能で効果の高い方法だと著者は述べている。

重要なポイント
  • 一度にまとめて勉強するよりも、時間を分散して勉強するほうが記憶の定着が良い
  • 分散学習の効果は幅広い分野で確認されている
  • 学習の間隔を長くあけるほうが記憶の定着が長い
  • アクティブリコールと分散学習を組み合わせた「連続的再学習」が効果的
理解度確認のための質問文
  • 分散学習とはどのような勉強法ですか?
  • 分散学習の効果が確認されている分野にはどのようなものがありますか?
  • 「連続的再学習」とはどのような勉強法ですか?

今日から実践したい!こんな勉強法 科学的に効果が高い勉強法3 精緻的質問と自己説明

精緻的質問と自己説明は、学習内容について自問自答し、自分の言葉で説明することで理解を深める方法である。勉強した内容に対して「なぜそうなっているのか」「どのようにそうなっているのか」と自分自身に質問したり、学んだ情報を自分の知識と関連づけて説明したりすることで、より勉強の効果が高まる。著者は、日常の些細なことに対しても「なぜ?」と問いかける習慣の重要性を指摘している。

重要なポイント
  • 学習内容について自問自答し、自分の言葉で説明することで理解が深まる
  • 「なぜ」「どのように」と自分自身に質問することが大切
  • 学んだ情報を自分の知識と関連づけて説明することで学習効果が高まる
  • 日常の些細なことに対しても「なぜ?」と問いかける習慣が重要
理解度確認のための質問文
  • 精緻的質問と自己説明とはどのような勉強法ですか?
  • 学習内容について自問自答することの重要性は何ですか?
  • 日常の些細なことに対して「なぜ?」と問いかける習慣の意義は何ですか?

今日から実践したい!こんな勉強法 科学的に効果が高い勉強法4 インターリービング

インターリービングは、似ているが異なる複数のスキルや勉強のトピックを交互に学習する方法である。数学や運動のスキルなど、幅広い分野でその効果が確認されている。一方で、全く異なる教科を混ぜこぜにしてもあまり効果は期待できない。著者は、医師国家試験の勉強で、問題を混ぜこぜにしてやることで知識の応用力を高めていたと述べている。

重要なポイント
  • 似ているが異なる複数のスキルやトピックを交互に学習する方法
  • 数学や運動のスキルなど、幅広い分野で効果が確認されている
  • 全く異なる教科を混ぜこぜにしてもあまり効果は期待できない
  • 問題を混ぜこぜにすることで知識の応用力が高まる
理解度確認のための質問文
  • インターリービングとはどのような勉強法ですか?
  • インターリービングの効果が確認されている分野にはどのようなものがありますか?
  • 著者が医師国家試験の勉強で行っていたインターリービングの方法とは何ですか?

CHAPTER3 覚えにくいものを覚える古代からの記憶術

覚えにくい情報を記憶するために、イメージに変換する記憶術が紹介されている。数字を語呂合わせでイメージに変換する方法や、複数の情報をストーリーとしてつなげるストーリー法、記憶の置き場所を決めてイメージを配置する場所法などがある。記憶術は、紀元前から人類が編み出してきた覚えにくいものを覚えやすくする「頭の使い方」であり、誰でも練習すれば使えるようになる。著者は、記憶術を試験勉強などで活用している。

重要なポイント
  • 覚えにくい情報をイメージに変換する記憶術が紹介されている
  • 数字の語呂合わせ、ストーリー法、場所法などの具体的な方法がある
  • 記憶術は紀元前から人類が編み出してきた「頭の使い方」
  • 記憶術は練習すれば誰でも使えるようになる
  • 著者は記憶術を試験勉強などで活用している
理解度確認のための質問文
  • 本章で紹介されている記憶術にはどのようなものがありますか?
  • 記憶術の起源はどこまで遡れますか?
  • 著者はどのように記憶術を活用していますか?

勉強にまつわる心・体・環境の整え方1 勉強のモチベーション

自分に関連した情報ほど覚えやすいため、学習内容と自分との関連性を考えることが重要である。また、自分ができるという感覚である自己効力感を高めることが、学習のモチベーションに影響する。内発的な目標の設定、自律性、有能感、他者とのつながりを満たすことが内発的動機づけにつながる。著者は、モチベーションに関する理論的枠組みとして、自己決定理論を紹介している。

重要なポイント
  • 学習内容と自分との関連性を考えることが重要
  • 自己効力感を高めることがモチベーションに影響する
  • 内発的な目標設定、自律性、有能感、他者とのつながりが内発的動機づけにつながる
  • 自己決定理論がモチベーションを考える上での理論的枠組みとして紹介されている
理解度確認のための質問文
  • 学習内容と自分との関連性を考えることの重要性は何ですか?
  • 自己効力感とは何ですか?それはどのようにモチベーションに影響しますか?
  • 自己決定理論の中核をなす概念は何ですか?

勉強にまつわる心・体・環境の整え方2 勉強のヒント

勉強する場所を変えることで、記憶の文脈効果を利用できる可能性がある。スキマ時間を有効活用することや、勉強で使えるツールとしてのアプリケーションの活用法が述べられている。一方で、スマートフォンは集中力を奪うため、勉強中は手元に置かないことが推奨される。筆者は、好奇心の赴くままに学ぶことの重要性を指摘し、勉強以外の人生の大切なことを忘れないようにと述べている。

重要なポイント
  • 勉強する場所を変えることで記憶の文脈効果を利用できる可能性がある
  • スキマ時間の有効活用が大切
  • アプリケーションの活用が学習の助けになる
  • スマートフォンは集中力を奪うため、勉強中は手元に置かない
  • 好奇心の赴くままに学ぶことが重要
  • 勉強以外の人生の大切なことを忘れないようにする
理解度確認のための質問文
  • 勉強する場所を変えることの意義は何ですか?
  • スマートフォンが集中力に与える影響とはどのようなものですか?
  • 著者が強調している、好奇心に従って学ぶことの重要性とは何ですか?

勉強にまつわる心・体・環境の整え方3 睡眠の大切さ

睡眠は記憶の固定化に重要な役割を果たしている。睡眠不足は健康被害だけでなく、学習効果の低下にもつながる。睡眠の質を高めるためには、光の管理、規則正しい生活習慣、眠る前の過ごし方に気をつける必要がある。学習者は、睡眠を学習の一部と捉え、意識的に良質な睡眠を取ることが求められる。

重要なポイント
  • 睡眠は記憶の固定化に重要な役割を果たす
  • 睡眠不足は健康被害と学習効果の低下につながる
  • 睡眠の質を高めるために生活習慣に気をつける
  • 睡眠を学習の一部と捉え、良質な睡眠を意識的に取ることが大切
理解度確認のための質問文
  • 睡眠が記憶の固定化に果たす役割とは何ですか?
  • 睡眠不足によってもたらされる問題にはどのようなものがありますか?
  • 良質な睡眠を取るために気をつけるべきことは何ですか?

勉強にまつわる心・体・環境の整え方4 運動の大切さ

運動には海馬の神経細胞の増殖を促し、認知機能を高める効果がある。1回の運動でも記憶力や集中力の向上が期待でき、長期的な運動習慣は認知症のリスク低下にもつながる。運動が脳に良い影響を与える要因の1つとして、BDNFの増加が挙げられる。著者は、運動を「素晴らしい薬」と表現し、勉強の効率化のためにも体を動かすことを推奨している。

重要なポイント
  • 運動は海馬の神経細胞の増殖を促し、認知機能を高める
  • 1回の運動でも記憶力や集中力の向上が期待できる
  • 長期的な運動習慣は認知症のリスク低下につながる
  • 運動が脳に良い影響を与える要因の1つはBDNFの増加
  • 運動は勉強の効率化のためにも推奨される
理解度確認のための質問文
  • 運動が認知機能に与える影響にはどのようなものがありますか?
  • BDNFとは何ですか?それはどのように運動と関連していますか?
  • 著者が運動を「素晴らしい薬」と表現する理由は何ですか?

勉強にまつわる心・体・環境の整え方5 勉強で不安を感じた時

勉強で不安を感じた時は、今できることに集中することが大切である。感情や考えを書き出すジャーナリングは、不安への対処法として有効である。著者は、読者一人一人に寄り添い、勉強を頑張っている人を応援するメッセージを送っている。

重要なポイント
  • 勉強で不安を感じた時は今できることに集中することが大切
  • 感情や考えを書き出すジャーナリングが不安への対処法として有効
  • 著者は勉強を頑張っている読者一人一人を応援するメッセージを送っている
理解度確認のための質問文
  • 勉強で不安を感じた時に大切なことは何ですか?
  • ジャーナリングとは何ですか?それはどのように不安への対処に役立ちますか?
  • 著者からのメッセージで、勉強を頑張っている読者に対して伝えたいことは何ですか?

おわりに

本書で紹介された学習法は、著者が新型コロナウイルス感染症パンデミックの中で、医療者として得た知見を多くの人に役立ててもらいたいという思いから執筆されたものである。人類の知の力を信じ、科学的根拠に基づいた学習法を実践することで、読者一人一人がより良い人生を歩めることを願っている。

重要なポイント
  • 本書で紹介された学習法は著者の医療者としての経験から生まれたもの
  • 科学的根拠に基づいた学習法を実践することで読者がより良い人生を歩めることを願っている
  • 人類の知の力を信じることの大切さが述べられている
理解度確認のための質問文
  • 本書で紹介された学習法の背景にある著者の経験とは何ですか?
  • 著者が読者に願っていることは何ですか?
  • 著者が強調している、人類の知の力とは何ですか?

よく使われる重要な概念の解説

  • アクティブリコール(Active recall):学習内容を積極的に思い出し、能動的に記憶から引き出す作業のこと。テスト効果(Testing effect)とも呼ばれ、記憶の定着に非常に効果的であることが知られている。具体的には、教材を見ずに学習内容を思い出して書き出したり、練習問題を解いたりすることを指す。
  • 分散学習(Distributed learning/practice):一度にまとめて勉強するのではなく、時間を空けて複数回に分けて勉強すること。集中学習(Massed learning/practice)の対義語。分散学習の効果は「分散効果(Spacing effect)」と呼ばれ、長期的な記憶の定着に有効であることが示されている。
  • 精緻的質問(Elaborative interrogation):学習内容に対して「なぜ」「どのように」といった問いを自分自身に投げかけ、深く考えること。新しい情報を既存の知識と関連づけて理解を深める方法の一つ。
  • 自己説明(Self-explanation):学んだことを自分の言葉で説明したり、自分の理解度を評価したりすること。自己説明を行うことで、学習内容の理解が深まり、メタ認知能力も向上すると考えられている。
  • インターリービング(Interleaving):異なるスキルやトピックを交互に学習すること。類似した問題を連続して解くブロック学習(Block learning)の対義語。インターリービングにより、知識の応用力が高まることが示唆されている。
  • イメージ変換法:覚えにくい情報を視覚的なイメージに変換して記憶する方法。数字の語呂合わせや、複数の情報をストーリーとして関連づけるストーリー法、記憶の置き場所を決めてイメージを配置する場所法などがある。
  • 自己効力感(Self-efficacy):ある目標を達成するために必要な行動を自分がどの程度うまく行えるかという認識。学習に対するモチベーションや学習成果に大きな影響を与える。
  • 自己決定理論(Self-determination theory):人間の動機づけを説明する理論の一つ。自律性、有能感、関係性の3つの基本的心理欲求が満たされることで、内発的動機づけが高まるとされる。

要点

本書「科学的根拠に基づく最高の勉強法」は、心理学や脳科学の研究によって得られた客観的な証拠に基づいて、効果的な勉強法を紹介している。著者は、科学的根拠のある勉強法を知り、実践することで、読者がより良い人生を過ごせることを願って本書を執筆した。

第1章では、再読、書き写し・まとめ、ハイライト・下線、学習スタイルの選択など、一般的によく行われているが科学的には効果が高くないとされる勉強法を取り上げ、その問題点を明らかにしている。

続く章では、アクティブリコール、分散学習、精緻的質問、自己説明、インターリービングといった、科学的に効果が確認された勉強法を具体的に説明している。これらの方法は、受動的な学習ではなく、能動的に記憶を引き出したり、学習内容について深く考えたりすることを促すという点で共通している。著者は、自身の経験を交えながら、これらの勉強法を日常生活の中でどのように実践できるかを示している。

また、記憶術の章では、覚えにくい情報をイメージに変換することで記憶の定着を助ける方法を紹介している。数字の語呂合わせ、ストーリー法、場所法など、古くから用いられてきた記憶術は、現代の学習にも応用可能であることが述べられている。

後半の章では、勉強に関連する心理的要因や環境要因に焦点が当てられる。学習内容と自分との関連性を考えることや、自己効力感を高めることがモチベーションの維持に重要だと指摘し、自己決定理論の観点からモチベーションについて考察している。また、睡眠と運動が学習に与える影響の大きさを強調し、生活習慣の改善が学習効率の向上につながることを説明している。

全体を通して、著者は読者に寄り添い、励ましのメッセージを送っている。特に、勉強で不安を感じた時には、今できることに集中することの大切さを述べ、ジャーナリングによる感情の整理を勧めている。

本書の内容は、著者が新型コロナウイルス感染症パンデミックの中で、医療者として得た知見を多くの人に役立ててもらいたいという思いから生まれたものである。科学的根拠に基づいた学習法を実践することで、読者一人一人がより良い人生を歩めることを願っている。また、人類の知の力を信じることの大切さを訴えかけている。

書評

「科学的根拠に基づく最高の勉強法」は、学習科学の知見を平易な言葉で説明し、読者に実践的なアドバイスを提供している点で優れた一冊である。著者の安川康介氏は、自身の医師としての経験と、学習科学の研究成果を巧みに織り交ぜながら、効果的な勉強法について述べている。

本書の最大の特徴は、科学的根拠に基づいて勉強法を評価している点にある。再読やハイライトなど、一般的によく用いられている方法の多くが、実際には学習効果が低いことを研究結果を引用しながら明らかにしている。一方で、アクティブリコールや分散学習といった、認知心理学の知見に基づく勉強法の有効性を強調している。これらの方法は、記憶の定着や問題解決能力の向上に直結するものであり、読者にとって実践的な価値が高い。

また、本書では、勉強法だけでなく、学習に関連する心理的要因や環境要因についても言及されている。モチベーションの維持、睡眠の重要性、運動の効果など、学習効率を高めるための生活習慣の改善点を具体的に提示している。特に、自己決定理論の観点からモチベーションについて分析した箇所は示唆に富んでいる。内発的動機づけを高めるためのポイントは、学習場面に限らず、日常生活のさまざまな場面で応用可能だろう。

本書のもう一つの魅力は、著者の個人的な経験が随所に盛り込まれている点である。アメリカの医師国家試験への準備の様子や、日常生活の中で実践している工夫など、具体的なエピソードを交えることで、読者に親しみやすさと説得力を与えている。また、勉強で不安を感じるのは著者自身も同じであるという姿勢は、読者に共感を与え、励ましとなるだろう。

一方で、本書にはいくつかの課題もある。まず、扱っている学習法の範囲がやや限定的である点だ。アクティブリコールや分散学習など、認知心理学の基本的な知見は網羅されているものの、近年注目されているメタ認知やセルフ・レギュレーションに関する言及は少ない。学習者の主体性を重視する観点から、これらの概念についてもより詳しく取り上げることで、本書の内容がさらに充実したものになったのではないだろうか。

また、本書で紹介されている勉強法の多くは、個人の学習場面を想定したものである。しかし、学校教育の現場など、集団での学習場面においてどのように活用できるのかについては、十分に言及されていない。協調学習やピア・ラーニングといった、グループでの学びを促進する方法についても触れることで、本書の適用範囲が広がったことだろう。

とはいえ、これらの点は本書の価値を大きく損なうものではない。むしろ、読者に学習科学への興味を抱かせ、さらなる探究を促すきっかけとなるかもしれない。

以上、「科学的根拠に基づく最高の勉強法」は、学習科学の知見を分かりやすく解説し、実践的なアドバイスを提供している点で優れた一冊であると言えよう。著者の安川康介氏は、医師としての経験と学術的な知識を融合させながら、読者に寄り添い、励ましのメッセージを送っている。本書を通じて、一人でも多くの人が効果的な学習法を実践し、より充実した人生を歩んでいくことを願ってやまない。

【読書ノート】Clean Architecture 達人に学ぶソフトウェアの構造と設計

書籍「Clean Architecture 達人に学ぶソフトウェアの構造と設計」を読んだので、内容をまとめた。
以下の内容は、ほとんどClaude3 Opusを使用して作成している。

まえがき・第I部 イントロダクション

まえがき

ソフトウェアシステムの構造を決定するルールは、システムの種類に関係なく普遍的である。ソフトウェアアーキテクチャの目的は、システム構築に必要な人材を最小限に抑えることであり、設計の品質は開発・保守に必要な労力で測ることができる。アーキテクチャは仮説であり、実装と計測によって証明すべきものである。本書は、時代を超越した不変のルールを解説する。

印象的なフレーズ
  • 恋のおそろしい化け物とは、意欲は無限だが実行は有限、欲する心ははてしないがおこなうには限度がある。
  • 優れたアーキテクチャのコストが高いと思うなら、劣ったアーキテクチャにすればいい。
  • 速く進む唯一の方法は、うまく進むことである。
重要なポイント
  • ソフトウェアアーキテクチャのルールは、システムの種類に関係なく普遍的で不変である
  • ソフトウェアアーキテクチャの目的は、システム構築に必要な人材を最小限に抑えること
  • アーキテクチャは仮説であり、実装と計測によって証明すべきもの
理解度確認のための質問文
  • ソフトウェアシステムの構造を決定するルールは、システムの種類によってどのように異なりますか?
  • ソフトウェアアーキテクチャの品質は何によって測ることができますか?
  • アーキテクチャとはどのようなものだと著者は主張していますか?

第1章 設計とアーキテクチャ

設計とアーキテクチャに明確な区別はなく、システムを形作る重要な意思決定を表したものである。優れたアーキテクチャの目的は、求められるシステムを構築・保守するために必要な人材を最小限に抑えることである。崩壊したコードを書くことは短期的にも長期的にもクリーンなコードを書くよりも遅い。速く進む唯一の方法は、うまく進むことである。

印象的なフレーズ
  • 設計とアーキテクチャについては、何年も混乱が生じている。設計とは何か?アーキテクチャとは何か?両者の違いは何か?
  • 速く進む唯一の方法は、うまく進むことである。
重要なポイント
  • 設計とアーキテクチャに明確な区別はない
  • 優れたアーキテクチャは、開発・保守に必要な人材を最小限に抑える
  • 崩壊したコードを書くことは短期的にも長期的にもクリーンなコードを書くよりも遅い
理解度確認のための質問文
  • 著者は設計とアーキテクチャの違いをどのように述べていますか?
  • 優れたアーキテクチャの目的は何だと著者は述べていますか?
  • 崩壊したコードを書くことの問題点は何だと著者は述べていますか?

第2章 2つの価値のお話

ソフトウェアは、振る舞いとアーキテクチャという2つの価値を持つ。振る舞いは緊急だが重要とは限らず、アーキテクチャは重要だが緊急とは限らない。開発者はアーキテクチャの重要性を強く主張する責任があり、ステークホルダーと対等に、ひるむことなく口論しなければならない。アーキテクチャを後回しにすると、開発コストが高くなり、変更不能になる。

印象的なフレーズ
  • 私には緊急と重要の2種類の問題がある。緊急と重要は違う。重要なことが緊急になるわけではない。
  • ソフトウェア開発者もステークホルダーであることは忘れてはいけない。保護すべきソフトウェアに対する責任がある。それが、あなたの役割であり、義務である。それが、あなたが雇われている大きな理由だ。
重要なポイント
理解度確認のための質問文

第I部の重要な概念

  • アーキテクチャ:ソフトウェアシステムの構造を決定する重要な設計上の意思決定のこと。システムの構築・保守に必要な人材を最小限に抑えることを目的としている。
  • 振る舞い:ソフトウェアがユーザーの要求を満たすために提供する機能のこと。一般的にステークホルダーにとって緊急な課題とみなされる。
  • 設計:ソフトウェアの構造や振る舞いを決定するための意思決定のこと。著者は設計とアーキテクチャを同義とみなしている。
  • 崩壊したコード:複雑で理解しづらく、変更が難しいコードのこと。短期的には早く書けるが、長期的には開発速度を低下させる。
  • アイゼンハワーマトリックス:緊急度と重要度の2軸で課題を分類するフレームワーク。緊急かつ重要なものから優先的に取り組むべきだとしている。

第I部の要点

本書の第I部では、ソフトウェアアーキテクチャの重要性と、開発者がアーキテクチャに注力すべき理由が説明されている。

著者は、ソフトウェアシステムの構造を決定するルールは普遍的で不変であると主張している。そして、優れたアーキテクチャの目的は、システムの構築・保守に必要な人材を最小限に抑えることであると述べている。

ソフトウェアには、ユーザーの要求を満たす「振る舞い」と、変更に柔軟な「アーキテクチャ」という2つの価値がある。振る舞いは緊急だが必ずしも重要ではなく、アーキテクチャは重要だが緊急ではないことが多い。開発者は、アーキテクチャの重要性をステークホルダーに強く主張する必要がある。

設計とアーキテクチャに明確な区別はなく、どちらもシステムの構造を決定する意思決定を指す。崩壊したコードを書くことは、短期的には速く書けるように見えて、長期的には開発速度を低下させてしまう。

本書では、アーキテクチャを重視することで、ソフトウェア開発の生産性を高く保ち、変更に強い柔軟なシステムを構築できると主張している。

第I部の考察

「Clean Architecture」の第I部では、ソフトウェアシステムの設計とアーキテクチャに関する著者の考えが述べられている。著者は、アーキテクチャを重視し、あらゆるステークホルダーに対してその重要性を訴え続けることが、開発者の責務であると主張している。

確かに、機能を重視するあまりアーキテクチャがおろそかになるという問題は、多くのソフトウェアプロジェクトで見られる。そのような「技術的負債」は、短期的には開発速度を上げられるものの、長期的にはシステムの複雑性を増大させ、生産性を低下させる原因となる。

一方で、アーキテクチャを重視しすぎるあまり、ビジネス要求の実現が後手に回るというリスクもある。アジャイルソフトウェア開発のように、機能の提供とアーキテクチャの改善を小さなサイクルで繰り返す手法は、両者のバランスを取る上で有効であると考えられる。

著者も指摘しているように、アーキテクチャは仮説であり、実装と計測によって検証していく必要がある。設計とアーキテクチャの区別を明確にしない点には疑問が残るが、アーキテクチャを意識し、ステークホルダーを巻き込んで議論していくという姿勢は、開発者にとって重要な示唆になるであろう。

本書の主張を実践に移すためには、アーキテクチャに関する知識だけでなく、コミュニケーションやマネジメントのスキルも必要になる。開発者一人ひとりがアーキテクチャに対する責任感を持ち、チームやステークホルダーとの対話を重ねていくことで、プロジェクトの成功確率を高められるはずである。

システムの長期的な発展を考えれば、アーキテクチャの重要性は論を俟たない。本書は、そのような問題意識を持つ開発者にとって、良き指針となるであろう。

第II部 構成要素から始めよ:プログラミングパラダイム

第3章 パラダイムの概要

構造化プログラミング、オブジェクト指向プログラミング、関数型プログラミングの3つのプログラミングパラダイムを紹介。各パラダイムプログラマから特定の能力を奪うことで規律を課している。これら以外の新しいパラダイムは1958年から1968年の間に発見されていない。

印象的なフレーズ
重要なポイント
  • 3つのプログラミングパラダイムは、それぞれ特定の能力を奪うことで規律を課している
  • 1968年以降、新しいプログラミングパラダイムは発見されていない
理解度確認のための質問文

第4章 構造化プログラミング

Edsger DijkstraはGOTO文の濫用がプログラムの構造を破壊することを発見し、構造化プログラミングを提唱した。構造化プログラミングでは、順次、選択、反復の3つの基本構造のみを使用し、GOTO文を排除する。これにより、プログラムを階層的に分割し、論理的に証明することが可能になった。ただし、数学的な証明は実用的ではなく、テストによってプログラムの正当性を示すことが一般的である。

印象的なフレーズ
  • 構造化プログラミングは、直接的な制御の移行に規律を課すものである
  • プログラムが正しくないことは証明できるが、正しいことは証明できない
重要なポイント
  • 構造化プログラミングは、GOTO文を排除し、順次、選択、反復の3つの基本構造のみを使用する
  • プログラムの正当性は数学的な証明ではなく、テストによって示される
理解度確認のための質問文
  • 構造化プログラミングが排除したものは何か?
  • 構造化プログラミングで使用される3つの基本構造は何か?
  • プログラムの正当性を示すために使われる方法は何か?

第5章 オブジェクト指向プログラミング

オブジェクト指向プログラミング(OOP)の本質は、ポリモーフィズムを使ってソースコードの依存関係を制御する能力である。OOPによってソースコードの依存関係を制御の流れとは逆転させることができ、これを依存関係逆転の原則という。これにより、上位レベルのポリシーを含むモジュールを、下位レベルの詳細を含むモジュールから分離し、独立してデプロイ・開発できるようになる。

印象的なフレーズ
重要なポイント
理解度確認のための質問文

第6章 関数型プログラミング

関数型プログラミングでは、変数は一度初期化されると変更されない。これにより、並行処理における競合状態やデッドロックなどの問題を防ぐことができる。ただし、現実のアプリケーションでは、状態を持つ部分と持たない部分に分離し、状態を持つ部分に適切な保護メカニズムを適用する必要がある。将来的には、十分な記憶容量と処理能力によって、アプリケーションを完全に不変にすることが可能になるかもしれない。

印象的なフレーズ
  • 関数型プログラミングは、代入に規律を課すものである
  • 十分な記憶容量と十分な処理能力があれば、アプリケーションを完全に不変にできる
重要なポイント
  • 関数型プログラミングでは、変数は一度初期化されると変更されない
  • 現実のアプリケーションでは、状態を持つ部分と持たない部分に分離し、適切な保護メカニズムを適用する必要がある
理解度確認のための質問文

第II部の重要な概念

  • プログラミングパラダイム:プログラミングの方法や考え方を表す概念。構造化プログラミング、オブジェクト指向プログラミング、関数型プログラミングなどがある。
  • 構造化プログラミング:GOTO文を排除し、順次、選択、反復の3つの基本構造のみを使用するプログラミングパラダイム。プログラムの論理的な構造を明確にし、理解や保守を容易にする。
  • オブジェクト指向プログラミング:データと関連する処理をオブジェクトとしてまとめ、相互作用させるプログラミングパラダイムカプセル化、継承、ポリモーフィズムの概念を持つ。
  • ポリモーフィズム:同じインターフェースを持つオブジェクトが、それぞれ独自の方法で振る舞うことができる性質。オブジェクト指向プログラミングの重要な概念の1つ。
  • 依存関係逆転の原則:上位レベルのモジュールが下位レベルのモジュールに依存するのではなく、両方が抽象化に依存するようにするという原則。オブジェクト指向設計の重要な原則の1つ。
  • 関数型プログラミング:副作用を避け、状態変化を最小限に抑えるプログラミングパラダイム。データを変更するのではなく、関数を使ってデータを変換する。

第II部の要点

「Clean Architecture」の第II部では、プログラミングパラダイムとそれらがソフトウェアアーキテクチャに与える影響について解説している。著者は、構造化プログラミング、オブジェクト指向プログラミング、関数型プログラミングの3つのパラダイムに焦点を当て、それぞれのパラダイムプログラマに課す規律と、その結果もたらされる利点について説明している。

構造化プログラミングはGOTO文を排除し、プログラムの論理的な構造を明確にした。オブジェクト指向プログラミングは、ポリモーフィズムを使ってソースコードの依存関係を制御する能力をプログラマに与えた。関数型プログラミングは、副作用を避け、状態変化を最小限に抑えることで、並行処理における問題を防ぐことができる。

著者は、これらのパラダイムプログラマから特定の能力を奪うことで、プログラムに一定の規律を課していると指摘する。そして、これらのパラダイムを適切に使うことで、ソフトウェアアーキテクチャをより柔軟で保守性の高いものにできると主張している。

第II部の考察

「Clean Architecture」の第II部で著者が示した洞察は、ソフトウェア開発の歴史を振り返り、プログラミングパラダイムの役割を再考するものである。著者は、3つの主要なプログラミングパラダイムがそれぞれプログラマに規律を課し、特定の問題を解決してきたと指摘する。これは、プログラミングパラダイムの意義を明確に示すものであり、ソフトウェア開発者にとって重要な示唆を与えてくれる。

特に、オブジェクト指向プログラミングと関数型プログラミングの重要性が強調されている。オブジェクト指向プログラミングは、ポリモーフィズムを通じてソースコードの依存関係を制御する能力を与え、システムの柔軟性と保守性を高める。一方、関数型プログラミングは、副作用を避け、状態変化を最小限に抑えることで、並行処理における問題を防ぐことができる。これらのパラダイムを適切に使うことで、ソフトウェアの品質と信頼性を向上させることができるだろう。

ただし、著者の主張にはいくつかの限界もある。まず、著者は1968年以降、新しいプログラミングパラダイムが発見されていないと述べているが、これは厳密には正しくない。例えば、アスペクト指向プログラミングやコンポーネント指向プログラミングなど、新しいパラダイムが提案されている。また、著者は関数型プログラミングの利点を強調しているが、現実のアプリケーションでは完全に状態を排除することは難しく、オブジェクト指向プログラミングとの適切な組み合わせが必要になる。

とはいえ、著者の主張は全体としてソフトウェア開発者に重要な示唆を与えるものである。プログラミングパラダイムの役割を理解し、それらを適切に使うことで、より柔軟で保守性の高いソフトウェアアーキテクチャを設計できるだろう。また、著者が指摘するように、十分な記憶容量と処理能力が利用可能になれば、関数型プログラミングの利点がさらに発揮され、ソフトウェアの信頼性と品質が向上することが期待できる。

ソフトウェア開発者は、これらのプログラミングパラダイムの利点と限界を理解し、適材適所で使うことが求められる。そのためには、各パラダイムの基礎となる原理を深く理解し、それらを実践に活かす努力が必要不可欠である。「Clean Architecture」の第II部は、そのための優れたガイドとなるだろう。

第III部 設計の原則

第7章 SRP:単一責任の原則

モジュールはたったひとつのアクターに対して責務を負うべきである。アクターとは、変更を求めるグループのことを指す。異なるアクターのコードを1つのモジュールにまとめると、想定外の重複や、マージの際のリスクが生じる。これを避けるために、アクターごとにコードを分割する必要がある。

印象的なフレーズ
  • モジュールはたったひとつのアクターに対して責務を負うべきである
  • 想定外の重複は避けられる
  • アクターの異なるコードは分割するべき
重要なポイント
  • モジュールを変更する理由は1つであるべき
  • 異なるアクターのコードを1つのモジュールにまとめるとリスクが生じる
  • アクターごとにコードを分割することが重要
理解度確認のための質問文
  • 単一責任の原則において、「アクター」とは何を指すか?
  • 異なるアクターのコードを1つのモジュールにまとめるとどのようなリスクが生じるか?
  • 単一責任の原則に従うためにはどのようにコードを分割すべきか?

第8章 OCP:オープン・クローズドの原則

ソフトウェアの構成要素は拡張に対して開いていて、修正に対して閉じていなければならない。変更の影響を受けずにシステムを拡張しやすくするために、システムをコンポーネントに分割し、コンポーネントの依存関係を階層構造にする。上位レベルのコンポーネントが下位レベルの変更の影響を受けないようにする。

印象的なフレーズ
  • ソフトウェアの構成要素は拡張に対して開いていて、修正に対して閉じていなければならない
  • 上位レベルのコンポーネントが下位レベルの変更の影響を受けないようにする
  • 変更の影響を受けずにシステムを拡張しやすくする
重要なポイント
  • ソフトウェアは拡張に開いていて、修正に閉じているべき
  • システムをコンポーネントに分割し、依存関係を階層構造にする
  • 上位レベルが下位レベルの変更の影響を受けないようにする
理解度確認のための質問文
  • オープン・クローズドの原則とはどのような原則か?
  • オープン・クローズドの原則に従うためにシステムはどのように設計されるべきか?
  • なぜ上位レベルのコンポーネントが下位レベルの変更の影響を受けないようにする必要があるのか?

第9章 LSP:リスコフの置換原則

S型のオブジェクトo1の各々に対応するT型のオブジェクトo2が存在し、Tを使って定義されたプログラムの振る舞いがo1に置き換えても変わらない場合、SはTの派生型であると言える。置換可能性に違反すると、システムのアーキテクチャが複雑になる。

印象的なフレーズ
重要なポイント
  • 派生型の置換可能性が重要
  • 置換可能性の違反はアーキテクチャを複雑にする
理解度確認のための質問文
  • リスコフの置換原則における「派生型」とはどのようなものか?
  • 置換可能性に違反するとどのような問題が生じるか?
  • リスコフの置換原則はアーキテクチャにどのような影響を与えるか?

第10章 ISPインターフェイス分離の原則

必要としないモジュールに依存することは有害である。使っていないメソッドの変更によって再コンパイルや再デプロイを強制されたり、使っていない部分の障害の影響を受けたりするリスクがある。インターフェイスを分離することで、このような問題を回避できる。

印象的なフレーズ
  • 必要としないモジュールに依存することは有害である
  • インターフェイスを分離することで問題を回避できる
重要なポイント
  • 不要なモジュールへの依存は有害
  • インターフェイスの分離によって依存関係の問題を回避できる
理解度確認のための質問文
  • インターフェイス分離の原則とはどのような原則か?
  • 不要なモジュールへの依存はどのような問題を引き起こすか?
  • インターフェイスの分離によってどのように依存関係の問題を解決できるか?

第11章 DIP:依存関係逆転の原則

ソースコードの依存関係は具象ではなく抽象を参照すべきである。変化しやすい具象クラスではなく、安定した抽象インターフェイスに依存することで、柔軟なシステムを作ることができる。依存関係逆転の原則を満たさない具象コンポーネントは分離する。

印象的なフレーズ
重要なポイント
理解度確認のための質問文
  • 依存関係逆転の原則が推奨するソースコードの依存関係とはどのようなものか?
  • なぜ変化しやすい具象クラスではなく、安定した抽象インターフェイスに依存すべきなのか?
  • 依存関係逆転の原則を満たさない具象コンポーネントをどのように扱うべきか?

第III部の重要な概念

  • モジュール:関連する機能や責任をまとめた、ソフトウェアの構成単位。
  • コンポーネント:独立してデプロイ可能な、ソフトウェアの構成要素。モジュールよりも大きな単位。
  • インターフェイス:モジュールやコンポーネントの機能を定義し、他の部分との契約を表す。
  • 抽象:具体的な実装の詳細を隠蔽し、本質的な機能や振る舞いを表現したもの。
  • 具象:抽象の具体的な実装。詳細な内部動作を含む。
  • 依存関係:あるモジュールやコンポーネントが他のモジュールやコンポーネントを利用する関係。
  • 責任:モジュールやコンポーネントが担当する機能や役割。
  • 変更:要件の変化や不具合の修正などによって、ソフトウェアに加えられる修正。
  • 拡張:既存の機能はそのままに、新しい機能を追加すること。
  • アーキテクチャ:ソフトウェアシステムの全体的な構造や設計方針。

第III部の要点

「Clean Architecture」の第III部では、SOLID原則と呼ばれる5つの重要な設計原則について解説されている。これらの原則は、変更に強く、理解しやすく、再利用性の高いソフトウェア構造を作るための指針となる。

単一責任の原則(SRP)は、モジュールが1つの責任のみを持つべきだと述べている。オープン・クローズドの原則(OCP)は、ソフトウェアが拡張に開いていて、修正に閉じているべきだと説明する。リスコフの置換原則(LSP)は、派生型がベースとなる型と置換可能であるべきだと主張する。インターフェイス分離の原則(ISP)は、不要なモジュールへの依存を避けるべきだと述べている。依存関係逆転の原則(DIP)は、具象ではなく抽象に依存すべきだと説明する。

これらの原則に従うことで、ソフトウェアシステムを構成するモジュールやコンポーネントの役割と責任が明確になり、変更の影響範囲を限定できる。また、抽象インターフェイスを介して疎結合な設計を実現することで、システムの柔軟性と拡張性を高めることができる。

SOLID原則は、適切なソフトウェアアーキテクチャを設計するための基礎となる考え方を提供している。これらの原則を理解し、実践することは、複雑なソフトウェアシステムを効果的に構築し、維持していくために不可欠である。

第III部の考察

「Clean Architecture」の第III部で紹介されているSOLID原則は、ソフトウェア設計における重要な指針を提供している。これらの原則に従うことで、変更に強く、理解しやすく、再利用性の高いソフトウェア構造を実現できる。特に、単一責任の原則と依存関係逆転の原則は、モジュールやコンポーネントの役割と責任を明確にし、疎結合な設計を促進する上で大きな役割を果たしている。

一方で、これらの原則を適用する際には、現実的な制約や trade-off についても考慮する必要がある。例えば、完全に独立したモジュールを作ることは理想的だが、時にはある程度の依存関係を許容しなければならない場合もある。また、インターフェイスの分離は重要だが、過度な分離はかえって複雑性を増大させる可能性がある。

SOLID原則は、ソフトウェア設計の基本的な考え方を示してくれるが、これらを絶対的なルールとしてではなく、状況に応じて柔軟に適用していくことが重要だと考える。開発チームは、これらの原則の本質的な目的を理解した上で、プロジェクトの特性や制約に合わせて適切に応用していく必要がある。

また、SOLID原則はオブジェクト指向設計の文脈で語られることが多いが、その本質的な考え方は、他のパラダイムアーキテクチャスタイルにも応用可能だと思われる。例えば、関数型プログラミングにおける純粋関数の考え方は、単一責任の原則と通じるものがある。

SOLID原則は、ソフトウェア設計における普遍的な価値を提供してくれる。これらの原則を深く理解し、現実的な制約の中で適切に応用していくことが、高品質なソフトウェアシステムを構築するための鍵となるだろう。同時に、これらの原則を絶対視するのではなく、状況に応じて柔軟に解釈し、適用していくことも重要である。

第IV部 コンポーネントの原則

第12章 コンポーネント

コンポーネントとは、デプロイ可能な最小単位のこと。かつてはプログラムの配置場所をプログラマが管理していたが、コンパイラの進化によってリロケータブル化が実現し、動的リンクによるコンポーネント化が可能になった。

印象的なフレーズ
  • 「プログラムは、コンパイルとリンクに使える時間を使い切るまで肥大化する」
重要なポイント
  • コンポーネントはデプロイ可能な最小単位である
  • リロケータビリティとは、プログラムを再配置可能にすること
  • 動的リンクによって、実行時にコンポーネントを入れ替えることが可能になった
理解度確認のための質問文

第13章 コンポーネントの凝集性

コンポーネントの凝集性には、再利用・リリース等価の原則(REP)、閉鎖性共通の原則(CCP)、全再利用の原則(CRP)がある。これらの原則は時にトレードオフの関係にあり、バランスを取ることが重要。

印象的なフレーズ
  • 「変更の種類が似ているクラスをひとつのコンポーネントにまとめる」
  • 「不要なものには依存しないこと」
重要なポイント
  • 再利用性と開発の利便性はトレードオフの関係にある
  • 再利用・リリース等価の原則(REP)は、再利用の単位とリリースの単位を一致させるべきとする原則
  • 閉鎖性共通の原則(CCP)は、同じタイミングで変更されるクラスは同じコンポーネントにまとめるべきとする原則
  • 全再利用の原則(CRP)は、再利用時に不要な依存を避けるべきとする原則
理解度確認のための質問文
  • 再利用・リリース等価の原則(REP)とは何か?
  • 閉鎖性共通の原則(CCP)とは何か?
  • 全再利用の原則(CRP)とは何か?

第14章 コンポーネントの結合

コンポーネントの結合には、非循環依存関係の原則(ADP)、安定依存の原則(SDP)、安定度・抽象度等価の原則(SAP)がある。コンポーネントの依存関係は時とともに変化するので、これらの原則を使って適切に管理する必要がある。

印象的なフレーズ
  • コンポーネントの依存構造は、システム設計の際に検討するだけのものではなく、その後もどんどん変わっていく」
  • 「無駄でもないし、大きな苦痛を伴うこともない」
重要なポイント
理解度確認のための質問文
  • 非循環依存関係の原則(ADP)とは何か?
  • 安定依存の原則(SDP)とは何か?
  • 安定度・抽象度等価の原則(SAP)とは何か?

第IV部の重要な概念

  • コンポーネント:独立してデプロイできる、ソフトウェアの構成単位。クラスやモジュールを含む。
  • 凝集性:コンポーネント内の要素がどれだけ密接に関連しているかを表す指標。高いほうがよい。
  • 結合度:コンポーネント間の依存関係の度合いを表す指標。低いほうがよい。
  • 循環依存:複数のコンポーネントが互いに依存し合っている状態。避けるべき。
  • 主系列:コンポーネントの抽象度と安定度のバランスが取れている状態。

第IV部の要点

第IV部では、ソフトウェアシステムをコンポーネントに分割する際の原則について説明されている。コンポーネントは独立してデプロイできる単位であり、クラスやモジュールをまとめたものである。コンポーネント分割の際には、凝集性と結合度を適切に管理することが重要である。

凝集性に関する原則としては、REP、CCP、CRPがある。再利用性を高めつつ、変更の影響範囲を限定するために、これらの原則を適用する。一方、結合度に関する原則としては、ADP、SDP、SAPがある。コンポーネント間の依存関係を適切に管理し、循環依存を避け、安定度と抽象度のバランスを取ることが重要である。

これらの原則を適用することで、保守性と拡張性の高いソフトウェアアーキテクチャを設計できる。ただし、原則同士がトレードオフの関係になることもあるため、状況に応じて適切なバランスを取る必要がある。また、コンポーネント構造は固定ではなく、システムの成長に合わせて変化していくものであることを理解しておくことも重要である。

第IV部の考察

「Clean Architecture」の第IV部で説明されているコンポーネントの原則は、ソフトウェアアーキテクチャを設計する上で非常に重要な概念だと言える。システムを適切なコンポーネントに分割することで、保守性や拡張性を高めることができる。特に、凝集性を高め、結合度を低く保つことは、変更の影響範囲を限定し、システムの進化を容易にする上で欠かせない。

著者が提示している個々の原則は、いずれも納得感のある内容であり、実際のソフトウェア開発で活用できる指針となっている。REPやCCPのように、保守性と再利用性のバランスを取ることを重視する原則もあれば、ADPやSAPのように、アーキテクチャの安定性を確保することを重視する原則もある。これらの原則をバランス良く適用することが、優れたアーキテクチャ設計につながるのだろう。

ただし、著者も指摘しているように、これらの原則はトレードオフの関係にあることが多い。そのため、画一的に適用するのではなく、システムの特性や要件に合わせて適切に取捨選択することが重要である。また、コンポーネント構造は固定ではなく、システムの成長に合わせて変化させていく必要がある。アーキテクトには、原則を理解した上で、柔軟に適用していく力量が求められると言えるだろう。

本書で示されている原則は、ソフトウェア開発者にとって非常に示唆に富む内容だと感じた。一方で、実際のソフトウェア開発では、これらの原則を完璧に適用することは難しいかもしれない。特に、レガシーシステムの改修や、短期的な開発プロジェクトにおいては、理想的なアーキテクチャ設計に時間を割くことが難しい場合もあるだろう。

とはいえ、長期的な視点に立てば、適切なアーキテクチャ設計は非常に重要である。本書で示されている原則を、開発現場で少しずつでも実践に移していくことが、ソフトウェアの品質を高め、開発の効率を上げることにつながるのではないだろうか。

第V部アーキテクチャ

第15章 アーキテクチャとは?

アーキテクチャの目的は、システムの開発・デプロイ・運用・保守を容易にすることである。優れたアーキテクトは、プログラミングを継続し、チームの生産性を最大化し、ソフトウェアを長期間にわたり使いやすくするための設計を行う。アーキテクチャの主な関心事は、システムのユースケース、運用、開発、デプロイをサポートすることであり、詳細な技術的決定をできる限り遅らせることが重要である。

印象的なフレーズ
  • 「優れたソフトウェアアーキテクトは最高のプログラマである」
  • アーキテクチャの主な目的は、システムのライフサイクルをサポートすること」
  • 「優れたアーキテクチャがあれば、システムを容易に理解・開発・保守・デプロイできる」
重要なポイント
  • アーキテクチャはシステムの「形状」を決定し、開発・デプロイ・運用・保守を容易にする
  • アーキテクチャはシステムの振る舞いを決定するものではない
  • アーキテクトは技術的な決定をできる限り遅らせ、選択肢を残すべき
理解度確認のための質問文
  • ソフトウェアアーキテクトの主な役割は何か?
  • アーキテクチャが直接的に影響を与えるのはシステムのどの側面か?
  • 優れたアーキテクチャを実現するための戦略は何か?

第16章 独立性

優れたアーキテクチャは、ユースケース、運用、開発、デプロイの4つの独立性をサポートしなければならない。これを実現するには、ビジネスルール、フレームワークユーザーインターフェイス、データベースなどを切り離す必要がある。アーキテクトは、モノリシック、コンポーネント、サービスなどの切り離し方式を状況に応じて選択し、コンポーネント間の依存関係を適切に管理する。

印象的なフレーズ
  • アーキテクチャの目的は、求められるシステムを構築・維持するために必要な人材を最小限に抑えること」
  • 「優れたアーキテクチャは、ソースコードを変更から保護してくれる」
  • 「優れたアーキテクチャがあれば、システムはモノリシックとして生まれ、サービスやマイクロサービスまでたどり着くことが可能」
重要なポイント
  • アーキテクチャは、ユースケース、運用、開発、デプロイの4つの独立性をサポートすべき
  • ビジネスルール、フレームワーク、UI、データベースなどを切り離すことが重要
  • モノリシック、コンポーネント、サービスなどの切り離し方式を状況に応じて選択する
  • 偶然の重複を排除するために、過剰な抽象化に注意する
理解度確認のための質問文
  • 優れたアーキテクチャがサポートすべき4つの独立性とは何か?
  • ビジネスルールとデータベースを切り離すことの利点は何か?
  • モノリシック、コンポーネント、サービスの切り離し方式の違いは何か?

第17章 バウンダリー: 境界線を引く

アーキテクチャの境界線は、「重要なもの」と「重要ではないもの」の間に引く。ビジネスルールとUIの間、ビジネスルールとデータベースの間などに境界線を引き、それぞれを独立して変更できるようにする。この境界線によって、フレームワークやデータベースなどの詳細な決定を遅らせることができる。境界線は、単一責任の原則(SRP)と閉鎖性共通の原則(CCP)を適用して決定する。

印象的なフレーズ
  • 「アーキテクトの目的は、求められるシステムを構築・維持するために必要な人材を最小限に抑えること」
  • 「境界線は、変更する理由の違いでシステムの要素を切り離すところに引く」
  • フレームワークは使用するツールであり、アーキテクチャが従うものではない」
重要なポイント
  • 境界線は「重要なもの」と「重要ではないもの」の間に引く
  • ビジネスルール、UI、データベースなどの間に境界線を引く
  • 境界線によって、詳細な決定を遅らせ、変更の影響を局所化できる
  • SRPとCCPを適用して境界線を決定する
  • フレームワークに依存しないアーキテクチャを設計する
理解度確認のための質問文

第18章 境界の解剖学

アーキテクチャの境界には、モノリシック、バイナリコンポーネント、ローカルプロセス、サービスの4つの形態がある。これらの境界は、関数呼び出し、動的リンク、プロセス間通信、ネットワーク通信などの方法で越えられる。境界を越えるときは、ソースコードの依存関係を適切に管理し、下位レベルから上位レベルに向かうようにする。複雑なシステムでは、これらの境界が混在することが多い。

印象的なフレーズ
重要なポイント
  • アーキテクチャの境界には4つの形態がある
  • 境界を越えるときは、ソースコードの依存関係を適切に管理する
  • 境界を越える通信には、シンプルなデータ構造を使用する
  • 複雑なシステムでは、複数の境界形態が混在する
  • サービスとアーキテクチャの境界の関係は一様ではない
理解度確認のための質問文
  • アーキテクチャの境界にはどのような形態があるか?
  • 境界を越える通信ではどのような点に注意すべきか?
  • サービスとアーキテクチャの境界の関係にはどのようなパターンがあるか?

第19章 方針とレベル

ソフトウェアシステムは、さまざまなレベルの方針を持つコンポーネントに分割される。レベルは、入力と出力からの距離で決まる。上位レベルの方針は下位レベルの詳細について知らず、下位レベルが上位レベルに依存する。コンポーネント間の依存関係は、上位レベルから下位レベルに向かう。方針は、変更頻度と重要性に基づいてコンポーネントにまとめられる。

印象的なフレーズ
  • 「ソフトウェアシステムは方針を示したものである」
  • 「レベルの厳密な定義は入力と出力からの距離である」
  • 「異なる理由で変更されるものとは何か? 明らかなものがいくつかある」
重要なポイント
  • システムはさまざまなレベルの方針を持つコンポーネントに分割される
  • レベルは入力と出力からの距離で決まる
  • 上位レベルは下位レベルの詳細を知らない
  • コンポーネント間の依存関係は上位レベルから下位レベルに向かう
  • 方針は変更頻度と重要性に基づいてまとめられる
理解度確認のための質問文
  • ソフトウェアシステムにおけるレベルとは何か?
  • コンポーネント間の依存関係はどのような向きになるべきか?
  • 方針をコンポーネントにまとめる際の基準は何か?

第20章ビジネスルール

ビジネスルールは、エンティティ(最重要ビジネスルールと最重要ビジネスデータ)とユースケース(アプリケーション固有のビジネスルール)に分類される。エンティティはビジネスの本質を表し、ユースケースはエンティティを制御する。ユースケースは、リクエストとレスポンスのデータ構造を使って、UIなどの詳細から独立する。ビジネスルールは、再利用可能で独立性の高いコードでなければならない。

印象的なフレーズ
  • 「ビジネスルールは、ソフトウェアシステムが存在する理由である」
  • 「エンティティはビジネスであり、それ以外の何者でもない」
  • 「ビジネスルールはシステムのなかで、最も独立していて、最も再利用可能なコードでなければいけない」
重要なポイント
  • ビジネスルールはエンティティとユースケースに分類される
  • エンティティは最重要ビジネスルールと最重要ビジネスデータを含む
  • ユースケースはアプリケーション固有のビジネスルールを含む
  • ユースケースはリクエストとレスポンスのデータ構造を使って詳細から独立する
  • ビジネスルールは再利用可能で独立性が高くなければならない
理解度確認のための質問文
  • ビジネスルールをエンティティとユースケースに分類する基準は何か?
  • エンティティとユースケースの関係はどのようなものか?
  • ビジネスルールが満たすべき特性は何か?

第21章 叫ぶアーキテクチャ

アプリケーションのアーキテクチャは、システムの本質的な要件(ユースケース)を反映し、そのことを明確に伝えるべきである。アーキテクチャフレームワークやデータベースなどの技術的な決定から独立し、ユースケースを中心に設計する。これにより、技術的な決定を遅らせ、システムの本質を理解しやすくなる。アーキテクチャは、フレームワークに依存せず、ユースケースを重視したテスト可能なものでなければならない。

印象的なフレーズ
  • 「アーキテクトの目的は、求められるシステムを構築・維持するために必要な人材を最小限に抑えること」
  • アーキテクチャフレームワークに関するものではない(そうあるべきではない)」
  • フレームワークはツールであり、生き方ではない」
重要なポイント
理解度確認のための質問文

第22章 クリーンアーキテクチャ

クリーンアーキテクチャは、エンティティ、ユースケースインターフェイスアダプター、フレームワークとドライバの4つの同心円で表される。中心に近いほどビジネスルールなどの上位レベルの方針を、外側に近いほどUIやデータベースなどの下位レベルの詳細を配置する。依存関係は内側から外側に向かうように制限する。これにより、フレームワークから独立し、テスト可能で、UIやデータベースの変更に強いシステムを実現できる。

印象的なフレーズ
  • 「ソフトウェアをレイヤーに分割して、依存性のルールを守れば、本質的にテスト可能なシステムを作り、それがもたらすメリットを受け取ることができる」
  • 「優れたシステムアーキテクチャは、このような決定を従属的かつ遅延可能なものにする」
  • 「ソフトウェアの要素を分離し、お互いのことがわからないように制限するというものである」
重要なポイント
理解度確認のための質問文

第23章 プレゼンターとHumble Object

Humble Objectパターンは、テストしにくい振る舞いとテストしやすい振る舞いを分離するために使用される。GUIビジネスロジックの分離には、Humble ObjectであるViewと、テスト可能なPresenterを使う。同様に、データベースゲートウェイやデータマッパー、サービスリスナーなどにもこのパターンが適用できる。アーキテクチャの境界でHumble Objectパターンを使用すると、システム全体のテスト容易性が向上する。

印象的なフレーズ
  • 「Humble Objectパターンは、ユニットテストを実行する人が、テストしにくい振る舞いとテストしやすい振る舞いを分離するために生み出されたデザインパターンである」
  • 「Viewは、Humble Objectである。こちらはテストが難しい。したがって、このオブジェクトのコードはできるだけシンプルに保っておく」
  • アーキテクチャの境界の近くには、Humble Objectパターンが潜んでいる」
重要なポイント
  • Humble Objectパターンは、テストしにくい振る舞いとテストしやすい振る舞いを分離する
  • GUIビジネスロジックの分離には、Humble ObjectであるViewとテスト可能なPresenterを使う
  • データベースゲートウェイ、データマッパー、サービスリスナーなどにもこのパターンが適用できる
  • アーキテクチャの境界でHumble Objectパターンを使用するとテスト容易性が向上する
理解度確認のための質問文
  • Humble Objectパターンの目的は何か?
  • GUIビジネスロジックを分離するためにどのようなオブジェクトを使うか?
  • Humble Objectパターンを適用することで得られる主な利点は何か?

第24章 部分的な境界

アーキテクチャの本格的な境界の構築にはコストがかかるため、状況に応じて部分的な境界を実装することがある。部分的な境界の実装方法として、独立してコンパイル・デプロイ可能なコンポーネントを準備した上で1つにまとめる方法、片方のみにインターフェイスを置く方法、Facadeパターンを使う方法などがある。部分的な境界の実装には、コストとメリットを考慮し、状況の変化に応じて段階的に進化させることが重要である。

印象的なフレーズ
  • 「本格的なアーキテクチャの境界はコストが高い」
  • 「優れたアーキテクトならば、このような境界はコストが高すぎると判断するだろう。だが、それと同時に、あとで必要になるかもしれないことを考えて、できるだけ境界を残したいとも思うだろう」
  • 「そう、これは一筋縄ではいかないのだ」
重要なポイント
  • 本格的な境界の構築にはコストがかかるため、部分的な境界の実装を検討する
  • 部分的な境界の実装方法には、コンポーネントの準備と統合、片方のみのインターフェイス、Facadeパターンなどがある
  • 部分的な境界の実装では、コストとメリットを考慮し、段階的に進化させることが重要
  • 状況の変化に応じて、境界の実装方法を見直し、適切な判断を下す必要がある
理解度確認のための質問文

1. 本格的なアーキテクチャの境界を実装するコストにはどのようなものがあるか?
2. 部分的な境界を実装する主な方法にはどのようなものがあるか?
3. 部分的な境界の実装において重要な考慮事項は何か?

第25章レイヤーと境界

小規模なシステムでは「UI」「ビジネスルール」「データベース」の3つのレイヤーで十分だが、大規模で複雑なシステムでは、より多くのレイヤーと境界が必要になる。レイヤーは、ユーザーインターフェイスビジネスロジック、永続化メカニズムなどの関心事で分割され、各レイヤーはAPIを通じて通信する。複数の情報の流れが存在し、それらがビジネスロジックで統合される。アーキテクトは、システムの進化に合わせて、適切な粒度でレイヤーと境界を設計し、管理する必要がある。

印象的なフレーズ
  • アーキテクチャの境界があらゆるところに存在することを示している」
  • 「我々アーキテクトは、それがいつ必要になるかに気を配らなければいけない」
  • 「優れたアーキテクトであれば、そうした変化を予見して、適切に進めていくのである」
重要なポイント
  • 複雑なシステムでは、多数のレイヤーと境界が必要になる
  • レイヤーは関心事で分割され、APIを通じて通信する
  • 複数の情報の流れが存在し、ビジネスロジックで統合される
  • アーキテクトは、システムの進化に合わせて、適切な粒度でレイヤーと境界を設計・管理する
  • 境界の実装には、コストと利点を考慮し、適切なタイミングで判断する必要がある
理解度確認のための質問文
  • 複雑なシステムにおいて、レイヤーはどのような基準で分割されるか?
  • レイヤー間の通信はどのように行われるか?
  • アーキテクトがレイヤーと境界の設計・管理において考慮すべき点は何か?

第26章 メインコンポーネント

メインコンポーネントは、システムの他のコンポーネントを作成・調整・監督する役割を持つ。メインコンポーネントは、システムの最下位レベルの方針であり、オペレーティングシステムに直接依存する。また、ファクトリやストラテジーなどのグローバルな要素を生成し、上位レベルのコンポーネントに制御を渡す。メインコンポーネントは、アプリケーションの初期状態や設定を扱い、外部リソースを管理する。メインコンポーネントは、アプリケーションのプラグインとして捉えることができる。

印象的なフレーズ
重要なポイント
理解度確認のための質問文

第27章 サービス:あらゆる存在

サービス指向アーキテクチャSOA)やマイクロサービスアーキテクチャは、サービス間の分離と開発・デプロイの独立性を強調するが、実際にはそれほど分離されておらず、独立性も部分的にしか実現できない。サービスはアーキテクチャを定義するものではなく、アーキテクチャの境界に囲まれた1つまたは複数のコンポーネントである。サービス内部でも、依存関係のルールに従ったコンポーネントアーキテクチャが必要である。サービスは、システムのスケーラビリティや開発の利便性に寄与するが、アーキテクチャにおいては付随的な要素である。

印象的なフレーズ
重要なポイント
理解度確認のための質問文
  • SOAやマイクロサービスが強調する点と、実際の限界は何か?
  • サービスとアーキテクチャの関係はどのようなものか?
  • サービス内部のアーキテクチャ設計において重要な点は何か?

第28章 テスト境界

テストはシステムの不可欠な一部であり、アーキテクチャに関与している。テストは、非常に詳細で具体的であり、テスト対象のコードに依存する。したがって、テストはアーキテクチャの最も外側の円に位置する。テストとシステムの間の結合度が高すぎると、テストの脆弱性が増し、システムの進化が妨げられる。この問題を解決するために、テストAPIを導入し、システムの構造からテストを分離する。テストAPIは、テストがシステムを操作し、検証するためのインターフェイスを提供する。

印象的なフレーズ
  • 「テストはシステムの外側ではない。安定度やリグレッションのメリットを提供するのであれば、テストもうまく設計すべきシステムの一部である」
  • 「テストをシステムの設計にうまく統合しないと、不安定なものになる。システムは硬直化し、変更は困難になるだろう」
  • 「テストAPIの目的は、テストをアプリケーションから分離することである」
重要なポイント
  • テストはシステムの不可欠な一部であり、アーキテクチャに関与している
  • テストはアーキテクチャの最も外側の円に位置し、テスト対象のコードに依存する
  • テストとシステムの高い結合度は、テストの脆弱性を増大させ、システムの進化を妨げる
  • テストAPIを導入し、システムの構造からテストを分離することが重要
  • テストAPIは、テストがシステムを操作し、検証するためのインターフェイスを提供する
理解度確認のための質問文
  • テストはアーキテクチャのどこに位置付けられるか?
  • テストとシステムの高い結合度がもたらす問題は何か?
  • テストAPIの目的と役割は何か?

第29章 クリーン組込みアーキテクチャ

組込みソフトウェアの開発では、ハードウェアの変化に適応し、ソフトウェアの寿命を延ばすことが重要である。そのために、ソフトウェアとハードウェアの依存関係を管理し、ハードウェア抽象化レイヤー(HAL)を導入する。また、プロセッサやOSの詳細をそれぞれ抽象化するプロセッサ抽象化レイヤー(PAL)とOS抽象化レイヤー(OSAL)を設けることで、ソフトウェアの移植性と柔軟性を高める。組込みソフトウェアにもSOLIDの原則を適用し、モジュール間の依存関係を適切に管理する。クリーン組込みアーキテクチャでは、ソフトウェアをターゲットハードウェアやOSから切り離し、オフターゲットでのテストを可能にする。

印象的なフレーズ
  • 「ソフトウェアは消耗しないが、管理できていないファームウェアやハードウェアの依存関係により、ソフトウェアが内部から破壊される可能性がある」
  • 「すべてのコードをファームウェアにすると、プロダクトの長期的な健康のためにならない」
  • 「クリーン組込みアーキテクチャは、プロダクトの長期的な健康のためである」
重要なポイント
  • 組込みソフトウェアの開発では、ハードウェアの変化への適応とソフトウェアの寿命の延長が重要
  • HAL、PAL、OSALを導入し、ソフトウェアとハードウェアの依存関係を管理する
  • 組込みソフトウェアにもSOLIDの原則を適用し、モジュール間の依存関係を適切に管理する
  • クリーン組込みアーキテクチャでは、ソフトウェアをターゲットハードウェアやOSから切り離し、オフターゲットでのテストを可能にする
理解度確認のための質問文
  • 組込みソフトウェアの開発において重要な2つの目標は何か?
  • HAL、PAL、OSALの役割は何か?
  • クリーン組込みアーキテクチャが目指すものは何か?

第V部の重要な概念

1. 依存関係のルール:ソースコードの依存関係は、常に内側(上位レベルの方針)に向かうべきである。
2. 境界:アーキテクチャの境界は、「重要なもの」と「重要ではないもの」の間に引かれ、コンポーネント間の依存関係を管理する。
3. Humble Object パターン:テストしにくい振る舞いとテストしやすい振る舞いを分離するためのデザインパターン
4. ユースケース:システムの本質的な要件を表し、アーキテクチャ設計の中心となるべきもの。
5. 抽象化:具体的な実装の詳細を隠蔽し、モジュールの独立性と柔軟性を高めるための手法。

第V部の要点

第V部では、クリーンアーキテクチャの原則を実際のソフトウェアシステムに適用するための具体的な方法論が提示されている。まず、システムを長期的に維持・発展させるための鍵となる「独立性」の概念が説明され、ユースケース、運用、開発、デプロイの4つの観点から、システムの各部分を独立させることの重要性が強調されている。

また、コンポーネント間の責務を明確に分離し、変更の影響範囲を局所化するための「境界」の概念が紹介され、その適切な設定方法が示されている。具体的には、単一責任の原則(SRP)と閉鎖性共通の原則(CCP)を適用することで、境界線を引くべき箇所を特定できることが説明されている。

さらに、クリーンアーキテクチャの中核をなす4層モデル(エンティティ、ユースケースインターフェイスアダプター、フレームワークとドライバ)が詳細に解説され、各層の役割と相互の関係性が明確化されている。この4層モデルに基づいてシステムを設計することで、ビジネスロジックフレームワークや技術的な詳細を分離し、システムの本質的な価値を守ることができる。

加えて、クリーンアーキテクチャの原則を、モノリシックシステム、コンポーネントベースのシステム、サービス指向のシステムなど、さまざまなアーキテクチャスタイルに適用する方法が示されている。特に、組込みシステムの開発において、ハードウェアとソフトウェアの依存関係を適切に管理する手法が具体的に提示されているのは、大きな特徴と言える。

以上のように、第V部では、クリーンアーキテクチャの原則を実践的に適用するための豊富な知見が提供されている。ただし、これらの原則を過度に追求することで、システムの複雑性が増大したり、開発の生産性が低下したりするリスクもあることには注意が必要である。アーキテクトには、プロジェクトの状況を見極め、適切なレベルでクリーンアーキテクチャの原則を適用することが求められる。

第V部の考察

第V部では、クリーンアーキテクチャの実践的な適用に焦点が当てられ、具体的な設計手法や留意点が詳細に説明されている。特に、システムを長期的に維持・発展させるための重要な概念として、「独立性」と「境界」が紹介され、これらを適切に管理することの重要性が強調されている。

「独立性」に関しては、ユースケース、運用、開発、デプロイの4つの観点から、システムの各部分を独立させることの意義が説明される。これにより、システムの一部の変更が他の部分に与える影響を最小限に抑え、保守性と柔軟性を高めることができる。また、「境界」の概念は、コンポーネント間の責務を明確に分離し、変更の影響範囲を局所化するために重要であると述べられている。

さらに、クリーンアーキテクチャの具体的な構成要素として、エンティティ、ユースケースインターフェイスアダプター、フレームワークとドライバの4つの層が提示され、それぞれの役割と相互の関係性が明確に示されている。この4層モデルに基づいてシステムを設計することで、ビジネスロジックフレームワークやデータベースなどの技術的な詳細を分離し、システムの本質的な価値を保護することができる。

また、クリーンアーキテクチャの原則を組込みシステムの開発に適用する方法が、具体的な事例を交えて説明されているのも特筆すべき点である。ハードウェアとソフトウェアの依存関係を適切に管理するための手法が提示され、組込みシステムの開発者にとって貴重な指針となっている。

一方で、第V部の内容は、かなり専門的で高度な話題が多く、初学者にとっては理解が難しい部分もあるだろう。また、クリーンアーキテクチャの原則を実践するには、プロジェクトの状況を見極め、適切なレベルで適用することが求められる。過度に原則に従うことで、かえってシステムの複雑性が増大したり、開発の生産性が低下したりする可能性もある点には注意が必要である。

とはいえ、総合的に見れば、第V部はクリーンアーキテクチャの実践的な適用に関する非常に有益な情報を提供していると言える。ここで示された原則やテクニックを習得し、自身のプロジェクトに適切に適用することで、長期的に維持・発展可能なソフトウェアシステムを構築することができるだろう。特に、経験豊富なアーキテクトやシステム設計者にとって、第V部の内容は大いに参考になるはずである。

第VI部 詳細

第30章 データベースは詳細

データベースはアーキテクチャの構成要素ではなく、単なるエンティティでデータを保持するツールに過ぎない。データベースはデータモデルとは別物であり、アーキテクチャ的にはデータの表現形式は重要ではない。そのため、アーキテクチャではデータベースの詳細を意識せずに設計を行うべきである。

印象的なフレーズ
  • データベースはドアノブのようなもの
  • データベースは詳細である
  • データモデルこそが重要
重要なポイント
理解度確認のための質問文
  • データベースをアーキテクチャの中心に据えるのはなぜ問題か?
  • アーキテクチャ設計においてデータモデルとデータベースはどのように扱うべきか?
  • アプリケーションはデータベースのデータ構造に縛られるべきか?

第31章 ウェブは詳細

ウェブはアーキテクチャの詳細であり、ビジネスロジックの中心と切り離して考えるべきである。ウェブは単なる入出力デバイスの一種で、60年代からデバイスに依存しないアプリケーションを書くことが求められていた。リッチなUIでもデバイス非依存のアーキテクチャは追求すべきであり、UIとアプリケーションの間の抽象化は可能である。

印象的なフレーズ
  • ウェブは何ひとつ変えなかった
  • ウェブはGUIであり、詳細である
  • UIとアプリの間の抽象化は可能
重要なポイント
  • ウェブはアーキテクチャの詳細である
  • ウェブはデバイスの一種で、デバイス非依存設計が重要
  • UIとアプリケーション間の抽象化は可能で追求すべき
理解度確認のための質問文

第32章 フレームワークは詳細

フレームワークアーキテクチャではなく、便利だが依存してはいけない詳細である。フレームワークの作者とユーザーの関係は不均等で、ユーザーはコミットメントを求められるがリスクを負う。そのため、フレームワークにはある程度距離を置き、ビジネスロジックから切り離すべきである。

印象的なフレーズ
重要なポイント
理解度確認のための質問文

第33章 事例:動画販売サイト

動画販売サイトの例を通じて、ユースケース駆動でコンポーネントを分割し、アクターごとに責務を切り分けるクリーンアーキテクチャの設計プロセスを示した。単一責任の原則と依存関係の方向に基づいてコンポーネントを分割することで、変更に強く、デプロイしやすいアーキテクチャが実現できる。

印象的なフレーズ
  • アクターとユースケースを見つける
  • 方針のレベルで分割する
  • 振る舞いとデータ構造を分離する
重要なポイント
理解度確認のための質問文

第34章 書き残したこと

設計の意図とは裏腹に、実装の詳細で設計が台無しになりやすい。レイヤー、機能、ポートとアダプター、コンポーネントなどの分割手法があるが、不適切なアクセス制御で設計の意図が損なわれる。そのため、コンパイラによるチェックやモジュール分割などの対策が必要である。設計を守るには実装の複雑さに配慮が欠かせない。

印象的なフレーズ
  • 悪魔は実装の詳細に宿る
  • 組織化とカプセル化は別物
  • 理想に走りすぎるな
重要なポイント
  • 設計の意図は実装詳細で台無しになりやすい
  • 設計意図を守るアクセス制御が重要
  • コンパイラチェックやモジュール分割などの対策を取る
  • 設計を守るには実装の複雑さへの配慮が必要
理解度確認のための質問文
  • 設計の意図が実装の詳細で損なわれやすい原因は何か?
  • 設計意図を守るためにはどのようなアクセス制御が重要か?
  • 設計を守るために実装の複雑さにどのように配慮すべきか?

第VI部の重要な概念

  • クリーンアーキテクチャビジネスロジックを詳細から独立させ、変更に強く、テスト可能で、デプロイしやすいソフトウェアアーキテクチャ
  • 詳細:ビジネスロジックから切り離すべき具体的な実装や技術のこと。データベース、フレームワーク、ウェブなどがある。
  • ビジネスロジック:アプリケーションの中核となる業務ルールや処理を指す。ドメインロジックとも呼ばれる。
  • ポートとアダプター:アプリケーションを内部(ドメイン)と外部(Infrastructure)に分け、疎結合アーキテクチャを実現するパターン。
  • インターフェイス分離の原則:クライアントが使用しないメソッドに依存することを避けるため、インターフェイスを小さく具体的な目的に沿って分割すること。
  • 単一責任の原則:モジュールを変更する理由がただ1つになるように、責務を分割してモジュール化すること。
  • 依存関係逆転の原則:上位レベルのポリシーを下位レベルの詳細に依存させず、詳細側がポリシーに依存するようにすること。

第VI部の要点

第VI部では、クリーンアーキテクチャの観点から見た詳細について議論している。まず、データベースやウェブ、フレームワークといった技術的詳細がアーキテクチャの中心であってはならないと主張する。これらは単なる実装の詳細であり、ビジネスロジックから切り離して扱うべきだという。

次に、動画販売サイトの例を通して、クリーンアーキテクチャに基づく設計プロセスを実演している。ユースケース駆動でコンポーネントを分割し、単一責任の原則と依存関係の方向に基づいてコンポーネントを配置することで、変更に強く、デプロイしやすいアーキテクチャが実現できることを示した。

最後に、設計の意図と実装詳細の関係について議論し、不適切なアクセス制御によって設計意図が損なわれやすいことを指摘する。設計を守るには、コンパイラチェックやモジュール分割などの対策とともに、実装の複雑さに配慮することが欠かせないと述べている。

全体を通して、ビジネスロジックを詳細から独立させ、設計意図を守ることの重要性が強調されている。そのためには、適切な設計原則の適用と、実装レベルでの配慮が必要不可欠であるというのが、本部のメッセージと言えるだろう。

第VI部の考察

エンジニアとして、「クリーンアーキテクチャ」の提唱する原則は非常に納得感がある。特に、ビジネスロジックを詳細から独立させることの重要性は、変更に強く、テスト可能で、再利用しやすいソフトウェアを実現する上で欠かせないポイントである。

一方で、現実のソフトウェア開発では、さまざまな制約の中でアーキテクチャ設計を行わなければならないのも事実である。納期やコストの制約、レガシーシステムの存在、チームメンバーのスキルレベルの差など、理想のアーキテクチャを適用することが難しい状況は多々ある。

そのような中で、設計の意図を可能な限り守りつつ、現実的な落とし所を見つけていくことが、アーキテクトに求められるスキルなのである。時には妥協も必要であるが、その場合でも、なぜ妥協するのかをチームで共有し、将来的な改善の余地を残しておくことが大切である。

また、設計意図を守るには、実装レベルの細かい配慮も欠かせない。コードレビューや静的解析ツールの活用など、ソースコードの品質を維持するための地道な活動を継続することが、アーキテクチャを守ることにつながるはずである。

クリーンアーキテクチャの原則は、あくまで設計のガイドラインであり、それをどのようにプロジェクトに適用するかは、エンジニアの創意工夫にかかっている。理想と現実のバランスを取りながら、ビジネスの価値につながるソフトウェアを作り上げていくことが、我々エンジニアの果たすべき責務である。

第VII部 付録・あとがき

付録A アーキテクチャ考古学

著者のソフトウェア開発キャリアの中で、アーキテクチャ的に興味深かったプロジェクトについて解説している。1970年代から1990年代初頭までのプロジェクトで学んだ教訓や失敗から、クリーンアーキテクチャの重要性を示している。境界の設定、モジュール化、インターフェイスの抽象化、プラグインアーキテクチャなどの概念の萌芽が見られる。技術の進歩とともにアーキテクチャも進化してきたが、基本的な原則は変わらないことを強調している。

印象的なフレーズ
  • 「体のありとあらゆる穴からコードがあふれてきた」
  • 「ビッグアーキテクチャの恐竜は消滅した」
重要なポイント
理解度確認のための質問文
  • アーキテクチャ考古学で紹介されたプロジェクトから学べる教訓は何か?
  • 著者の経験の中で、クリーンアーキテクチャの概念の萌芽が見られたのはどのような点か?
  • 技術の進歩とともにアーキテクチャがどのように進化してきたか?

あとがき

1990年代のビッグアーキテクチャの時代から、アジャイル開発の台頭によってソフトウェアアーキテクチャも機敏になったと述べている。しかし、フラジャイルアーキテクチャの問題点を指摘し、設計原則とクリーンアーキテクチャの重要性を訴えている。開発者がアーキテクトのように考え、現在の価値を提供しつつ将来の変更に備えたコードを書くことが求められる。そのためには、設計原則を実践し、チームで共有し、継続的に学習することが必要だと説いている。

印象的なフレーズ
  • 「価値を提供するためにすばやく拡張することはできるが、イノベーションのペースを維持することが非常に難しい設計」
  • 「今日の価値を提供しながら、明日の価値を阻害しないコードを書く」
  • 「本当の旅はここから始まる」
重要なポイント
  • アジャイル開発によってソフトウェアアーキテクチャも機敏になったが、フラジャイルアーキテクチャの問題がある
  • 現在の価値を提供しつつ、将来の変更に備えたコードを書くことが重要
  • 設計原則を実践し、チームで共有し、継続的に学習することが必要
理解度確認のための質問文

第VII部の重要な概念

  • 境界: システムの異なる部分や責務を明確に分離するための概念。適切な境界設定によって、モジュール化やインターフェイスの抽象化が可能になる。
  • モジュール化: システムを独立した機能単位に分割すること。変更の影響範囲を限定し、保守性や拡張性を高める。
  • インターフェイスの抽象化: モジュール間の依存関係を抽象的なインターフェイスを介して行うこと。実装の詳細を隠蔽し、柔軟性を確保する。
  • プラグインアーキテクチャ: 共通のインターフェイスを定義し、異なる実装を動的に差し替え可能にする設計。拡張性と柔軟性に優れている。

第VII部の要点

本書の第VII部では、著者のソフトウェア開発の経験から得られたアーキテクチャに関する知見が語られている。1970年代から1990年代初頭までのプロジェクトを通して、クリーンアーキテクチャの基礎となる概念の萌芽が見られることを示している。時代とともに技術は進歩してきたが、アーキテクチャの基本原則は普遍的であることを強調している。

また、1990年代のビッグアーキテクチャの時代から、アジャイル開発の台頭によってソフトウェアアーキテクチャも機敏になったことに触れている。しかし、フラジャイルアーキテクチャの問題点を指摘し、現在の価値を提供しつつ将来の変更に備えたコードを書くことの重要性を訴えている。そのためには、設計原則を理解し実践すること、チームで知識を共有すること、継続的に学習することが必要不可欠であると説いている。

第VII部の考察

本書の第VII部では、著者のソフトウェア開発の経験を通して、アーキテクチャの重要性と普遍性が語られている。時代とともに技術は進歩し、開発手法も変化してきたが、アーキテクチャの基本原則は変わらないことが強調されている。境界の設定、モジュール化、インターフェイスの抽象化、プラグインアーキテクチャなどの概念は、クリーンアーキテクチャの基礎となるものであり、著者の過去のプロジェクトにおいてもその萌芽が見られる。

また、ビッグアーキテクチャの時代からアジャイル開発の時代への移行について触れ、ソフトウェアアーキテクチャも機敏になったことを指摘している。しかし、フラジャイルアーキテクチャの問題点を指摘し、現在の価値を提供しつつ将来の変更に備えたコードを書くことの重要性を訴えている。

著者の主張は、設計原則とクリーンアーキテクチャの重要性を開発者に理解してもらい、実践につなげてもらうことにあると考えられる。開発者一人一人がアーキテクトのように考え、コードを書くことが求められている。そのためには、設計原則を学び、実践し、チームで知識を共有し、継続的に学習することが不可欠である。

本書の内容は、ソフトウェア開発者にとって示唆に富むものであり、アーキテクチャの重要性を再認識させてくれる。著者の経験に基づく知見は、現代のソフトウェア開発においても十分に通用するものである。一方で、具体的な実践方法やツールについては言及が少なく、読者自身が考えて適用していく必要がある。

また、アーキテクチャの原則を実践することが、必ずしも短期的な生産性の向上につながるわけではない点には注意が必要である。長期的な視点に立ち、継続的にアーキテクチャを改善していくことが重要であろう。

全体を通して、本書はソフトウェア開発者にとって価値ある一冊であり、アーキテクチャに関する理解を深め、実践するための指針を与えてくれる。著者の知見を活かし、クリーンアーキテクチャを目指して日々精進することが、開発者に求められていると言えるだろう。

まとめ

本書は、ソフトウェアアーキテクチャの重要性と、クリーンアーキテクチャの原則を理解し実践するための指針を提供している。著者の豊富な経験に基づく知見は、現代のソフトウェア開発においても十分に通用するものであり、開発者にとって示唆に富む内容となっている。クリーンアーキテクチャを目指して日々の開発に取り組むことで、保守性、拡張性、テスト容易性に優れたソフトウェアを構築することができるだろう。

【読書ノート】最適輸送の理論とアルゴリズム

Stable Diffusion 3は、Flow Matchingが使用されており、Flow Matchingは最適輸送とも関連するということなので、積んでおいた「最適輸送の理論とアルゴリズム」を読んだ。

数式をほとんど読み飛ばして読んだまとめである。
以下の内容は、ほとんどClaude3 Opusを使用して作成している。

概要

第1章 確率分布を比較するツールとしての最適輸送

最適輸送は確率分布を比較するためのツールであり、KLダイバージェンスと比較して、距離構造を捉えられる、距離の公理を満たす、サポートが一致していなくても定義できる、分布の対応関係を得られる、などの利点がある。本書では、ヒストグラムの比較、点群の比較、連続分布の比較の3つの問題設定を扱う。

第1章のポイント
  • 最適輸送は分布の「山」を最適に動かすコストとして解釈できる
  • KLダイバージェンスは距離構造を無視し、サポートが重ならない分布間は無限大になる
  • ワッサースタイン距離は最適輸送コストの特殊例で距離の公理を満たす
  • 最適輸送行列から分布間の対応関係が得られ、応用に役立つ
第1章の質問

1. KLダイバージェンスと最適輸送の主な違いは何ですか?
2. ワッサースタイン距離とはどのようなものですか?
3. 最適輸送行列からどのようなことがわかりますか?

第2章 最適化問題としての定式化

最適輸送問題は線形計画問題として定式化でき、ヒストグラムの比較、点群の比較、連続分布の比較に適用できる。双対問題を導出することで、元問題の解釈や感度分析ができ、最適輸送問題と最小費用流問題の関係も明らかになる。最適輸送問題の最適解は疎になる性質がある。

第2章のポイント
  • 最適輸送問題は線形計画問題として定式化できる
  • 双対問題から元問題の解釈や感度分析ができる
  • 最適輸送問題と最小費用流問題は互いに帰着可能
  • 最適解は疎になり、一様分布の場合は一対一対応となる
第2章の質問

1. 最適輸送問題はどのように定式化されますか?
2. 双対問題を導出するとどのようなメリットがありますか?
3. 最適輸送問題の最適解にはどのような性質がありますか?

第3章 エントロピー正則化とシンクホーンアルゴリズム

最適輸送問題にエントロピー正則化を加えると、シンクホーンアルゴリズムという高速な反復解法が利用できるようになる。シンクホーンアルゴリズムは行列スケーリング問題とも関係が深い。正則化を加えると、パラメータに関して解が微分可能になるため、勾配法による最適化が可能になる。正則化の強さは、ソフトな最適解と高速な計算のトレードオフとなる。

第3章のポイント
第3章の質問

1. エントロピー正則化を加えるとどのようなメリットがありますか?
2. シンクホーンアルゴリズムと行列スケーリング問題の関係は何ですか?
3. 正則化により最適輸送がどのように使いやすくなりますか?

第4章 敵対的ネットワーク

敵対的ネットワークは、二つの分布を区別する分類器を学習させることで、分布間の距離を推定する方法である。これには重みの切り捨てや勾配ペナルティなどの正則化が必要となる。生成モデルの学習に適用したものがワッサースタインGANであり、オートエンコーダやドメイン適応にも応用できる。

第4章のポイント
  • 分類器を使って分布間の距離を推定する
  • 重みの切り捨てや勾配ペナルティで正則化する
  • ワッサースタインGANは生成モデルの学習に用いる
  • オートエンコーダやドメイン適応などにも応用可能
第4章の質問

1. 敵対的ネットワークでは分布間の距離をどのように推定しますか?
2. ワッサースタインGANとはどのようなものですか?
3. 敵対的ネットワークにはどのような応用がありますか?

第5章 スライス法

スライス法は、高次元空間の点群の比較を一次元に射影した上で最適輸送を計算することで高速化する手法である。一般化スライス法では射影関数を柔軟に選べるようになっている。最大化スライス法は最も差が出るような射影を選ぶ。木構造に射影するとより豊かな構造を保ちつつ高速に計算できる。

第5章のポイント
  • 高次元の点群を一次元に射影して効率的に最適輸送を計算する
  • 一般化スライス法では多様な射影関数を選べる
  • 最大化スライス法は最も差が出る射影を用いる
  • 木構造に射影すると豊かな構造を保ちつつ高速に計算できる
第5章の質問

1. スライス法ではどのように計算を高速化しますか?
2. 一般化スライス法と最大化スライス法の違いは何ですか?
3. 木構造に射影するとどのようなメリットがありますか?

第6章 他のダイバージェンスとの比較

確率分布間の距離尺度にはφ-ダイバージェンス積分確率距離があり、最適輸送はこれらの一般化となっている。距離尺度の選択は、サンプルからの推定における収束レートに影響する。最適輸送は分布の弱収束と密接に関わっており、KLダイバージェンスよりも適切な距離となる。

第6章のポイント
  • φ-ダイバージェンス積分確率距離は分布間距離の一般的な枠組み
  • 最適輸送はこれらの距離の一般化になっている
  • サンプルからの推定における収束レートは距離尺度の選択に依存する
  • 最適輸送は分布の弱収束と密接に関連する適切な距離である
第6章の質問

1. φ-ダイバージェンス積分確率距離はどのような枠組みですか?
2. 距離尺度の選択はサンプルからの推定にどのように影響しますか?
3. 最適輸送が分布の弱収束と関連するとはどういうことですか?

第7章 不均衡最適輸送

不均衡最適輸送問題は、比較する分布の質量が異なる場合や、すべての質量を移動させる必要がない場合に用いられる。質量の生成・消滅にペナルティを課すことで定式化される。ペナルティにはL1ノルムやKLダイバージェンスが用いられ、正則化を加えた一般化シンクホーンアルゴリズムで解くことができる。

第7章のポイント
  • 質量が異なる分布の比較に不均衡最適輸送が用いられる
  • 質量の生成・消滅にペナルティを課して定式化する
  • L1ノルムやKLダイバージェンスがペナルティとして使われる
  • 正則化した一般化シンクホーンアルゴリズムで効率的に解ける
第7章の質問

1. 不均衡最適輸送問題とはどのような問題ですか?
2. 不均衡最適輸送ではどのようにペナルティを課しますか?
3. 一般化シンクホーンアルゴリズムとはどのようなものですか?

第8章 ワッサースタイン重心

ワッサースタイン重心は、複数の確率分布の重み付き平均を最適輸送の観点から定義したものである。重心を求める最適化問題には、サポートを固定する定式化と、サポートも最適化に含める定式化がある。前者は線形計画問題や劣勾配法で解け、後者は交互最適化で解ける。正則化を加えるとより効率的に解ける。

第8章のポイント
  • ワッサースタイン重心は分布の重み付き平均を最適輸送の観点で定義したもの
  • サポートを固定する定式化とサポートも最適化する定式化がある
  • 固定サポートは線形計画問題や劣勾配法で解ける
  • 自由サポートは交互最適化で解ける
  • 正則化を加えるとより効率的に解くことができる
第8章の質問

1. ワッサースタイン重心とはどのようなものですか?
2. 固定サポートの定式化ではどのように最適化問題を解きますか?
3. 正則化を加えるとワッサースタイン重心の計算がどのように変わりますか?

第9章 グロモフ・ワッサースタイン距離

グロモフ・ワッサースタイン距離は、異なる空間に埋め込まれた分布間の距離を定義したものである。距離空間間の距離の差が最小となるような分布間の対応を見つける問題として定式化される。距離の公理を満たすが、最適化問題は非凸となる。エントロピー正則化と近接勾配法を用いた解法がある。

第9章のポイント
第9章の質問

1. グロモフ・ワッサースタイン距離はどのような距離ですか?
2. グロモフ・ワッサースタイン距離の最適化問題にはどのような特徴がありますか?
3. グロモフ・ワッサースタイン距離はどのように計算しますか?

重要な概念の解説

  • 確率分布: 確率変数がとりうる値とその確率を定めたもの。本書では有限離散分布、点群、確率密度関数を持つ分布を扱う。
  • 最適輸送問題: 二つの確率分布の間の輸送コストが最小となる輸送方法を求める問題。輸送コストは輸送前後の点の間のコストの総和で定義される。
  • ワッサースタイン距離: 最適輸送コストの特殊ケースで、コスト関数が距離関数の場合に距離の公理を満たす。数学的な扱いやすさと幾何学的な解釈を併せ持つ。
  • 双対問題: 主問題をラグランジュの未定乗数法により変形した、主問題と最適値が等しくなる別の最適化問題。主問題の構造を知る手がかりとなる。
  • エントロピー正則化: 最適化問題の目的関数に解のエントロピーに関する項を加えること。最適輸送に加えると凸最適化問題になり、シンクホーンアルゴリズムにより高速に解くことができる。
  • シンクホーンアルゴリズム: エントロピー正則化した最適輸送問題を交互最適化により高速に解くアルゴリズム。行列のスケーリングを繰り返すことで最適解に近づく。

要点のまとめ

最適輸送は確率分布間の距離を定義するための数理的なツールであり、機械学習などにおける分布の比較に広く用いられている。特にワッサースタイン距離は数学的な扱いやすさと幾何学的な解釈を兼ね備えており、分布間距離の標準的な選択肢となっている。最適輸送問題は線形計画問題として定式化でき、双対問題を解くことで元問題の知見が得られる。計算効率の面では、エントロピー正則化を施すことで凸最適化問題となり、シンクホーンアルゴリズムにより高速に求解できる。機械学習への応用では敵対的ネットワークの枠組みが重要であり、生成モデルなどに用いられている。最適輸送の考え方は、スライス法、不均衡輸送、ワッサースタイン重心、グロモフ・ワッサースタイン距離など、さまざまな問題設定に拡張されている。本書ではこうした最適輸送の理論と計算手法を包括的に解説しており、最適輸送を実際の問題に活用するための技術の基盤を提供している。

書評

本書「最適輸送の理論とアルゴリズム」は、機械学習分野で急速に注目を集めている最適輸送の理論体系を、数理的な基礎から計算アルゴリズム、実際の応用に至るまで包括的に解説した良書である。

従来の確率分布間距離と比較した最適輸送の利点が、数学的および直観的な議論により明快に示されている。理論面では線形計画問題としての定式化と双対定理により、計算アルゴリズムの導出と最適解の構造に関する洞察が与えられている。実務的には、エントロピー正則化による計算の効率化、シンクホーンアルゴリズムによる高速解法など、大規模な問題を扱うための技術が丁寧に説明されている。

特筆すべきは、理論と実践のバランスの取れた構成である。数学的な定理の導出では、証明の核心をなす数式を丁寧に記述しつつ、直観的な解釈を随所で与えることで、読者の理解を助けている。さらに、数式の意味を図解などで補足することで、数式が苦手な読者でも内容を追いやすいよう配慮されている。実装面でも、現代の深層学習の枠組みとの親和性の高さを示し、技術の実用性を印象付けている。

機械学習分野に新たな地平を拓きつつある最適輸送理論を、理論・アルゴリズム・応用の観点から縦横に論じた好著である。最適輸送を実務に活用したいと考える機械学習実践者のみならず、分野の数理的基礎を理解したい数学者、新しい計算技術に触れたい計算機科学者など、幅広い読者に推薦したい一冊である。

【読書ノート】エリック・エヴァンスのドメイン駆動設計

最近、ソフトウェア開発を行っているので、ソフトウェア設計に関する勉強をしている。
エリック・エヴァンスのドメイン駆動設計」を読んだので、内容をまとめた。
以下の内容は、ほとんどClaude3 Opusで書いている。

概要

第1部 ドメインモデルを機能させる

本書の第1部は、ドメイン駆動設計の中核をなす考え方を説明している。複雑なソフトウェアに立ち向かうには、問題の本質を捉えた優れたドメインモデルが不可欠である。そのモデルを作り出すには、ドメインの知識を注意深く分析し、実装に適した形に洗練する「知識のかみ砕き」のプロセスが必要だ。

モデルはチーム全体で共有され、「ユビキタス言語」を通してソフトウェアに反映されなければならない。開発者は言葉の使い方に細心の注意を払い、コードがモデルを如実に表すようにする。モデルとコードの間に乖離があってはならない。

したがって、伝統的な「分析」と「設計」の分離をやめ、モデリングとコーディングを一体化した「モデル駆動設計」のアプローチを取るべきだ。そのためには、開発チームの全員が「実践的モデラ」となり、ドメインの理解とモデリングのスキルを持たねばならない。

ドメイン駆動設計は、難しいが大きな価値を生む。本書はそのためのノウハウを提供している。

第2部 モデル駆動設計の構成要素

本書の第2部では、ドメイン駆動設計を支える構成要素が詳述されている。

まず、ドメインを他の関心事から隔離することの重要性が説かれ、レイヤ化アーキテクチャによるドメイン層の分離が推奨される。ドメインの中核を成すのはエンティティと値オブジェクトであり、両者の違いを理解して適切に使い分けることが肝要だ。エンティティは同一性によって定義され、状態は変化するが同一性は不変。値オブジェクトは属性値によって定義され、不変で交換可能。

ドメインの操作は、エンティティや値オブジェクトに自然に属さない場合、サービスによってモデル化される。サービスは状態を持たない。

関連するオブジェクトの整合性を保つ必要がある場合、集約を定義する。集約はルートエンティティを中心に構成され、外部からはルートのみ参照可能とすることで不整合を防ぐ。
オブジェクトのライフサイクルを通じて、生成の複雑さを隠蔽するファクトリと、永続化を隠蔽するリポジトリが有用である。

関係データベースの制約にも配慮しつつ、パターンの適用とモデルの継続的な洗練によって、ドメインを忠実に表現する設計を追求することが重要である。

第3部 より深い洞察へ向かうリファクタリング

本書の第3部では、ドメインモデリングと設計をより深いレベルへと洗練させていくための考え方とテクニックが示されている。

鍵となるのは、ドメインへの継続的な学習と、モデルの表現力を高めるための地道なリファクタリングの積み重ねだ。その過程で、ときに飛躍的な前進(ブレイクスルー)が訪れる。こうした機会を活かすには、一時的な混乱を恐れず、チームが集中的に取り組む必要がある。

より良いモデルのためのヒントは、ドメインエキスパートとの対話や、既存のコードのぎこちなさ、ドメインの文献などから得られる。見出した概念は明示的にモデル化し、試行錯誤で洗練させていく。既存のアナリシスパターンデザインパターンも、ドメインの文脈に合わせて応用できる。

こうして作り上げるモデルは、単に精緻なだけでなく、開発者にとって理解と拡張が容易な「しなやかさ」を備えていなければならない。意図が明快で、副作用がなく、概念の本質的な関連に基づく設計を目指す。

より深いモデルと、しなやかな設計は、ソフトウェアに対するチームの継続的な取り組みを通じて、少しずつ、ときに劇的に発展していく。それは直線的でも予測可能でもないプロセスだが、DDD実践者はその価値を信じ、チャンスを逃さずに前進し続ける。

第4部 戦略的設計

本書の第4部では、大規模で複雑なシステムを開発するためのドメイン駆動設計の戦略的な側面が論じられている。複数のチームによって開発が進められると、モデルの断片化が問題となる。そこで、「境界づけられたコンテキスト」の概念を用いて、モデルの適用範囲を明示的に定義し、「コンテキストマップ」によってシステム全体のコンテキストを整理する。コンテキスト間の関係は、共有カーネル、顧客/供給者、順応者など、状況に応じたパターンで統合される。

一方、「戦略的設計」では、モデルの本質的な部分である「コアドメイン」に注力し、汎用的な概念を括り出して純粋なコアを「隔離」「蒸留」する。開発者は、「凝集したメカニズム」を見出し、複雑な処理をまとめて隠蔽することで、ドメインモデルの本質を際立たせる。

大規模なシステムでは、「大規模な構造」によって、モデル全体に一貫性のある枠組みを与える。比喩的な「システムのメタファ」、階層的な「責務のレイヤ」、ランタイムの柔軟性を与える「知識レベル」、疎結合な「プラグイン可能なコンポーネントフレームワーク」など、様々なパターンが存在する。ただし、これらの構造は絶対的なものではなく、プロジェクトと共に「進化」させるべきだとされる。

複雑なシステムの核心を見極め、洗練していく過程では、開発チーム全体で「ユビキタス言語」を醸成し、境界づけられたコンテキストごとの「方言」を尊重しつつ、モデルについてのコミュニケーションを深めることが求められる。



各章の主要な概念

第1部 ドメインモデルを機能させる

第1章 知識をかみ砕く

開発チームがソフトウェアを役立つものにするには、対象ドメインの知識を身につける必要がある。しかし、情報は断片的で大量にあり、どれが必要かわからない。モデルはこの知識を選び抜いて意図的に構成したものであり、チームがモデルを作る過程で知識をかみ砕いていく。モデルが改良されるたびに、チームの理解が深まり、さらにモデルが洗練される。こうしたモデルは実用的で厳密でなくてはならない。

第2章 コミュニケーションと言語の使い方

モデルに基づいた言語(ユビキタス言語)を用いることで、チーム内のコミュニケーションが明確になり、実装とつながる。チームは言語を実験的に使用し、モデルを改良する。図やドキュメントも言語によって補完される。チーム全体がこの言語を使うことで相互理解が深まり、言語自体も進化する。

第3章 モデルと実装を結びつける

分析モデルと設計を分けるのではなく、単一のモデルを探し、モデルとコードを緊密に結びつける(モデル駆動設計)。モデルを忠実に実装し、フィードバックによってモデルを改良する。ユビキタス言語によってチーム全体の理解がモデルに反映される。モデリングとコーディングは分離せず、開発者全員がドメインを理解し、モデルに責任を持つ。

第2部 モデル駆動設計の構成要素

第4章 ドメインを隔離する

ドメインの概念を他の関心事から切り離すことで、モデルに集中できる。レイヤ化アーキテクチャでは、ドメイン層を分離。利口なUI アンチパターンは、ドメイン駆動設計と相容れない。レイヤ間の関係づけにはパターンがある。ドメインサービスは、ドメインの操作をモデル化。ドメイン層内でも差別化が必要。

第5章 ソフトウェアで表現されたモデル

関連の設計で無駄をなくす。エンティティは同一性で定義され、値オブジェクトは属性の値で定義される。サービスはドメインの操作を表現。モジュールはモデルを意味のある塊に分割。関係DBの制約に適応しつつ、モデルとの整合性を保つ。

第6章 ドメインオブジェクトのライフサイクル

集約は整合性の境界を定義。ファクトリは生成の複雑さをカプセル化リポジトリは永続化を隠蔽。設計の妥協点を見極めることが重要。

第7章 言語を使用する-応用例

貨物輸送ドメインを段階的にモデリング。レイヤ化、エンティティと値の区別、集約、リポジトリの選択、ファクトリの設計など、ドメイン駆動設計の構成要素を適用。新規機能の追加に伴い、モデルを洗練。

第3部 より深い洞察へ向かうリファクタリング

第8章 ブレイクスルー

開発が進むと、突如として深い洞察が得られ、モデルと設計が大きく前進することがある。これをブレイクスルーと呼ぶ。ブレイクスルーは予測不可能だが、連続的なリファクタリングから生まれる。リスクもあるが、機会を逃してはならない。

第9章 暗黙的な概念を明示的にする

優れたモデルには、ドメインの中心となる概念が明示的に含まれる。開発者は、会話に出てくる手がかりや、設計のぎこちなさ、矛盾などから、そうした概念を見出さなければならない。見出した概念は試行錯誤でモデル化する。

第10章 しなやかな設計

意図が明確で、副作用のない関数や表明によって部品の組み合わせが安全になり、概念の輪郭に従った設計により意味の単位が安定する。こうしたしなやかな設計は、開発者が理解と変更を繰り返しながら、複雑さに立ち向かえるようにする。

第11章 アナリシスパターンを適用する

アナリシスパターンは、ドメインに関する他者の経験を利用できる。だが既製の解決策ではなく、洞察とモデリングの糧となる。プロジェクトの状況に合わせて選択し、現場の知識とかみ合わせる必要がある。

第12章 デザインパターンをモデルに関係づける

オブジェクト指向デザインパターンの一部は、ドメインの概念とも合致する。ドメインとの関連を意識しながらデザインパターンを用いると、モデルがより明確になり、実装面の利点も得られる。

第13章 より深い洞察へ向かうリファクタリング

より深い洞察へ向かうには、ドメインに馴染み、物事に新しい見方をし、ドメインエキスパートとの対話を続けることだ。チームで集中的に取り組み、外部の知識も活用する。危機に見える変化もブレイクスルーの好機となり得る。

第4部 戦略的設計

第14章 モデルの整合性を維持する

複数のチームが関わる大規模プロジェクトでは、モデルの断片化が問題になる。これを防ぐため、モデルが適用される範囲を明示的に定義した「境界づけられたコンテキスト」の概念を導入する。さらに、コンテキストマップを描いてコンテキスト間の関係を整理し、関係性に応じた様々な統合方法を選択する。統合パターンには、共有カーネル、顧客/供給者開発チーム、順応者、腐敗防止層などがある。

第15章 蒸留

巨大で複雑なモデルの本質的な部分に注目し、モデルを煮詰めるプロセスを「戦略的設計」と呼ぶ。戦略的設計では、最も価値のあるコアドメイン、汎用的な概念を扱う汎用サブドメイン、複雑な処理を隠蔽する凝集したメカニズムを見極める。さらに、補助的な要素を切り離して純粋なコアドメインを「隔離」し、深く洞察に満ちたモデルへと「蒸留」する。

第16章 大規模な構造

巨大なモデルを統一的に理解するため、システム全体に対する設計の方針となる「大規模な構造」を導入する。具体的には、ユビキタス言語の比喩表現としての「システムのメタファ」、モデルを階層化する「責務のレイヤ」、状況に応じて変化するモデルを実現する「知識レベル」、疎結合コンポーネント構成の「プラグイン可能なコンポーネントフレームワーク」などのパターンがある。構造はプロジェクトと共に「進化」すべきである。



印象的なフレーズ

第1部 ドメインモデルを機能させる

  • ソフトウェアの核心は、ドメインに関係した問題をユーザのために解決する能力である。
  • 知識をかみ砕く
  • ユビキタス言語
  • モデル駆動設計
  • 実践的モデラ

第2部 モデル駆動設計の構成要素

  • 「利口なUI アンチパターン
  • 「オブジェクトには概念的な同一性がない。そういうオブジェクトは、物事の特徴を記述する。」
  • 「集約をモデリングし、ファクトリとリポジトリを設計へ追加することで、モデルオブジェクトの操作を体系的に、それもライフサイクルを通じて意味のある単位で行えるようになる。」
  • 「時には、単純に『物』とはできないこともある。」
  • 「戦略的設計」
  • 「パターンを使用する際は、フレームワークと対立してはならない。」

第3部 より深い洞察へ向かうリファクタリング

  • 洞察のブレイクスルーをもたらす可能性が作り出される
  • 暗黙的だった概念を明示的にするこうした変化が、時には、深いモデルへとつながるブレイクスルーになることもある
  • 手に負えなくなった評価メソッドは、うまく拡張して独立オブジェクトにする
  • 概念を掘り出す
  • しなやかな設計は、深いモデリングを補完するものだ
  • 設計は、それを変更しようとする開発者にとっても役に立たなければならない
  • アナリシスパターンは活用すべき知識である
  • デザインパターンであると考えられるパターンが、ドメインモデルに対してどう適用できるか
  • より深い洞察へ向かうリファクタリングは、多くの側面を持つプロセスである

第4部 戦略的設計

  • 「木を見て森を見ず」
  • 「信頼するが、検証もする」
  • 剽窃せよ!誰の研究も見逃してはならない。ただ、いつも調査と呼ぶことを忘れずに」
  • 「Less is more」
  • 「オブジェクトはスペシャリストだが、開発者はジェネラリストである」



重要なポイント

第1部 ドメインモデルを機能させる

  • 複雑さに対処するには、ドメインモデルが鍵となる。
  • モデルを作成することはドメインの知識をかみ砕くプロセスである。
  • チーム全体がモデルに基づいた言語を使うことで、コミュニケーションと実装の質が向上する。
  • モデルとコードは密接に結びつけるべきで、分析と設計を分離すべきではない。
  • 開発者全員がドメインモデリングを理解する必要がある。

第2部 モデル駆動設計の構成要素

  • ドメインを他の関心事から隔離することの重要性
  • エンティティと値オブジェクトの違いと使い分け
  • サービスによるドメインの操作のモデル化
  • 集約による整合性の境界の定義
  • ファクトリとリポジトリによるライフサイクル管理の隠蔽
  • 関係データベースとの整合性を保ちつつモデルを表現する工夫
  • パターンの適用とフレームワークとの整合性
  • モデルの継続的な洗練

第3部 より深い洞察へ向かうリファクタリング

  • ブレイクスルーはリスクもあるが、モデルと設計を大きく前進させる機会である
  • ドメインの中心的な概念を見出し、モデルに明示的に表現することが重要である
  • 意図が明確で副作用のない設計により、開発者は複雑さに立ち向かえる
  • アナリシスパターンは、そのまま使える解決策ではなく、モデリングの手がかりを与えてくれる
  • オブジェクト指向デザインパターンドメインの概念に合わせて使うと、モデルが明確になる
  • より深い洞察のためには、ドメインへの理解を深め、新しい見方を取り入れ、対話を重ねる
  • 危機に見える変化もブレイクスルーのチャンスかもしれない

第4部 戦略的設計

  • 複数のモデルを整理するためのコンテキストマップとコンテキスト間の関係パターン
  • 大規模モデルの本質を見極める戦略的設計と、隔離・蒸留によるドメインモデルの深化
  • チーム全体で共有可能な大規模な構造パターンと、状況に応じた「進化」の重要性
  • モデルの断片化を防ぐ継続的な統合と、境界づけられたコンテキスト間の慎重な統合
  • 戦略的設計とユビキタス言語の相互作用による、深い洞察に基づくモデルの構築



理解度チェック用の質問文

第1部 ドメインモデルを機能させる

第1章
  • 知識をかみ砕くとはどういうことか?
  • モデルの目的は何か?
  • チームの理解とモデルの関係はどのようなものか?
第2章
  • ユビキタス言語とは何か?
  • チームはどのようにしてモデルを改良するか?
  • 言語はどのようにしてチームのコミュニケーションを明確にするか?
第3章
  • モデル駆動設計とは何か?
  • 分析モデルと設計を分けることの問題点は何か?
  • 開発者がモデリングから離れてはいけない理由は何か?

第2部 モデル駆動設計の構成要素

第4章
第5章
  • エンティティと値オブジェクトはどのように区別されるか?
  • サービスはドメインモデルにおいてどのような位置づけか?
  • モジュール分割の目的は何か?
第6章
  • 集約はどのような問題を解決するか?
  • ファクトリの役割は何か?
  • リポジトリはオブジェクトのライフサイクルのどの段階を扱うか?
第7章
  • 貨物輸送ドメインにおける集約のルートにふさわしいエンティティは何か?
  • 「荷役イベントのコレクション」から「荷役イベントリポジトリ」への変更の理由は何か?
  • 腐敗防止層はどのような役割を果たしたか?

第3部 より深い洞察へ向かうリファクタリング

第8章
  • ブレイクスルーとは何か?どのようにして起こるか?
  • ブレイクスルーにはどのようなリスクがあるか?
  • ブレイクスルーが起きた時にチームはどう行動すべきか?
第9章
  • ドメインの中心的な概念を見出すために、開発者はどこに着目すべきか?
  • 見出した概念をどのようにモデル化すればよいか?
  • 仕様オブジェクトとは何か?どのような利点があるか?
第10章
  • しなやかな設計とはどのようなものか?なぜ必要か?
  • 意図が明確な設計とは?どう実現できるか?
  • 概念の輪郭とは何か?設計はそれにどう従うべきか?
第11章
第12章
第13章
  • より深い洞察へ向かうリファクタリングで重要な3つのポイントは?
  • より深い洞察へのブレイクスルーはどのようなきっかけで起こるか?
  • ブレイクスルーの機会をどう捉えるべきか?

第4部 戦略的設計

第14章
  • 境界づけられたコンテキストとは何か?なぜそれが重要なのか?
  • コンテキストマップにはどのような要素が含まれるか?
  • 境界づけられたコンテキストを統合する代表的なパターンにはどのようなものがあるか?
第15章
  • 戦略的設計において、なぜコアドメインを見極めることが重要なのか?
  • 汎用サブドメインとはどのようなものか?それをコアドメインから分離する利点は何か?
  • 大規模なモデルを理解しやすくするための「蒸留」とはどのような行為を指すか?
第16章
  • 大規模な構造を導入する目的は何か?代表的なパターンにはどのようなものがあるか?
  • 知識レベルとはどのような概念か?それによってどのような利点が得られるか?
  • 「進化する秩序」とはどういう意味か?なぜ大規模な構造は「進化」すべきなのか?



重要な概念の解説

第1部 ドメインモデルを機能させる

  • ドメインモデル:問題領域(ドメイン)の本質的な概念やルールを表現した抽象化。ソフトウェアの核となる。
  • 知識のかみ砕き:大量の情報から本質を抽出し、実用的なモデルに落とし込む継続的なプロセス。
  • ユビキタス言語:モデルに基づいた、チーム全体で共有される明確な言語。コミュニケーションと実装を強力に結びつける。
  • モデル駆動設計:分析と設計を分けずに、単一の洗練されたモデルをコードに直接的に反映させる設計手法。
  • 実践的モデラ:ドメインとコードの両方に精通し、モデリングとコーディングを一体的に行う開発者。

第2部 モデル駆動設計の構成要素

  • レイヤ化アーキテクチャ:アプリケーションを複数の層に分割する設計手法。ユーザインタフェース層、アプリケーション層、ドメイン層、インフラストラクチャ層に分ける。ドメイン層を他の関心事から隔離できる。
  • エンティティ:同一性によって定義されるオブジェクト。エンティティの状態は変化するが、同一性は不変。
  • 値オブジェクト:属性の値によって定義されるオブジェクト。不変であり、交換可能。
  • サービス:ドメインの操作を表現するが状態は保持しないオブジェクト。エンティティや値オブジェクトに自然に属さない操作を受け持つ。
  • 集約:整合性を保つ必要のある関連オブジェクトの集まり。ルートエンティティを中心に構成され、境界の外部からはルートのみ参照可能。
  • ファクトリ:オブジェクトの生成の複雑さを隠蔽し、生成ロジックを集約するオブジェクト。
  • リポジトリ:永続化の複雑さを隠蔽し、オブジェクトのライフサイクルを管理するオブジェクト。

第3部 より深い洞察へ向かうリファクタリング

  • ブレイクスルー: 開発者がドメインへの深い理解を得て、モデルや設計が飛躍的に改善されること。予測は難しいが、継続的なリファクタリングから生まれる。リスクもあるが、大きなチャンスでもある。
  • 暗黙的な概念: ドメインの重要な概念のうち、まだモデルで明示的に表現されていないもの。会話の端々に表れたり、既存の設計のぎこちなさの原因になっていたりする。見出して明示的にモデル化することが重要。
  • しなやかな設計: 意図が明確で、副作用がなく、概念の輪郭に合致した設計。開発者が理解と拡張を繰り返しやすくなる。深いモデリングと相互に補完し合う。
  • アナリシスパターンドメインに関するベストプラクティスをパターン化したもの。モデリングのヒントを与えてくれるが、そのまま当てはめられるわけではない。プロジェクトの文脈に合わせて応用する。
  • 概念の輪郭: ドメインの中で本質的に関連し合う概念の集まりの境界線。モデルと設計は、この輪郭に沿って構成要素を切り出すべきである。

第4部 戦略的設計

  • 境界づけられたコンテキスト: モデルを適用できる範囲を明示的に定義したもの。モデルの断片化を防ぎ、言語的な統一性を保つ。
  • コンテキストマップ: システムを構成する複数のコンテキストとその関係を俯瞰的に示した地図。統合作業の指針となる。
  • 戦略的設計: モデルの本質を見極め、洗練させるための継続的な取り組み。コアドメインを際立たせ、モデルを深化させる。
  • コアドメイン: システムの中で最も価値を生み出す、特徴的なモデルの部分。戦略的設計の主眼となる。
  • 汎用サブドメイン: ドメインに関連するが、標準的な概念を扱う、再利用可能なモデルの部分。コアドメインの対比として重要。
  • 大規模な構造: システム全体を貫く設計上の方針や概念的な枠組み。モデルに一貫性をもたらし、開発者間のコミュニケーションを助ける。
  • 凝集したメカニズム: 複雑だが、まとまりのある一連の処理を隠蔽するサブシステム。ドメインモデルのもつれを解消する。
  • ユビキタス言語: チーム全体で共有されるモデルについての言語。境界づけられたコンテキストごとに「方言」が存在する。
  • パターン: 文脈を共有する問題に対する、再利用可能な解決の枠組み。パターンは名前、問題、解決、結果で構成される。



考察

第1部 ドメインモデルを機能させる

エリック・エヴァンスの「ドメイン駆動設計」は、複雑なソフトウェア開発に挑むための強力な方法論を提示している。その中核をなすのは、問題領域を深く理解し、その本質を巧みにモデル化することだ。開発チームがドメインの専門家と協力し、徹底的に知識をかみ砕いてソフトウェアの設計に落とし込む。コードはモデルを如実に反映し、ドメインの言葉がそのまま生きる。

これは理想的なアプローチだが、実践には高いハードルがある。専門的知識を持つ担当者の確保、チーム全体でのスキル習得、綿密なコミュニケーションなど、なかなか難しい課題が多い。また、モデリングとコーディングの一体化は、技術的複雑性を増す恐れもある。

とはいえ、著者の豊富な経験に基づく指針は示唆に富む。単に形式的な方法論ではなく、プロジェクトを成功に導く哲学と言える。ポイントは、ドメインの専門性とソフトウェア構築のスキルを統合することにある。チームワークと学習を重視する組織文化も欠かせない。

従来の開発方式への根本的な挑戦であるだけに、一朝一夕には浸透しないだろう。だが、イノベーティブなシステムを生み出すには欠かせないアプローチと言える。人材育成を含め、息の長い取り組みが求められる。本書で提示された知見は、これからのソフトウェア開発を導く指針となるはずだ。

第2部 モデル駆動設計の構成要素

本書の第2部は、ドメイン駆動設計の中核をなす構成要素を体系的に提示しており、モデルを実装に落とし込む上で道標となる。レイヤ化による関心事の分離、エンティティと値オブジェクトの使い分け、サービスによる操作のモデル化など、示されたパターンは納得感があり、実践的である。
特に、モデルの実装において陥りがちな、トランザクション整合性の問題に対する集約の導入は腑に落ちる。また、ライフサイクル管理の複雑さを隠蔽するファクトリやリポジトリは、モデルに集中するためにも不可欠だ。終盤の貨物輸送ドメインの例は各要素の適用イメージを掴むのに役立つ。
一方で、関係データベースとの整合性をいかに保つかについては、やや深掘りが足りない印象を受けた。モデルとテーブル設計の乖離は実務ではよく直面する問題であり、両者のバランスについてはもう少し議論が欲しかった。
とはいえ、ドメインモデルをどう実装に落とし込むかという普遍的な課題に対し、筋の通った方法論を提示した点で、本書の価値は非常に高い。経験則に基づくパターンの適用と、フレームワークとの整合性の取り方など、示唆に富む知見が随所に見られた。エンティティや集約など、用語の定義も明快で、ドメインモデリングを行う上で常に参照したくなる良書である。

全体としては、ソフトウェア開発の本質であるモデリングと実装の間の翻訳を、いかにして整合性高く行うかを真摯に考究した良著であり、難解なドメインに立ち向かう開発者必読の書と言えるだろう。

第3部 より深い洞察へ向かうリファクタリング

「エリック・エヴァンスのドメイン駆動設計」の第3部は、洗練されたドメインモデリングと設計のための実践的な指針を提示している。それは、単に技法の羅列ではない。むしろ、開発者に、ドメインを深く理解し、その本質を細部に至るまでソフトウェアに反映させようとする姿勢を求めている。

特に印象的なのは、「ブレイクスルー」というアイデアだ。画期的な発見や大幅な改善は、スケジュール通りに起きるわけではない。だが著者は、日々の地道な歩みを信じ、チャンスを逃さない用意を促している。これは、ソフトウェア開発というクリエイティブな営みの本質を捉えた洞察だと言えるだろう。

また、「しなやかな設計」の重要性も説得力を持って語られている。ドメインを深く理解しても、それを使いやすいコードに落とし込めなければ意味がない。かといって、設計のための設計に走ってもいけない。あくまで、ドメインの概念を明晰に、安全に、過不足なく表現できることが肝要なのだ。

反復的に理解を深め、モデルを練り上げ、設計をしなやかに進化させること。著者が説くこのプロセスは、きれいごとを言っているわけではない。変化を恐れず、試行錯誤を厭わない覚悟が必要だ。トレードオフも避けられない。だがそれでも、ドメインモデリングを真摯に追求する意義は失われないと、私は本書から教えられた。

もちろん、すべてのプロジェクトでここまで突き詰められるわけではないだろう。モデルの妥当性の評価も難しい問題だ。とはいえ、現実と向き合いながら、ソフトウェアにドメインの本質を宿すことをあきらめない姿勢には、大きな感銘を受ける。設計のプロとして、この高い理想に少しでも近づきたいと思わずにはいられない。

第4部 戦略的設計

本書の第4部で提示されている戦略的設計の原則とパターンは、大規模で複雑なシステムを開発する上で、極めて示唆に富む指針となっている。特に、モデルの断片化を防ぐための「境界づけられたコンテキスト」、本質を見極めるための「戦略的設計」、全体を見渡すための「大規模な構造」は、ドメイン駆動設計の真髄といえる考え方であり、複雑なドメインに立ち向かう開発チームにとって、羅針盤のような役割を果たすものといえる。

著者のエリック・エヴァンスは、実際のプロジェクトで得られた知見をもとに、抽象的な原則だけでなく、具体的で実践的なパターンを数多く提示している。「コンテキストマップ」「責務のレイヤ」「プラグイン可能なコンポーネントフレームワーク」など、エンジニアリングの現場ですぐにでも活用可能なテクニックが詰まっていることは、本書の大きな魅力の1つである。

また、「進化する秩序」という考え方は、アジャイル開発の思想とも通底するものがあり、ソフトウェア開発プロセス全般に対する重要な示唆を与えている。drilldownとemergenceのバランスを重視し、状況の変化に柔軟に対応しながら、モデルを洗練していく姿勢は、DDD実践者のみならず、全てのソフトウエアエンジニアが学ぶべき教訓だと言える。

一方で、「凝集したメカニズム」や「知識レベル」といった概念は、やや抽象度が高く、実践の難易度も高いと感じられた。これらのパターンをどのように実装に落とし込むか、具体的な事例を交えた補足説明があればより理解が深まったのではないだろうか。

また、ドメインモデリングユビキタス言語の重要性は本書全体を通して強調されているが、複数の「方言」が生まれた場合の言語的な統合プロセスについては、もう少し踏み込んだ議論が欲しいところである。

とはいえ、これらはあくまで些細な望蜀の念に過ぎない。エリック・エヴァンスが提唱する戦略的設計の原則とパターンは、今日のソフトウエア開発に携わる技術者に対し、示唆と活力を与えてくれる貴重な知的資産である。系統的で論理的な議論の末に、「優れたソフトウエアを作成することは、学び考える活動である」という含蓄のある言葉で結ばれていることからも、著者の豊かな洞察が窺い知れる。本書は、単なる開発技法の解説書ではなく、ソフトウエアエンジニアリングの真髄を問う、1つの思想書としても読み継がれるべき書物だと言えるだろう。

まとめ

エリック・エヴァンスの「ドメイン駆動設計」は、複雑なソフトウェア開発に立ち向かうための強力な方法論を提示している。その中核をなすのは、問題領域を深く理解し、その本質を巧みにモデル化し、ソフトウェアに反映させることだ。開発チームがドメインの専門家と協力し、知識をかみ砕いてモデルを構築する。そのモデルは、ユビキタス言語を通してチーム全体で共有され、コードに直接的に反映される。

本書で解説されている、レイヤ化アーキテクチャ、エンティティと値オブジェクト、集約、ファクトリ、リポジトリなどの構成要素は、モデルを実装に落とし込む上で強力な手がかりとなる。一方、関係データーベースとの整合性の取り方など、実践上の難しさも残されている。

より洗練されたモデルを目指すには、ブレイクスルーのチャンスを逃さず、しなやかな設計を追求する必要がある。そのためには、アナリシスパターンデザインパターンを応用しつつ、試行錯誤を重ねる覚悟が問われる。

さらに、複数のチームが関わる大規模なシステム開発では、戦略的設計の原則とパターンが不可欠だ。境界づけられたコンテキスト、コンテキストマップ、コアドメインの見極めなどにより、モデルの断片化を防ぎ、本質を追求することができる。状況の変化に合わせてモデルを進化させる柔軟な姿勢も重要となる。

ドメイン駆動設計は、理想的ではあるが実践のハードルも高い。組織の文化や個人のスキルの問題も絡む。とはいえ、ソフトウェア開発の真髄を捉えたアプローチであることは間違いない。イノベーティブなシステムを生み出し、ビジネス価値を高めるには、避けて通れない道のりなのだ。本書から学んだ洞察を糧に、地道な努力を重ねていきたい。

dlshogiのPyTorch Lightning対応 その5(Warm-upに対応したスケジューラ)

大規模なモデルの学習に効果があるとされる学習率スケジューリングの手法にWarm-upがある。
しかし、Pytorchの標準のスケジューラには、Warm-upに対応したスケジューラが提供されていない。

PyTorch Lightning Boltsには、Warm-upに対応したCosineAnnealingLRがある。
Linear Warmup Cosine Annealing — Lightning-Bolts 0.7.0 documentation

まだレビュー中のステータスで、機能的にもリスタートや減衰には対応していない。

深層学習界隈でよく使われるtimmには、Warm-upの他にリスタート回数や減衰率の調整が可能なCosineAnnealingLR学習率スケジューラがある。
SGDR - Stochastic Gradient Descent with Warm Restarts | timmdocs

そこで、先日作成したdlshogiのPyTorch Lightning CLIの訓練スクリプトで、timmのCosineAnnealingLRを使おうと試そうとしたが、PyTorchのLRSchedulerを継承していないため、標準的な方法では使うことができなかった。

PyTorch Lightning CLIをカスタマイズすることで使えるようにはできるようだが、PyTorch Lightning CLIを使うメリットが薄れてくるので、できればあまりカスタマイズしたくない。
How to utilize timm's scheduler? · Issue #5555 · Lightning-AI/pytorch-lightning · GitHub

そこで、LRSchedulerを継承して、timmのCosineAnnealingLRと同じ動作をするスケジュールを自作することにした。

LRSchedulerを継承したtimmのCosineAnnealingLRと同等のスケジューラ

""" This code is based on the Cosine Learning Rate Scheduler implementation found at:
https://github.com/huggingface/pytorch-image-models/blob/main/timm/scheduler/cosine_lr.py
"""

import math

from torch.optim.lr_scheduler import LRScheduler


class CosineLRScheduler(LRScheduler):
    def __init__(
        self,
        optimizer,
        t_initial,
        lr_min=0.0,
        cycle_mul=1.0,
        cycle_decay=1.0,
        cycle_limit=1,
        warmup_t=0,
        warmup_lr_init=0,
        warmup_prefix=False,
        k_decay=1.0,
        last_epoch=-1,
    ):
        self.t_initial = t_initial
        self.lr_min = lr_min
        self.cycle_mul = cycle_mul
        self.cycle_decay = cycle_decay
        self.cycle_limit = cycle_limit
        self.warmup_t = warmup_t
        self.warmup_lr_init = warmup_lr_init
        self.warmup_prefix = warmup_prefix
        self.k_decay = k_decay

        if last_epoch == -1:
            base_lrs = [group["lr"] for group in optimizer.param_groups]
        else:
            base_lrs = [group["initial_lr"] for group in optimizer.param_groups]
        if self.warmup_t:
            self.warmup_steps = [(v - warmup_lr_init) / self.warmup_t for v in base_lrs]
        else:
            self.warmup_steps = [1 for _ in base_lrs]

        super().__init__(optimizer, last_epoch)

    def get_lr(self):
        t = self.last_epoch
        if t < self.warmup_t:
            lrs = [self.warmup_lr_init + t * s for s in self.warmup_steps]
        else:
            if self.warmup_prefix:
                t = t - self.warmup_t

            if self.cycle_mul != 1:
                i = math.floor(
                    math.log(
                        1 - t / self.t_initial * (1 - self.cycle_mul), self.cycle_mul
                    )
                )
                t_i = self.cycle_mul**i * self.t_initial
                t_curr = (
                    t - (1 - self.cycle_mul**i) / (1 - self.cycle_mul) * self.t_initial
                )
            else:
                i = t // self.t_initial
                t_i = self.t_initial
                t_curr = t - (self.t_initial * i)

            gamma = self.cycle_decay**i
            lr_max_values = [v * gamma for v in self.base_lrs]
            k = self.k_decay

            if i < self.cycle_limit:
                lrs = [
                    self.lr_min
                    + 0.5
                    * (lr_max - self.lr_min)
                    * (1 + math.cos(math.pi * t_curr**k / t_i**k))
                    for lr_max in lr_max_values
                ]
            else:
                lrs = [self.lr_min for _ in self.base_lrs]

        return lrs

timmの方では、最大の学習率をoptimizerから取得して、メンバ変数に保持しているが、PyTorchのスケジュールは、optimizerのinitial_lrにコピーを持たせているので、その作法に合わせている。

また、timmのスケジューラは、step()にステップ数を渡すようになっているが、PyTorchのスケジューラは、step()は引数なしでlast_epochから取得するようになっているため、そちらに合わせた。

更新間隔

PyTorch Lightningの標準のスケジューラの更新間隔は、epoch単位になっている。
将棋AIでは1epochが大きいステップ数になるため、Warm-upやCosineAnnealingLRを使う場合は、ステップ単位で更新したい。

PyTorch Lightningは、更新間隔を変更するオプションがないため、LightningCLIを継承してクラスメソッドのconfigure_optimizersをオーバーライドする必要がある。
Change the scheduler interval in CLI · Lightning-AI pytorch-lightning · Discussion #13975 · GitHub

class LightningCLI(cli.LightningCLI):
    @staticmethod
    def configure_optimizers(lightning_module, optimizer, lr_scheduler=None):
        if lr_scheduler is None:
            return optimizer
        return {
            "optimizer": optimizer,
            "lr_scheduler": {
                "scheduler": lr_scheduler,
                "interval": "step",
                **(
                    {"monitor": lr_scheduler.monitor}
                    if isinstance(lr_scheduler, ReduceLROnPlateau)
                    else {}
                ),
            },
        }

動作確認

config.yamlに以下のように定義を行い動作確認を行った。
チェックポイントをリジュームして継続できるかも確認した。

lr_scheduler:
  class_path: dlshogi.lr_scheduler.CosineLRScheduler
  init_args:
    t_initial: 200
    lr_min: 1e-8
    cycle_mul: 2
    cycle_limit: 8
    cycle_decay: 0.5
    warmup_t: 100
    warmup_lr_init: 1e-7
    warmup_prefix: true

Tensorboardのグラフが50ステップ間隔なため、カクカクでわかりにくいが、warmup_tやcycle_mul、cycle_decayのパラメータが機能していることが確認できる。

まとめ

dlshogiにWarm-upに対応したスケジューラを追加した。
Warm-upにどれくらい効果があるかは別途検証したい。

dlshogiモデルの枝刈りを試す

前回、深層強化学習において、モデルの枝刈りによりスケーリングが可能であることを示した論文を紹介した。

dlshogiの強化学習でもモデルの枝刈りが効果があるか試したいと考えているが、まずはモデルの枝刈りのみを行って、精度と探索速度にどう影響するかを調べてみる。

モデルの枝刈り

モデルの枝刈り(pruning)は、休止状態のニューロンを削除することで、モデルサイズを削減し、推論速度を向上させる手法である。

PyTorchには枝刈りの方法として、unstructuredとstructuredの2種類の方法が用意されている。

unstructuredは、層のパラメータ全体から一定の割合でパラメータを削除する。

structuredは、一定の割合で畳み込みのチャンネル全体を削除する。

パラメータの削除は、実際には削除は行っておらずパラメータを0にすることで実装されている。

値が0のパラメータも演算は必要なため、推論速度を向上するには、ハードウェア的な支援が必要になる。

NVIDIAGPUでは、Ampere以降で、structuredの枝刈りに対応している。
NVIDIA Ampere アーキテクチャと TensorRT を使用してスパース性で推論を高速化する - NVIDIA 技術ブログ

ただし、連続する4つのチャンネルのうち2つが0である必要があるため、枝刈り率50%以上でないと効果がない。

先述の論文では、枝刈りは5%でパフォーマンスが上がることが報告されているため、枝刈りしても推論速度の向上は期待できない。

PyTorchでの実装

チェックポイントを読み込んで、モデルの各層のモジュールをnamed_modules()で取得して、畳み込み層の場合、weightに対して、prune.ln_structuredを適用する。

コードは、以下の通り簡単に記述できる。

import argparse

import torch

from dlshogi.common import *
from dlshogi.network.policy_value_network import policy_value_network
from torch.nn.utils import prune

parser = argparse.ArgumentParser()
parser.add_argument("checkpoint")
parser.add_argument("output_checkpoint")
parser.add_argument("--network", default="resnet10_swish", help="network type")
parser.add_argument("--amount", type=float, default=0.05)
args = parser.parse_args()

device = torch.device("cpu")
model = policy_value_network(args.network)

checkpoint = torch.load(args.checkpoint, map_location=device)
model.load_state_dict(checkpoint["model"])

# prune
for name, module in model.named_modules():
    if isinstance(module, torch.nn.Conv2d):
        prune.ln_structured(module, name="weight", n=1, dim=0, amount=args.amount)
        prune.remove(module, "weight")

checkpoint["model"] = model.state_dict()
torch.save(checkpoint, args.output_checkpoint)

実験条件

dlshogiの30ブロック384フィルタのモデルを使用する。
枝刈り率は、論文と同じ5%の他に、推論速度の違いを見るため50%、90%でも試す。
テストデータには、floodgateのR3800以上の棋譜を使用する。
探索速度は、初期局面で10秒思考したときのNPSを測定する。
GPUは4090 1枚を使用する。

精度

通常は枝刈り後にファインチューニングを行うが、ファインチューニング前の精度を確かめた。

枝刈り 方策損失 価値損失 方策正解率 価値正解率
なし 1.3057 0.4402 0.5585 0.7765
5% 4.484 0.644 0.3173 0.6775
50% 7.3963 0.8144 0.0090 0.5878
90% 9.6545 1.5117 0.0001 0.4989


枝刈り5%でも、方策の正解率は24%、価値の正解率は9.9%下がっており、精度はかなり落ちる。
枝刈り50%、90%は、方策の正解率が1%未満であり、使い物にならない精度である。

推論速度

ソース修正

TensorRTで、枝刈りしたモデルの推論速度を向上させるには、オプションの設定が必要になる。

公式ドキュメントのSparsityの項目に説明がある。
Developer Guide :: NVIDIA Deep Learning TensorRT Documentation

ソースコードに以下の行を追加した。

config->setFlag(BuilderFlag::kSPARSE_WEIGHTS);
比較結果
枝刈り NPS
なし 20255
5% 19836
50% 23805
90% 26020

枝刈り5%の場合、枝刈りなしとほぼ同じの探索速度である。
枝刈り50%の場合17.5%、枝刈り90%の場合28.5%向上する。

ハードウェア支援が効果があることが確認できた。

kSPARSE_WEIGHTSオプションなしの場合

kSPARSE_WEIGHTSオプションなしの場合でも確認した。

枝刈り NPS
なし 20255
5% 19698
50% 20898
90% 20470

どの条件もほぼ同じ探索速度である。

まとめ

dlshogiモデルで枝刈りを試した。
5%の枝刈りでも精度が大きく落ちることが分かった。
50%の枝刈りでは方策正解率が1%未満になり使い物にならないほど精度が下がった。

また、TensorRTでオプションを有効にすると、枝刈り50%以上では探索速度が向上することが確認できた。
しかし、枝刈り5%では探索速度は変わらなかった。
論文で報告されている枝刈り率は5%のため、探索速度の向上は期待できない。

ファインチューニングを行った後に精度が回復するかは別途確認したい。