アプリ開発の基礎

株式会社デジタルクエスト エンジニア Advent Calendar 2018 7日目担当のTakeuchiです。

今年はアプリ開発を進める際の基礎について書いていこうと思います。

（筆者はAndroidアプリ開発がメインなのでJavaで書かせて頂きます）


##Model編
アプリを作る上で欠かせない**Model**。

**Modelをどれだけ使いやすく作るか**で画面の実装が楽になったり出戻り作業がなくなったりします。

**ここだけは適当に進めてはいけません！**

どんな画面を作るにしてもModelから情報をとってくる処理を書く必要があると思います。
ただ、このModel、新規開発案件がスタートした時なんかはサーバ側も同時にスタートするためDB構造が決まっていなくてすぐ作れなっかたりします。

そんな時どうやってアプリを先行して作っていくのがいいのか？？


例えばユーザのリスト（名前、性別、年齢）をサーバから取得して表示する画面があったとします。

おそらくModelはこんな感じになると想像されます。

```
public class UserModel {
    private String name;
    private int gender;
    private int age;

    public UserModel(String name, int gender, int age) {
        this.name = name;
        this.gender = gender;
        this.age = age;
    }
}
```

しかし実際どうなるかは確定していないので、「gender」はカラム名が「sex」になるかもしれないし、「gender」も「age」もStringかもしれない。など不確定な要素があります。

GsonなどのLibraryを使って、レスポンスのJsonからModelを作る場合は特にカラム名はサーバとなるべく一致させたいと思いますが、このModelを「仮」で作って、後から通信を繋ぎこむような開発を行うとどうなるでしょう。

おそらくはListViewのAdapter内に

```
UserModel userModel = data.get(position);

textViewName.setText(userModel.name);
textViewGender.setText(userModel.gender == 1 ? "男" : "女");
textViewAge.setText(userModel.age + "歳");
```

のような処理が入るので「gender」が「sex」に変わったらmodelだけではなく、各画面のコードも一括で置換するような作業が発生してきます。
もっというと「gender」がStringだった場合、

```
userModel.gender == 1
```
の部分も修正しなければならなくなり後々大変ですね。

どうしていれば良かったんでしょうか。

###①画面表示用のInterfaceをつくる！
```
public interface UserModelInterface {
	String getUserName();
	int getUserGender();
	int getUserAge();
}
```

こんな感じのInterfaceを作ってあげて、ListViewに渡すのはUserModelではなく**UserModelInterface**にしましょう。

```
UserModelInterface userModel = data.get(position);

textViewName.setText(userModel.getUserName());
textViewGender.setText(userModel.getGender() == 1 ? "男" : "女");
textViewAge.setText(String.valueOf(userModel.getAge()) + "歳");
```

こうしておいて、後でサーバ側が確定してから**UserModelInterface**を**継承**した**UserModel**をつくれば出戻りは一切なくなります。

```
public class UserModel implements UserModelInterface{
    private String name;
    private int sex;
    private int age;

    public UserModel(String name, int sex, int age) {
        this.name = name;
        this.sex = sex;
        this.age = age;
    }
    
    public String getUserName(){
    	return this.name;
    }
    //カラム名はsexが正しかったのでgetUserGender()のメソッドでsexを返す
    public int getUserGender(){
    	return this.sex;    
    }
    public int getUserAge(){
    	return this.age;
    }
}
```

画面側はInterfaceのメソッドを経由しているので修正する必要はないという訳です。


###②表示する際にadapter側で条件文挟むのはやめる！

上の例でいうと

```
textViewName.setText(userModel.gender == 1 ? "男" : "女");
```

こいつですね。

「gender」がintなので画面に表示する際に1だったら男、それ以外は女としているようですが、この条件文はadapterでやるべきではなくModelが継承したInterfaceのメソッド内でやるべき作業です。

そうすれば型変更がきても画面側のコードを直す必要はなくなります。

```
public interface UserModelInterface {
    String getUserName();
    //そもそも「男」か「女」を返すメソッドにする
    String getUserGender();
    //こちらも「XX歳」を返すメソッドにしてしまう
    String getUserAge();
}
```

```
public class UserModel implements UserModelInterface{
    private String name;
    private int sex;
    private int age;

    public UserModel(String name, int sex, int age) {
        this.name = name;
        this.sex = sex;
        this.age = age;
    }
    
    public String getUserName(){
        return this.name;
    }
    public String getUserGender(){
    	//1だったら「男」それ以外は「女」を返す
		return this.sex == 1 ? "男" : "女";  
    }
    public String getUserAge(){
    	//「歳」を追加して返す
        return String.valueOf(this.age) + "歳";
    }
}

```

Adapterのコードも綺麗になります。

```
UserModelInterface userModel = data.get(position);

textViewName.setText(userModel.getUserName());
textViewGender.setText(userModel.getGender());
textViewAge.setText(String.valueOf(userModel.getAge());
```

こんな感じですね。

##まとめ
今はユーザの一覧を表示するだけのシンプルな画面を例にとりましたが、複雑な画面になるにつれModelの情報も増え、Modelの種類も増えていきます。

また、Modelの中にModelがいるなど構造が深くなって来た際にModelの出来が悪いとコード量が増えるだけでなく、何の値をとってきているのかわからなくなってくるなどコードが読みづらくなってきます。

そんな時は画面表示用のInterfaceを作ってあげてわかりやすいメソッド名をつけてあげればコードも読みやすくなるので是非画面表示用のInterfaceを先に作成してみてはいかがでしょうか。

以上です！