B-Teck!

お仕事からゲームまで幅広く

【映画】シュガー・ラッシュ・オンラインを見た

この記事は下記キャンペーンに参加し、シュガー・ラッシュ・オンラインの感想を書いています。
内容のネタバレを含みますので、視聴後の閲覧を推奨します。

映画「シュガー・ラッシュ:オンライン」の感想 #シュガラお題 blog.hatena.ne.jp

続きを読む

【Kotlin】Sequenceを使おう

Sequenceとは?

Kotlinにおけるコレクション遅延操作の仕組み。
Java8で導入されたStreamに似ており、各要素を直列に評価したあと、最終的な結果を取得する。
こう書くと難しそうなので、実際のコードを見てもらったほうが早いと思います。

Sequenceを使うと何が嬉しいか

ループ回数が少なくなる

Sequenceを使わない場合

(1..3).map { it * 10 }
      .map { it * 10 }
      .map { it * 10 }

このような処理の場合、通常のCollectionのまま操作を行うと、map毎にループが発生し、Listを生成します。
実際に行われている処理は下記のような感じで、ループ回数は9回、Listは4つ生成されているのがわかりますね。

val list = mutableListOf(1, 2, 3)  
val list2 = list.map { it * 10 }  
val list3 = list2.map { it * 10 }  
val list4 = list3.map { it * 10 }  

Sequenceを使った場合

Sequenceを使った場合は、このように書きます。

(1..3).asSequence()
      .map { it * 10 }
      .map { it * 10 }
      .map { it * 10 }
      .toList()

見た目はほぼ変わらないのですが、実際に行われる処理は全く異なります。

val list = mutableListOf(1, 2, 3)  
val list2 = list.map {  
  val result1 = it * 10  
  val result2 = result1 * 10  
  result2 * 10  
}  
println(list2)  

生成されるListは2つ、ループ回数は3回と、大幅に計算量が減っています。

不要な計算をスキップできる

ループ回数よりもこちらのほうが、計算量に大きな差が出ます。

Sequenceを使わない場合

(1..3).map { it * 10 }
      .map { it * 10 }
      .map { it * 10 }
      .first{ it == 2000 }

このような処理の場合、first() の手前まですべての要素を処理してから結果を生成します。
実際に行われている処理は下記のような感じで、先述した計算に加えて、
first()で2000に行き当たるまでの2回計算回数が増えています。
また、Listも一つ多く生成されて5個になっていますね。

val list = mutableListOf(1, 2, 3)  
val list2 = list.map { it * 10 }  
val list3 = list2.map { it * 10 }  
val list4 = list3.map { it * 10 }  
val list5 = list4.first{ it == 2000 }  

Sequenceを使った場合

Sequenceを使った場合は、このように書きます。

(1..3).asSequence()
      .map { it * 10 }
      .map { it * 10 }
      .map { it * 10 }
      .first{ it == 2000 }

こちらも見た目はほぼ変わらないのですが、実際に行われる処理は全く異なります。

val list = mutableListOf(1, 2, 3)  
val list2 = list.first {  
  val result1 = it * 10  
  val result2 = result1 * 10  
  val result3 = result2 * 10  
  result3 == 2000  
}  
println(list2)  

生成されるListが2つなのは前回と同じですが、この場合なんとループ回数が2回で終わります。
要素をひとつずつ処理するので、 first()take() などのように、
全ての要素を処理する必要がないケースで絶大な効果を発揮するのです。

まとめ

  • Kotlinで、Collectionに対して複数の処理を行う場合は asSequence()Sequence として扱うと良いよ
  • 全ての要素を処理する必要がないケースではほぼ必須レベルだよ

参考

【Kotlin】Server Side Kotlin やってみた

tl;dr

  • Server Side Kotlinは特に特殊なことはないよ
  • Kotlinの言語仕様は便利だよ
  • Null安全の機構を導入することでアプリ側とのすり合わせがしやすくなるよ
  • Kotlinかわいい

はじめに

Kotlinってかわいいですよね。
サーバーサイド開発者の皆さん、Android開発者がうれしそうにKotlinの話をしているときに、
嫉妬したことはありませんか? 私はあります

今年1月に転職してから、色々と新しい事をやらせてもらえる環境になったので、
思いつきでKotlin入れませんか?と言ってみたところ上長から快諾され、導入できました。
そんなこんなで2018年後半はずっとSever Side Kotlinを書いていた感じでした。

なぜKotlinを導入したのか?

Android界隈でさんざん語られ尽くしている話題なので今更感もあるのですが、一応。
Kotlin導入以前のシステムは、主にJava8+Lombokでできていました。
なので、実は環境的に不満はあまりなかったんですね。
でも、Lombokのアノテーションとか毎回書くのめんどくさいじゃないですか、とか。
あとは込み入った処理になるとどうしても記述が多くなって読みづらくなってしまう、
Javaを使っている故の制約を感じるとか。
そういう細かい部分で気になることが多くて解決策を探していたところ、
Better Java(この言葉最近良く見ますね)としてKotlinを挙げる記事を多く見かけました。
特に気になったのはこの辺の仕様です。

  • mutable、immutableな値の宣言の簡潔さ
    • 型レベルでわかれてるのも良い。(List <-> MutableListとか)
  • data classの簡潔さ
    • そもそもclassでもgetter setterがいらない部分とか
  • Javaとの相互運用性(特に気にせずライブラリを呼び出せる)

タイミング的にも、エムスリーさんが導入事例を広く公開しだした時期だったため、
話題性で上司にプッシュしやすかったという理由もあります。
エムスリーで「サーバサイドKotlin」を導入したチームに話を聞きました - エムスリーテックブログ

実際にKotlinを導入してみた

元々Java + Jersey2で稼働しているシステムがあったので、
イチから作り直すという選択肢はありませんでした。
折よく新規API開発の案件が降ってきたので、ものは試しと新規API部分のみKotlinで書くことに決定。

私は下記の連載を読みながらとりあえず書いてみるという形で進めました。おすすめです。
一週間程度書いていれば手に馴染んでしまうのではないでしょうか。
毎日Kotlin | シリーズ | DevelopersIO

mavenの記述にKotlinへの依存を追加しそのままktファイルを作成してみたところ、
いくつか困る部分はあったものの割とすんなり導入に成功。
懸念していたJavaとの接続部分も特に問題なし。優秀です。

困った部分で一番大きかったのが下記記事に書いた件です。
アノテーションの対象を明示的に書いてやらないとうまく作用しないというのがわからず、
無限に時を溶かしました。
【Kotlin】KotlinでJava EEのBean Validationを使うときの注意点 - B-Teck!

もう一個かなり困ったのが、EclipseだとKotlinのplugin入れてもかなり厳しいということです。
Kotlin導入するなら素直にIntelliJ IDEA買いましょう。。。

導入成功に気を良くして、もりもりKotlinを増やしていたら新しいプロジェクトが始まったので、
実績を盾に開始時から基本的にすべてKotlinで書いています。
どうしてもKotlinに書き換えるとうまく動作せずJavaで書いた箇所はありますが、
概ね95%程はKotlinで書かれています。
最近では流行に乗ってCoroutinesも入れてみたりしました。

Server Side Kotlin導入のPros/Cons

Pros

  • 書きやすい!記述が少ない!
    単純に少ない記述で書ける事は正義です。
  • data classが神!
    サーバーサイドではアプリへの返却値作成のため、値を保持するクラスを大量に使います。
    用途にマッチしたdata classは本当にありがたいです。
  • アプリとNullableな値について認識を共有しやすい
    これまでは認識を合わせた上で返却値を実装で縛るしかなかったのですが、
    実装の時点でNullableの値を決められるので、認識の共有や実装がシンプルかつスムーズ
  • アプリ開発者が触りやすい
    Kotlinは、Android開発者はもちろん、Swiftにも記法が似ているため、
    アプリ開発者も比較的馴染みやすいようです。
    実際、プロジェクト内でもiOS開発者がサーバーサイドの実装を行い、
    2〜3時間程度のペアプロ・レクチャーで簡単なAPIを作成しました。

Cons

  • サーバーサイドKotlinの日本語の知見がだいぶ少なかった
    前述したBeanValidationの情報は最初全然見つからなくて、
    下記の記事を見つけたときは本当に嬉しかったです。
    jpa - kotlin data class + bean validation jsr 303 - Stack Overflow
    今はだいぶ増えたので、困ることは少ないかもしれないです。
  • 公開されている知見がアプリばかり
    当然といえば当然なんですが、Kotlinに関する知見がほぼアプリのものなので、
    そのまま適用できるのかどうかがわからず難しかったです。
  • KotlinのコミュニティはAndroidと密結合で、参加しづらかった
    知見の話にも共通するのですが、Androidに関係なくKotlinの話ができる場所、
    コミュニティが少なく感じました。
    Server Side Kotlinが広まるにつれて増えてほしいなと思っています。
  • 解決できないときに、原因の切り分けが難しかった
    Server Side Kotlin特有の問題か、そうでないのかの切り分けが難しかったです。
    これも今は事例が増えたので困らないかもしれないですね。
  • IDEA使わないで書くのが地獄
    Kotlinを書くならIntelliJ IDEA一択なのが辛いです。
    Eclipseを使っている人に勧めづらく、プロジェクトで利用するなら全員で移行する必要があります。
    IDEとしては優秀なのでとても好きですが。。。

まとめ

既存Javaプロジェクトへの部分的な導入も簡単!
既存ライブラリとの相互運用性もバッチリ!
簡潔でモダンな記述でイケイケエンジニアになれる!
事例が増えてきて、情報少ない問題も解決しつつある!
Server Side Kotlinは怖くない!みんなもやろう!!