モバイルファクトリー Advent Calenadar 16日目の記事です。
今日はネイティブアプリエンジニアの@mattakがお送りします。
前置き
AndroidのプロジェクトにKotlinを導入してみて半年弱たちました。
いままで開発してみてのメリット、デメリット含めてふりかえってみました。
メリット
導入が容易
KotlinはJavaと完全に同居することができ、また相互に呼び出しが可能です。
-
src/main/java/Hoge.java
とsrc/main/java/Fuga.kt
がディレクトリに共存できる -
src/main/java/Hoge.java
とsrc/main/java/Fuga.kt
が相互に呼び出せる
新規プロジェクトでないと導入できないようなハードルの高さは無く、過去のプロジェクトもKotlin化することが容易です。
導入コストの低さとも相まってなのですが、困ったならばJavaで一旦記述して、Auto Converterをかけてしまえば簡単にKotlinファイルへの変換が可能です。
Javaより安全
Nullableな型と、そうでない型を厳密に区別することができるのでNullPointerExceptionを引き起こしてしまう機会が激減しました。
最近のAndroidでは引数に @NonNull
@Nullable
をAnnotationにつけることが多いですが、書いているとついついつけ忘れてしまうことも多いです。
Kotlinではなにも考えずともNullableな変数かどうかを区別していけるので、デフォルトで非常に安全です。
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {}
override fun onCreate(savedInstanceState: Bundle) {}
またImmutableな変数(val
)とMutableな変数(var
)を明示的に分ける必要があるので、副作用や初期化順序を気にしなければならない処理が減りました。
val immutable: String = ""
immutable = "" // 再代入不可能
var mutable: String = ""
mutable = "" // 再代入可能
Kotlinの世界でコードを記述していると、Javaでいままで書いていたコードがいかにルーズであったかを認識できます。
Javaより見やすい
特に違いがでるのは無名関数です。
view.setOnClickListner(new OnClickListener() {
@Override
public void onClick(View v) {
// processing
}
});
view.setOnClickListner {
// processing
}
とくにcallbackが多いシーンでは、KotlinとJavaで大きな可読性の差がでます。
RxJavaなど無名関数が頻繁に出てくるライブラリを使っていると、Javaには戻れないような快適さを味わえます.
(Java8やRetroLambdaを使えばいいという話もありますが、Android開発においてはKotlinほどの手軽さはありません。)
標準ライブラリが充実
standard libraryにutility関数が豊富に生えています。
とくに Collection系 のextensionが便利です。
この強力なライブラリ群のおかげで日常的に書く関数がすっきりしました。
Kotlinを書いているとforloopを使う機会は少なく、Javaよりスリムに見通しやすくなります。
Javaよりコードが短くなった
Fragmentが20個, CustomViewが90個程度のプロジェクトなのですが、今のところアプリケーションコード全体の95%以上のファイルが100行未満で構成できています。
Javaだと数百行のファイルはザラで、ひどいものだと数千行にわたることもままあります。
もちろんプロジェクトの構成は大事なのですが、Kotlin化するだけでも相当数のファイルを短くできます。
単純な話ですが、行数を減らせば減らすほど目に優しく、レビューがはかどりました。
embugする可能性は減り、コードの可読性は上がっていったと感じます。
とくにEntityなどの冗長なコードは非常にすっきりしました。
class PersonEntity {
private final String firstName;
private final String lastName;
PersonEntity(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return this.firstName;
}
public String getLastName() {
return this.lastName;
}
}
data class PersonEntity(
val firstName: String,
val lastName: String
)
またM13から対応したJavaから参照するgetter/setterがkotlinから見るとpropertyとしてアクセスできる機能 も非常に便利で、KotlinからJavaを参照した時にもすっきりアクセスできるのは嬉しい限りです。
遅延初期化が簡単
これも定番の話ですが、遅延初期化が非常に楽です。
class Hoge {
val message: String by lazy { "hello" }
}
このように宣言しておくと、プロパティのアクセスがあるまで初期化が走らないようにできます。
プロジェクトではとくに理由がない限りは遅延プロパティを利用することを推奨しており、おかげでアプリ自体の初期化も最小限の処理に留めることができています。
object Fuga {}
余談ですが、objectも遅延初期化されます。
使いドコロは限定しているのですが、singletonを簡便に記述できるので重宝しています。
Swiftユーザにやさしい
nullsafeな記述、val/varでのimmutableな変数の別離、lazyなどswiftで記述している人には慣れ親しんだ概念で記述できます。
すでにSwiftを日常的に書いているならば、スムーズに取り入れられると思います。
デメリット
アプリの容量が微増する
チュートリアルによると、1.0.0-betaで1MB弱ふえてしまうようです。
Kotlin has a rather small runtime file size: the library is approximately 930KB (as of build-1.0.0-beta-3595). This means Kotlin adds just a little to .apk file size.
アプリのmethod数が増加する
$ dex-count-jar kotlin-stdlib-1.0.0-beta-3595_afc4a91b6eb5f09f622b41da1977233153e3eff8.jar
7429
$ dex-count-jar ./app/build/intermediates/pre-dexed/debug/kotlin-runtime-1.0.0-beta-3595_4986d642f69c0d131789ce0e465fa098d31e9ad0.jar
1103
そこそこメソッド数が増加します。 どうしてもmulti dex化したくないアプリなどでは使わないほうがいいかもしれません。
まとめ
Kotlinよいです、導入も楽です。
特にプロジェクトに厳しい制約がないならば得られるメリットは大きいと思います。
明日は、200 OKこと yashims85 さんです。
引き続きAndroid周りの記事をご期待ください。