べろろろろろろ

まず Power shell をダブルクリックで起動できるようにしろだぜ☆

[ここを読む(https://qiita.com/muzudho1/items/3a5784faddfa77df99f9)

設定ファイルを探して設定しろ。

ディレクトリ構成を合わせろ。

リリース・ビルドだけでなく、デバッグ・ビルドも持っとけ。
リリース・ビルドで強制終了したら　エラー原因が分からん。ログを吐く .exe 必須。

ログ吐く前に　強制終了してたら　設定ファイル読み込めてない可能性高い。

```
target
|
+-- release
|
+-- debug
```

特に設定していなければ rust の場合 `cargo build` で target/debug ディレクトリの下に .exe や .d が出力されている。
`cargo build --release` なら target/release。

.d はテキストファイルで開けば分かるが デバッグで使ってるだけなんで本番環境で要らない。

# 人間がボトルネック

当日の修正でバグを盛り込んでしまう。結果を見る前から　修正　という言葉を使うのは矛盾している。修正ではなく変更。

感情がない人というのは　１つ１つの感情表現が豊かな人に比べて　感情を細かく多めに使ってしまって　平坦になっている人のことだ。

# ディレクトリー構成

テスト環境と、本番環境では　ディレクトリーのここに置け、という制約が変わることがある。
だいたいConfigみたいな感じの名前の付いている設定ファイルがあると思うが、設定しても、
管理者権限や、パーミッションを別途　要求される場合があるので　まず　ドキュメント・ディレクトリーに配置して
そもそも　動くのか確認する。

全部絶対ファイルパスで書いてみる。

# 古いプログラムが動いていて、新しいプログラムが動かないのなら

プログラム言語の環境を　再インストール、アップデートだ！

```
rustup update

rustc --version
```

これでバージョンがそろってて、あとは何が違うのか。

調べてみると、 debug ビルドのものは動いて、 release ビルドのものは動かない。

たどっていくと、ディレクトリ構成が異なるのを認識し、
`logs` フォルダーが無いと強制終了するようになっている。

```rust
    /// Write line.
    pub fn println(&self, line: &str) {
        println!("{}", line);

        let mut file = OpenOptions::new()
            .create(true)
            .write(true)
            .append(true)
            .open(&self.log_file_name)
            .unwrap();

        if let Err(e) = writeln!(file, "{}", line) {
            eprintln!("Couldn't write to file: {}", e);
        }
    }
```

ファイルが無ければ上書きするが、ディレクトリーがない場合は .unwrap() で強制終了するのでエラーも吐かない。

```
    /// Write line.
    pub fn println(&self, line: &str) {
        println!("{}", line);

        // ディレクトリー作成。
        if let Some(parent) = Path::new(&self.log_file_name).parent() {
            match fs::create_dir_all(parent) {
                Ok(_x) => {}
                Err(err) => panic!(err),
            }
        } else {
            panic!("Create directory fail. {}", self.log_file_name);
        }

        let mut file = OpenOptions::new()
            .create(true)
            .write(true)
            .append(true)
            .open(&self.log_file_name)
            .unwrap();

        if let Err(e) = writeln!(file, "{}", line) {
            eprintln!("Couldn't write to file: {}", e);
        }
    }
```

OpenOption をぜんぶ検索して　ディレクトリー作成コードを付けまくって応急処置。

**`.unwrap()` とか適当に使ってると　エラーが出ない。**

`.unwrap();` を機械的に `.unwrap_or_else(|| panic!(""));` に置き換えるとどうだろうか？
それでもログに残らないので、ログに残るように改造する。
 
panic! の代わりに形式上 String を返す関数を作り、その中で ログ取って、panic! する。

と思ったら、 `unwrap_or_else` の仕様はメソッドによってバラバラなようだ。

```rust
        let ext = get_extension_from_filename(&in_file)
            .unwrap_or_else(|| app.comm.panic_as_str("Fail. get_extension_from_filename."))
            .to_uppercase();
```

雰囲気的にはこんな感じで、戻り値の違うログ取りパニック関数を用意していく。

`unwrap_or_panic()` が欲しい。戻り値の種類は　有限だが山ほどある。

```rust
    /// panic! で包んで使う。
    pub fn panic(&self, msg: &str) -> String {
        self.println(msg); // コンソールに表示して、ログも取る。
        String::from(msg)
    }
```

こういう自作関数を作る。

```rust
    let file = args
        .output_file
        .unwrap_or_else(|| panic!(app.comm.panic("Fail. args.output_file.")));
```

こんな雰囲気で使う。

`Result` 型の .unwrap() を .unwrap_or_else() に変えるとなんかエラーが出る。

```rust
    /// 入出力エラーの時、 panic! で包んで使う。
    pub fn panic_io(&self, err: &std::io::Error) -> String {
        let msg = format!("{}", err);
        self.println(&msg);
        String::from(msg)
    }
```

こうすりゃいいのか。
しかし Error クラスはいっぱいある。 int型のパースの Error も別クラス。
rust のエラークラスの操作は統一されてないのか？

```rust
unwrap_or_else(|f| panic!(app.comm.panic(&f.to_string())))
```

`.to_string()` できるやつはこれでいける。

```rust
            let id: i8 = id_vec[i].parse().unwrap();
```

文字列、数値変換のときのパース失敗時のパニックのメッセージをログに取るのがむずかしい。

```rust
            let id: i8 = match id_vec[i].parse() {
                Ok(x) => x,
                Err(err) => panic!(app.comm.println(&format!("{}", id_vec[i]))),
            };
```

数値変換のたびに　こんな長いの書きたくない。

```
            let id: i8 = id_vec[i]
                .parse()
                .unwrap_or_else(|err| panic!(app.comm.println(&format!("{}", err))));
```

短くしてこうか。

１００個ほどの '.unwrap()' を '.unwrap(' で検索し、すべて '.unwrap_or_else' で書き直し
ログ出力するように２時間ほどで書き直し。

本番環境で release フォルダーに入れていたので ファイルパスが違っていたことが分かったので
release フォルダーの外に出したら動いた。