流れるようなインターフェース？-良いコード書くきっかけを与えたい。3[C#リファクタリングサンプル]

# 流れるようなインターフェースの使い方はこれで正しいのか？
ある現場でJava経験の長い人にC#のプロジェクトを手伝ってもらったことがある。その中で、流れるようなインターフェースを使用しているコードがあったがずっと納得がいかない部分があった。そのときのコードを参考にしてサンプルコードを作成してみた。

仕様）DBから取得した結果に対して画面の値をマージしてDB更新する。
1. DBにはHeader1,Header2,Header3があり、全て更新対象とする。
2. 画面で値編集可能であり、マージのタイミングは登録ボタンクリック時。
    
```csharp
        /** メイン処理 **/
        private Dao _dao = new Dao();

        public void Main()
        {
            // DBから現時点の情報を取得する。
            var param = new UpdateParameter(_dao)
                            .SetHeader(1)
                            .SetHeader2("a")
                            .SetHeader3(2);

            // 画面の情報を反映する。
            SetValueFromView(param);

            // DBを更新する。
            _dao.Update(param);
        }

        private void SetValueFromView(UpdateParameter param)
        {
            // 画面の値を取得したパラメータのHeader1,2,3に反映する。
            // コードは省略
        }

        /** DB更新テーブルのDTOを一つにまとめたパラメータクラス **/
        public class UpdateParameter
        {
            public Header Header { get; private set; }
            public Header2 Header2 { get; private set; }
            public Header3 Header3 { get; private set; }

            private readonly Dao _dao = null;

            public UpdateParameter(Dao dao)
            {
                _dao = dao;
            }

            public UpdateParameter SetHeader(int id)
            {
                Header = _dao.GetHeader(id);
                return this;
            }

            public UpdateParameter SetHeader2(string code)
            {
                Header2 = _dao.GetHeader2(code);
                return this;
            }

            public UpdateParameter SetHeader3(int id)
            {
                Header3 = _dao.GetHeader3(id);
                return this;
            }
        }

        /** Header1,2,3のDTO **/
        public class Header
        {
            public int Id { get; set; }
        }

        public class Header2
        {
            public string Code { get; set; }
        }

        public class Header3
        {
            public int Id { get; set; }
        }

        /** データ取得、および更新用Dao **/
        public class Dao
        {
            public Header GetHeader(int id)
            {
                // ヘッダーの取得
                return new Header() { Id = id };
            }

            public Header2 GetHeader2(string code)
            {
                // ヘッダー２の取得
                return new Header2() { Code = code };
            }

            public Header3 GetHeader3(int id)
            {
                // ヘッダー３の取得
                return new Header3() { Id = id };
            }

            public void Update(UpdateParameter param)
            {
                // DB更新処理を実行する。コードは省略
            }
        }
```

<details>
<summary>java</summary>
<div>

```java
    private Dao dao = new Dao();

    public void main() {
        // DBから現時点の情報を取得する。
        UpdateParameter param = new UpdateParameter(dao)
                .setHeader(1)
                .setHeader2("a")
                .setHeader3(2);

        // 画面の情報を反映する。
        setValueFromView(param);

        // DBを更新する。
        dao.update(param);
    }

    private void setValueFromView(UpdateParameter param) {
        // 画面の値を取得したパラメータのHeader1,2,3に反映する。
        // コードは省略
    }

    public class UpdateParameter {
        private Header header = null;
        private Header2 header2 = null;
        private Header3 header3 = null;

        private final Dao dao;

        public UpdateParameter(Dao dao) {
            this.dao = dao;
        }

        public UpdateParameter setHeader(int id) {
            this.header = dao.getHeader(id);
            return this;
        }

        public UpdateParameter setHeader2(String code) {
            this.header2 = dao.getHeader2(code);
            return this;
        }

        public UpdateParameter setHeader3(int id) {
            this.header3 = dao.getHeader3(id);
            return this;
        }

        public Header getHeader() {
            return header;
        }

        public Header2 getHeader2() {
            return header2;
        }

        public Header3 getHeader3() {
            return header3;
        }

    }

    /** Header1,2,3のDTO **/
    public class Header {
        private int id;

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }
    }

    public class Header2 {
        private String Code;

        public String getCode() {
            return Code;
        }

        public void setCode(String code) {
            Code = code;
        }

    }

    public class Header3 {
        private int Id;

        public int getId() {
            return Id;
        }

        public void setId(int id) {
            Id = id;
        }
    }

    /** データ取得、および更新用Dao **/
    public class Dao {
        public Header getHeader(int id) {
            // ヘッダーの取得
            Header header = new Header();
            header.setId(id);
            return header;
        }

        public Header2 getHeader2(String code) {
            // ヘッダー２の取得
            Header2 header2 = new Header2();
            header2.setCode(code);
            return header2;
        }

        public Header3 getHeader3(int id) {
            // ヘッダー３の取得
            Header3 header3 = new Header3();
            header3.setId(id);
            return header3;
        }

        public void update(UpdateParameter param) {
            // DB更新処理を実行する。コードは省略
        }
    }

```
</div>
</details>

## 気になったこと
UpdateParameterが流れるようなインターフェースになっているようなのだが、このコードには以下の問題がある。
1. UpdateParameterがDaoを参照している。
2. テーブルが増えたら直す箇所が複数ある。
3. SetHeader1～SetHeader3を必ず呼び出さなければならない。

流れるようなインターフェースはStringBuilderのようなクラスだと利点が理解できる。一方、UpdateParameterのような単純な情報を持つだけのクラスで使うと違和感がある。

## 無難なコードに直してみる。
UpdateParameterのDao参照を削除して、メイン処理側でDB取得するようにしただけであるが、このコードなら納得できる。
```csharp
       /** メイン処理 **/
        private Dao _dao = new Dao();

        public void Main()
        {
            // DBから現時点の情報を取得する。
            var param = new UpdateParameter();
            // メイン処理でDBからデータを取得する。
            param.Header = _dao.GetHeader(1);
            param.Header2 = _dao.GetHeader2("a");
            param.Header3 = _dao.GetHeader3(2);

            // 画面の情報を反映する。
            SetValueFromView(param);

            // DBを更新する。
            _dao.Update(param);
        }

        private void SetValueFromView(UpdateParameter param)
        {
            // 画面の値を取得したパラメータのHeader1,2,3に反映する。
            // コードは省略
        }

        /** DB更新テーブルのDTOを一つにまとめたパラメータクラス **/
        public class UpdateParameter
        {
            public Header Header { get; set; }
            public Header2 Header2 { get; set; }
            public Header3 Header3 { get; set; }

            // Daoの参照を削除
        }

        /** Header1,2,3のDTO **/
        public class Header
        {
            public int Id { get; set; }
        }

        public class Header2
        {
            public string Code { get; set; }
        }

        public class Header3
        {
            public int Id { get; set; }
        }

        /** データ取得、および更新用Dao **/
        public class Dao
        {
            public Header GetHeader(int id)
            {
                // ヘッダーの取得
                return new Header() { Id = id };
            }

            public Header2 GetHeader2(string code)
            {
                // ヘッダー２の取得
                return new Header2() { Code = code };
            }

            public Header3 GetHeader3(int id)
            {
                // ヘッダー３の取得
                return new Header3() { Id = id };
            }

            public void Update(UpdateParameter param)
            {
                // DB更新処理を実行する。コードは省略
            }
        }

```

<details>
<summary>java</summary>
<div>

```java
    private Dao dao = new Dao();

    public void main() {
        // DBから現時点の情報を取得する。
        UpdateParameter param = new UpdateParameter();
        // メイン処理でDBからデータを取得する。
        param.setHeader(dao.getHeader(1));
        param.setHeader2(dao.getHeader2("a"));
        param.setHeader3(dao.getHeader3(2));

        // 画面の情報を反映する。
        setValueFromView(param);

        // DBを更新する。
        dao.update(param);
    }

    private void setValueFromView(UpdateParameter param) {
        // 画面の値を取得したパラメータのHeader1,2,3に反映する。
        // コードは省略
    }

    public class UpdateParameter {
        private Header header = null;
        private Header2 header2 = null;
        private Header3 header3 = null;

        // Daoの参照を削除

        public void setHeader(Header header) {
            this.header = header;
        }

        public void setHeader2(Header2 header2) {
            this.header2 = header2;
        }

        public void setHeader3(Header3 header3) {
            this.header3 = header3;
        }

        public Header getHeader() {
            return header;
        }

        public Header2 getHeader2() {
            return header2;
        }

        public Header3 getHeader3() {
            return header3;
        }

    }

    // 以下のコードは省略
```
</div>
</details>

## まとめ
Javaの開発経験は1年程度なので、Javaだとサンプルであげたようなコードは普通なのか気になるところ。
また、「気になったこと」に記載した問題点をそのままにしてでも、流れるようなインターフェースを使う理由はなんだろう。

[前の記事(ちょっと気になるコード集)]
(http://qiita.com/csharpisthebest/items/7d9d2c7e4da4b89488fd)

[次の記事(冗長な代入文)]
(http://qiita.com/csharpisthebest/items/f9ebc741e40037553d5b)

[目次](http://qiita.com/csharpisthebest/items/57f27a33085f01211166)