PairsでKotlinを採用した5つの理由
eureka Advent Calendar 2016の16日目です。
昨日は恩田さんの「Terraformを1年間運用して学んだトラブルパターン4選」でした。
こんにちは。Pairs Global事業部でAndroidエンジニアをやっている海藤です。
皆さん、Kotlin書いてますか? 実はPairsのAndroidチームでは開発言語として正式にKotlinを採用しました。そこで、この記事ではPairsでKotlinを採用した理由を紹介したいと思います。記事のタイトルにある通り、理由は以下の5つです。
- v1.0のリリース
- Javaとの相互運用性
- Null Safety
- 高階関数
- 気持ちよさ
1. v1.0のリリース
Kotlinは2016年2月にv1.0がリリースされています。公式ブログでも述べられているように、KotlinはJetBrainsの製品にも使われていたり、国内でプロダクションへの採用事例もいくつか出てきたりしています。また、今後もJetBrainsがKotlinに対して継続的に投資していくということが明確に書かれているというのも重要なポイントです。
Kotlinはオープンソースで開発されていて、現在までに130名以上のContributorがおり、万が一JetBrainsがサポートをやめたとしてもすぐにKotlinが使えなくなるということはなさそうです。そして、社内の某AndroidエンジニアはKotlinへのコントリビュートを狙っているとかいないとか。
2. Javaとの相互運用性
Pairsはリリースから3年以上が経過し、ソースコードもかなり大規模になっています。以前は全てJavaで書かれており、これを一気にKotlinに置き換えるのは現実的ではないため、しばらくはJavaとKotlinが同じプロジェクト内に同居することになります。その場合にJavaとの相互運用性が重要になってきます。
公式サイトでKotlinの4つの特徴が挙げられており、KotlinはJavaとの相互運用性を重視していることが分かります。
- Concise:簡潔性
- Safe:安全性
- Versatile:多様性
- Interoperable:相互運用性
JavaとKotlinはクラス単位で書き分けることが可能で、JavaからKotlinを参照することも可能ですし、逆にKotlinからJavaを参照することももちろん可能です。もし、Kotlinだと都合が悪い部分があっても、そこだけはJavaで記述するというような運用が可能になります。
Kotlinだと都合が悪いパターンの具体例としてよく話題に上るのが、Annotation Processingです。2016年12月現在、KotlinとAnnotation Processingを組み合わせるとうまく動かない場合があるものの、JetBrainsもkotlin-kaptとして解決策を検討しているようですし、ワークアラウンドも確立されつつあります。
3. Null Safety
Javaの参照型はnullを許容するため、nullになってはいけない変数もNullableとして記述することになります。万が一、コードにミスがあり、nullが入り込んでしまった場合に、それが発覚するのは実行時ということになります。開発段階で検知できれば問題ありませんが、ミスに気が付かずにリリースしてしまった場合、アプリのクラッシュなどにつながってしまいます。そう、悪名高いNullPointerExceptionですね。
一方で、Kotlinは言語仕様としてNull Safetyがサポートされているため、NonNullとNullableを明確に区別します。万が一、NonNullな変数にnullが入り得るようなコードを書いてしまった場合でもコンパイルエラーが発生するため、実行前に確実にミスを検知することが可能になります。
4. 高階関数
PairsではRxJavaを全面的に採用しています。RxJavaをお使いの方は分かるかと思いますが、大量の無名クラスを使用するのでコードが非常に長くなってしまいます。Kotlinを使うとこのようなコードを簡潔に書くことができます。具体的な例を見てみたいと思います。
0 ~ 5までの数字から偶数を取り出して、それらを100倍したものを出力するプログラムをRxJavaを使って書いてみます。
まずはJavaの場合です。
Observable<Integer> observable = Observable.from(Arrays.asList(0, 1, 2, 3, 4, 5));
observable.filter(new Func1<Integer, Boolean>() {
@Override
public Boolean call(Integer integer) {
return integer % 2 == 0;
}
})
.map(new Func1<Integer, Integer>() {
@Override
public Integer call(Integer integer) {
return integer * 100;
}
})
.subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {}
});
次にKotlinの場合です。
val observable = Observable.from(0..5)
observable.filter { integer -> integer % 2 == 0 }
.map { integer -> integer * 100 }
.subscribe { }
コードを見てもらえば一目瞭然ですが、Kotlinの方が明らかに簡潔になっていることが分かると思います。Javaの場合は言語仕様の制約上、無名クラスをいくつも使う必要がありますが、Kotlinは高階関数が使えるため、本質的なロジックだけを簡潔に記述することが可能になります。
5. 気持ちよさ
私と同じPairs事業部の愛澤が以前Kotlinの気持ちよさという記事を書いていた通り、Javaと比べてKotlinは書いていて非常に気持ちがいいです。
この記事ではKotlinの魅力については詳しくは書きませんが、Kotlinには以下のように様々な機能があります。
- スコープ関数
- 拡張関数
- 名前付き引数
- デフォルト引数
- データクラス
- オブジェクト
- スマートキャスト
- etc…
Androidアプリを開発する上でこれらの機能は必須というわけではありませんが、書いていて気持ちがいいというのはエンジニアのモチベーションにも影響しますし、エンジニアのモチベーションが上がればプロダクトのクオリティもそれに比例して上がっていくのではないか、という期待もあります。
まとめ
この記事では、PairsでKotlinを採用した理由として以下の5つを紹介しました。
Ver. 1.0のリリース
- 言語として一定の完成度になっていること、今後継続的にメンテナンスしていくという表明がなされていること
- Javaとの相互運用性
- クラス単位で共存が可能で、既存プロジェクトへの導入障壁が低いこと
Null Safety
- 言語仕様としてNull Safetyが取り入れられており、適切に運用することでNullPointerExceptionを撲滅できること
高階関数
- Javaでは無名クラスとして記述しなければいけない箇所を高階関数として記述することで、より簡潔かつ本質的なことにフォーカスして記述可能なこと
気持ちよさ
- エンジニアのモチベーションアップにつながること
あくまで弊社がKotlinを採用するに至った理由を紹介しましたが、これは弊社に限った話ではなく、どの企業でも当てはまることかなと思います。この記事がKotlinの採用を検討している方のお役に立てば幸いです。
明日は大久保さんの「データ分析の誤りを未然に防ぐ!MySQL4つの検算テクニック」です。