メモ


## 🔧 クラス構成（概要）

```
CsvSplitAndConvertApp
├── Program.cs                  // エントリポイント
├── CsvProcessor.cs            // 全体制御：CSVの読み込み・分割・変換・書き出し
├── CsvSplitter.cs             // 分割処理：必要項目だけを抽出し、4つのグループに分ける
├── IConverter.cs              // インターフェース：変換ルールの共通基盤
├── Converters/                // 各変換ルール群（多態性で実装）
│   ├── SimpleValueConverter.cs    // 例：1→02, 2→05
│   ├── FixedValueConverter.cs     // 例：列10に"さんぷる"
├── ConvertRule.cs             // 変換ルールの定義を保持（どの列にどの変換を適用するか）
├── CsvFileWriter.cs           // ファイル出力を担当
└── Models/
    ├── CsvRow.cs              // 1行分のデータモデル
    └── ConvertedRow.cs        // 変換後の出力データモデル
```

---

## 🧩 各クラスの役割（詳細）

### `Program.cs`
- `Main(string[] args)`で起動。
- CSVファイルパスを引数から取得し、`CsvProcessor`を呼び出す。

---

### `CsvProcessor.cs`

```csharp
public class CsvProcessor
{
    public void Process(string csvPath)
    {
        var allRows = CsvLoader.Load(csvPath);
        var splitRows = CsvSplitter.Split(allRows);

        foreach (var group in splitRows)
        {
            var convertedRows = ConverterEngine.Convert(group.Value, group.Key);
            CsvFileWriter.Write($"{group.Key}.csv", convertedRows);
        }
    }
}
```

- CSVのロード → 分割 → 変換 → 書き出しのフローを統括。

---

### `CsvSplitter.cs`

```csharp
public static class CsvSplitter
{
    public static Dictionary<string, List<CsvRow>> Split(List<CsvRow> rows)
    {
        var result = new Dictionary<string, List<CsvRow>>
        {
            { "File1", new List<CsvRow>() },
            { "File2", new List<CsvRow>() },
            { "File3", new List<CsvRow>() },
            { "File4", new List<CsvRow>() }
        };

        foreach (var row in rows)
        {
            result["File1"].Add(ExtractForFile1(row));
            result["File2"].Add(ExtractForFile2(row));
            result["File3"].Add(ExtractForFile3(row));
            result["File4"].Add(ExtractForFile4(row));
        }

        return result;
    }
}
```

- 入力CSVの0番目の列（識別ID）を共通で使いつつ、各ファイル用に必要な項目を抽出。

---

### `IConverter.cs`（インターフェース）

```csharp
public interface IConverter
{
    string Convert(string input);
}
```

---

### `SimpleValueConverter.cs`

```csharp
public class SimpleValueConverter : IConverter
{
    private readonly Dictionary<string, string> _map;

    public SimpleValueConverter(Dictionary<string, string> map)
    {
        _map = map;
    }

    public string Convert(string input)
    {
        return _map.ContainsKey(input) ? _map[input] : input;
    }
}
```

---

### `FixedValueConverter.cs`

```csharp
public class FixedValueConverter : IConverter
{
    private readonly string _fixedValue;

    public FixedValueConverter(string fixedValue)
    {
        _fixedValue = fixedValue;
    }

    public string Convert(string _) => _fixedValue;
}
```

---

### `ConvertRule.cs`

```csharp
public class ConvertRule
{
    public int ColumnIndex { get; }
    public IConverter Converter { get; }

    public ConvertRule(int columnIndex, IConverter converter)
    {
        ColumnIndex = columnIndex;
        Converter = converter;
    }
}
```

- 列インデックスと適用する変換をセットで定義。

---

### `ConverterEngine.cs`

```csharp
public static class ConverterEngine
{
    public static List<ConvertedRow> Convert(List<CsvRow> rows, string fileKey)
    {
        var rules = ConvertRuleFactory.GetRulesForFile(fileKey);

        return rows.Select(row => 
        {
            var newValues = new List<string> { row[0] }; // 識別ID
            foreach (var rule in rules)
            {
                newValues.Add(rule.Converter.Convert(row[rule.ColumnIndex]));
            }
            return new ConvertedRow(newValues);
        }).ToList();
    }
}
```

---

### `ConvertRuleFactory.cs`

```csharp
public static class ConvertRuleFactory
{
    public static List<ConvertRule> GetRulesForFile(string fileKey)
    {
        // ファイルごとにルールを定義（例）
        return fileKey switch
        {
            "File1" => new List<ConvertRule> {
                new ConvertRule(1, new SimpleValueConverter(new Dictionary<string, string>{{"1", "02"},{"2", "05"}})),
                new ConvertRule(10, new FixedValueConverter("さんぷる"))
            },
            // 他ファイルも同様
            _ => new List<ConvertRule>()
        };
    }
}
```

---

### `CsvRow.cs / ConvertedRow.cs`

```csharp
public class CsvRow
{
    public List<string> Columns { get; }

    public CsvRow(List<string> columns)
    {
        Columns = columns;
    }

    public string this[int index] => Columns[index];
}
```

---

## ✅ メリット

- **変換処理をルールクラスに分離**しているため、拡張しやすい
- 単体テストがしやすく、責務が分かれていて**保守性が高い**
- 将来GUI版やWeb API版への発展も容易

---