ナカザンドットネット

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

ScalaとTypeScriptが似てる気がしたお話。

ScalaとTypeScriptを交互に勉強していたら、なんか似てるなあと思ったので、そう思った理由らしきものを書いてみた。
[JS]とあるものは、TypeScriptがJavaScriptから受け継いだ特性です。

もちろんこれ以外の視点で見れば全然違う言語だし、両者の型推論が同じレベルかというとそうでもなかったりもするんだろうけど、なんか書いてて雰囲気が似てるなあ、と思った次第。
「JSに型を付けた言語」と「Javaを関数型&スクリプトっぽくした言語」が似たような書き味に仕上がったのだとしたら、面白い話だなあ(小並感)

*1:なお、Scalaの「メソッド」はファーストクラスオブジェクトではないとのお話を id:nkgt_chkonk さんからいただきました。このへんの話らしい→ https://sites.google.com/site/scalajp/home/scala-pitfalls/method_neq_object

8/31でウォーターセル株式会社の取締役を退職しました

2013年8月31日をもちまして、丸2年務めたウォーターセル株式会社の取締役を退職しましたことをお知らせいたします。


また、2013年9月1日より、ウォーターセル株式会社に社員として入社することをお知らせいたします。




というわけで釣り記事ですが、エイプリルフールではないので本当に役員辞めました。
客観的に見ると降格人事なので、何事かと思う方もいらっしゃるかもしれませんが、今回はかなり前向きというか、喜ばしいご報告になります。

今回の人事の理由について

創業初期のベンチャーというのは、まあ多かれ少なかれ、昼も夜も平日も休日もなく働ける人間が何人か必要になるものだと思いますし、そういった目的のためには会社役員という立場が必要です。
その立場から僕が外されたということは、会社がそういった働き方をする人間を必要としなくなる程度には、不安定な状況を脱しつつある、ということになります。

今後の仕事内容について

今までと変わらないと思います。
主な業務はAndroidアプリの設計・開発ですし、イベントの説明員をたまにやったりしますし、エンジニアチームの意見調整(という名の軽い喧嘩)をするのも今まで通りです。

ただ、肩書きはまだ決まってないので、名刺作りのためにも早めに考えないとなあ、といったところです。
ハイパー○○クリエイター的なのかっこいいですよね(棒)

個人的には

個人的な思惑の話で言えば、文化祭前夜みたいな状況がずっと続くのも、楽しいといえば楽しいのですが、そろそろ身を固めないとなーということも考えたりすると、ここらで一度普通の社員に戻って働き方を考えなおすのもありかなと思った次第であります。

年収的なところで言うと、役員でも社員でも、そんなに変わらない(残業代を加味するとちょっと役員のほうが少ないかもしれない)くらいだったので、直近の判断材料としては重大には考えませんでした。

会社の利益と僕個人の利益の最大化を考えた時に、僕が役員でいたほうが互いにとって都合がいい状況が生まれた時には、また役員に指名してもらえればなあ、と思います。
まあ、一般論として、会社が大きくなった時に創業初期メンバーが邪魔になるパターンというのも世の中にはあるらしいので、役員云々言ってられる状況じゃなくなる可能性もありますが、そのときはそのときで。


そんなわけで、生まれ変わった(ように見えて何も変わっていない)中川を、今後ともよろしくお願い致します。

enchantMOON開封の儀

f:id:Nkzn:20130802003356j:plain

ちゃんむー届きましたので、新潟限定ビイル 風味爽快ニシテとチャーシューを添えてご紹介したいと思います。

注意書き

f:id:Nkzn:20130802004220j:plain

USBケーブル繋ぎっぱなしで電源入れるとバグるらしい。超クール。あとビール美味そう。

開けてみた

f:id:Nkzn:20130802004356j:plain

本体とペンがお目見え。あとビール美味そう。

付属品を並べてみた

f:id:Nkzn:20130802004529j:plain

  • 説明書
  • ACアダプタ
  • 専用USBケーブル
  • 初回限定ストラップ

あたりが入ってました。
なお、チャーシューとビールは付属品ではないですが、美味そうです。

説明書

f:id:Nkzn:20130802004839j:plain

ビールを飲みたい気持ちを抑えながら、説明書を開いてみます。

f:id:Nkzn:20130802004841j:plain

「ある日」

1ページ目から攻めてる感じですね。あとビール美味そうですね。
2ページ目以降もなかなか攻めてる感じなので、読みたい方は是非購入して下さい。
なお新潟限定ビイル 風味爽快ニシテサッポロビール創業者と初代開発者が新潟出身だったことを記念して作られた新潟限定の美味しいビールです。

Wi-Fiパスワード入力

f:id:Nkzn:20130802005715j:plain

突然見慣れたAndroidのキーボードが出てきて「解せぬ・・・」ってなったけどビールが美味しそうに写ってるので許した。チャーシューも輝いていますね。

チュートリアルでMOON書いたりしてた

f:id:Nkzn:20130802005836j:plain

間違えてペンで丸書いちゃったりしてた。コマンドのための囲みは指でやらないといけないんですね。それはそうとチャーシューが美味しそうなので早くビールと一緒に飲みたい。

おまけ:シリアル

f:id:Nkzn:20130802010147j:plain

972番でした。ビール飲みながら撮りました。

まとめ

f:id:Nkzn:20130802010249j:plain

ひと通り触ってみましたが、処理落ちによる書き損じは評判通り多いように感じました。でも、できること、できないこと、といった用途の面に限って言えば、期待を大きくは外れていないように感じました。むしろブラウザとか要らないんじゃないかと思うくらい。

それはそうと、今回紹介させていただいた新潟限定ビイル 風味爽快ニシテは、サッポロビールが新潟のために作ってくれた美味しいビールです。皆様、新潟にお越しの際には是非お飲み下さい。

とある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]

訳注

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