経緯
SGrepOption の廃止を進めようとしてましたが、
PR #2634 のレビューで、次のご意見をいただきました。
GrepInfo inherits SGrepOption にするかどうかは悩みドコロ。
同じコメントで「CGrepAgent::DoGrep の実行に必要なパラメーターが揃っていることを担保する責任は誰にあるのか」「揃ってなかったら UI 表示して入力要求するのがスジなんじゃないか」という問いも挙げられていました。
続きの作業に入る前に、この点の方針を決めたいと思います。
現状
|
定義場所 |
メンバー数 |
SGrepOption |
sakura_core/agent/CGrepAgent.h |
12 |
GrepInfo |
sakura_core/basis/GrepInfo.h |
18 |
このうち 12 個は同名・同型で重複しています。
| 区分 |
メンバー |
| 両方にある(12) |
bGrepReplace bGrepSubFolder bGrepStdout bGrepHeader nGrepCharSet nGrepOutputLineType nGrepOutputStyle bGrepOutputFileOnly bGrepOutputBaseFolder bGrepSeparateFolder bGrepPaste bGrepBackup |
GrepInfo のみ(6) |
cmGrepKey cmGrepRep cmGrepFile cmGrepFolder sGrepSearchOption bGrepCurFolder |
DoGrep() が SGrepOption::FromGrepInfo( gi ) で 12 個を詰め替え、その結果を DoGrepTree() / DoGrepFile() / DoGrepReplaceFile() / SetGrepResult() / OutputPathInfo() へ渡しています。
決めたいこと
(a) SGrepOption を廃止し、GrepInfo に一本化する
GrepInfo に Normalized()(Grep 置換時に否ヒット行出力を行単位出力へ落とす補正)を持たせ、SGrepOption と FromGrepInfo() を削除します。DoGrepTree() 以降の引数型を const GrepInfo& に変更します。
理由は、SGrepOption の存在意義が「DoGrepFile() へ安く値コピーするための部分集合」だったのに対し、GrepInfo を const 参照で渡せば値コピーが発生しないため、部分集合を作る動機が無くなることです。
(b) GrepInfo : public SGrepOption にする
GrepInfo から重複する 12 メンバーを削除し、SGrepOption を基底クラスにします。Normalized() は同様に用意し、FromGrepInfo() は削除します。
SGrepOption の 12 個はすべてまともな既定値を持ち、揃っていなくても Grep は動きます。一方 GrepInfo が足す cmGrepKey / cmGrepFile / cmGrepFolder などは揃っていないと Grep が成立しません。継承にすると「既定値で動く部分」と「入力を要求すべき部分」が型で分かれるので、上に挙げていただいた「担保する責任は誰にあるのか」という問いに対応しやすくなるかもしれません。
比較
|
(a) 廃止 |
(b) 継承 |
DoGrepTree() / DoGrepFile() / DoGrepReplaceFile() の引数型 |
const GrepInfo& へ変更(6 箇所) |
変更なし(派生から基底への変換で通る) |
SetGrepResult() / OutputPathInfo() の引数型 |
const GrepInfo& へ変更 |
変更なし |
DoGrep() 内の詰め替え |
削除 |
削除 |
GrepInfo の 12 メンバー |
現状のまま |
削除して基底から継承 |
SGrepOption の置き場所 |
消える |
basis/ へ移す必要あり |
| メンバーの初期化方法 |
現状のまま |
GrepInfo の NSDMI と SGrepOption のコンストラクター初期化子リストの混在をどうにかする必要あり |
| 変更規模 |
5 ファイル・約 190 行 |
(a) より小さくなる見込み |
(b) を採る場合に決めたいこと
1. SGrepOption の置き場所
basis/GrepInfo.h から agent/CGrepAgent.h を include すると basis/ → agent/ の逆依存になるため、SGrepOption を basis/ 配下へ移す必要があります。
basis/GrepInfo.h に同居させる
basis/ に別ファイルを作る(GrepOutputOption.h など)
2. 既定値をどちらに合わせるか
3 つのメンバーで既定値が食い違っています。
| メンバー |
GrepInfo |
SGrepOption |
bGrepSubFolder |
false |
true |
nGrepCharSet |
CODE_SJIS |
CODE_AUTODETECT |
nGrepOutputLineType |
0 |
1 |
現状はどちらの既定値も実行時には使われていません(GrepInfo はコマンドライン解析または CDlgGrep::MakeGrepInfo() が全メンバーを設定し、SGrepOption は FromGrepInfo() が全メンバーを上書きするため)。ただし継承にすると GrepInfo の既定値が SGrepOption のものに変わるので、どちらへ寄せるかを決めておく必要があります。
後続作業への影響
2026-06-20 に挙げていただいた 3 区分(ファイル抽出 / ファイル内検索 / 結果報告)のうち「結果報告」を sakura_core/grep/ へ切り出す作業を予定していますが、これは本件の結論に依存します。
- (a) の場合、切り出し先は
const GrepInfo& を受け取ります
- (b) の場合、切り出し先は
const SGrepOption& を受け取ります(SGrepOption の置き場所が決まっている必要があります)
お願い
(a) / (b) のどちらでも実装できます。方針をいただければ、それに合わせて進めます。
経緯
SGrepOptionの廃止を進めようとしてましたが、PR #2634 のレビューで、次のご意見をいただきました。
同じコメントで「
CGrepAgent::DoGrepの実行に必要なパラメーターが揃っていることを担保する責任は誰にあるのか」「揃ってなかったら UI 表示して入力要求するのがスジなんじゃないか」という問いも挙げられていました。続きの作業に入る前に、この点の方針を決めたいと思います。
現状
SGrepOptionsakura_core/agent/CGrepAgent.hGrepInfosakura_core/basis/GrepInfo.hこのうち 12 個は同名・同型で重複しています。
bGrepReplacebGrepSubFolderbGrepStdoutbGrepHeadernGrepCharSetnGrepOutputLineTypenGrepOutputStylebGrepOutputFileOnlybGrepOutputBaseFolderbGrepSeparateFolderbGrepPastebGrepBackupGrepInfoのみ(6)cmGrepKeycmGrepRepcmGrepFilecmGrepFoldersGrepSearchOptionbGrepCurFolderDoGrep()がSGrepOption::FromGrepInfo( gi )で 12 個を詰め替え、その結果をDoGrepTree()/DoGrepFile()/DoGrepReplaceFile()/SetGrepResult()/OutputPathInfo()へ渡しています。決めたいこと
(a)
SGrepOptionを廃止し、GrepInfoに一本化するGrepInfoにNormalized()(Grep 置換時に否ヒット行出力を行単位出力へ落とす補正)を持たせ、SGrepOptionとFromGrepInfo()を削除します。DoGrepTree()以降の引数型をconst GrepInfo&に変更します。理由は、
SGrepOptionの存在意義が「DoGrepFile()へ安く値コピーするための部分集合」だったのに対し、GrepInfoをconst参照で渡せば値コピーが発生しないため、部分集合を作る動機が無くなることです。(b)
GrepInfo : public SGrepOptionにするGrepInfoから重複する 12 メンバーを削除し、SGrepOptionを基底クラスにします。Normalized()は同様に用意し、FromGrepInfo()は削除します。SGrepOptionの 12 個はすべてまともな既定値を持ち、揃っていなくても Grep は動きます。一方GrepInfoが足すcmGrepKey/cmGrepFile/cmGrepFolderなどは揃っていないと Grep が成立しません。継承にすると「既定値で動く部分」と「入力を要求すべき部分」が型で分かれるので、上に挙げていただいた「担保する責任は誰にあるのか」という問いに対応しやすくなるかもしれません。比較
DoGrepTree()/DoGrepFile()/DoGrepReplaceFile()の引数型const GrepInfo&へ変更(6 箇所)SetGrepResult()/OutputPathInfo()の引数型const GrepInfo&へ変更DoGrep()内の詰め替えGrepInfoの 12 メンバーSGrepOptionの置き場所basis/へ移す必要ありGrepInfoの NSDMI とSGrepOptionのコンストラクター初期化子リストの混在をどうにかする必要あり(b) を採る場合に決めたいこと
1.
SGrepOptionの置き場所basis/GrepInfo.hからagent/CGrepAgent.hを include するとbasis/→agent/の逆依存になるため、SGrepOptionをbasis/配下へ移す必要があります。basis/GrepInfo.hに同居させるbasis/に別ファイルを作る(GrepOutputOption.hなど)2. 既定値をどちらに合わせるか
3 つのメンバーで既定値が食い違っています。
GrepInfoSGrepOptionbGrepSubFolderfalsetruenGrepCharSetCODE_SJISCODE_AUTODETECTnGrepOutputLineType01現状はどちらの既定値も実行時には使われていません(
GrepInfoはコマンドライン解析またはCDlgGrep::MakeGrepInfo()が全メンバーを設定し、SGrepOptionはFromGrepInfo()が全メンバーを上書きするため)。ただし継承にするとGrepInfoの既定値がSGrepOptionのものに変わるので、どちらへ寄せるかを決めておく必要があります。後続作業への影響
2026-06-20 に挙げていただいた 3 区分(ファイル抽出 / ファイル内検索 / 結果報告)のうち「結果報告」を
sakura_core/grep/へ切り出す作業を予定していますが、これは本件の結論に依存します。const GrepInfo&を受け取りますconst SGrepOption&を受け取ります(SGrepOptionの置き場所が決まっている必要があります)お願い
(a) / (b) のどちらでも実装できます。方針をいただければ、それに合わせて進めます。