Professional Documents
Culture Documents
Kotlin
おおたに
@liris
まえおき
●言語自体に特にこだわりはないです
●Kotlinはそれほどとんがった言語ではないです
●将来的にはJava自体がKotlinに似てくるんじゃないですかね?
結論
サーバサイドでも
問題なく
Kotlinは使えます
今日しゃべること
●なぜ、Kotlinにしたのか?
●サーバサイドでのミドルウェアとか
●実際にKotlinで開発してみて
自己紹介
おおたに・2001
アリエルネットワークの創業メンバーになったお。
自己紹介
おおたに・2013
パーフェクトPythonを少しだけ書いたお
おおたに・2001
アリエルネットワークの創業メンバーになったお。
自己紹介
● 仕事の開発言語
おおたに・2017 ○ Java → Kotlin
(株)ビズリーチに入社したお
新製品を開発してるお
おおたに・2001
おおたに・2013
アリエルネットワークの創業メンバーになったお。
パーフェクトPythonを少しだけ書いたお
おおたに・2001
アリエルネットワークの創業メンバーになったお。
作っているもの
まだ、リリースしていないので
秘密です
サーバのインフラ構成
App Server
(BeansTalk) PostgreSQL
Kotlin
AWS SNS
Cognito
認証
cron
(Cloud Watch)
schedule manager
(Lambda) Kotlin
● Webアプリケーションサーバ
● Lambdaの処理
➔ サーバ側でコードを書くところは全てKotlin
➔ クライアント側はKotlinはまだ使っていない
なぜ、Kotlinを採用したか?
Javaの言語について
● 1996年 JDK1.0から20年以上
○ 記述が冗長である
■ 関数を書く時、常にclassの中に入れないといけない。
■ 関数ポインタがない
■ getter/setterはめんどくさい
○ 検査例外は本当に効率的なのか?
■ streamと相性が悪くない?
○ ヌルポからは解放されるのだろうか?
➔ Java7ぐらいまでは書いていて楽しくない!!!
classの中にメッソドを書くのはめんどい
public class StaticClass {
static LocalDate today() {
return LocalDate.now();
}
}
‣ パッケージが名前空間を定義しているので、わざわざclassで囲まなくても
いいよね。
‣ Kotlinならこれだけ
‣ IDEが自動生成してくれるけど、めんどい
検査例外、しんどい
public void doSomething() throws OtherException {
try {
// do something
} catch (SomeException e) {
throw new OtherException(e);
}
}
‣ 例外は結局はフレームワークなり、呼び出し元で処理され
るだけ
‣ Kotlinなら検査例外がない
LombokはJavaでの開発をどう変えたか
● Javaの冗長性からある程度解放
○ Getter/Setterの自動生成
○ val/var による型推論 (純粋なJavaにもそのうちくるよね)
○ Builderパターンなどの自動生成
lombokでなら
@AllArgConstructor
public class LombokSample {
@Getter
@Setter
private String s1 = "";
}
‣ かなりスッキリ。
‣ でも、まだ、余分な装飾がある
‣ Kotlinならより簡潔に
class Test(val s1: String="")
LombokはJavaでの開発をどう変えたか
➔ Javaでもある程度はハッピーになれたかも
◆ 関数がファーストクラスオブジェクトになれない
◆ 関数がオブジェクトではない
◆ 荒ぶるlombok
● なぜかコンパイルが通らないことがあった
● eclipseがいうことを聞いてくれないことがあった
不満はあってもJVM自体は悪くない
● API / バイトコードの互換性の安心感
○ 例: pythonの2 -> 3の互換性問題は悲しい
● Javaの豊富なライブラリ・ミドルウェア
● ビルド環境やディプロイなどの周辺環境
➔ JVM言語で、Better Javaを探している
JVM言語
● Jython
● JRuby
● Scala
● Kotlin
● Clojure
● Rhino
● …
➔ JVM言語はたくさんあるけど、ほしいものはBetter Java
Better Javaとは
● 僕の不満を解消してくれてJavaからの学習コストが低いこと
○ 関数・メソッドがオブジェクトである
○ val/varがあること
○ null安全性
○ lombokのように荒ぶらない
○ 一つのファイルの中に複数のクラスを定義できる
○ いい意味でJavaっぽさも出せる
これまでの社内でのJVM言語の利用
Javaがメイン
Scalaがいくつかのプロダクトで利用
Scalaは悪くない、でも、難しい…
● Python使いなので、implicitは好きになれない
● 言語が複雑
○ Better JavaとしてJavaっぽくはできる
○ それは、プログラマの規約で言語が強制できない
○ 学習が容易ではない
● 型合わせゲームが好きになれない
➔ 僕が言語をちゃんと理解した気分になれない
そこでKotlinですよ
● 言語自体はJavaとScalaの中間の子(私見)
○ Scalaプログラマなら数時間で学習できる
○ 普通のJavaプログラマでも一週間ぐらいで学習できる
● Javaでの不満をある程度解消
● Scalaほど複雑ではない
Kotlin
● 2011年JetBrain社からKotlin登場
● 2016年2月バージョン1がリリース
● 2017年GoogleがAndroidの開発言語に正式に採用
○ 言語自体の良さとは別にAndroidの正式採用が選択の理由
○ 開発者の母集団が増える = 教育コストの低減
○ 言語自体の安定性の担保
Kotlinの特徴とか文法とか
✤Javaとの相互運用性
✤nullに対する安全性
✤冗長性の排除
✤あとは、ググってください
開発環境・フレームワーク・ライブラリ
とか
開発環境(IDE)
● Eclipse
○ 僕は2005年ぐらいからEclipseユーザ
○ 時々、壊れる
○ デバッグでシームレスにJavaの世界と行き来できる
Webフレームワーク
● Kotlin製
○ Ktor → JetBrain社製。
■ 個人での開発ならOK
■ チームでの開発は未知数
○ wasabi → Ktorに取り込まれた
○ Kara → JetBrainの人が開発。でも開発は続いているの?
● Java製
○ JavaEE (Jerseyなど)
○ Spring Boot
■ Javaのフレームワークは実績や開発体制など安定感があって◎
OR Mapper
● Kotlin製
○ Exposed → JetBrain製
○ Kwery → 個人で開発
○ kotoliquery → 個人で開発
● Java製
○ Hibernateなど色々
➔ Exposedを使ってみた
Exposedを使ってみた結果
● spring-transactionで@transactionalアノテーションが使える
● kotlinっぽく書ける
● バグが多い
○ データベースに書き込む時のスケジューラに問題
● ドキュメントが不十分
○ ソース読め
● 機能不足
○ Array型がないなど
➔ 割といばらの道なので、Java製のORMを使った方がいい
ビルド環境など
● maven
● gradle + Kotlin plugin
○ 既存のJavaのエコシステムに乗ります
○ + AllOpen plugin
■ SpringはDIの時に既存のクラスを自動で継承して拡張する
■ kotlinのクラスはデフォルトでfinal
■ pluginでkotlinのクラスをopen(継承可能)にする
ここまでのまとめ
● フレームワークやライブラリはサーバサイドで利用するには未成熟か開発体
制が不十分
● 無理をせずにJavaのエコシステムにのって広く利用されているものを利用す
るのがよい
● 人柱になりたい人は、ぜひKotlin製のものを使うか、作ってください
Kotlinを実際に使ってみて
Kotlinのstream的なもの
● KotlinにはJava 8のStream APIのようなメソッドがiterbleに定義
○ mapやfilterなど名前や機能が似ている = かなり混乱する
○ kotlinのiterableのmapやfilterでは戻り値がList型になる
■ 常にListが生成されている。
■ mapやフィルタのたびに、iterableの要素数だけループが回る
● それじゃ、StreamとKotlinのmapなど速度差はどれくれい?
ベンチマークのテスト
Stream Kotlin
list.stream() list
.map { it + 1 } .map { it + 1 }
.map { it - 1 } .map { it - 1 }
.map { it + 1 } .map { it + 1 }
.map { it - 1} .map { it - 1}
.map { it + 1 } .map { it + 1 }
.map { it + 1 } .map { it + 1 }
.map { it - 1 } .map { it - 1 }
.map { it + 1 } .map { it + 1 }
.map { it - 1} .map { it - 1}
.map { it + 1 } .map { it + 1 }
.collect(Collectors.toList())
listは0から10,000,000のIntの配列
ベンチマークの結果
← 縦軸はmsec
● チェーンをたくさん繋げるとやっぱり
kotlinは遅くなる
● 少なければ誤差の範囲内
● kotlinはstream()とtoList()は書かなくても
よいので、少し楽
● 速度を求めるならstream()
● コレクションの大きさとチェーンの数に
よって使い分けるべき
KotlinのItearable.map/filterなどは遅いが…
● Iterableではなく、Sequenceとして扱うこ list.asSequence()
.map { it + 1 }
とでJavaのStreamと同等の速度になる
.map { it - 1 }
.map { it + 1 }
○ Sequenceにすることで、mapのたびにい
.map { it - 1}
リストを作らずに、ループの回数がリスト
.map { it + 1 }
のサイズと同等になる。 .map { it + 1 }
.map { it - 1 }
.map { it + 1 }
.map { it - 1}
.map { it + 1 }
.toList()
annotationの違い
● scalaも基本は同じ
● コンストラクタ、メンバー変数のval/varはフィールド定義・getter/setterにな
る
● アノテーションをつける時にどこに対してアノテーションをつけるか明示し
ないといけない
アノテーションの例
class Example(@field:Hoge val foo, // field
@get:Hoge val bar, // getter
@param:Hoge val buzz) // パラメータ
ケースによっては
のように同じアノテーションを複数つけなければならない
letの使いすぎ
● if文でnull判定するのを悪だと感じてしまう
● 複数の変数を?.let (JavaのOptional.ifPresent的なもの)で判定して入れ子にす
る
こんな感じ
return someBar?.let { bar1 -> return if (someBar != null && otherBar != null) {
} ?: 0 0
} ?: 0 }
if文を使っても負けじゃない!
デフォルト引数とDI
● DIはKotlinで書いたクラスのオブジェクトを自動生成する
● コンストラクタにデフォルト引数を設定すると、自動生成できない
○ Javaの世界からKotlinのデフォルト引数が扱えない
● @JvmOverloadsをつけてあげる
不満なところ
●ElixerのPipelineのようなものが欲しい
●()は省略したい
●Javaのクラスにstaticなメソッドも生やしたい
●lombokのようにbuilderパターンを簡単に実装したい
結論
サーバサイドでも
問題なく
Kotlinは使えます
おしまい