visible true

技術的なメモを書く

「解剖 Kotlin ~バイトコードを読み解く~」をGitBookで公開しました。

テクブの夏コミ(C90)のアンドロイドアカデミアに書いた解剖 Kotlin ~バイトコードを読み解く~をGitBookにて公開しました。

GitBook

こちらから読めます

解剖 Kotlin ~バイトコードを読み解く~

概要

解剖 Kotlin ~バイトコードを読み解く~はKotlinで書いたプログラムを逆アセンブルすることで、Kotlinが提供している特徴的な機能がJavaでどのように表現されているかを読み解いていきます。Kotlinの特徴的な機能たちもJavaになってしまえばこっちのもの。なーんだKotlinもJavaなんだね。

目次

  • Introduction
  • KotlinとJava
  • 本書のアプローチ
  • 1. null許容型の正体
  • 2. 関数型とラムダ式の正体
  • 3. インライン関数の正体
  • 4. 拡張関数の正体
  • 5. プロパティの正体
  • 6. デリゲートプロパティの正体
  • 7. 末尾再帰最適化の正体
  • おわりに

Circle CIでAndroid SDK周りのライセンス許諾をローカル環境に合わせる

Circle CIの公式ドキュメントのTest Android Applications - CircleCIにある通りAndroid SDKをCircle CIでダウンロードするには次のようにcircle.ymlに記述する必要がある。

dependencies:
  pre:
    - echo y | android update sdk --no-ui --all --filter "package-name"

この記述の場合package-nameが可変なため、新しいSDKが出た時に変わることがありCIがコケる。 新しい名前をパッと調べる方法がよくわからないので大体はまる。つらい。

CI環境でAndroid SDKのダウンロードを自動化する2016 - Qiitaにローカル環境で行ったライセンス許諾のライセンスファイルを使う方法が書かれていて、最高だったのでCircle CIにも適用した。

ライセンスファイルの中身をコピーする

ライセンスファイルの中身はハッシュ値になっている。ファイルは次の場所にある。

$ANDROID_HOME/licenses/android-sdk-license

circle.ymlに設定

ライセンスファイルから取り出した値をcircle.ymlに設定する。 ディレクトリを作ってechoでライセンスファイルを作ればOK。

dependencies:
  pre:
    # 省略
    - mkdir $ANDROID_HOME/licenses
    - echo "ここにライセンスファイルの値" >> $ANDROID_HOME/licenses/android-sdk-license

これでローカル環境で許諾したものと同様のSDKを自動的にインストールできるようになる。

WEB+DB PRESS vol.94で特集「はじめてのKotlin」を書きました

2016年8月24日発売のWEB+DB PRESS vol.94(¥1,598)で特集「はじめてのKotlin」を書きました。

特集「はじめてのKotlin」について

「はじめてのKotlin」の目次は技術評論社WEB+DB PRESS Vol.94のページで見られます。以下に抜粋しつつ補足の解説をします。

  • 第1章:Kotlinとは何か
    • Kotlinの概要と特徴、近年のAndroidの開発言語を取り巻く環境に言及し、なぜAndroidの開発言語として注目されているのかについて、具体的な理由を解説します。Jack and Jillを含めたJava8環境とKotlinのどちらを選択するべきかについても言及しています。
  • 第2章:Try Kotlinで基本文法を学ぼう
    • null許容型,スマートキャスト,制御構文,クラスなどKotlinを使う上で必要な基礎を解説します。最低限の知識は身につくはずです。
  • 第3章:ラムダ式と関数を使いこなそう
  • 第4章:Android開発に導入しよう
    • KotlinをAndroidプロジェクトへ導入する方法と,つまずきやすいポイントの解説とその解決方法を説明します。
  • 第5章:Kotlinを活用しよう
    • 拡張関数を使ったAndroid APIの改善や、スコープ関数の解説、kaptの使い方、Kotlin Bytecodeによるコンパイル結果の確認などについて解説します。
  • 第6章:Kotlinの将来
    • 公式採用の可能性について言及しています。またKoltin 1.1で追加される予定の機能などについて解説します。

全体的にAndroidエンジニアを対象として書いていますが、2章、3章はKotlinにだけ言及するので、Androidエンジニアでない方にも価値がある内容になっているのではないかと思います。

執筆の感想

4月か5月頃に技術評論社 編集長の稲尾さんに声をかけていただき、一度ランチしながらKotlin特集のプランニングをして、その後Goが出て書き始めたといった感じでした。ランチの時に「バリバリ書いて前倒しっすよ〜」とか言っていたんですが案の定ギリギリとなってしまいました。ちょうど仕事の方も修羅場になっていて全体的に修羅場でした。

稲尾さんは流石に何人もの技術者を相手してきているだけあって、サクーッと進める所は進め、シュッと用意するところは用意し、バシバシッと尻を叩く所は叩くというメリハリある編集の進行で、執筆者として大変安心して取り組めました。原稿はGithub上で管理していて、稲尾さんもissueをバンバン立てたりPRをバンバン出すのでめっちゃやりやすいです。

原稿書いてる時はマジで「ああなんでやるって言ってしまったんだろう?」と辛い思いになる事が沢山あるんですが、終わってみると「あれとかこれとかも書きたいな」とか思っちゃうので危険ドラッグでは〜?って気がします。技術書典夏コミ(C90)の原稿も重なって「死ぬのかな...?」って思いました。

最後に

特集のページ数が31Pなのでかなり盛々で濃い内容になってると思います。一方で言語の解説としては網羅性は足らないので、特集を読んでKotlinを気に入った方はぜひKotlinスタートブックも読んでください。

また、夏コミ(C90)で頒布したアンドロイドアカデミアに、Kotlinのnull許容型やラムダ式、関数型、インライン関数、拡張関数などがJavaバイトコード上ではどのように表現されているのかを読み解く「解剖 Kotlin ~バイトコードを読み解く~」という章を書いたので、こちらも合わせてぜひお読みください。

Kotlin学習の知見のかたまり「Kotlinスタートブック」はサイコーのKotlin入門本です

Kotlinスタートブックを献本頂いたので感想を書きます。

Kotlinスタートブック-新しいAndroidプログラミング

概要

KotlinスタートブックはJavaエンジニアおよびAndroidアプリケーションエンジニア向けにKotlinの基本を解説する本です。Kotlinの文法や機能を広範囲にわたって身に付けられます。また後半にはAndroidアプリケーションへKotlinを適用する例を解説する章があり、Androidアプリケーションにどのように導入するかイメージをつかむことができるでしょう。

こんな人におすすめ

  • Kotlinを効率的に学習したいひと
  • Android Javaに疲れたひと
  • Android Javaはやりたくないひと
  • AndroidはまぁJava 8でいいじゃん、と確認したいひと

解説

Kotlinについて「聞いたことがある」とか「ちょっと触ったことがある」とかいった人にとても良い入門本だと思います。また1.0未満のときに触って捨てた人にも良いです。

Kotlin学習の知見のかたまり

Kotlinのドキュメントや情報はそれなりに充実してきているものの、どこから手をつけるか、どのように活用するかについてはKotlinを触る人それぞれに依存していました。 Kotlinスタートブックは日本Kotlinユーザグループ代表の@ngsw_taroさん(黙認エバンジェリスト)が、Kotlinに出会ってから現在に至るまでの約3年間のあいだに学んだ事をしっかりと消化したうえで、これからKotlinを学ぶ人へ向けて適切な学習の順序付けを行った本です。3,780円でKotlinを学習するために必要な時間を大幅に節約できるのでたいへんお得です。

Androidに適用するアイデアがたくさん

Androidは開発に占める言語の割合が小さいので、Kotlinに対しては腰が重い人が多いのではないかと思います。 KotlinスタートブックにはKotlinの基本を学んだあとAndroidアプリケーションをひとつ作る章があります。 アプリケーション自体はシンプルであるものの、そこかしこにKotlinのフレーバーが散りばめられており、Kotlinを学んだあとに読めばきっと「なるほどこういう風に使えばいいのか最高だな」と思うに違いありません。 さらにそこから「では、こういったことは出来るのだろうか?」という問いが立ち上がり、芋づる式にさまざまなAndroidにまつわる課題の解法を思い描いていけるのではないかと思います。

感想

個人的には「本を書く時あるある」を感じながら楽しんで読めました。「あ〜ここ、こういう風に書き出したくなるよなー」「ここは指摘があって色々見直した跡があるな」「説明めんどくさすぎてこれ省略したな」「ここはめちゃくちゃ攻めたな」とかいった箇所がたくさんあって面白いと共に胃がキュッとなりました。

Kotlinを実際にAndroidアプリケーション開発に導入する気がなくても、新しい言語を学ぶという側面で読む価値があると思うのでぜひ皆さんお手にとってお召し上がりください。

KotlinのDestructuring Declarationsを非構造化宣言呼ぶことにした けど色々あって分解宣言にした〜

分割代入とか分解宣言とか呼んだりするケースを見かけるけどどうもしっくりこないので非構造化宣言と呼ぶことにした。

  • Destructuring = 非構造化
  • Declarations = 宣言

じっさいデータ構造を複数の変数へ非構造化してるしー。まぁそれなら分解でもいいじゃんて気もするけどDestructuringは分解じゃないっぽいしー

val (id, name) = Pair(1, "mike")

まーそんなにこだわりはないけどー。

2016/6/6 追記

こういう感じがいいのではというアドバイスを元に「分解宣言」と呼ぶことにする事にしました。ありがとうございます。

中略

AndroidでJava8環境 2016

RxAndroidとRetrolambdaで大体Java8をAndroidに持ち込む - visible trueから1年以上経過して界隈も色々更新されていってます。ということでイマドキのJava8環境構築をメモします。

バックポートライブラリとJava8の機能

バックポートライブラリとそのライブラリがカバーするJava8の機能を列挙します

実現不可の機能

次の機能はバックポートライブラリ等では実現不可能です*1

  • interfaceのデフォルト実装
  • interfaceのstaticメソッド

build.gradle

次の設定はRetrolambdaを使っています。そのまんまコピペでは使えないと思うので適切な場所にコピーしてください。

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
      classpath 'me.tatarka:gradle-retrolambda:3.2.5'
    }
}


apply plugin: 'me.tatarka.retrolambda'

dependencies {
  compile 'com.annimon:stream:1.0.9'
  compile 'com.jakewharton.threetenabp:threetenabp:1.0.3'
}

まとめ

結構イケるねJava8。

*1:一応minSdkVersionを24にすればいけます

Kotlin Tips: Reified Type Parametersで型チェックを汎用化する

問題

Kotlin Tips : Intentに必要な値が入っていない場合例外をスローしたい - visible trueではgetLongOrThrow()をIntentに追加しlazyを使う事で可読性を高めた。

Intent.getIntOrThrow(key: String)のおさらい

fun Intent.getIntOrThrow(key: String): Int =
  this.extras.get(key).let {
    if (it !is Int) {
      throw IllegalArgumentException("Extras don't have Int value specified by key $key")
    }
    return it
  }

さて、ではStringならどうか。当然次のようなコードを追加すれば実現できる。

fun Intent.getStringOrThrow(key: String): String =
  this.extras.get(key).let {
    if (it !is String) {
      throw IllegalArgumentException("Extras don't have String value specified by key $key")
    }
    return it
  }

getIntOrThrow(key: String)とほとんど同じ実装で戻り値と型チェック部分だけが異なる。今回は以下の点にフォーカスする。

  • IntentのgetExtraの型の種類は28個ある。28回実装するのはつらい
  • getStringOrThrowなど機能的な命名を出来るだけ意図を表す命名にしたい

改善策

Reified Type Parametersを使う。Reified Type Parametersは具象化された型パラメータを利用できる機能。これによりロジック中の型チェックをTを使って行える(つまりあたかも型消去が起こらなかったかのように扱える。T::class.javaClassとかもできるよ)。

inline fun <reified T> Intent.getRequired(key: String): T {
  extras?.get(key).let {
    if (it !is T) {
        throw IllegalArgumentException("Extras don't have a value specified by key $key")
    }
    return it
  }
}

さらに利用時には型推論によって以下のように書ける。

val value:String = intent.getRequired(key)

ただしlazyを使う時は型の明示が必要となる。といっても型情報は1度しか出てこないので冗長になることはない。

val value by lazy<String> { intent.getRequired(key) }
// or
val value by lazy { intent.getRequired<String>(key) }

やったね

  • Reified Type Parametersによって複数種類の型の取り出しを汎用化できた
  • 型推論のために型はどこかに必ず宣言されるのでメソッド名に型名を含めなくてよくなった
  • Intent.getRequired(key:String)という名前によって意図が明快になった

ついでに

Intent.getOptional()も実装しておく。

inline fun <reified T> Intent.getOptional(name: String, default: T): T {
  extras?.get(name).let {
    if (it == null) {
        return default
    } else {
        return it as T
    }
  }
}

さらなる議論

Reified Type Parametersはinlineだからこそ実現できる機能である。そのためインライン展開のデメリットについては考慮したほうがよさそうだ。といってもバイトコードが膨らむくらいしか思いつかない...。