C#プロジェクトにNullable要素を追加するツール(再帰版。リファクタリング)
Commandパターンでリファクタリングした。
成果物
残念なコード
前回、コードがとても見づらくなってしまった。
class Program { static void Main(string[] args) { if (ShowHelp(args)) return; foreach (string path in GetProjectFiles(args)) { var xml = CreateNullableXDocument(path); using (var writer = CreateOmitXmlDeclarationWriter(path)) { xml.Save(writer); } } } static bool ShowHelp(string[] args) { if (0 < args.Length && "-r" != args[0]) { Console.WriteLine(@".csprojファイルに<Nullable>enable</Nullable>を設定する。<Nullable>が既存なら何もしない。引数-rで再帰的に処理する。"); return true; } else { return false; } } ... }
どこが問題か。終了するパターンが1つでなく2通りになったことで条件分岐が必要になってしまった。そのせいで複雑化した。
終了パターンは以下2通りである。
- ヘルプ表示して終了する
<Nullable>
挿入して終了する
これを「ヘルプ表示する」と「<Nullable>
挿入する」という2つのコマンドとして捉えることができる。コマンドをインタフェースとして共通化すれば呼出元がスッキリ書けるはず。
リファクタリング
ヘルプと<Nullable>
挿入処理を共通インタフェースにして、別クラス内で処理を実装する。
interface ICommand { public void Run(string[] args); } class ShowHelpCommand : ICommand { public void Run(string[] args) { // ヘルプを表示する処理 } } class SetupNullableCommand : ICommand { public void Run(string[] args) { // <Nullable>enable</Nullable>を挿入する処理 } }
これで以下のように呼出元がスッキリした。すばらしい。
class Program { static void Main(string[] args) { ICommand cmd = Parse(args); cmd.Run(args); } static ICommand Parse(string[] args) { if (0 < args.Length && "-r" != args[0]) { return new ShowHelpCommand(); } else { return new SetupNullableCommand(); } } }
1回の実行あたり1つのコマンドを1回実行する構造。コマンドが処理する内容は、各コマンドクラスで実装する。
所感
いい感じ。
対象環境
- Raspbierry pi 3 Model B+
- Raspbian stretch 9.0 2018-11-13 ※
- bash 4.4.12(1)-release ※
- SQLite 3.29.0 ※
- C# dotnet 3.0.100
$ uname -a Linux raspberrypi 4.19.42-v7+ #1218 SMP Tue May 14 00:48:17 BST 2019 armv7l GNU/Linux