Java未経験のエンジニアがKotlinでプロダクトコードを書くまでに勉強したこと

## はじめに

こんにちは。ナビタイムジャパン ACTS(研究開発部門) サーバーグループの [chov](https://github.com/t-chov) です。

[Kotlin で JUnit 5 を使ってみた](https://qiita.com/navitime_tech/items/a66f553af224eaff490a) にて紹介されている Kotlin 製 API サーバ開発に、Java 経験なしでジョインしました。(※業務での Java 経験がないだけで、基本文法は理解しています)

コードレビューで揉まれつつ、なんとかメインで大きめの機能追加を実施できるまでになりましたので、勉強の方針や感想、Kotlin 初学者向けのちょっと嬉しい話について書いていきたいと思います。

## 対象読者

* 何らかのプログラミング言語について開発経験はあることが前提で
    * Java 未経験だが Kotlin 案件にジョインすることになった人
    * 全く知らない言語の開発案件にジョインすることになった人

筆者の開発経験ですが、 前職では SIer にて 4年ほど PHP (5.3〜5.6) での開発を行っておりました。 利用フレームワークは主に [Slim Framework](http://www.slimframework.com/) 、単体テストは PHPUnit です。

## 対象としない範囲

* サーバサイド Kotlin 案件の始め方
* フレームワーク、言語仕様の詳細な説明
* 開発自体の未経験者

## TL;DR

大まかな流れを箇条書きにすると以下のようになります。この4行で伝わる人はこの後を読まずに今すぐ Koans をやりましょう。(IDEAからでなくてもできます)

1. IntelliJ IDEA を手に入れる
2. Kotlin Koans をやる
3. プロダクトの設計思想をペアプロ/モブプロを通して学ぶ
4. テストを書く

## IntelliJ IDEA を手に入れる

Kotlinをやるのであればこれが最も重要かもしれません。JetBrains 社が言語とIDEを両方開発しているのも大きいですが、強力なコーディング支援機能が数多く搭載されています。

アプリケーションのローカル起動が容易になるなど、サーバサイド Kotlin であれば有償版があると非常に効率が上がるため、是非導入しましょう。筆者の所属チームでは、全員有償版を利用しています。

## Kotlin Koans をやる

Kotlin に限らず、最近のプログラミング言語は公式で豊富なチュートリアルが用意されていることが多いです。(と感じています)

代表的なところでいえば以下の3つでしょうか。

* [Kotlin Koans](https://kotlinlang.org/docs/tutorials/koans.html)
* [A Tour of Go](https://tour.golang.org/)
* [The Book (Rust)](https://doc.rust-lang.org/book/)

本記事では Kotlin Koans について主に扱いますが、他の経験の少ない言語案件にジョインする方は適宜読み替えていただければと思います。

### Kotlin Koans は IDE で

Kotlin Koans は Web でも可能ですが、IDE からも実行可能ですので、Kotlin を始める方であれば IntelliJ IDEA または Android Studio で実行することを推奨します。

Kotlin Koans を IDE から行うことを推奨するには明確な理由があり、

* 振り返りができる
* IDE の使い心地に慣れることができる
* 使い慣れたキーバインドでコードが書ける

といったメリットを享受することができます。

#### 振り返りができる

Kotlin Koans はかなりボリュームがあるので見返すことができて嬉しい、という理由だけではありません。

Kotlin Koans では演算子のオーバーロードなどかなり踏み込んだ内容まで扱います。実際に案件で活用する際、かつて自分がどう取り組んだか振り返ることができることは想像以上に大事でした。

#### IDE の使い心地に慣れる

IntelliJ IDEA は高機能な IDE です。高機能であるゆえに、機能を使いこなすには時間がかかります。プロダクトコードに集中する時間を増やすためにも、勉強するうちから IDE の使用感に慣れていたほうが良いでしょう。

IntelliJ IDEA には多数のショートカットがありますが、ショートカットを覚えるのが苦手な人のためのプラグインもあります。[Presentation Assistant](https://plugins.jetbrains.com/plugin/7345-presentation-assistant/) はショートカットを実行した時のみならず、右クリックから操作を実行した場合も操作を画面下部に表示してくれるため、表示を見ながら少しずつ覚えていけばきっと使いこなせるはずです。

#### 使い慣れたキーバインドでコードが書ける

Mac であればブラウザ上でも一部の Emacs キーバインドが使えますが、Vimmer の方はきっと Vim キーバインドでコードを書きたいはず。Emacs ユーザの皆様も、もっと綺麗に Emacs キーバインドを使いたいかと思います。

IntelliJ IDEA は設定で Emacs キーバインドに対応、[IdeaVim](https://plugins.jetbrains.com/plugin/164-ideavim/) プラグインで Vim キーバインドを利用することができます。Vimmer である筆者は SIer 時代、 Eclipse で Vrapper を頑張って使っていましたが当時に比べ非常に快適なコーディングができています。

### チュートリアルをやる意義

上述しましたが、 Kotlin Koans では普段あまり使わない機能まで扱います。

ひとまず業務プログラミングで使う範囲を勉強するのであれば、 [Collections](https://play.kotlinlang.org/koans/Collections/) を重点的に行うのが良いでしょう。Java の Stream API よりもシンプルな記法でより多くのことを扱える高階関数は、 Kotlin の大きな武器の一つです。個人的には `count` と `zip` を気に入っています。

#### 楽しい高階関数の例

単純な例として、整数のリストに対する操作を行うことを考えます。

```java
/**
 * 奇数の個数を数える
 */
public static long countOdds(List<Integer> numbers) {
    return numbers.stream().filter(num -> num % 2 == 1).count();
}
```

```kotlin
fun countOdds(numbers: List<Int>) : Int {
    return numbers.count { it % 2 == 1 }
}
```

`count` は Stream API では `filter` と `count` を組み合わせるような処理を1つの関数で処理できます。また、`zip` は Java8 の時点では実装されておらずインデックスを指定して取得する必要がありますが、Kotlin では言語機能として利用することができます。

※ Guava などを利用すれば Java 8 でも可能です

高階関数に慣れれば、スコープ関数もすんなり理解できるようになるかと思います。

```java
/**
 * 2番目の文字列が1番目の部分文字列かどうか判定する
 */
public static List<Boolean> containsGivenString (List<String> list1, List<String> list2) {
    return IntStream.range(0, Math.min(list1.size(), list2.size())).mapToObj(i ->
            list1.get(i).contains(list2.get(i))
    ).collect(Collectors.toList());
}
```

```kotlin
fun containsGivenString(list1: List<String>, list2: List<String>): List<Boolean> =
    list1.zip(list2).map { (first, second) -> first.contains(second) }
```

#### その他の嬉しいポイント

Kotlin の嬉しいポイントとしてよく語られることに Null Safety な言語仕様が挙げられます。筆者もこの点については強く感じていますが、それを踏まえた上で嬉しいポイントに `if` や `when` が式である点を挙げたいと思います。

例)

```java
public SomeObject someMethod(SomeArgument argument) {
    if (argument.isFoo()) {
        return this.doSomething(this.someValue)
    }
    return this.doSomething(this.anotherValue)
}
```

Java ではこのようなコードを書くこともあるかと思いますが、Kotlin では以下のように書けます。

```kotlin
fun someMethod(argument: SomeArgument) : SomeObject =
    this.doSomething(v = if (argument.isFoo) this.someValue else this.anotherValue)
```

#### 高度なチュートリアルの是非

なぜ Kotlin Koans は一見すると初学者には不要そうなチュートリアルが載っているのでしょうか。

これは想像でしかないですが、少しずつ理解が深まってきた今 Kotlin Koans をやり直すとまた新しい発見があることを踏まえると、学び直しを前提としたチュートリアルなのではないかと感じています。

Java の理解が深まると初学者の頃にはおまじないでしかなかった `public static void Main(String args[])` の意味が分かってくるようになるのと似たような感じで、最初はあまり分からず回答を読んでいた機能がすんなりと理解できるようになる辺りには難易度設定の妙を感じます。

また、特定の機能があることを知っておくことは不要な実装を防ぐ効果もあります。忘れられがちですが、知らないことは調べられません。必要なときに調べられるという観点からも、チュートリアルで多少難易度の高いことをやる思想には個人的には納得する部分が多いです。

## ペアプロ/モブプロから学ぶ

チュートリアルをやり、いざプロダクトコードに立ち向かうと「わからない」という感想が先行しがちです。これは言語やフレームワークへの理解が足りないことだけが原因ではなく、プロダクトの持つ文脈に対する知識が足りていないことも原因です。

この文脈理解の差を埋めるために、積極的にペアプロ/モブプロで実装を進めることを推奨します。

最初は有識者の実装を横で見たあとにドライバーをやり、小さめの機能追加から参画するのが王道かと思います。

ペアプロやモブプロのノウハウについては世の中に溢れているので、詳細はそちらに譲ります。取り組みというほど大仰なものではありませんが、所属部署ではペアプロ/モブプロ用の席が存在しており、気軽に「モブ席でやろうよ」と言える環境ができております。専用部屋を用意するのはなかなか難しいと感じていらっしゃる方の参考になれば幸いです。

## テストを書く

テストについては [上に挙げた記事](https://qiita.com/navitime_tech/items/a66f553af224eaff490a) に詳しいですが、書きやすく明瞭なテストがあることで自信を持って変更を行うことができました。

IntelliJ IDEA を利用している場合は `Shift + Command + T` (Mac) または `Shift + Ctrl + T` (Win) で対象クラスのテストを作る/遷移することが可能です。便利ですね。

もしテスト駆動開発の経験が薄い方でしたら、一度 [『テスト駆動開発』](https://www.amazon.co.jp/dp/B077D2L69C/) を通読することをお勧めします。言語を問わず有効な知識ですし、第二部で小さいテスティングフレームワークをフルスクラッチ実装することで xUnit 系フレームワークへの理解が深まります。

## まとめ

チュートリアル、ペアプロ、テストの三本柱によって未経験言語の案件にもなんとかジョインすることができました。優しくフォロワーシップのあるチームメンバーに恵まれたことも大きいですが、方針自体は他の開発現場でも応用できることが多いかと思います。

チュートリアルは技術そのものに対する知識を、ペアプロはプロダクトに対する理解を、単体テストは変更に対する自信を生み出してくれます。この記事が新しい言語に挑む皆様のお役に立てば幸いです。