PHPがメインのエンジニアがJavaのSpring Bootを触ってみた

# 前書き
普段PHPとjavascriptをメインで触っているのだが、JavaのSpring Bootを触る機会があったので、そのときに勉強したこと、便利だと思ったことなどを書こうと思います。

# 環境
java version 1.8.0_92
Spring Boot v1.5.8
Maven

# IDE
PHPだと、前職ではvimを、最近はphpstromを利用していましたが、JavaのSpring Bootの開発環境は、eclipseかSTS(Spring Tool Suite)を使うとのこと。STSもeclipseが元になっているらしく、今回使ってみたがほぼeclipseと同じ印象を受けました。

# アノテーション
多分、Springの最大の特徴がこのアノテーションだと思います。phpunitなどを利用したことがある人は、@Testとか@dataProviderとか利用したことある人も多いと思いますが、そういったアノテーションがいたるところで利用可能です。自分が一番使ったであろう、アノテーションをいかに2つだけ記載しておきます。

- @Autowired

Dependency Injection：依存性の注入 とか言われるやつです。
@Autowiredをクラス内で宣言するとnewでオブジェクトを作成していないのにオブジェクトを利用できるようになります。

```
@Autowired
private TestClass testClass;
```

- @Query 

SQLを定義しておき、設定したメソッドが呼ばれた時にそのSQLを実行することができます。
また、その際、springの様々な書き方が利用可能です。

```
@Repository
public interface TableDao {
    @Query("SELECT s FROM table s ORDER BY id DESC")
    List<Table> findAllRecord();

    @Query("FROM Table WHERE id = ?1)
    List<Table> findById(int id);
}
```

# ライブラリの利用
PHPで標準関数以外のライブラリを利用したくなったら、composerを利用するのが今の主流だと思うが、Mavenを利用したJava開発の場合、dependencyで利用するライブラリを設定します。

mavenで利用可能なライブラリはMaven Repositoryから探すことができます。
https://mvnrepository.com/

具体的には、プロジェクトを作成すると、その中にpom.xmlというファイルが作成されるため、そこに利用したいリポジトリを以下のように記載します。ただし、IDEを利用していれば、自分でコードを書かなくても、設定画面でパラメータを入力するだけで、以下の設定を勝手に記載してくれるので便利です。

```
<dependencies>
	<dependency>
		<groupId>org.apache.commons</groupId>
		<artifactId>commons-csv</artifactId>
		<version>1.5</version>
	</dependency>
</dependencies>
```

# アプリケーションの設定
Spring bootではアプリケーションの設定をsrc/main/resources/application.propertiesというファイルに記載します。
例えば以下のように。

```
# setting of database
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test
spring.datasource.username=root
spring.datasource.password=1234

# Redis
# Specify the DNS URI of your Redis cache.
spring.redis.host=localhost

#### application properties ####
# application log dir
path.log-dir=/Users/user/tmp/logs
```

このように書くことで、redisやdatabaseなど様々な設定を簡単に変更することができ、
また、例えばコードで

```
public class Application {
    @Value("${path.log-dir}")
    private String logDir;

    public static void main(String[] args) {
        System.Out.Println(logDir);
    }
}
```

のようにpropertiesに書いた設定を利用することもできます。


# MVCフレームワーク
PHPだと、Model, View, Controllerと呼びますが、SpringだとService, View, Controllerと呼ぶそうです。
Serviceにはビジネスロジックを記載するそうですが、ほぼModelと同じと思っていいと思ってます。自分はServiceの下にThreadクラスを作り、Serviceから呼び出す形にしていましたが、結構一般的なようです。

# マルチスレッド
PHPにない概念のため、最初かなり実装苦労しました。
Javaではスレッドを同時に複数走らせることができるため、その際に他のスレッドに影響を与えないようにスレッドセーフで作ったりなどコードをちゃんと考える必要があります。シングルスレッドで実装すれば問題ないのですが、せっかくJavaで実装しているのであれば、マルチスレッドにして性能を最大限に発揮したいものです。

# 記述しなければいけないコード量が多い
これはJavaのコードを書いていて不便だなと思ったことです。
例えばphpでコマンドラインでコマンドを実行したい場合は、

```
if ( !exec('command 2>&1',$array)) {
    var_dump($array);
}
```

のように記述すれば終わりです。
それがJavaだと、

```
String executeCmd = new String[] { "bash", "-c", command };
Process p = new ProcessBuilder(executeCmd).start();
p.waitFor();
BufferedReader buffRead = new BufferedReader(new InputStreamReader(p.getErrorStream()));

while ((strLine = buffRead.readLine()) != null) {
    System.Out.Println(strLine);
}
buffRead.close();
```

のようになるわけです。(Javaではもっと簡単な書き方はあるのかもしれませんが、自分が調べたやり方はこのやり方でした)
Javaに慣れていないせいもあると思うのですが、このいたるところでJavaで書く際にコード量が増えることにより、プログラムの書き方を調べる調査時間が大幅に増えていきました。

また、Javaではいたるところでtry{...}catch(){...}を記述が必要になります。IDEが補完してくれるとはいえ、PHPに比べるとかなり不便に感じました。

# 型が厳しく辛い。PHPのarrayのような便利な型がない。
JavaはPHPとは違い、型変換がかなり厳しいです。
最近はPHPでも、関数などの宣言で型を書くことが増えてきましたが、必ず型を書かなければいけないのは、PHPになれた自分からしたらかなり窮屈でした。

特に、PHPのarrayのようなハッシュや配列を便利に扱えなかったり、返り値のためにわざわざクラスを作る必要があったりがかなり辛かったです。
例えば、

```
public String getClient(){
   return "name";
}

String client = getClient();
```

という関数に、nameの他にclientのidを一緒に返したくなった場合、PHPなら、

```
public function getClient(){
    return array("name", 1);
}

list ($name, $id) = getClient();
```

のように、変更が容易ですが、Javaだとちゃんと書くのであれば、

```
class Client {
   private int id;
   private String name;

   public Client(int id, String name) {
       this.id = id;
       this.name = name;
   }
}

public Client getClient() {
   return new Client("name", 1);
}

Client client = getClient();
```

のように、わざわざ返り値のクラスを作る必要があります。
もちろん、Object[]にしたり、String[]で返してintにキャストし直してもいいのですが、Javaで書く場合は結果をちゃんとクラスで作るのが一般的でしょう。そうすると、phpに比べてかなりコードを書く必要があり、そこが自分にとってかなり大変でした。

# エラーの対処方法は選ぶだけなので便利。
phpstormもかなりエラーに関しては対策案を提案してくれるので便利ですが、Javaは本家静的言語だけあって、かなりエラーの対処が親切です。エラーがあったら、IDE上でエラーをクリック→解決案を選ぶだけでほとんどのエラーは解決してくれます。Javaで本格的に開発したことがなくても、エラーでつまずくことが少なく、この部分は本当に素晴らしいと思いました。

# 結論
すべてはJavaに慣れていないということに尽きるのかもしれませんが、PHPに比べてJavaだと開発スピードがかなり遅くなってしまいました。　やはり自分はPHPが快適で好きです。ただ、PHPのように雑に実装することがJavaだとできないため、エンジニアの質が低くてもPHPよりはメンテナンス性の高いコードがかけるのも確かだと思います。

また、springはなぜか日本語の文献が少なく、何をするにも英語で調べたほうが早かったので、日本語でドキュメントが充実しているPHPに慣れている人は、そういったところも辛いかもしれません。