ナカザンドットネット

それって私の感想ですよね

とあるSIerのエレベーター要件定義(ネタ・フィクション)

※このお話はフィクションです
f:id:Nkzn:20130510210334j:plain

ある日、とあるSIerの部長さんが、当面PJにアサインされる予定のない人員を会議室に集めました。

部長「みんな、今年の初めにこういう議論があったことは知っておるかね」

間違えやすい「エレベーターの開閉ボタン」をJAYPEGでデザイナーたちがリデザインしてみた - NAVER まとめ
http://matome.naver.jp/odai/2135925440564258701

部長「私はえらく感動した! エレベーターという普段使うもの、つまり『常識だと思っていたもの』にも疑問の目を向け、さらに使いやすいものにしようとする姿勢! こういった姿勢を持つ人間こそが、よりよい企画を生み出せるのではないかね。
君たちにもこれに倣って、エレベーターの改善案を考えて欲しい。前例では内部のUIを考えるものだったから……(ニヤリ)我々はその逆を行こう(ドヤァ)。エレベーターの外側のUIに疑問を投げかけたまえ。何も方針がないのも酷な話だから、ユーザーを最速で目的の階へ届けられる新しいUIを作るということを目標にするといい。後は任せた」

続きを読む

理屈っぽい意識低い人がダイエットらしきものに手を出した1年間のお話

意識の高さを前提とした手法なんて滅べばいい(挨拶)

今回はダイエットというか健康管理のお話です。(後記:終盤のグラフを出したかっただけの記事です)
僕のことを2009年以降からご存知の方(旧WinMo界隈、Android界隈の方はこの辺の層だと思います)は、僕のことをデブ層もしくはピザ層としてご認識いただいていることと思いますが、高校・大学時代をご存知の方に僕の当時の体格の話を聞くと「ガッシリしているイメージ」「逞しい体つき」など、デブをオブラートに包んだ言い方とも取れますが引き締まったマッスル系の肉体を持っていたことが伺えます。

全ては2009年末の卒論進行でチョコをバカ食いしたのがいけなかった・・・!!!

まあ過ぎ去った日々のことを言っても仕方ないので、とりあえずどげんかせんといかんと思い、2011年10月ごろ、ダイエットなるものを初めてみようかと思いました。

なかざんさん@がんばってみた

とりあえず新潟駅南のコナミスポーツクラブに通うことにしました。
2011年といえば弊社はまだ1年目ベンチャー。当然大した給料はもらえてませんし万年金欠状態です。そんな中での毎月9,000円近い出費。

「金欠の人間がわざわざお金払ったら、モチベーション上がるはず」

 →上がりませんでした。

まあ仕事が忙しかったのもありましたが、2011年12月〜2012年3月にかけて、合計35kものお金をドブに捨てるという大惨事が起きました。

敗因

スポーツクラブに行ったら、気合入れて運動しないといけないと思っていたのです。
残念ながら、僕はスケジュールが押している時に運動する分のモチベーションまでは起こらない派の人間だったようでした。
時間を削ってまで体力増進に努める意義を見いだせていなかったというのもありました。

理屈っぽいとよく言われますが、まあそのとおり。頑張るための理屈が足りなかったのです。

なかざんさん@がんばらなくてもいいんじゃね

話は変わりまして、弊社で出しているアグリノートというサービスがあるのですが、現状のコンセプトは「キャンパスノートや手帳といったデータ可用性の低い媒体に記録を取っている農家さんに、デジタル媒体のデータ置き場をあげてデータを活用してもらおう」というものです。
「農業のPDCAサイクルを、Check(≒現状把握)から始めてみませんか」という提案でもあります。

・・・現状把握?

そういえば、ダイエットを頑張ろう的なことをぼんやりと考えていましたが、自分の体がどうなっていて、どこがゴールなのかをよく考えていませんでした。
強いて言えば体重の目標はありましたが、後述の通り、体重は目標の置き方によっては何の役にも立たない指標です。
ゴールを設定していない長距離走のモチベーションが上がらないのは、当然といえば当然のことなのでした。

なかざんさん@がんばらない

そもそもからして、根本的に僕は意識が低い人間なのです。一般的なダイエットって意識的に頑張ったり我慢したりする行為じゃないですか。無理ですよそんなの。

つまり、

というわけで、意識を低く保ったまま勉強するみたいな仕組みが必要である。
意識を低く保つための tips - life.should be_happy # => 1 examples, ? failures

こんな感じになるわけですね。
自発的・内面的な意識喚起など期待しない。がんばらない。でも痩せたい。がんばらざるをえない状況に自分を持って行きたい。
がんばらないドリブンダイエット(GDD)と名付けました(嘘)

その前提に立った結果、僕が至った結論は「スポーツクラブに来たからって運動しなきゃいけないわけじゃない」でした。
スポーツクラブに通うメインの目的を、運動から逸らすことにしたのです。

主立ったところだと、以下の2点。

  • スーパー銭湯で普段よりもリッチなお風呂タイムを満喫する
  • 現状把握のためにボディスキャン計測の記録を取る

スーパー銭湯

実は僕、割と入浴している時間というものが好きでして。大浴槽もそうですが、寝湯とかサウナとか露天風呂とかがあるスポーツクラブの浴場はなかなか満足度が高いのです。
さらなる工夫として、スポーツクラブ用の持ち物に入れてある自前のシャンプーやらボディソープのランクを、自宅用のものよりワンランク上げてあります。
これにより、風呂に入るためだけにスポーツクラブに行くという素敵な図式が生まれました。
本当に風呂だけ入って帰る日もありますし、気分が乗ったら運動もしています。

ボディスキャン

コナミスポーツクラブ民の皆様にはお馴染みの、体組成計ですね。

ボディスキャン
http://www.konamisportsclub.jp/goods/club/bodyscan/

当初は僕も「わー色々とデータが出てくるもんだなー」と思って見ていただけだったのですが、このデータを活用すると、がんばらないドリブンの精度が上がるのではないかと思い、継続的にデータを取ることにしました。

実際に1年間、GoogleスプレッドシートGoogleフォーム)に取ってみたデータがこちらになります。

f:id:Nkzn:20130413211633p:plain

ボディスキャンの計測項目は以下の12項目です。

  • 体重(kg)
  • 基礎代謝量(kcal)
  • 体脂肪率(%)
  • BMI
  • 内臓脂肪指数
  • うでの脂肪率(%)
  • あしの脂肪率(%)
  • 筋肉量(kg)
  • うでの筋肉量(kg)
  • あしの筋肉量(kg)
  • 水分率(%)
  • 骨量(kg)

これだけのデータがあると、なかなか面白いことが見えてきます。
主に、体重の増減で一喜一憂する必要はない、ということです。

体重×体脂肪率

f:id:Nkzn:20130413231329p:plain

体重と体脂肪率って正比例しないんですね。
脂肪は減ったはずなのに体重単品だけ見るとむしろ増えてるケースまであります。これ体重しか測ってなかったら絶望してもう何もしたくなくなるレベルです。

体重×筋肉量

f:id:Nkzn:20130413231522p:plain

筋肉筋肉ー!(訳:リトバス1期やっと終わったね!)

はい、というわけで、どうやら筋肉量と体重はほぼほぼ比例しているようです。
諸説あるようですが、筋肉は脂肪より何倍か重いらしいので、体脂肪率が減っても筋肉が増えたらそりゃー体重も増えるってもんです。

基礎代謝量×筋肉量

f:id:Nkzn:20130413232454p:plain

で、体脂肪率が減った原因はたぶんこっちなんだろうな、的なデータ。
筋肉量の増加に伴い、基礎代謝量が増えてきています。

なんか楽しくなってきた

運動よりもデータ取りがメインになっていた時期もありましたが、ある程度データが溜まってきて、以下の様なことが分かって来ました。

  • 体脂肪率が減ると身体のぷにぷに感は減る(最終目標)
  • 基礎代謝を増やすと、体脂肪率は勝手に減る
  • 基礎代謝を増やすには、筋肉を増やせばいい
  • 基礎代謝を活かすには、日頃のカロリー摂取を控えればいい
  • 筋肉を増やすと体重は増える

僕個人としては、スリムになりたいとかそういう欲求はなくて、とりあえず皮下脂肪と内臓脂肪を減らせれば最終的にマッチョな体重80kgでも構わないので、つまり基礎代謝の効果を最大限増やすようなことをすれば良いようです。

1年間データを取ってみて、自分の運動との付き合い方みたいなものが段々見えてきたような気がします。

まとめ

1年間取ってきたデータを踏まえると、世間的にダイエットの本丸とされている「体重を減らす」というのは、結構馬鹿馬鹿しい話やなと思えます。一時的なものでよければ、筋肉減るような生活するのが一番手っ取り早く痩せます。オススメです。その後脂肪が減らなくなりますが、とにかく早く減らしたいだけなら筋肉減らして下さい。オススメです。

我々「理系の人々」は、とかく理屈で動きますが、このデータ取り→考察という流れはとても理屈っぽくて、比較的とっつきやすいのではないかと思いました。

ここ3ヶ月くらいで「炭水化物減らすダイエット」というがんばらない系の取り組みでPDCAサイクルを1周できてますし、スーパー銭湯に行くついでに体重測るのと大して変わらない労力で出た成果としては上々なのではないかなと。

そんなわけで、なんとか意識低いながらも1年間データが取れたので、嬉しくなって記事を書いてしまったお話しでした。

* 余談:fitbit始めました

f:id:Nkzn:20130413212740j:plain:h480

ダイエットとは半ば関係なく、Androider界隈で流行ってたのでつい。

このへんにいます→ http://www.fitbit.com/user/254H9V

CoronaSDKで無料でストア向けアプリを作れるようになりました

2011年7月に僕がCoronaSDKの入門書を出したのは記憶に新しくないところですが、CoronaLabsのブログで、Corona SDKの料金プランの改定が発表されました。

State of Corona: New Public Release + FREE + Re-imagining Pro | Corona Labs
http://coronalabs.com/blog/2013/04/04/state-of-corona-new-public-release-free-re-imagining-pro/

この記事は、これまでPlay StoreやApp Store向けの公開用アプリをビルドするために最低99ドル/年が必要だった時代が終わり、無料で公開用アプリが作れるようになったことを知らせるものです。
(あとPROライセンスの見直しとか、OpenGL/ES強化の情報とかも載ってますので、興味ある方は元記事を御覧ください)

新料金体系

f:id:Nkzn:20130406134722p:plain
http://coronalabs.com/products/corona-sdk/faqs/

以前の料金体系からINDIESが無くなり、新たにSTARTERが入った形になります。

料金

  PRICE Revenue Limit()
STARTER 無料 10万ドルまで
PRO 599ドル/年 50万ドルまで
ENTERPRISE 999ドル/年 50万ドルまで
  2,499ドル/年 なし

Revenue Limit : 昨事業年度の収入による利用制限。*1

できること

STARTER
  • SDKの安定ビルドをダウンロードできます
  • シミュレータでアプリを作れます
  • アプリ(.apk/.app)をビルドできます(クラウドビルドなのでオンライン時のみ)
  • ビルドしたアプリはPlay StoreやApp Storeで有料/無料問わず公開できます*2
  • アプリに広告を載せることができます(参考:Can I have ads in my apps made with Corona SDK Starter?)
PRO
  • STARTERの機能全て
  • アプリ内行動解析(Corona Cloudの1機能)を利用できます
  • アプリ内課金に類するもの(Premium Manetization Services)が利用できます
  • SDKの最新ビルド(Daily Builds)をダウンロードできます
  • 各種新機能・新サービスのプレリリースが利用できます
  • Project Gluonによって作成された、サードパーティサービス(FacebookやAmazonなど)のプラグインが使用できます
  • 各プラットフォームのAPI(Java/Obj-C)に、Luaからアクセスできます(参考:Android/iOS
  • 有償サポート(参考)
ENTERPRISE
  • PROの機能すべて
  • Coronaの処理系をCやらJavaやらObj-Cで弄れます(参考)
  • オフラインでの、待ち時間無しのビルドができます*3
  • カスタマイズしたCoronaでのビルドをシミュレータから行えるようになります(2,499ドルプランのみ)
  • Corona Labsのエンジニア1名による1時間のQ&Aセッションと、環境構築のサポート(2,499ドルプランのみ)
  • Eメールサポート(2,499ドルプランのみ)

本当に公開できるのん?

僕のサブスクリプションは1年以上前に切れているのでちょうどいいと思い、実際にCoronaのサンプルにあったカメラアプリをPlay Storeに公開してみました

f:id:Nkzn:20130406155141p:plain

お金払ってないのにdebug.keystore以外のkeystoreファイルを使ってちゃんと署名ができました。これは嬉しい。
というか最新のCorona SDKを落とし始めてから公開設定の完了まで30分とかかりませんでした。お手軽感がパないです。

余談

はじめる!CoronaSDKを出した後の僕はと言えば、本を出すだけ出しておいて(転職があってバタバタしていたのもありますが)あまりCoronaの普及活動に精を出していなかったように思っています。

最大の理由は料金体系のしんどさでした。最近の料金体系は追ってなかったのですが、Play StoreかApp Storeのどちらか向けのビルドをするために99ドル、両方だと249ドルとか、初心者にはオススメしづらかったです正直。
もちろん仕事でガッツリ使うツールとしては高くはないですし、作ったアプリでちゃんとビジネスをして稼げれば2万円や3万円は軽く取り返せるでしょう。
ただそれは、割と意識の高いほうの考え方です。世の中の「スマートフォンアプリというものを自分にも作れるなら作ってみたい」みたいな趣味レベルの人たちには、そこまでの意識の高さは求められません。
そういう点で今回の料金改定は、初心者がサクッとスマートフォンプログラミングに触ってみるという点で、物凄くハードルが下がったと感じ、歓迎しています。

// 現実的には、Enterpriseで充分お金が取れるようになったから、
// 裾野を広げるほうの戦略にシフトしてくれたのかなーと思ってます。

*1:どうやって調べるつもりなんだろう・・・?

*2:別途、GoogleへのAndroidデベロッパー登録料25ドル(初回のみ)、または、AppleのiOS Developer Program登録料99ドル(毎年)がかかります。

*3:自動化が捗りますね

An MVP Pattern for Androidを訳してみた

新年あけましておめでとうございます。 ブログで書き初めというのも粋かなと思いまして、仕事でAndroidでのMVPパターンを調べている一環でAn MVP Pattern for Androidを意訳してみました。それではどうぞ。

An MVP Pattern for Android

Separating the presentation of the application's UI from the logic of its UI is usually a good idea. This separation of concerns creates more de-coupled code, which is much cleaner, and even allows for more unit testing coverage. Android bundles the UI and UI logic into the Activity class, which necessitates Instrumentation to test the Activity. Since Instrumentation is introduced, it is much more difficult (or impossible) to properly unit test your UI logic when the dependencies in the code cannot be mocked. However, a simple MVP pattern will help de-couple the UI and UI logic in Android applications.

一般的に、アプリのUIの見た目をロジックから切り離すのは良い考え方です。この関心の分離は、コードを疎結合で簡潔なものにし、ユニットテストカバレッジを改善することもできるでしょう。AndroidのUIとUIロジックはActivityに纏められており、ActivityをテストするにはInstrumentationの利用が必須となっていますが、Instrumentationの仕組みが現れて以来、コードの依存性をモック化できないUIロジックに対して適切なユニットテストを行うことが、非常に困難(または不可能)になっています。しかし、シンプルな MVPパターン を用いることで、Androidアプリケーション内のUIとUIロジックの分離をしやすくなります。

The MVP pattern stands for Model-View-Presenter, and it separates the UI concerns between the data of the UI (Model), the display of the UI (View), and the logic of the UI (Presenter). For Android, the View is the Activity, which will handle gathering user input and updating the display; the Presenter is a class that will handle communication between the Model and View; the Model will handle persisting and retrieving data, along with any business logic that the data must adhere to. Interfaces will be used to de-couple each of these components. A simple Customer View will be used to illustrate how this can be accomplished.

MVPパターンは、 Model-View-Presenter を表しており、UIに出すデータ( Model )、UIの見た目( View )、UIのロジック( Presenter )という、UIに関わる関心ごとを分離しています。Androidにおいては、ユーザーからの入力や画面更新を取りまとめているActivityView 、ModelとViewの間で行われるやりとりを制御するクラスが Presenter 、データの保持や検索など、データに従った形の各種ビジネスロジックを扱うクラスを Model と呼べばよいでしょう。各コンポーネント疎結合に保つための仕組みとしては、インターフェースを使います。シンプルなCustomer Viewを例に挙げて、これらをどの様に実現していくかを説明していきます。

An MVP Pattern for Android - Magenic Blog

First, our CustomerActivity (the View) will have textboxes for the Customer's ID, first name, and last name:

先ず、今回作るCustomerActivity(これが View ですね)は、カスタマーID、名前、名字のテキストボックスを持っています。

private EditText mFirstNameEditText, mLastNameEditText, mIdEditText;

The user will load a customer using the mIdEditText and a Load Button. Likewise, the user will save a customer using a Save Button:

ユーザーはカスタマー情報をmIdEditTextmLoadButtonを使ってロードします。また、同じように、カスタマー情報をmSaveButtonでセーブします。

private Button mSaveButton, mLoadButton;

We must now create a CustomerPresenter with the following methods:

さて、そろそろ以下のメソッドを持つCustomerPresenterクラスを作成しましょう。

public CustomerPresenter(ICustomerView View)
public void saveCustomer (String firstName, String lastName) 
public void loadCustomer (int id)

We then can wire it all up in the CustomerActivity's onCreate method:

ここでCustomerActivity#onCreateに繋いでいきます。

mCustomerPresenter = new CustomerPresenter(this);
mSaveButton.setOnClickListener(this); 
mLoadButton.setOnClickListener(this);

The CustomerActivity class must now implement the interfaces OnClickListener (for handling the Button's OnClickListeners) and ICustomerView (for the CustomerPresenter constructor). The OnClickListener defines the method void onClick(View v), and our method will look like the following:

CustomerActivityクラスにはインターフェースとしてOnClickListener(Button用のリスナ)と、ICustomerView(CustomerPresenterコンストラクタ用)を実装して下さい。また、OnClickListeneronClick(View v)を実装する必要がありますが、下記のようにして下さい。

switch (v.getId()) {
case R.id.saveButton:
    mCustomerPresenter.saveCustomer(mFirstNameEditText.getText().toString(), 
    mLastNameEditText.getText().toString());
    break;
case R.id.loadButton: 
    mCustomerPresenter.loadCustomer(Integer.parseInt(mIdEditText.getText().toString()));
    break;
}

The previous two code sections show that when the Save Button is clicked, the saveCustomer method of our presenter will be called with the Customer's first name and last name information; and when the Load Button is clicked, the loadCustomer method of our presenter will be called.

前2つのコードは、mSaveButtonがクリックされた時に PresentersaveCustomerメソッドが名字と名前を引数として呼ばれるという話と、mLoadButtonがクリックされた時に PresenterloadCustomerメソッドが呼ばれるという話でした。

We haven't defined ICustomerView, so we'll do that now. When loading the customer, the CustomerPresenter will need to be able to update the CustomerActivity's last name, first name, and ID EditTexts, so ICustomerView will look like the following:

まだICustomerViewに手を付けていませんでしたので、そろそろ定義しましょう。カスタマー情報をロードするときには、CustomerActivityの名字、名前、カスタマーIDのEditTextをCustomerPresenterから書き換えられるよう、ICustomerViewを下記のようにしましょう。

void setLastName (String lastName); 
void setFirstName (String firstName);
void setId(int id);

The CustomerActivity's implementation of these methods will set the corresponding EditText to the value of the parameter.

CustomerActivityへの(ICustomerViewの)実装では、各メソッドに対応するEditTextへパラメータをセットしておいてください。

The CustomerPresenter, then, will look like the following:

CustomerPresenterは下記のようになります。

private ICustomerView mCustomerView;
private ICustomerModel mCustomerModel;
public CustomerPresenter(ICustomerView view) {
    mCustomerView = view;
    mCustomerMode = new CustomerModel();
}
@Override
public void saveCustomer(String firstName, String lastName) {
    mCustomerModel.setFirstName(firstName);
    mCustomerModel.setLastName(lastName);
}
@Override
public void loadCustomer(int id) {
    (mCustomerModel.load(id)) 
    {
        mCustomerView.setId(mCustomerModel.getId());
        mCustomerView.setFirstName(mCustomerModel.getFirstName());
        mCustomerView.setLastName(mCustomerModel.getLastName());
    }
}

The implementation of the CustomerModel isn't important for our purposes; we just need to know that it is being saved to a repository of some sort. Furthermore, the CustomerModel is currently tightly-coupled to the CustomerPresenter, which can be remedied by injecting it as a dependency.

CustomerModelの実装は今回の目的から見るとあまり重要ではありません。何らかの保存場所にデータがセーブされていればよいのです。その上、今回のCustomerModelCustomerPresenterと密結合していますので、依存性注入を行う形などで修正したほうがよいでしょう。

The CustomerPresenter allows the CustomerActivity class to be as simple as possible. The activity now only gathers user input for the presenter and provides simple UI update methods for the presenter. Since the CustomerView and CustomerModel implement interfaces and can be injected into the CustomerPresenter, it is not dependent on them. Therefore, they can by mocked, which allows the CustomerPresenter logic to be unit tested.

CustomerPresenterによってCustomerActivityクラスは可能な限り完結になり得ます。今回のActivityPresenter にユーザーからの入力を集め、 Presenter から触るためのシンプルなUI更新メソッドを提供しています。CustomerViewCustomerModelはインターフェースにより実装されているため、CustomerPresenterからのインジェクションができるくらいに依存性がありません。そのため、それぞれのモックさえ作ればCustomerPresenterのロジックはユニットテストが可能になるのです。

After Note: This MVP pattern is sometimes referred to as Passive View, since the view only passes along data, either to or from its presenter. The MVP pattern can also be implemented such that the View knows of the model. The view responds to state changes in the model for simple UI updates, while the presenter handles more complex UI logic. This more complex pattern is sometimes referred to as Supervising Controller.

後記:今回のMVPパターンは、 View が単に Presenter に対して入出力するだけのものなので、Passive Viewパターンとも呼ばれるものになっています。MVPパターン自体は ViewModel にアクセスできる場合にも成り立ちます。 ViewModel の状態の変化に反応して、シンプルなUI更新を行い、複雑なUIロジックが必要な場合に Presenter に投げます。この複雑なパターンのことを特にSupervising Controllerパターンと呼ばれたりします。

In Android, this can be accomplished by the Model using Java's Observable class and the View implementing the Observer interface; when something changes in the Model, it can call the Observable's notifyObservers method. It can also be implemented with Android's Handler class; when something changes in the Model, it can send a message to a handler that the View injects into it.

Androidでは、JavaObservableクラスを用いた Model と、Observerインターフェースを実装した View によってMVPパターンが実現できます。 Model に変更があった時にObservable#notifyObserversを呼び出すのです。また、AndroidHandlerクラスでも同様の実装ができます。 Model に変更があった時に、 View に変更を伝えられるHandlerに対して、メッセージを投げるのです。

An MVP Pattern for Android - Magenic Blog]

訳注

言うとおりに作ったらこうなりました

これからAndroidを始めるヅ大生にオススメしたい7冊の本

ハイ、Aizu Advent Calendar 22日目は、ヅ大最速で卒論テーマにAndroidを選んだ残念な人のわたくしがお送り致します。
僕がAndroidに初めて触れた2009年の夏には、右も左も分からない中で手探りで情報を探すしかない状態でした。しかし2012年の今日ではAndroid+iPhoneによってガラケーが駆逐されかけているという、当時から想像はしていたものの本当にそうなってビックリしているような時代になっています。
そんな状況に比例して、もちろん技術書の数も当時とは比べ物にならないくらいに増えています。というか、増えすぎです。


f:id:Nkzn:20121222004922p:plain


入門書だけで42冊とか何かのジョークやで。
そんなわけで、これからAndroidアプリ開発に手を出したいんだけど、どの本から読んだらいいかさっぱり分からないヅ大生たちに、独断と偏見で選んだ7冊を紹介します。

前略、1次情報を疎かにしてはいけない

Develop | Android Developers
Design | Android Developers

会津の新兵どもへ。貴様らは英語で数学を学び、英語でオートマトンを学び、英語でデータベースを学び、英語でアーキテクチャを学んできた。
今更何を日本語に拘っている! 全ての情報は公式にこそある! 公式を読め!!!

訳:

Androidの公式チュートリアルや公式ドキュメントは、内容だけ見れば大変丁寧で、かつ網羅的であり、更新も頻繁に行われています。また、(技術系の英文全般に言えることですが)日常英会話に比べると、比較的平易な言葉で書かれており、会津大学で数年を過ごした感覚があれば、充分に読解が可能なレベルです。
以降紹介していく「2次情報」としての技術書はしばしば、ページ数の制限などから、重要な点のみに絞って手法の紹介を行なっており、読み進めていく中で疑問に思う点がいくつか出てくるかと思います。そんなときには、公式ドキュメントを紐解き、疑問を解決するのが最も確実な方法でしょう。


それでは、気を取り直して一冊目の紹介に参ります。

自分でプログラムを組むの自体が初めての貴方へ

楽しみながら作ってみよう! はじめてのAndroidアプリプログラミング

楽しみながら作ってみよう! はじめてのAndroidアプリプログラミング

id:gabuchan が書いた、まさしく初心者のための本です。
ちょっと派手な電卓アプリを完成させることをゴールにしており、初心者を一歩一歩確実に導いてくれます。
初心者向けではありますが、Android 3.0で登場した画面分割と再利用を容易にした概念"Fragment"や、横フリックで画面切り替えを行う標準コンポーネント"ViewPager"を積極的に利用するなど、イマドキな開発の基本もしっかり抑えている良著です。
値段も2,310円と、技術書の中では割とお安いのも嬉しいところ。

慣れてきたぞ!と思ったときに手元に置いておきたい

Google Androidプログラミング入門 改訂2版

Google Androidプログラミング入門 改訂2版

!!!!WARNING!!!!
入門と銘打っていますが、この本を1番最初に買ってはいけません。心が折れます。

Androidアプリ開発でハマりがちなカユいところに手が届く、必携の一冊です。いつも手の届くところに置いておいて、「あれ?」と思った時に公式リファレンスよりも先に読むと疑問が解けるかも知れません。
ただし、全体的にエッセンスの紹介が中心であり、1から10まで教えてくれるようなゆとり仕様ではないので、「onClickってどうやると実装できるんだっけ・・・?」とかいうレベルの人がこの本を読むと高確率で死にます
2冊目くらいに買っておいて、末永く垢がつくほど読み込むのが正しい読み方です。

Android SDK開発のレシピ

Android SDK開発のレシピ

垢がつくほど読み込んで欲しい本その2。
この本は名前そのまま、「ちょっとこんなことしたいんだけどどうしたらいいだろう」に応えてくれるレシピ本です。
がぶちゃん2冊目だけど別に回し者ではないよ!! #がぶちゃん奢って
130個の収録レシピは、きっと小さなたくさんの「困った」を解決してくれるはず!
買ったらとりあえず目次だけひと通り読んで、興味のあるページだけ流し読んだら、あとは本棚で出番待ちをさせてあげてください。たぶんある程度の規模のアプリを作ろうとすると、常に手元にないと心細くなる時期があるくらいに役立つ本です。

アプリ開発の腕を洗練したくなったら

「アプリをもっと気持ちよくしたい!」と思った時に読んで欲しいのがこの3冊。

Androidプログラミング上達読本

Androidプログラミング上達読本

まずは、コード側が原因で起こっていた『モッサリ感』を解消するための一冊。
アプリの操作中になんの前触れもなく、いつ復帰するかも分からないまま画面が数秒フリーズしたら誰でも嫌ですよね。そんな嫌さを解消するためのノウハウを初めとして、Java側?からアプリを気持ちよくする方法が詰まった一冊です。

Android UI Cookbook for 4.0 ICS(Ice Cream Sandwich)アプリ開発術

Android UI Cookbook for 4.0 ICS(Ice Cream Sandwich)アプリ開発術

次はレイアウトXML側からアプリを気持ちよくするお話。
あなたがアプリを作るとき、InstagramPathのように、全てのコンポーネント(ボタンやチェックボックスなど)を自作しない限りは、標準コンポーネントのお世話になることになります。
標準コンポーネントにはどのような種類があり、どんな風にカスタマイズや配置を行えば綺麗に見えるようになるのか、それにより見えてくる「Androidらしさ」とはどんなものなのか。
奇をてらった独自UIを作る前に、1度読んで欲しい一冊です。

アプリの気持ちよさを求めたくなったら

iPhoneアプリ設計の極意 ―思わずタップしたくなるアプリのデザイン

iPhoneアプリ設計の極意 ―思わずタップしたくなるアプリのデザイン

原著の名前は"Tapworthy"、直訳すると「タップする価値のある」という形容詞(造語?)です。別名@fladdict本。
全体的に読み物と呼ばれるジャンルで、プログラムの話は全くと言っていいくらい出てきません。
この本に出てくるのは、iOSの名作における「気持ちよさ」や「タップしたくなるボタン」はどんなものに由来していて、我々がアプリを作る際にはどんなところに心血を注がなければならないか。何を目指し、何をするべきで、何をしてはいけないか。そんなことを教えてくれる本です。
1度ひと通り読んでフムフムと頷いてから、アプリを1本仕上げ、そのあとでもう一度読みたくなるような、そんな本だと思います。

スマートフォンデザイン見本帳

スマートフォンデザイン見本帳

最後の一冊は来週発売なのでオススメもクソもないのですが、simejiのデザイン担当にしてAndroid女子部の部長にしてデザインのカリスマ、矢野さんが実例を上げながらスマートフォンデザインのパターンと在り方について語る本とか、良著の匂いしかしないのです。
単純にいろんなアプリのデザインを見るだけでもたぶん価値のある一冊。

最後に

Androidを真面目にやろうとすると、多様な画面サイズ&縦横比、進化を続けるチップセット、一向に互換性を持たないカメラとGPS、などなどの特異性に頭を抱えることになりますので、できれば手を出すな。どうしてもスマホアプリ開発がしたかったらiOSから入りなさい。(台無し)
それでもなお、Androidからこの魔法の世界に入門したいというのなら、今回紹介した本など読みながら、迷子にならないように気をつけて歩んでいって下さい。
Androidは開発者からすると、まあ、ちょっとクセのあるダメな子な部分はありますけど、なかなか可愛いやつなんです。こういうことを言うようになると、だいたいもう手遅れなので、皆さんはこうなる前にiOSなりWindows Phone 8に退避したほうがいいかもしれません。
それでは皆さん、よいAndroid開発ライフを。


明日は@先生です。よろしく。

テストコード付きのFizzBuzz

なるほど。
「あるint型の数値を渡すとfizz, buzz, fizzbuzz, 数値の文字列のいずれかを返す関数」のテストをJUnit4で書いてみた。

package net.nkzn.fizzbuzz;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class FizzBuzzTest {

  @Test
  public void testFizzBuzz() {
    
    for(int i=0; i < 1000000; i++) {
      
      String value = FizzBuzz.eval(i);
      
      if (i % 3 == 0 && i % 5 == 0) {
        assertThat(value, is("fizzbuzz"));
      } else if (i % 3 == 0) {
        assertThat(value, is("fizz"));
      } else if (i % 5 == 0) {
        assertThat(value, is("buzz"));
      } else {
        assertThat(value, is(String.valueOf(i)));
      }
      
    }
  }
}

どうせなのでワンライナー実装もしてみたけど上手くできなかった・・・。

package net.nkzn.fizzbuzz;

public class FizzBuzz {

  public static String eval(int n) {
    return ""+((n%3==0)?"fizz"+((n%5==0)?"buzz":""):(n%5==0)?"buzz":n);
  }
  
}

感想

  1. テストと実装を両方とも自分でやると条件判定を二種類考えないといけなくてダルいので、人にやらせる場合はテストだけ書かせれば充分やな感ある
  2. 事実上テストと実装で同じ条件判定してるので、このテストでFizzBuzzの正しさを証明できているかというと割と自信ない(;´Д`)

Galaxy Nexusで起きた、画像についてのおかしな出来事

ある画像について、ギャラリーの「詳細情報」で見たファイルサイズと、Javaコード内でFile#length()したときのファイルサイズが大きく異なるという事象に遭遇したので、ひとまず現象だけ覚書。

ギャラリーで詳細情報を見た時のファイルサイズ

f:id:Nkzn:20120715223602p:image:w320

1.04MB。

File#length()したときのファイルサイズ

検証コード@gist
↑インテントでギャラリー呼んで、選んだ画像のファイルパスを手に入れるだけのコードです。

f:id:Nkzn:20120715223828p:image:w320

1965307Byte≒1.87MB。

ギャラリーに表示されているものの倍近いサイズです。なんぞ。

Dropbox経由で引っ張りだしてMac側で見た時のサイズ

f:id:Nkzn:20120715224225p:plain

1965307バイト。File#length()と同じ結果ですね。
んん? なんでギャラリーでは小さく表示されるんだろう?

Android File Transferで見た時のサイズ

Android File Transferとは、端末をマスストレージモードにしなくてもExternal Storage領域のデータをやりとりできる、Mac10.5&Honeycomb以上限定の素敵かどうかと言われると微妙なツールなのである!

ということで何となくこのツールでもファイルを見てみた。

f:id:Nkzn:20120715224427p:plain

1.0MB・・・?

流石に不審です。ドラッグアンドドロップでファイルを引きずり出してみましょう。

f:id:Nkzn:20120715224553p:plain


えっ

Android File Transfer経由で引っ張りだしてMac側で見た時のサイズ

f:id:Nkzn:20120715225233p:plain

サイズとかそういう次元じゃなかった。なんか欠損してる。
1095414Byte≒1.04MBなので、当初のギャラリーでの表示とは辻褄が合ってる。

考察

GNのファイルシステムがサイズの計算間違えてる感じなんだろうか。

  1. 何故かファイルシステムはこの画像を1.04MBだと思っている(というのがたぶんメタ情報として入っちゃってる)
  2. ギャラリーはイチイチ画像とか直接読んでられないので、たぶんメタ情報だけを見て1.04MBだって言ってる
  3. 本当は1.87MBある画像ファイルをFile Transferで取り出そうとすると、1.04/1.87MB分しか転送しない
    • なのでMacに転送されたものには欠損が起こる(別に端末内で欠損が起こってるわけではないたぶん)
  • DropboxやFile#length()はファイルシステム上どうかに関係なく実際のファイル全体を読んだり送ったりしているために影響を受けていないのでは
  • この現象が起きるファイルと起きないファイルがあるが、条件はよく分からない

感想&まとめ

むーん・・・。なんなんだろうこれ。
ひとまずFile#length()で読んでくる値は正しい感じがするから、仕事で詰まってた部分に関しては問題ないかな・・・。

うちにあるGN以外では試してないので、他所でも起きる現象なのかどうかは分かりませんが、とりあえずこんなことがありましたということで。