Macで貧弱なネットワーク回線を再現してスマホアプリをテストするTips

QAさんに口頭で伝えるのが大変そうだったのでブログエントリにする。

iPhone/AndroidアプリのQA時に貧弱なネットワーク回線を再現したいことがままある。そういうときは「Network Link Conditioner」と「インターネット共有」を使うと便利だよという話。

  1. Network Link Conditionerで速度を絞る
  2. Macを有線インターネット接続し、WiFiをアクセスポイントにする
  3. このアクセスポイントに任意のスマホをつなぐと低速回線が再現される

1. Network Link Conditioner

https://developer.apple.com/download/more/

から「Additional Tools for Xcode」をダウンロード。その時々で最新のものを選ぶと良さそう。今日時点でmacOS High Sierra (10.13.3) + Xcode 9.3用のAdditional Toolsで動作を確認。

f:id:fushiroyama:20180221120002p:plain

古いNetwork Link ConditionerはHigh Sierraで正しく動かないので注意。

 

展開。Hardware > Network Link Conditioner.prefPane をダブルクリック。

f:id:fushiroyama:20180221120110p:plain

 

こんな感じでSystem Preferencesに入る。

f:id:fushiroyama:20180221120132p:plain

 

任意のProfileを選んでONにするだけ。Profilesは帯域やパケットロスも含めて細かくカスタマイズ可能。

f:id:fushiroyama:20180221120134p:plain

 

2. インターネット共有

「共有する接続経路」に有線インターネットのデバイスを選択する。ここではUSBイーサネットアダプタを選択しているが環境によって読み替えて欲しい。

「相手のコンピュータでのポート」に「Wi-Fi」を選択して「インターネット共有」を有効にするとアクセスポイントができる。

f:id:fushiroyama:20180221120139p:plain

右下の「Wi-Fiのオプション」からSSIDとかパスフレーズとかを設定できる。

 

3. つなぐ

AndroidでもiPhoneでもなんでもつないでください。低速回線が再現されます。

f:id:fushiroyama:20180221120143j:plain

 

Androidも使える方法でもっと楽なのがあったら教えて。

DroidKaigi 2018で登壇してきたので振り返りとか補足とか

DroidKaigi 2018で登壇してきたよ!

 

資料はこれ。

speakerdeck.com

ハンズオンのサンプルプロジェクトと課題はこれ。

github.com

 

良かった点

前日こんなツイートしてかつDroidKaigi公式アカウントがそれをRTしてくれたせいか、ハンズオンなのに立ち見/地べた座り参加者が出るほどの盛況だった。

それから参加者の半分はUnit Testが初めてかそれに近い状況で、資料もハンズオン課題(の前半部分)もまさにそういった方に向けて一生懸命作ったのでそれに関しては満足している。

 

反省点

いっぱいある…

  • Robolectricが初回実行時にダウンロードするライブラリの差分が会場ネットワークの詰まりで進まず、ハンズオンがストップした。これは運営さんやインフラを責めているのでまったくなく、そのような可能性に思い至らなかった自分が悔しい。
  • GitHub APIが同一IPからの単位時間あたりの接続数上限に達してしまい会場でサンプルアプリが動かなくなった。これも事前の調査不足というか、実際にそういう目に遭ってみないと考えつきもしなかった。
  • サンプルアプリをAndroid-CleanArchitecture風に設計し、その各レイヤごとにUnit Testを書けるようになるとめちゃくちゃ有意義なのでは?という想定のもとすべてを準備したが、会場の参加者がそれを求めていたように感じられなかった。完全に自分の独りよがりになった。
  • ハンズオンとして参加者に書いてもらう部分の調整の甘さ。僕はUnit Testを書くことそのものは大好きだが、ハンズオンをそれほど主催したことがなく、課題として空欄にして埋めてもらう部分の難易度設定に難があったように思う。
  • ハンズオン課題を英語対応しなかった。会場には日本語を解さない海外からの参加者の方もいて、その方には個別に対応したが、そもそもこれだけの規模のイベントでそういう参加者が当然に来てくださることをもっと真剣に考慮すべきだった。

とまあこれらはすべてもし次回があったときの糧としたい。まだ初日が終わったところで、2日目の早朝にぐずる赤ん坊を抱っこしながらこのエントリを書いているので、最終的なフィードバックの集計を待ちたいところだ。

 

サンプルアプリに関する補足

今回はスライドで座学をしたあと、前述のハンズオン課題をもくもく解いてもらった。

これはGitHubアカウントを入力したらその人のレポジトリ一覧を表示するという人類が一体どれだけ同じものを作ったのか想像もつかないほどありふれたアプリだが、設計には慎重な考慮を重ねてUnit Testもできるだけ「明日から仕事で使える感」を目指した。

 

個人的に課した縛りは次の2点。

理由は単純で、それぞれこのライブラリのことを説明するだけで50分のセッションができるほど習熟が大変だからだ。RxやDaggerが出てくることで今回の設計やUnit Testの本質がブレてしまうことを避けたかったのだ。

したがって非同期処理基盤には古き良きThreadPoolExecutorを用いDIはシンプルなコンストラクタインジェクションとFactoryパターンという古典に則った。

しかしながらシンプルで理解しやすさを求めて敢えてこれらの込み入ったライブラリを用いなかったことで却ってこれらのライブラリの恩恵でスマートに解決できている問題を自分で処理せねばならないという皮肉な結果となった。

このときには資料づくりは佳境でなかなか方向転換もままならなかった。参加者のみなさんの感想が楽しみでもあり怖くもあるが、なんとかこれらのライブラリを使わずありふれたJavaコンポーネントだけで書いたことによる可読性の方がわずかでも勝っていると信じたい🙏

 

で、サンプルアプリで特に注目して欲しいのはやはり各レイヤのテストコードだ。

前述のレポジトリはハンズオン向けにcloneしたらデフォルトでtasksというブランチがチェックアウトされるようになっている。こちらはUnit Testが空欄になっている。これをmasterブランチに切り替えると僕が普段書いているようなUnit Testをひととおり書いてある。興味のあるひとは是非見てみて欲しい。

Repositoryより下のビジネスロジックの部分はみんなも関心が高いしテストコードも結構書いてると思うんだけど、ちょうど同期と非同期が混じり合うUseCaseの部分はどうやってテスト書いていいか苦慮すると思うし、Presenterなんかもテスト書きづらいんじゃないかな。Presenterはちゃんと書くとViewとのインタラクションを検証できるので是非プロジェクトをcloneしてみてフィードバックが欲しい。

 

DroidKaigiの感想

とにかく最高のひと言。

After Partyでスピーカーには風船を付けさせるアイディアは最高で、これのお陰もあって「白山さんですよね?」と数え切れないほどの人に話しかけてもらって本当に光栄だった。

 

それからAndroid 設計パターン入門という本の著者陣がほとんど居るという豪華な状況が嬉しくて子供のようにサインを求めて回った。

 

返す返す、これほど素晴らしいAndroid関連イベントは世界でも早々ないであろう。代表の日高さん、スタッフのみなさん、登壇者のみなさん、そして参加者のみなさん全員に深く感謝したい。

まだ2日目が控えているが、こういうのは早ければ早いほどその時の熱気が文章に乗ると思ったので赤ん坊に3回目の授乳をして抱っこしたまま早朝の暗い部屋の片隅でこれを書いている。

今日もまたみなさん楽しみましょう。じゃあの。

DroidKaigi2018「はじめてのUnit Test」の資料事前共有とフィードバックのお願い

2/8の DroidKaigi 2018 にて「はじめてのUnit Test」というハンズオンを担当します。

で、setohさんのこのツイートにシビレたので僕も資料を事前共有することにします。

 

 

資料はこちら。

speakerdeck.com

 

念のため確認ですが、僕のセッションはあくまでハンズオンであって、

  1. 座学パートでこの資料をみながらUnit Testの書き方を解説する
  2. その後はチューターとしてサポートしながら各自ハンズオン形式でUnit Testを書いていく

ことを予定しています。ここで共有したのは前者の参考資料です。

本当はハンズオンのコードを共有したかったのですが、もうちょっと作り込みたいのでちょっと待って下さい。

一応、

  1. 初心者向け課題として、この資料にでてくるサンプルコード片のテストコードをひととおり用意しているので好きなように書いてもらいます。まったく初めての方はこれが達成できたら万々歳です。
  2. 中級者向け課題として、完全に動くシンプルなAndroidアプリを用意しており、これはいわゆるClean Architectureに範をとった構成になっています。これの各レイヤーのよくあるテストコードを書いてもらいます。かなり実践的な内容が詰まっていて、僕も共有するのが楽しみです。

という感じです。

 

で、これを見てくださったみなさんは資料でもうえに書いたハンズオン課題(構成案ですが)でもいいので、何でもコメントください。Twitter@fushiroyama にリプライでもDMでもください。

 

とにかく参加者のみなさんに「有益だった!」と言ってもらえる時間にしたい。そのためには一時的に恥をかいてもなんら構わない。なんでもコメントください。それではよい週末を。

 

macOS High Sierraのzshでちょっとハマったのでメモ

2年経って会社の開発マシンがリプレースの時期になったので今日からMacBook Pro (15-inch, 2017) Touch Barモデルで開発している。 思ったほど困ってないがzshの設定で少しハマったのでメモ。

ログインシェルをzshにできない

% brew install zsh
% chsh -s `which zsh`

としてもiTermを立ち上げ直すと $SHELL = /bin/bash に戻っている。

% sudo vim /etc/shells

/usr/local/bin/zsh # 追記

これで使えるようになった。

aliasと同名の関数を定義できない

Sierra環境で使っていたzshrcをそのまま使おうとすると

% source ~/.zshrc
/Users/shiroyama/.zshrc:188: defining function based on alias `ssh'
/Users/shiroyama/.zshrc:188: parse error near `()'

というようなパースエラーが出るようになった。たしかに alias sshssh() {} が存在する。 zshのことは全く詳しくないのでエラーでググったらどうやら関数に明示的に function ssh() {} のように function とつけてやれば良いようだ。 全部そのようにしたら晴れてエラーが解消した。

ちなみにHigh Sierraだからじゃなくて普通に考えてzshのバージョンだと思う。

% zsh --version
zsh 5.4.2 (x86_64-apple-darwin17.3.0)

Touch Barモデル雑感

よくESCがないとツライと聞くが、僕はESCC-jに割り当てているのでvimを使う上では何ひとつ困らない。 ただファンクションキーがないのは明確につらくて、カナ変換とかで思わず手がF7を探しちゃうし明るさも音量も調整にまごつく。 デスクに座ってる限りは外付けキーボードとトラックパッドを使っているので違いは感じないが携帯したときにストレスを感じるかもしれない。

あと、ポートがUSB-C * 4だけというのが一番気が狂いそうになる。電源もイーサネットアダプタ1もディスプレイケーブルもスマホも何もかも全部ぜーんぶUSB-Cである。 何年後かにこの世にほとんどUSB-Cだけが生き残っていたらもう少し生きやすいのかもしれないが、その前にAppleさんはiPhoneをUSB-Cにしなかったのはなんでなんですかね… そんくらいかな!

なお古いMacBookを返却する際にベタベタに貼りまくったステッカーを全部はがし終わるのに60分要した。 もう二度とこんなアホなマネはせえへんぞとステッカーをはがすたびに思うがどうしても再びやってしまうのは自分でも理解できない。


  1. ワイヤレスが不安定なのがストレスなのでデスクに座っているときはMacBookでも好んで有線接続している。

口が悪いエンジニア論争

通勤の暇にかこつけて今話題の「口は悪いが凄腕の技術者を雇うべきか」論争に対する自分の考えを残しておく。

まず大前提として「技術力も人間力もある」のがベストというのは揺るぎのないものであり、僕もここを目指したいと常々考えている。
その上でだけど、僕は「そうすることが必要な場面では口の悪さに目を瞑って技術力を取る」選択もありだと考える。

みんなこれには一家言あるようだけど、結局のところ全員前提としている状況が違うので意見が異なるのは当然のことだ。ただ僕が言いたいのは「ある種の問題はそれを解決することがそもそもできない絶対的な壁がある」ということだ。

本件に関して様々なツイートを拝見したが「そもそも技術力は育てられるが人間性は中々変えられない」という意見には、後半こそ賛同するものの前半には両手をあげて賛同できない。ある種の課題、プログラマのコンテキストで言えばいわゆるNP困難な問題は中庸なプログラマを100人並べても対処できない。ゼロだ。

なんでもいいんだけど例えば事業の課題としてGoogle Mapを超える最強の地図アプリを作ろうとするじゃない。そしたら最短経路とか求めないといけないけど、これそういう教育を受けてない人には無理じゃないですか。
ダイクストラ法ぐらいならググれば出てくるけどダイクストラ法はコストが負のノードがひとつでもあったら成り立たない。じゃあそれの改良版のコレコレを使いましょうとかね。

こういうのって数ヶ月から数年の教育と訓練と実務で身につける類のもので、人間性の優れた素人プログラマを10人集めても倒せない。こういうとき、酒癖も女癖も最悪だけど一騎当千呂布みたいな武将に力を借りざるを得ないのは仕方ないと思う。

なのでまとめとしては最初に書いたとおり、場合によっては口の悪さぐらいでは引き換えにならないぐらい技術力には壁があるんじゃないかしらということだ。それからこれが1番言いたいことなんだけど、みんな人間性の優れた呂布になろうな。僕も頑張る。

近況と2018年の抱負

ご挨拶

新年明けましておめでとうございます。

このブログは普段のAndroid開発の気付きとかを他ならぬ未来の自分(最近つとに忘れっぽい)のために書き残していたのであるが、人生について書いたエントリが随分バズってしまったのでやっていきブログと思われているかもしれない。なのでこの辺で意図的に本来予定していたゆるさに戻していく。

元同僚の定期的なブログ更新の良さについて - 滞舎路日記というエントリに賛同する部分が多かったので僕もとりあえずネタがなくても何か書いていこうと思う。

渡米準備

ビザの書類には数え切れないほど用意するものがあってもちろん会社や代行業者がサポートしてくれるんだけどそれでもめっちゃ大変(語彙の喪失)

あとは引っ越しの準備とか手放すものの整理とか郵便の転送とかそれから仕事の引き継ぎとか英会話とか娘の保育園の手続きとかDroidKaigiのスライドとか毎日目も回らんばかりだ。

子育て

僕はフルタイムお父さんであってパートタイムプログラマである。とにかく子供たちと毎日精いっぱい生きている。やはりプログラマの端くれなので新しいことに挑戦する時間が取れなくなると切なさを感じないではないが、これまでは夜9時に寝て朝4時に起きるなどして何とかしてきた。ところが次女が昨夏生まれて以来ふたたび夜泣き対応を経験しており「あ〜、あったな〜こんな時代」としみじみしている。まあそんでも子供がお父ちゃ〜んと背中にまとわりついてくれるのなぞせいぜい満4-5歳ぐらいと考えたら最後の一滴まで味わいつくしたい。

ベンチャーキャピタルさんと新規事業

2018年は米国のラボで新規事業やらなんやらをやる。弊社がLP出資しているVCがあってその縁で彼らがこちらの新規事業のアドバイスを定期的にしてくれているようだ。で、こないだ初めてこのVCとこちらのMTGに参加させてもらったんだけどこれは詳しくは書けないけどまあひどい内容で、思わず間に入って最初から最後までずっと通訳*1狂言回しをするハメになった。この先のことを考えると暗澹たる気分になったが、その後VCのメンバーとの会食で「君は一番印象に残ったよ。これからもよろしく頼む」と褒めてもらってそれは自信になった。これは正直僕が頑張らないとどうにもならんという感想だし、まあ結局のところだからこそ僕が送り込まれるのだと腹をくくった。とにかく結果を出したい。

ともかく楽しくなりそうではある。2018年もよろしくお願いいたします。

 

*1:これが1番納得いってない。プログラマなのに!

僕は僕にどういう教育を授けたか

まえがき

会社の若い子に「情報系出身でもないのに一体どうやって勉強してきたんですか?」と聞かれたのでランチを食べながら「こんな本読んだ。これもタメになった。あ、これもタメになった」とKindleを広げながらリストアップした。思い返せばたくさん本を読んだ。その中には役に立ったものもあれば時間の無駄だったものもある。すると「あ、役に立った本だけ抽出したら有益かもしれないな」と思ったのでエントリにする。

僕は文章を簡潔に分かりやすくまとめる才能が致命的にないのでこのエントリもげっそりするほど長い*1が、2017年も暮れなのでここはひとつ日本酒でもかっ喰らいながら自分の人生を振り返ってみようと思う。

無理やり要点をまとめるならば、

を身につけたらどんなに低く見積もっても僕と同程度のプログラマをつくるレシピには充分だと思う。具体的な書籍名も挙げてあるので誰かの人生に勇気を与えられたらいいな。

 

僕について

あー超言いたくないので今まで隠してたんですが僕は英文学部出身*3なんですよ。チョムスキーとか読んでました。割と自由な学科だったので英文学と英語学に飽きてからは通訳の授業を取ったりしていた。

数学は1A2Bまでしかやっていない。生物と化学はちょっとだけ覚えている。物理はまともにやった記憶すらない。コンピュータサイエンスの教育は1秒も受けていない。

ピアノと耳コピが趣味でMIDIにハマったのがきっかけでそれを発表するためのサイトを始めた。そのうち第三者の作品投稿を募るようになってPerlCGIを書き始めた。どこかで買ってきた本*4を見ながら無料公開された掲示板CGIを元にコピペと改造を繰り返してサグラダファミリアを建築していた。

3年次に大学を中退。前述のプログラミングもどきをきっかけに知り合った大学の先輩が起業したのでその会社で働き始めた。

 

インフラ

会社での僕の業務は雑用全般だったのでクビになることを恐れて誰もやり手がいなかったLinuxサーバ管理をし始めた。当然すべて物理サーバ。当時使っていたのはRedHat 9。そして出たばかりのFedora Coreに乗り換えてyumコマンドで依存ライブラリも含めて一発でインストールできることに感動したのを覚えている。ここではいくつか重要な知識を身につけた。

この業務に5年間たずさわったが、ほぼ次の本を読めば同等の知識を獲得できる。 

TCP/IPの絵本 ネットワークっておもしろい!

TCP/IPの絵本 ネットワークっておもしろい!

 

右も左もわからない人がざっとインターネットプロトコルスイートについて雰囲気を知るのに良い。

 

ネットワークはなぜつながるのか 第2版 知っておきたいTCP/IP、LAN、光ファイバの基礎知識

ネットワークはなぜつながるのか 第2版 知っておきたいTCP/IP、LAN、光ファイバの基礎知識

 

ルーティングの基礎がちゃんとわかる。

 

マスタリングTCP/IP 入門編 第5版

マスタリングTCP/IP 入門編 第5版

 

マスタリングTCP/IPを入門編でも読めればTCPダンプも怖くない。

 

CentOS7で作るネットワークサーバ構築ガイド (Network server construction gu)

CentOS7で作るネットワークサーバ構築ガイド (Network server construction gu)

 

ここだけ、この本を手放しに推奨するということじゃなくて「自分の使ってるLinuxディストリビューションApache/Nginx, Postfix, Bind, Samba等々を『全部入りで』解説されてる本」で自分にあうものを1冊探して欲しい。僕は現在はもっぱらDebianばかり使っておりRedHat系を推奨するという意図はない。

 

プログラマ転身

インフラのかたわらで会社のサーバサイド開発を手伝うようになってちょっとずつプログラマとしての経験値を貯めていった。僕のおすすめのアプローチは「何かひとつ『これさえあればとりあえず安心して何か書ける』ようになるまでひとつの言語を集中して頑張ること」だ。僕の場合はそれはJavaだった。

Java、なぜか今日では古くさくてイケてない言語の代名詞みたいに若い人に思われてそうだけど2017年現在ですら充分有力な選択肢ですぞ〜。

  • C++やRustを除くと最速の部類の実行性能を誇る
  • JVMGCのチューニングや運用実績も豊富
  • コアライブラリの代表的なデータ構造*6は種類も豊富だし実装も参考になる
  • ジェネリクス
  • 強力なスレッドサポートとconcurrentパッケージ
  • 昔でいうとAWTやSwing、いまならJavaFXとかでスタンドアロンGUIアプリケーションも書ける
  • AndroidJavaライクな言語で開発できる
  • 巷に開発者が多く、枯れた知見や強い静的型付けのおかげでチーム開発にも向いている
  • 別にやりたきゃFat Jarにして配布したりスクリプト処理だってできる

ちょっと最後は無理やりか!ほとんどのプログラミング言語は本質的にやろうと思えばなんだってできるね。

とにかく僕の場合はJavaだったわけだ。ジェネリックプログラミングやマルチスレッド処理、GUI開発の知見なんかは僕の現時点での最大の武器であるAndroid開発にも非常に役立った。 

いまからJavaを身につけるのは何がいいんだろうな…とりあえず

 Javaメモ目次(Hishidama's Java Memo)

の2つには大変お世話になった。Javaは「とりあえず使い始める」という点でちょっと分量が多いように感じられて*7初学者はウッ…となるかもしれないので何でも良いので本屋さんで簡単なのを買ってみるというのも手です。

 

改訂2版 パーフェクトJava

改訂2版 パーフェクトJava

 

これを手放しに推奨というわけではないけど何も知らない人は一旦ざっと俯瞰できる本を何か買ってください。始めた頃の僕みたいな実力だったらもっと入門的なものでも良いかもしれない。

 

EFFECTIVE JAVA 第2版 (The Java Series)

EFFECTIVE JAVA 第2版 (The Java Series)

 

これはJava書きのバイブル。Java 8, 9時代の内容を反映した3rd Editionも原著(英語)はすでに予約を開始してる。

 

新装版 リファクタリング―既存のコードを安全に改善する― (OBJECT TECHNOLOGY SERIES)

新装版 リファクタリング―既存のコードを安全に改善する― (OBJECT TECHNOLOGY SERIES)

 

僕はリファクタリングをチーム開発、使いやすいAPI設計、テストを書きやすい構造等々のすべての高品質なプログラミングの基礎だと考えており、この本は一歩前に進むために必読であった。Javaが題材なので手に取りやすい。

 

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

 

言語に依らずシンプルで分かりやすいコードを書くためのテクニックが簡潔にまとまっている。新入社員には必ず薦めている。

 

Java並行処理プログラミング ―その「基盤」と「最新API」を究める―

Java並行処理プログラミング ―その「基盤」と「最新API」を究める―

 

これ絶版なのが惜しくて惜しくてしょうがない。Javaが持つ強力なマルチスレッドプログラミングをjava.util.concurrentパッケージを使って安全に使うためのテクニックがすべて詰まっている。また「スレッドセーフとは何なのか」という観点から、単純にロックを安全に取る方法のみならずトラバースを安全に行うことに特化したアプローチなども学ぶことができる。

 

無職、そして東京へ

さて5年経って会社もIPOを目指すスタートアップからただの中小企業と化してしまったし僕も自分の人生に行き詰まりを感じて最初のスタートアップを退職した。*8

僕はちょっとだけ無職をしつつ自分が次になにをすべきか考えていたが、ふと「そういや大学3年まで取った単位もったいねえな。どっかに入り直すとして1回生からやり直すカネはないし引き継げたりせんかな」と思って中退した大学の教務課に行ったところ「確かに中退してるけど、キミ、5年以内なら無試験で復学できるね。ああ、来月末で5年だね。」と言われ、そのあまりのタイミングの良さに運命を感じて大学に戻ることにした。この時は手に職があったので知人経由で割のいいプログラミングのバイトを貰って働きつつ1年で卒業した。*9 

この間に後に嫁さんになる女性とコミケで出会った。向こうは同人誌を作る側、こちらは同人誌を買う側である*10。奇しくも冬コミ初日の今日これを書いているのは感慨深いな。大学卒業後よめさんを追いかけて東京で職を探した。

 

ネイティブアプリ開発

ウェブの会社に拾ってもらってここで技術者としての基礎を全て叩き直された。京都時代にちょっと触ってたAndroid開発を本格的にやるようになった。ネイティブアプリ開発にはいくつかコツがあることを知った。

スレッド間通信

ネイティブアプリ開発のコツというとライフサイクルコールバックとか非同期処理とか貧弱なネットワークやハードウェアリソースなんかが挙げられると思うけど、最も大切かつ既存のほとんどすべてのGUIフレームワークに共通する仕組みがある。それがイベントループとメッセージパッシング機構でありこれらは取りも直さずスレッド間のメッセージのやり取りために存在している。

イベントループ

あるスレッドに関連付けられイベントやメッセージを待ち受けてる人。AndroidではLooperがこれに相当する。MessageQueueというその名の通り届いたメッセージをキューに積んで処理したりする。

メッセージ

スレッド間でやり取りされるメッセージ。AndroidではMessageというそのままの名前。

ハンドラ

イベントループにメッセージを届けたり処理を記述するための仕組み。AndroidではHandlerというこれまたそのままの名前のクラスがある。

 

なんでこれらの知識が必要かというと、こういった仕組みはGUIフレームワークに普遍的な考え方であり何かトラブルが起こった時の調査の取っ掛かりになるばかりか、まったく新しいGUI開発に従事した際にも充分に応用が効くようになるからだ。ここに挙げたものはiOSにもまったく同じものがあるしJava Swingにもあったし未来に生まれる次世代のスマホOSでも同じものが提供されるであろうことが想像に難くない。

ここまで分かるようになってくると、UIスレッドというのがそういう名前が付いただけのシングルスレッドであることも分かるし、反対にメッセージループの機構が単に別スレッドからUI部品を更新するためだけのものではなく任意のスレッド間の柔軟なメッセージングに使えることが分かる。

ちょっと脱線したけどAndroid開発の参考書籍をいくつか。

いきなり書籍じゃないけど「Androidの入門書なにがいいか?」って一番困る質問なんだよね…すでに僕はAndroid入門者じゃないので当時の気持ちが思い出せない…

ただこのトレーニングコースは無料で簡潔かつ本質的であり、今なお色褪せぬAndroid開発の極意をごく短期間で身につけることができる。

どうしてもIDEのインストールから手取り足取りやりたいひとはAmazonで適当に検索して評判の良さそうなものをなんでも1冊手にとって見ればいいと思います。

 

黒帯エンジニアが教えるプロの技術 Android開発の教科書(ヤフー黒帯シリーズ)

黒帯エンジニアが教えるプロの技術 Android開発の教科書(ヤフー黒帯シリーズ)

 

ヤフー黒帯本。Androidに限らずiOSもそうだと思うが公式の方法と現場で使われているデファクトスタンダードの乖離が初学者の挫折ポイントだったりすると思うので、最近の知見をサッと1冊で詰め込めるのはおいしい。

 

Androidを支える技術〈I〉──60fpsを達成するモダンなGUIシステム (WEB+DB PRESS plus)

Androidを支える技術〈I〉──60fpsを達成するモダンなGUIシステム (WEB+DB PRESS plus)

 

Androidの内部に切り込んだ世界でもこれ以上の書籍はないと思われる名著。I巻はGUIにフォーカスを置いている。前述のHandlerのような話題もはるかに深く掘り下げられている。

 

Androidを支える技術〈II〉──真のマルチタスクに挑んだモバイルOSの心臓部 (WEB+DB PRESS plus)
 

II巻はActivity(iOSのViewControllerに相当)に関する内容。普段何気なく利用しているActivityが誰によってどのように生成/破棄されているのかと言ったライフサイクルの心臓部の解説がある。

 

Androidを支える技術の別冊「詳説 Binder」。すいませんこれ怒られるかもしれないけどまだ読んでなくて正月休みに読む予定なんだけど、AndroidにはBinderというプロセス間通信の仕組みがあって普通にIDEの参照ジャンプで辿っていくだけだとこのBinderの層でプッツリと途絶えてその先を見つけられないのだ。

ここを読むにはAndroidのなかみ InsideAndroidという書籍*11の解説とかを見ると助けになるんだけど、著者の有野さんも

と仰っているしdex.fmでご本人が熱弁しておられた様子をお聞きしても名著であることを確信したのでここで紹介した。

 

アルゴリズムとデータ構造

たぶんここまで来るだけでモバイルアプリ開発者としてなんとなく食っていくには充分だと思うんだけど外資に転職したくて勉強したアルゴリズムとデータ構造について理解を深めるにつれ「これは順番が逆だった!これを知ってからプログラミングをやるべきだった」という思いに強く駆られたので紹介しないといけない。

 

アルゴリズム

アルゴリズムはある問題を解くためのアプローチだ。数列を昇順に並べ替えるアルゴリズム木構造から目的のデータを素早く探すためのアルゴリズム等がある。

 

データ構造

アルゴリズムを実装する際に効率的に処理するためにデータの集まりを都合の良い状態に整えたもの。整列済みの配列は立派なデータ構造だし、平衡二分木もB+木も赤黒木もデータ構造である。

 

で、普段こんなの使わんでしょ?と思いきや全然そんなことなくて、自分で実装することはほとんどないかも知れないけど普段のプラグラミングやサービス開発でよく使うものでこれらアルゴリズムとデータ構造の恩恵を受けていないものは存在しないほど身近で重要なものだったりする。

普段使ってるRDBMSファイルシステムはB+木のお陰で挿入も削除も検索も高速だし、全文検索エンジンはトライ木の一種のサフィックス木で実装されてるかもしれない。

身近なプログラミングでダントツに重要なデータ構造としてHashMap(Dictionary)があると思うけど、普段これがどうやって実装されてるか*12考えたことがあるだろうか?

このあと紹介する参考書籍とかを読めば分かるけど、HashMapはキーのハッシュ値をモジュロ演算して固定長配列*13に割り当てて、ハッシュ値の衝突は連結リストの後ろにつなげていくだけで実現されている。それぞれは非常にシンプルなデータ構造とシンプルなアルゴリズムを工夫してこのようなベンリなデータ構造を作ってるわけである*14

またAndroidにはキーが任意の型Tではなくint固定の代わりにメモリ効率が良いとされているSparseArrayというデータ構造があるが、これは内部では2分探索木が使われている。つまりエントリが爆発的に増えればおそらく挿入時にはSparseArrayの方が有利だし検索時にはHashMapの方が有利であることを示唆している*15

こういう知識はいざ自分で新しい何かを生み出せばならないときに強力な持ち駒として力を発揮するはずだ。

 

この本は何個か読んだ中でも比較的とっつきやすかった。使い慣れたJavaだし。

 

なっとく!アルゴリズム

なっとく!アルゴリズム

 

この本はアルゴリズム本の中で特別読みやすかった。図もたっぷりで軽妙な語り口。それでいて動的計画法のナップザック問題あたりまでもカバーする骨太さ。言語はPythonだが読めないということはまずないだろう。

 

アルゴリズムクイックリファレンス 第2版

アルゴリズムクイックリファレンス 第2版

 

僕が読んだ中で最も広範かつ深くアルゴリズムについて学べる本。いきなり「アルゴリズムの数学」と題して計算量とは、最良・最悪・平均性能とは何なのかみっちりと解説してくれる。その後他のアルゴリズム本にもあるような整列、探索、グラフに始まりAI、ネットワークフローの深きまでがっつり入っていく。これをマスターすれば怖いものなし。僕はマスターしていない!

 

AtCoder代表のchokudaiさんによるTopCoderSRMに挑むための訓練本。やや難易度が高いけど実際のプログラミングコンテストに挑むための力をつけることができる。外資企業の面接で間違いなく力を発揮する。

 

UNIX/Linux

個人のPCレベルだとWindowsがまだ世界で90%ものシェア*16を持っててまさに圧倒的という言う他ないんだけど、ことサーバ環境においては7割近くがUNIX系OS*17という調査もあるようで元インフラ出身の僕の肌感覚とも近い。それにiOSDarwinというUNIXだしAndroidLinuxをベースにしていることを考えるとUNIX/Linux力は非常に重要だと思う。

ここでUNIX/Linux力といった場合単純にコマンドを扱えるよりもうちょっと踏み込んだ点を指していて、具体的には次のようなことだ。

  • 入出力
  • ファイル(inodeとか)
  • プロセスのフォークやシグナル
  • pthreadと同期
  • プロセス間通信(名前付きパイプとかUNIXドメインソケットとか)

で、これらは普通にコマンドを利用してるぐらいでは中々身につけるのは難しくて、やっぱりglibc越しにシステムコールを呼ぶようなプログラムを書かないといけない。

かつて一回だけ本番環境のMySQLが原因不明のタイミング*18でネイティブクラッシュを繰り返して生きた心地がしなかったんだけどstraceコマンドでシステムコールトレースをつぶさに追ったところRDSのホスト名が長すぎて名前解決キャッシュのテーブルの最大バイト長を超えて書き込もうとしてセグメンテーション違反を起こしていたのを突き止めたことがある*19

 

詳解UNIXプログラミング 第3版

詳解UNIXプログラミング 第3版

 

上に挙げたようなことをすべて身につけることができる本。900ページぐらいあってめっちゃムズイけどCを書いてコンパイルしてっていうのは実は生まれて初めてだったので楽しかった。全部やるのは無理だった。

 

詳解UNIXプログラミングのLinux版かつテーマをグッとしぼった感じの本。初学者はこちらの方がずっとオススメ。grep等のよくあるコマンドを自分で実装してみることができる。

 

教養

直接なにか利益を受けるつもりで学んだものではないんだけど回り回って血となり肉となった知識がいくつかあって、その中のひとつが関数型プログラミングだ。

特にHaskellモナドを学んで将来確定する計算結果をパイプライン処理するというような考え方はAndroid開発時にRxJavaを見た時にすんなり理解できる助けになってくれたりして大いに役立った。また昔は特に苦手だった再帰も、スタックフレームを消費する末尾呼び出しとアキュムレータを用いた最適化可能な末尾再帰を使い分けることができるようになったりと得るものが多かった。再帰的な考え方は再帰的なデータ構造やアルゴリズムを考える時に脳の体操になるので非常に役立つ。

 

すごいHaskellたのしく学ぼう!

すごいHaskellたのしく学ぼう!

 

たぶんHaskellの入門書で圧倒的に一番分かりやすい。Haskellの機能をシュールな絵とともにのらりくらりと解説してくれるんだけど、Functor, Apprecative, Monoidとステップを踏んで最終的にMonadを作るところまで学ぶことができる。

 

ScalaをBetter JavaというよりはかなりHaskellっぽく使うための様々なアプローチが紹介されている。随所に練習問題があって難しいが素晴らしい本。

 

Land of Lisp

Land of Lisp

 

スポンジボブのようなシュールな絵でLispの歴史の解説に始まり最終的にCommon Lispを使ってちょっとしたゲームまで作ってしまう面白い本。S式という連結リストと関数だけというかなり割り切った言語設計とカッコだらけの見た目でかなりぎょっとするが、再帰を使って連結リストに関数適用していくという関数型プログラミングの醍醐味のようなものを学ぶことができる。

 

フロントエンド開発

むしろ僕が教えていただきたい…僕のフロントエンドの知識はjQueryprototype.jsで停まっている化石状態だ。

ただ来春の僕のミッションに素早いプロトタイピングが加わるのでReact Nativeでクライアントサイドを、Cloud Functionsでバックエンドを書いていこうかなと思っているので双方に共通する技術スタックとしてTypeScriptを速習予定だ。

 

TypeScript実践マスター

TypeScript実践マスター

 

とりあえずこれはパラパラ読んでみたが初学者には良さそうだった。

 

数学

数学の出来なさがかなり僕のコンプレックスになっており自分なりに少しずつ努力している。僕はビッグオー記法のO(logN)の意味が最初わからなくて指数対数からやり直したレベルだ…こちらは完全に教養として本当に少しずつ進めているので進展があったら共有したい。

このエントリで拝見した高専の数学は良さそうである。

 

やっていき

いや〜長すぎてもう誰も読んでないと思うので最後にちょっと好きなことを書きます。

自分がこれだけ路傍の石ころみたいな状態からプログラマになってこうしてなんとか食ってこれたのは、やっぱり諦めなかったからだと思う。僕は常にいまの自分が許せなかった。いまの自分の不甲斐なさが悔しかったのだ。これは裏を返せば自分の可能性を信じているわけだ。まだやれるはず、まだ道は続いているはずだと信じている。

ちゃんと教育を受けた人が大学で4年、修士で2年、博士で3年だとしてざっと10年。僕はこのような専門教育は受けていないがかれこれ12年自分で自分にコンピュータサイエンスを教え続けてきた。努力を積み重ねれば彼らに追いつくのも不可能とは限らないのだ。毎日は1㍉1㍉の積み重ねだが12年経って振り返った時に「気付かないうちに随分登ったなあ」と小高い丘から目を細めながら過去の自分を見下ろせればそれで良い。

22歳からでも、いや30歳からでも遅すぎるということはないのだ。自分が今日より若い日は今後一生ないのだと思うと何歳からはじめても今日が最善の日だ。やっていこう!

 

情熱プログラマー ソフトウェア開発者の幸せな生き方

情熱プログラマー ソフトウェア開発者の幸せな生き方

 

技術書以外はめったに読まないんだけどとても好きな本。オフショアでの衝撃的な経験や生きるためにコードを書くということ、採用に対する考え方、エンジニアとしての幸せなど示唆に富んだ本。

 

最後に

2017年は本当にお世話になりました。来年はちょっと今まで目を背けつづけてきた機械学習にチャレンジせねばと思っています。どうか良いお年を。

*1:マジで長くて1万字を超えちゃって笑ってしまった

*2:身も蓋もないけどコレはホント。しかし運は待つのではなく無理やりつかみ取りに行くのです。

*3:だから英語に苦手意識がないんですね〜。けどこの時の英語力はハナクソみたいなもんだったのでその後のトレーニングの方が大事。

*4:これはもはや記憶にない。何でも良かったのだ。

*5:29ビットマスクのグローバルIPをやりくりしていた

*6:List, Set, Hash, Dequeなんでもいいんだけど、Arrayを元にしたものやLinkedな実装など用途に応じて自在に使い分けできる。僕はアルゴリズムとデータ構造を学んでからJavaのコアライブラリの凄さを見直した。

*7:リテラルも弱いし配列やコレクションもRubyPythonとかより使いにくくてとっつきづらいよね…

*8:僕を引っ張ってくれた恩人の先輩もそれからほどなく共同創業者に株式を売り払って東京に出ていった

*9:思えばこのとき2年かかってもいいから理学部情報学科にでも編入試験を受ければよかったな〜。でも学士を取れてよかった。

*10:「ここここのあとののの飲みにいきませんか」みたいなことを言った。通報も逮捕もされなくてよかった。

*11:こっちは読んだ!

*12:もっというとどうやってO(1)の検索を実現しているか

*13:ホントは然るべきタイミングでリサイズしないといけない。卜部先生のブログに詳しい。

*14:これを理解するとどうしてMapが挿入順序を持たないか簡単に分かるだろう

*15:ただし一般的なアプリで現実的なデータ量では2分探索木でもO(1)に近い性能が出ると思われる。参考サイト

*16:https://news.mynavi.jp/article/20170904-a057/

*17:https://w3techs.com/technologies/overview/operating_system/all

*18:後にレプリケーションのタイミングと判明

*19:これは --skip-name-resolve オプションを付けていればそもそも起きなかったミスではあるが…