# 通知設計書 1-ポータビリティ警告

## 概要

本ドキュメントは、Juliaランタイムにおけるポータビリティ警告通知の設計を記述する。ファイルリダイレクト先としてプラットフォーム固有のnullデバイスパス（Windowsの`NUL`、Unix系の`/dev/null`）が使用された場合に、ポータブルな`devnull`定数の使用を推奨する警告ログを出力する。

### 本通知の処理概要

**業務上の目的・背景**：Juliaは複数のプラットフォーム（Windows, Linux, macOS）で動作するクロスプラットフォーム言語である。コマンドのI/Oリダイレクト先にプラットフォーム固有のnullデバイスパス（`/dev/null`や`NUL`）を直接指定すると、異なるOS間での移植性が損なわれる。Juliaが提供する`devnull`定数を使用することで、プラットフォームに依存しないコードを記述できる。本通知はこのベストプラクティスを開発者に伝える目的で設計されている。

**通知の送信タイミング**：`FileRedirect`構造体のコンストラクタが呼び出された際に、引数として渡されたファイル名がプラットフォームのnullデバイスパスと一致する場合に通知が発生する。具体的にはバッククォート記法によるコマンドのI/Oリダイレクト時に評価される。

**通知の受信者**：Juliaプログラムを実行している開発者。ログメッセージとして標準エラー出力（または設定されたログハンドラ）に出力される。

**通知内容の概要**：「For portability use devnull instead of a file redirect」というメッセージが`@warn`マクロにより出力される。プラットフォーム固有のnullデバイスパスの代わりにJulia組み込みの`devnull`を使用すべきことを示す。

**期待されるアクション**：開発者はファイルリダイレクトを`devnull`定数に置き換える。例えば`pipeline(cmd, stdout="/dev/null")`を`pipeline(cmd, stdout=devnull)`に変更する。

## 通知種別

ログ出力（Warnレベル） - Juliaの`@warn`マクロによるロギングシステム経由の警告通知

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（`FileRedirect`コンストラクタ内で即座に出力） |
| 優先度 | 低（開発支援向けの推奨事項） |
| リトライ | 無し |

### 送信先決定ロジック

Juliaのロギングフレームワーク（`CoreLogging`）に委譲される。デフォルトでは`stderr`に出力される。`maxlog=1`が指定されているため、同一セッション内で最大1回のみ出力される。

## 通知テンプレート

### メール通知の場合

該当なし（ログ出力のみ）

### 本文テンプレート

```
┌ Warning: For portability use devnull instead of a file redirect
└ @ Base cmd.jl:197
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| なし | 固定メッセージのため変数なし | - | - |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| API呼び出し | `FileRedirect`コンストラクタの実行 | `lowercase(filename)`がプラットフォームのnullデバイスパスと一致 | Windowsでは`"nul"`、Unix系では`"/dev/null"`との比較 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| `maxlog=1` | 同一セッション内で2回目以降は抑止される |
| ファイル名がnullデバイスパスでない場合 | 条件不一致により通知されない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[FileRedirectコンストラクタ呼び出し] --> B{filenameがnullデバイスパスか?}
    B -->|Yes| C["@warn 出力 (maxlog=1)"]
    B -->|No| D[通常処理続行]
    C --> E[FileRedirectオブジェクト生成]
    D --> E
    E --> F[終了]
```

## データベース参照・更新仕様

### 参照テーブル一覧

該当なし（データベースは使用しない）

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| なし | 本通知自体はエラー処理を持たない | - |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| セッションあたり上限 | 1件（`maxlog=1`） |

### 配信時間帯

制限なし（コード実行時に即座に出力）

## セキュリティ考慮事項

本通知にはセキュリティ上の懸念はない。個人情報や機密情報は含まれない。

## 備考

- 本通知はJulia 1.0以降で存在する
- `@static Sys.iswindows()`によりコンパイル時にプラットフォーム判定が行われる
- ファイル名の比較は`lowercase`で正規化されるため、大文字小文字を問わない

---

## コードリーディングガイド

本通知を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、コマンドとファイルリダイレクトに関連するデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | cmd.jl | `base/cmd.jl` | `Cmd`構造体（13-40行目）と`FileRedirect`構造体（191-201行目）の定義を確認する |

**読解のコツ**: `FileRedirect`は`filename`と`append`フィールドを持つシンプルな構造体である。コンストラクタ内で警告チェックが行われる点に注目する。

#### Step 2: エントリーポイントを理解する

`FileRedirect`コンストラクタが通知の発生ポイントである。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | cmd.jl | `base/cmd.jl` | `FileRedirect`の内部コンストラクタ（195-201行目） |

**主要処理フロー**:
1. **195行目**: `FileRedirect(filename::String, append::Bool)`コンストラクタ定義
2. **196行目**: `lowercase(filename)`をプラットフォーム固有のnullデバイスパスと比較
3. **197行目**: 一致した場合`@warn "For portability use devnull instead of a file redirect" maxlog=1`を出力
4. **199行目**: `new(filename, append)`で構造体を生成して返す

#### Step 3: 呼び出し元を理解する

`FileRedirect`は各種リダイレクト関数から生成される。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | cmd.jl | `base/cmd.jl` | `redir_out`、`redir_err`関数群（439-443行目）がファイル名文字列からFileRedirectを生成する |

**主要処理フロー**:
- **439行目**: `redir_out(src::AbstractCmd, dest::AbstractString)` - stdoutをファイルにリダイレクト
- **440行目**: `redir_out(src::AbstractString, dest::AbstractCmd)` - ファイルからstdinにリダイレクト
- **441行目**: `redir_err(src::AbstractCmd, dest::AbstractString)` - stderrをファイルにリダイレクト

### プログラム呼び出し階層図

```
ユーザーコード: pipeline(cmd, stdout="/dev/null")
    |
    +-- pipeline(cmd; stdout="/dev/null")  [base/cmd.jl:461]
        |
        +-- redir_out(cmd, "/dev/null")  [base/cmd.jl:439]
            |
            +-- FileRedirect("/dev/null", false)  [base/cmd.jl:195]
                |
                +-- @warn "For portability..."  [base/cmd.jl:197]
```

### データフロー図

```
[入力]               [処理]                    [出力]

filename文字列 ──> FileRedirectコンストラクタ ──> @warn ログ出力 (stderr)
"/dev/null"        lowercase比較              FileRedirectオブジェクト
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| cmd.jl | `base/cmd.jl` | ソース | コマンド・リダイレクト関連の型定義と通知ロジック |
| process.jl | `base/process.jl` | ソース | プロセス生成時にFileRedirectを利用するsetup_stdio関数 |
