この記事は Florina Muntenescu による Android Developers - Medium の記事 "More productivity with Kotlin" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。

Kotlin は簡潔なプログラミング言語として知られています。そしてそれは、高い生産性を意味します。そして実際に、Kotlin を使っている Android デベロッパーの 67% が、生産性が向上したと述べています。このブログ投稿では、Kotlin を使ってパートナーのエンジニアたちが生産性を向上させた方法をいくつか共有し、そのために役立つ Kotlin の機能も紹介します。


簡潔さ、シンプルさと生産性

  • Kotlin の簡潔さは、開発のあらゆる段階で効果を発揮します。

  • コードの作成者は、構文ではなく、解決しなければならない問題に集中できます。 テストやデバッグするコードが少なくなれば、バグが生まれる可能性も少なくなります。

レビューやメンテナンスの担当者は、読むコードが少なくなるので、コードが行っていることを理解しやすくなります。そのため、レビューやメンテナンスが楽になります。

その一例として、Flipkart のチームを紹介しましょう。

「弊社の社内調査によると、デベロッパーの 50% が、Kotlin でモジュールを書くと [機能を完成させるまでの] 見積りが小さくなると回答しました」(Flipkart)


Kotlin の機能と生産性

Kotlin の機能のほとんどは、簡潔さと高い可読性を持つため、高い生産性につながります。特によく使われる機能について見てみましょう。


デフォルト引数とビルダー

Java プログラミング言語では、コンストラクタのパラメータが省略可能な場合、一般的に次の 2 つの方法のどちらかを利用します。

Kotlin ではデフォルト引数を利用できるので、どちらも必要ありません。デフォルト引数を使うと、ボイラープレートを追加することなく、関数のオーバーロードを実装できます。

Cash App チームが Kotlin を使い始めたとき、多くのビルダーを削減し、書く必要があるコードの量を減らすことができました。場合によっては、コードのサイズが 25% 少なくなりました。

たとえば、以下の一例は、 Task オブジェクトの実装で、タスクの名前のみが必須パラメータになっています。ビルダーを使った場合と、デフォルト引数を使った場合でそれぞれどうなるかを示しています。

/* Copyright 2020 Google LLC.

   SPDX-License-Identifier: Apache-2.0 */


- public class Task {

-     private final String name;

-     private final Date deadline;

-     private final TaskPriority priority;

-     private final boolean completed;

-

-     private Task(String name, Date deadline, TaskPriority priority, boolean completed) {

-         this.name = name;

-         this.deadline = deadline;

-         this.priority = priority;

-         this.completed = completed;

-     }

-

-     public static class Builder {

-         private final String name;

-         private Date deadline;

-         private TaskPriority priority;

-         private boolean completed;

-

-         public Builder(String name) {

-             this.name = name;

-         }

-

-         public Builder setDeadline(Date deadline) {

-             this.deadline = deadline;

-         return this;

-         }

-

-         public Builder setPriority(TaskPriority priority) {

-             this.priority = priority;

-             return this;

-         }

-

-         public Builder setCompleted(boolean completed) {

-             this.completed = completed;

-             return this;

-         }

-

-         public Task build() {

-             return new Task(name, deadline, priority, completed);

-         }

-     }

-}

+ data class Task(

+     val name: String,

+     val deadline: Date = DEFAULT_DEADLINE,

+     val priority: TaskPriority = TaskPriority.LOW,

+     val completed: Boolean = false

+) 


デフォルト引数の詳細については、連載シリーズ Kotlin Vocablary のブログ記事「Kotlin のデフォルト引数」をご覧ください。


オブジェクトとシングルトン

おそらく、シングルトン パターンはソフトウェア開発で特によく使われるパターンの 1 つでしょう。オブジェクトのインスタンスを 1 つだけ作成し、他のオブジェクトから共有してアクセスできるようにしたい場合に役立ちます。

シングルトンを作るには、インスタンスが 1 つだけ存在するようにオブジェクトの作成方法を制御し、コードがスレッドセーフであることを保証する必要があります。Kotlin では、object キーワードだけでこれを実現できます。

 /* Copyright 2020 Google LLC.

   SPDX-License-Identifier: Apache-2.0 */

   

- public class Singleton{

-    private static volatile Singleton INSTANCE;

-    private Singleton(){}

-    public static Singleton getInstance(){

-        if (INSTANCE == null) {                // Single Checked

-            synchronized (Singleton.class) {

-                if (INSTANCE == null) {        // Double checked

-                    INSTANCE = new Singleton();

-                }

-            }

-        }

-        return INSTANCE;

-    }

-    private int count = 0;

-    public int count(){ return count++; }

- }


+ object Singleton {

+     private var count = 0

+     fun count(): Int {

+         return count++

+     }+ }

演算子、文字列テンプレートなど

Kotlin 言語の簡潔さとシンプルさは、演算子オーバーロード、分割代入、文字列テンプレートなどの機能から明らかです。そのため、コードはとても読みやすくなります。

たとえば、本を集めたライブラリがあるとしましょう。ライブラリから本を取り出し、そのタイトルだけを出力する場合、コードは次のようになります。

/* Copyright 2020 Google LLC.

   SPDX-License-Identifier: Apache-2.0 */


fun borrow(){

    library -= book

    val (title, author) = book

    println("Borrowed $title")

} 


使われている Kotlin の機能は次のとおりです。


 

まとめ

Kotlin を使うと、コードは読みやすく、書きやすくなります。シングルトンや委譲などのパターンが言語に組み込まれており、たくさんのコードを書く必要がないため、バグが紛れ込む確率が低くなり、メンテナンスの負荷も軽減されます。また、文字列テンプレートラムダ式エクステンション関数演算子オーバーロードなどの機能で、コードをさらに簡潔かつシンプルにできます。書くコードが少なくなれば、読むコードやメンテナンスするコードも少なくなり、エラーが減って生産性が上がります。


詳しくは、Kotlin と Android Kotlin でより優れたアプリを作成するをお読みください。また、各社のケーススタディをご覧ください。デベロッパーにとっての Kotlin のメリットが確認できます。世界で特に好まれている開発言語の 1 つである Kotlin を使ってみたい方は、入門ページをご覧ください。

Reviewed by Yuichi Araki - Developer Relations Team and Hidenori Fujii - Google Play Developer Marketing APAC


ユーザーは皆さんのアプリにシームレスな体験を期待しています。アプリがクラッシュすれば、低評価のレビューやアンインストールが増え、ブランドにダメージを与えてしまうでしょう。その一方で、コミュニティの皆さんとの対話の中で、Kotlin を採用する主な理由の 1 つはコードの高い安全性であるということをよく耳にします。実際に何社かのパートナーは、Kotlin を使ってコードの安定性を改善しています。この投稿では、その方法をいくつか紹介するとともに、Google Play ストアの統計結果にも注目し、Kotlin とクラッシュ数との間に相関関係があるかどうかを確認してみたいと思います。

アプリの品質

アプリの品質が影響するのは、ユーザー エクスペリエンスだけではありません。クラッシュ多いと、他のいくつかの要素にも悪影響が生じます。


  • アプリの見つけやすさ — Google Play ストアのおすすめは、人間による選定とアルゴリズムによる計算の組み合わせで行われています。この計算においては、アプリの品質が特に重要な考慮事項となっています。

  • ブランド — プロダクトのパフォーマンスは評価やレビューに影響する可能性があり、それがブランドに影響する可能性があります。

  • (エンゲージメントの高い)ユーザーの多さ — 実質的なトラフィックとブランドの認知が上昇すれば、ユーザーの獲得と維持が促進される可能性が上がります。それにより、エンゲージメントや下位ファネルの指標にも影響が出る可能性があります。


Kotlin で構築したアプリはクラッシュする可能性が 20% 低い


Google Play のトップ 1,000 アプリを調査してみたところ、Kotlin を使っているアプリは、それ以外のアプリよりもユーザー 1 人あたりのクラッシュ発生率が 20% 低いことがわかりました。

その具体例として、コードの 74% が Kotlin である Swiggy のエンジニアリング チームは、新機能の開発を Kotlin に移行して以来、クラッシュを 50% 減らしました。こういった結果を Kotlin はどのように実現しているのか見ていきましょう。


NullPointerException を回避する

Google Play でのクラッシュの原因ナンバーワンは NullPointerException です。Google Home チームは、2018 年よりすべての新機能を Kotlin で書いています。その結果、1 年前と比べて null ポインタによるクラッシュが 33% 減少しました。


Google Home が NullPointerException を 33% 削減


NullPointerException を避けるには、メソッドを呼び出したりメンバーにアクセスしたりする前に、扱っているオブジェクトの参照が null でないことを確認しなければなりません。Kotlin では、null 可能性が型システムの一部として組み込まれています。たとえば、変数は最初から null 可能か null 不可能かを宣言する必要があります。null 可能性を型システムの一部として組み込むことで、コードベースについての自分の記憶や知識、またコンパイル時警告(フィールドやパラメータに @Nullable アノテーションを付けた場合)に頼る必要はなくなります。null 可能性を強制することで、単なる警告ではなく、コンパイル時にエラーが発生します。null 可能性を扱う方法については、こちらのページをご覧ください。


一般的な問題を回避する

私たちデベロッパーは、気づかないうちにアプリにたくさんの問題を紛れ込ませています。そのほとんどはあまりに軽微で、調査するのは難しいかもしれません。そのような問題のうち、Kotlin を使うことで回避できるものをいくつか紹介しましょう。


hashCode() と equals()

2 つのオブジェクトが等しい場合、それらのハッシュコードも同じである必要があります。しかし、どちらかのメソッドを実装し忘れたり、クラスに新しいプロパティを追加したときに更新し忘れてしまったりすることがよくあります。データを保持するためだけのクラスを扱う場合は、Kotlin のデータクラスを使うようにしましょう。データクラスを使うと、コンパイラが hashCode() と equals() を生成してくれるので、クラスのプロパティを変更すると自動的に更新されます。


構造等価性と参照等価性

2 つのオブジェクトは構造が等しい(中身が同じ)のでしょうか。それとも、参照が等しい(ポインタが同じ)のでしょうか。Java プログラミング言語では、プリミティブには常に == を使います。そのため、実際には構造が等しいかどうかを確認(equals() を呼び出してチェック)したいのに、オブジェクトにも ==(参照が等しい)を使ってしまうというのがよくある誤りです。まず、Kotlin にはプリミティブ型はなくInt や String などのクラスを使います。つまり、すべてがオブジェクトなので、オブジェクトとプリミティブ型の区別を気にする必要はありません。次に、Kotlin では == は構造が等しい、=== は参照が等しいと定義されています。したがって、誤って参照が等しいかどうかを確認してしまうことはありません。


else if else if else では十分でない場合にどうするか

enum を扱う場合、通常はすべての可能なケースを記述しなければなりません。そのため、switch や if else チェーンを使うことになります。enum を修正して新しい値を追加する場合、enum を使っている各コード スニペットを手動でチェックし、新しいケースに対応しているかどうかを確認する必要があります。しかし、これはエラーにつながりがちです。Kotlin では、when を式として使うと、この確認をコンパイラに任せることができます。すべての可能な分岐に対応していない場合、コンパイラ エラーが発生します。


まとめ

ユーザーやブランドにとって、アプリの安定性は重要です。Kotlin を使い始めてクラッシュ率を減らし、ユーザーの満足度を高めてアプリの高評価を守り、ユーザーの維持や獲得につなげましょう。

詳しくは、Kotlin でより優れたアプリを作成するためにできることをお読みください。また、ケーススタディをご覧いただき、Kotlin のメリットをご確認ください。世界でデベロッパーに広く使われている言語の 1 つである Kotlin を使ってみたい方は、入門ページをご覧ください。


Reviewed by Yuichi Araki - Developer Relations Team and Nori Fujii - Google Play Developer Marketing, APAC