ファンタジー生産管理システムの開発1

勉強のために簡単な生産管理システムを作ってみるテスト。
徐々に拡張する予定。

## TL;DR
生産管理システム＝生産計画と製造実績を管理するシステム

* 生産＝いわゆる付加価値の創造のこと
* 一般的に、生産活動を行う企業は工場を持つ
* 工程を経て、投入品から製造品が作られる

## 前提
システム的には以下を想定。
　・Windows
　・RDBMSなし（そのうち導入予定）
　・C#

## 女騎士さんはSEになりました。
※物語風に書いてみたら長くなったのでばっさりカットして要約
![image0020.png](https://qiita-image-store.s3.amazonaws.com/0/86588/ed1d9bd9-5979-5cf9-8c61-414266431f5e.png)

女騎士「ジョブチェンジを間違えた……」
オーク「よく来たな、女騎士よ。生産管理システムを作るぞ」
女騎士「くっ、殺せ！」

## オークさんがホワイドボードに記入しました。

### 生産管理の管理対象
大きく2つある
・**生産計画**：何を、（どこで、）いつ、いくつ、（なぜ）作るか
・**製造実績**：何を、（どこで、）いつ、いくつ、（なぜ）作ったか
計画と実績とを紐付けて記録していくことが基本
過去の実績を参考に計画を作り出すこともある
最近の生産管理システムは在庫管理、MRP計算、ロットトレース、購買管理、品質管理、出荷管理などの副次的機能を持つ

図1. 生産計画と製造実績の相互作用
![image0000.png](https://qiita-image-store.s3.amazonaws.com/0/86588/4733f163-3c54-cc32-8f89-a7cd71f508a3.png)

### 生産活動の概要
生産＝いわゆる**付加価値の創造**のこと
一般的に、企業の生産活動は一度きりでなく、再生産可能な仕組み（工場）を持つ

生産活動の例
・木の棒に穂先を付けて槍にする
・原石を磨いて宝石にする
・りんごを絞ってりんごジュースにする
・ぶどうを発酵槽に入れてワインにする

例に挙げたように、原材料から、工程を経て、より価値のあるもの（製造品）を作る
組み立て・加工・抽出・発酵など多種多様な工程がある
通常、原材料から多工程を経て最終製品が生産される

投入品と製造品
・投入品＝原材料／仕掛品など工程へ供されるもの
・製造品＝仕掛品／製品など工程で作り出されるもの

図2. 投入品を工程へ投入し、製造品が製造されるイメージ
![image0010.png](https://qiita-image-store.s3.amazonaws.com/0/86588/82a460cb-4d60-b0f0-db23-82fd42476c95.png)

### 製造品の製造実績を入出力するプログラム
単純な製造数量だけを入出力してみる（まだ生産管理とか関係ない）。

仕様
・コンソールアプリケーション
・標準入力で` j 製造数`が入力される
→これ以外の標準入力は無視してもよい
→製造数は整数
・標準出力で"製造品数量：{製造数}"を表示する
・例外処理は考えなくてもよい

例
j 100
製造品数量：100

オーク「入力した製造数をint型変数に代入してくれ」
女騎士「承知した。しかし、本当に整数を入力するんだな」
オーク「仕様以外の入力はしないぞ」
女騎士「小数とか文字列を入力するなよ。いいか、絶対だぞ！」
オーク「分かったから早く書け」

## 女騎士さんが動くコードを書きました。
**女騎士さんの成果物（Main部分だけ抜粋）**

```csharp 
static int Main(string[] args)
{
    int quantity = 0;    //製造品の数量

    //標準入力（半角スペースで区切ってある）
    string line = Console.ReadLine().Trim();
    string[] parameters = line.Split(' ');

    try
    {
        if (parameters.Length > 0)
        {
            //「j 製造数量」を受け取って標準出力
            if (parameters[0] == "j")
            {
                quantity = int.Parse(parameters[1]);
                Console.WriteLine("製造品数量：{0}", Convert.ToString(quantity));
            }
        }
    }
    catch
    {
        return -1;
    }

    return 0;
}
```

オークさんがコードをレビューしました。

* `if (parameters.Length > 0)`のくだりが冗長。`parameters.Length`は必ず1以上になるのでは。もし書くなら`if (parameters.Length == 2)`

規約がない中、すまないが、

* 異常終了時の戻り値は0以外なら何でもいいけど、とりあえず1で
* 短い変数名を好む人が多いので短くできるか

## オークさんが仕様を変更しました。
### 製造品の製造実績を入出力するプログラム
繰り返しになるけど、まだ生産管理とか関係ない。
仕様
・コンソールアプリケーション
・**某sqlplusコマンドっぽく動作して**
・標準入力で` j 製造数`が**連続で**入力される
・**標準入力で`q`が入力されたら終了する**
→これ以外の標準入力は無視してもよい
→製造数は整数
・**` j 製造数`が入力されるたび、**標準出力で"製造品数量：{製造数**合計**}"を表示する
・例外処理は考えなくてもよい

例
j 100
製造品数量：100
j 20
製造品数量：120
q

女騎士「仕様変更だと……。くっ、殺せ！　あとsqlplusとか知らない」
オーク「こんな感じで入力時にプログラム名を表示したかったのだ」
オークさんがホワイトボードに記入しました。
fpms> j 100
製造品数量：100
fpms> j 20
製造品数量：120
fpms> q
女騎士「分かった。やってみる」

**女騎士さんの成果物**

```csharp:Program.cs
using System;

namespace FantasyProductionManagementSystem
{
    class Program
    {
        const string DEFAULT_PROMPT_MESSAGE = "fpms> ";

        static string ReadLine(string promptMessage)
        {
            Console.Write(promptMessage);
            return Console.ReadLine();
        }

        static int Main(string[] args)
        {
            int qty = 0;    //製造品の数量

            try
            {
                while (true)
                {
                    //標準入力（半角スペースで区切ってある）
                    string line = ReadLine(DEFAULT_PROMPT_MESSAGE).Trim();
                    string[] prms = line.Split(' ');

                    //「j 製造数量」を受け取って標準出力
                    if (prms[0] == "j")
                    {
                        qty += int.Parse(prms[1]);
                        Console.WriteLine("製造品数量：{0}", Convert.ToString(qty));
                    }
                    else if (prms[0] == "q")
                    {
                        break;
                    }
                    else
                    {
                        return 1;
                    }
                }
            }
            catch
            {
                return 1;
            }

            return 0;
        }
    }
}
```

オークさんがコードをレビューしました。

* ちょっとでも入力ミスしたらその時点で異常終了するところが素敵だな

規約がない中すまないが、 

* ループ内`break`とか複数の`return`をなるべく回避したい
* `while (true)`以外の書き方にするとしたら？（フラグ制御しかないか？）

## 製造品の製造実績を入出力するプログラム（暫定版）
女騎士「できた！　できたぞ！」
オーク「プログラム終了すると今まで入力したデータが消えるし、製造品が何かも分からないし、もう少し改良が必要だな」
女騎士「くっ。ちなみに、qはquitの略として、jは何の略なんだ？」
オーク「実績入力だ」
女騎士「ひどくダサいな」
オーク「……くっ、殺して」

**女騎士さんの成果物**

```csharp:Program.cs
using System;

namespace FantasyProductionManagementSystem
{
    class Program
    {
        const string DEFAULT_PROMPT_MESSAGE = "fpms> ";

        static string ReadLine(string promptMessage)
        {
            Console.Write(promptMessage);
            return Console.ReadLine();
        }

        static int Main(string[] args)
        {
            int qty = 0;    //製造品の数量

            bool flgEnd = false;    //true⇒ループ終了、false⇒ループ続行
            while (!flgEnd)
            {
                //標準入力（半角スペースで区切ってある）
                string line = ReadLine(DEFAULT_PROMPT_MESSAGE).Trim();
                string[] prms = line.Split(' ');

                //「j 製造数量」を受け取って標準出力
                if (prms[0] == "j")
                {
                    try
                    {
                        qty += int.Parse(prms[1]);
                        Console.WriteLine("製造品数量：{0}", Convert.ToString(qty));
                    }
                    catch
                    {
                        Console.WriteLine("入力エラーです。");
                    }
                }
                else if (prms[0] == "q")
                {
                    flgEnd = true;  //ループ終了
                }
                else
                {
                    if (!string.IsNullOrEmpty(prms[0]))
                    {
                        Console.WriteLine("コマンドが無効です。");
                    }
                }
            }

            return 0;
        }
    }
}
```