CORDEA blog

Android applications engineer

YAPC::Fukuoka 2017 HAKATA 前夜祭で LT してきました

最近 GitHub から緑が消え始めてて危機感しか感じません。

それはさておき、
YAPC::Fukuoka 2017 HAKATA に参加して来たのでその感想を書きます。

前夜祭

Possibility of terminal」 という題で Terminal (というか prompt) の可能性について話してきました。

speakerdeck.com

この手の話がどう受け止められるか (というか受けるのか) 分からなかったので結構心配なところはありましたが、
笑っていただけた部分もあったようで良かったです。

反省点は色々あるので、それは次の機会に改善します。

ちなみに普通に Terminal に表示するとこんな感じでした。

f:id:CORDEA:20170704091341p:plain

初参加だったので知り合いもいないし、Perl も知らないし福岡に住んでないし、なんで参加したのかよく分からない人間筆頭でしたが
発表したことである程度「なんか見たことある」人になっていたようで助かりました。

当日

会場がすごかった...

いくつか印象に残った Talk について。

ウェブセキュリティの最近の話題早分かり

脆弱性の紹介とデモの手際が良くて非常に面白かったです。
これだけでも福岡に行った甲斐あったなぁという感じでした。

はてなブログ最近の開発テクニックと最新の開発風景のご紹介

色々と感銘を受ける部分は多かったですが、
デザイナーとの開発のくだりがかなり良かったです。
デザイナーがデザイン周りのレイアウトとか組めたら良いよねって言うのは簡単なんですけど、
そこから先導入して行くのってとても体力が要るので、
言うだけで終わってたらダメだよなぁと感じた Talk でした。

あとコードレビューが遅い PR に未経験歓迎がつくの、なかなか良いですね。使っていきたい

The plan of Aniki 2.0

ORM にありがちな問題、よく分からないクエリ発行あたりはあるなぁ...って感想でした。
それに対する解決策としての Aniki 1.0 の特徴もなかなか良さそうに感じました。
Phantom Row Object, 面白そうですね。

終わりに

懇親会で YAPC 限定の Pawoo モバイルバッテリーいただきました。
ありがとうございました!

それと前夜祭含め、スタッフの皆さま、話していただいた皆さまありがとうございました。
とても楽しかったです!

来年までに Perl 力を高めておきたいと思います。

umeda.apk #3 に参加してきました

umeda.apk #3 に参加してきたので、その感想です。

shibuya-apk.connpass.com

Best Practices to Slim Down Your App Size

前々から少し話題になっていたので知ってはいましたが、
やはり Cancellation Rates vs. Download Size と、
Uninstall Rates vs. Installed Size のグラフは結構印象的でした。

自分自身もストレージに余裕なくなると使ってないものでサイズがでかいものから消すので
まぁそりゃそうだよねって話ではありますが...

あと APK Analyzer 便利ですね。

ユーザーが敏感な割に作ってる側が鈍感なことが多いので、
ここら辺は APK Analyzer とか使いつつエンジニアから提案した方が良さそうです。

Speeding up your Android Gradle builds

Multi-module project はあまりやったことが無かったものの、
api と implementation の違いはなるほど、という感じでした。

Slow builds are not normal というフレーズは、言われてみればまぁそうだよね...という感じ。
2 年前くらいに「ビルド遅くない?」って言ってたのを思い出しました。

ただ 10 分かかるビルドは見たことがない...

info はよく使うものの、profile と dry-run は見たことが無かったので
これは使っていきたいです。

Actions On Google

Google Assistant の設計の話が印象的でした。

本や映画の脚本を書くように、ユーザーとの会話を掘り下げていきながら設計するあたり、
今までの設計とは全く異なるものを要求されそうで面白いですね。
これはマネージャーやデザイナーも知っておくべきだと感じました。

Api.ai は一回プロジェクト作成して放置してしまっているので、
近々試してみようかなと思います。

あと、アプリ探してもらう / 探すのがちょっと難しそうだなという印象を受けました。

Kotlin in Google I/O 2017

今何かと話題の Kotlin の話。

CyberAgent さんの FRESH! で Kotlin が採用されていて、
Kotlin M11 の時期で本格的に開発が行われているというのはやっぱり驚きでした。

自分の GitLab の記録を見る限り、
一番初めに Kotlin のアプリが commit されているのが今から一年半くらい前、
なので自分がちゃんと書き始めたくらいにサービスロンチくらいの勢いでした。

Kotlin を採用するにしろ、Java の知識が必要というのはとても大事なことだと思います。
開発していても絶対に必要になるし、Kotlin から入るにしても Java の勉強は必要。
個人的には、「なんとなく Java が苦手 / 嫌いだから」で入るのは辛いと思っています。
そういう人少ないかもしれませんが。

Swift とは似て非なる言語で共通化できないというのも納得できる話でした。
「Swift を使っている iOS エンジニアが Android に入る際、Kotlin から入ると心理的に少しやりやすいかも」
くらいだと思っています。大分前にそんな感じの話を社内でしましたが、その時の他のエンジニアからの評価もそんなものだったかと。
いま Swift を使ってアプリ開発をしている iOS エンジニアが興味を持つきっかけにはなり得ると思います。

Kotlin の自由度が高いという話は実務で確かに問題になりそうな話でした。
ルールを決める際は是非 Kotlin っぽいものを選んでいきたいですね。

あと Kotlin 学習の例を見て、
社内で広めるならやっぱりこれくらいしないとなぁ...と感じました。
Rust でも Go でも Kotlin でも、「やってみたい」止まりな人は多いので、
そのあたりを巻き込んで盛り上げていけたらと思います。

LT

ここからは飲みながら話しながら聞いていたのでちょっとうろ覚えで書きます。

Cool Tips for Firebase

スピード感がよくてとても面白かったです。
Remote Config で Locale によってアプリの色変えるみたいな話がちょっとあって、
そういうのやりたいなーと思いました。

Layout ファイルのメンテナンスについて

Layout xml の行数をいかに削減するかという話。

前半はなるほどなーと思って聞いていたものの、
後半は、そこまでする...?という感じでかなり盛り上がっていました。

What's new Android Wear

Android Wear の動向の話。
Android Wear 2.0 の話とか...スタンドアロンアプリの話とかされていた記憶があります...

Android Wear つけてる人ー!みたいな質問で全然手をあげてなかったのは正直笑いました。
持ってなくてすみません...

actions on google

LT ではあるものの、前段の発表よりももう少し踏み込んだ話でした。
前段の話を聞いてからだったので、知らない人にも伝わりやすくなっていたように思います。

懇親会で少しお話させてもらったところ、
実際の Api.ai の画面を見せてもらいつつ説明していただけたので、
とても参考になりました。

懇親会 (歓談)

自分が話した人がたまたまそういう人ばかりだったのかもしれませんが、
Java / Kotlin で、普段業務でアプリ書いてますって人があまりいなくて、
サーバーサイドのエンジニアだったり、Unity のエンジニアだったりしたのが印象的でした。

懇親会でも Kotlin の話がよく出ていて、注目されているようで嬉しかったです。

あと、スコープ関数の使い所がいまいち掴めないんですよねみたいな話も聞いたりしました。
スコープ関数が使ってあるコードを見て始めたばかりの人が悩んだり、使い所に困ったりというのは、
Python の内包表記に似た感じを受けました。

これは割と色々な言語にあることだと思っていて、
しばらく書いていると「ここってなんかしっくりこないんだよなー」みたいなところが出てきて、
その時によりそれっぽい書き方を調べたりするので、
個人的にはスコープ関数はそんな感じでも遅くないんじゃないかなーと思っています。

最後に

最初から最後まで非常に楽しい勉強会でした。
最終的に結構遅い時間までお話しさせてもらいました。

ありがとうございました!

Docker で MediaWiki を立てる

自分の作っているライブラリで、WikipediaAPI 叩けないよー的な話が来たので
MediaWiki を Docker で立てて検証しようと思ったところ、
これが面倒だったので記録しておきます。

検証用にローカルで立てた手順です。

手順

Docker Hub で引っ張ってこられる MediaWiki はバージョンが古く、バグが残っていたため、最新のものを使用するよう修正しました
mediawiki-docker を clone します

$ git clone https://github.com/wikimedia/mediawiki-docker.git

Dockerfile を修正します
私の場合は以下のように修正しています

diff --git a/Dockerfile b/Dockerfile
index 5a4a8a4..115c32d 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,9 +1,9 @@
-FROM debian:sid
+FROM debian:latest
 MAINTAINER Gabriel Wicke <gwicke@wikimedia.org>
 
 # Waiting in antiticipation for built-time arguments
 # https://github.com/docker/docker/issues/14634
-ENV MEDIAWIKI_VERSION wmf/1.27.0-wmf.9
+ENV MEDIAWIKI_VERSION wmf/1.30.0-wmf.4
 
 # XXX: Consider switching to nginx.
 RUN set -x; \

Pull Request 投げようかとも思いましたが同じような奴が放置されてました...


build します

$ docker build --rm -t mediawiki .


今回は検証のために立てただけなのでパスワードとかも適当です
MySQL 5.7.5 以上だと動かないみたい*1のでご注意ください (もしかしたら修正されている問題かも)

$ docker run -it -d -e MYSQL_ROOT_PASSWORD=pass --name mysql mysql:5.6
$ docker run -it -d -e MEDIAWIKI_RESTBASE_URL="http://localhost/api.php" --name mediawiki --link mysql -p 80:80 mediawiki

これでとりあえずアクセスはできるようになったはず
後は、UI に従ってインストールします

データベースに接続の画面で入力するデータベースのホストは localhost じゃないです

$ docker inspect -f '{{ .NetworkSettings.IPAddress }}' mysql 


インストールが完了すると LocalSettings.php を移せと言われるので移します

$ docker cp ./LocalSettings.php mediawiki:/usr/src/mediawiki/  
$ docker exec -u www-data mediawiki ln -s /usr/src/mediawiki/LocalSettings.php /var/www/html/LocalSettings.php


これでとりあえず動くはず

余談

MediaWiki コンテナを restart しようとすると失敗します
この場合は entrypoint.sh を修正します

$ docker cp mediawiki:/entrypoint.sh ./
diff --git a/entrypoint.sh b/entrypoint.sh
index 37e7d33..40c14b9 100755
--- a/entrypoint.sh
+++ b/entrypoint.sh
@@ -115,7 +115,7 @@ EOPHP
 
 cd /var/www/html
 # FIXME: Keep php files out of the doc root.
-ln -s /usr/src/mediawiki/* .
+ln -sf /usr/src/mediawiki/* .
 
 : ${MEDIAWIKI_SHARED:=/data}
 if [ -d "$MEDIAWIKI_SHARED" ]; then
$ docker cp entrypoint.sh mediawiki:/
$ docker start mediawiki

Razer Chroma SDK を使って Keyboard をピカピカさせる

先日 Razer Blade Stealth を買ったのですが、
キーボードの光り方を見て何か面白いことできないかと思って調べたのでメモ

Razer Chroma SDK

Razer Developer Portal でダウンロードできます。

http://developer.razerzone.com/chroma/

あと、Razer Synapse が入ってて、Chroma 対応のデバイス接続してあると勝手にインストールされるみたいです。

Razer Synapse は入っているものの SDK がインストールされている気配はなく、
Razer Developer Portal で直接 SDK ダウンロードしてインストールしたら途中でエラー吐いて進みませんでした。

困った挙句に、Razer Synapse で Chroma アプリの On/Off をおもむろに切り替えつつ Synapse 再起動とかしてたら更新が降ってきて、
更新したらインストールされてました。謎

Colore

今回 C# で書いたので、Colore という Chroma SDK のライブラリを使用しました。

github.com

何ができるかは、Corale.Colore.Tester を動かすのが一番分かりやすいと思います。

ピカピカ

ようやく本題。
Visual StudioC# Console Application とかそこらへんの Project を作りつつ、Nuget から Colore をインストールする。
ここまで来たらほぼ終わり

Keyboard の Instance は以下のようにして取得します

Keyboard.Instance

Keyboard 全体を青色に光らせる

Keyboard.Instance.SetAll(Color.Blue);

A だけ赤色にする

Keyboard.Instance.SetKey(Key.A, Color.Red);

押されたキーを青色にする

Keyboard.Instance.SetReactive(new Reactive(Color.Blue, Duration.Short));

アニメーションとか

Keyboard.Instance.SetEffect(Effect.SpectrumCycling);
Keyboard.Instance.SetWave(Direction.RightToLeft);

Clear

Keyboard.Instance.Clear();

まとめ

vim とか Visual Studio, Atom とかと連携すると面白そう。

それはともかく Razer Core 全然入荷しない...Razer Blade Stealth だけ持っててもゲームできない...つらい

OCaml で Subcommand をパースする

Arg module のドキュメント読んでもどうすればいいかいまいち分からなかったので
OCaml で Subcommand とそのオプションを Arg module でパースする方法をメモしておきます。

何か間違っているところなどあればコメント、ツイートなど下さい。

実装

parse_dynamic を使用する

let usage = ""

let options = ref []

let hoge_options = [
    ("-hoge",
        Arg.Unit(fun () -> print_endline "hoge option"),
        "");
]

let huge_options = [
    ("-huge",
        Arg.Unit(fun () -> print_endline "huge option"),
        "");
]

let parse arg =
    if !Arg.current = 1 then
        match arg with
        | "hoge" -> options := hoge_options
        | "huge" -> options := huge_options
        | _ -> raise (Arg.Bad "Invalid subcommand")

let () =
    Arg.parse_dynamic options parse usage
;;

確認

$ ocamlbuild demo.native
$ ./demo.native hoge -hoge
hoge option
$ ./demo.native hoge -huge
demo.native: unknown option '-huge'.

  -help  Display this list of options
  --help  Display this list of options
$ ./demo.native huge -huge
huge option
$ ./demo.native huge -hoge
demo.native: unknown option '-hoge'.

  -help  Display this list of options
  --help  Display this list of options
$ ./demo.native demo
demo.native: Invalid subcommand.

  -help  Display this list of options
  --help  Display this list of options

参考

Io で Unicode エスケープ形式から元に戻す

Io language で API を叩いていて、
"\u3042" とか出てきて元に戻す必要があったので調べた

結論

私の見た限りでは、一つ method 呼べばなんとかなるようには見えなかったので、以下のようにしてとりあえず解決した
簡単な方法あったら教えてください

str matchesOfRegex("u[a-f0-9]{4}") replace(x, ("0x" .. (x string exSlice(1))) toBase(10) asNumber asCharacter)

str は元の文字列
こんな感じ

Io> str := "\u3042\u3042\u3042\u3042\u3042\u3042"
==> u3042u3042u3042u3042u3042u3042
Io> str matchesOfRegex("u[a-f0-9]{4}") replace(x, ("0x" .. (x string exSlice(1))) toBase(10) asNumber asCharacter)
==> ああああああ

解説っぽいやつ

最初の方は不要だと思うので途中から

x string exSlice(1)

ここの x には "u3042" が入っているはずなので、slice で u を捨てる (replace でよかったかも)
そのあと、16 進数から 10 進数に変換したいので

"0x" .. ...

ここで "0x" を足して "0x3042" とし、
その上で 10 進数に変換 (toBase(10)) する

そうするとここで得られるのは "12354" という文字列 (Sequence)
このまま asCharacter に渡すと怒られるので、Number に変換する (asNumber)

asCharacter は渡された値に対して有効な UCS マッピングがあればそれにあたる文字を返してくれる
なので例えば先ほどの 12354 を渡すと "あ" が返ってくる

Io> 12354 asCharacter
==>

Factor で http-request の response body が byte-array になった時

あるサービスの API レスポンスで body が byte-array になったので調べた

結論

charset が指定されていなくて byte-array になったら適切な形で decode する
utf-8 なら

http-get drop body>> utf8 decode json> .

詳細

サーバー側で charset が指定されていない場合は content-encoding が binary になるので
response body は byte-array になります.

例えば,以下のようなコードを書いた場合

"http://example.com" http-get drop .
charset が指定されていない場合
T{ response
    { version "1.1" }
    { code 200 }
    { message "OK " }
    { header
        H{
            { "connection" "close" }
            { "date" "Sun, 29 Jan 2017 08:48:16 GMT" }
            { "content-length" "12" }
            { "x-content-type-options" "nosniff" }
            { "server" "WEBrick/1.3.1 (Ruby/2.4.0/2016-12-24)" }
            { "content-type" "application/json" }
        }
    }
    { cookies { } }
    { content-type "application/json" }
    { content-encoding binary }
    { body B{ 123 34 115 116 97 116 117 115 34 58 49 125 } }
}
charset が指定されている場合
T{ response
    { version "1.1" }
    { code 200 }
    { message "OK " }
    { header
        H{
            { "connection" "close" }
            { "date" "Sun, 29 Jan 2017 08:47:25 GMT" }
            { "content-length" "12" }
            { "x-content-type-options" "nosniff" }
            { "server" "WEBrick/1.3.1 (Ruby/2.4.0/2016-12-24)" }
            { "content-type" "application/json; charset=utf-8" }
        }
    }
    { cookies { } }
    { content-type "application/json" }
    { content-charset "utf-8" }
    { content-encoding utf8 }
    { body "{\"status\":1}" }
}

charset が指定されていないと,いざ body 取って json として読み込もうとした場合に

Generic word json> does not define a method for the byte-array class. 

で怒られます.

こういう場合は

"http://example.com" http-get drop body>> utf8 decode json> .

のように decode して読み込む.

以上,charset 大事という話でした.