kazasiki's blog

プログラミングとかVRゲームとか

Nike FuelBand SEを2年間使ってみて

Nike FuelBand SE(以下、FuelBand)を購入して早2年が経ちましたので、所見を纏めます。買って1週間くらいのレビューは巷に溢れてますが、2年後のレビューはなかなかないと思います。

f:id:kazasiki:20151211115116p:plain

筆者のNike+ ダッシュボード(2015/12/11当時)

 

Nike FuelBand SEだけでなく、運動を測定するタイプのウェアラブルデバイス全体についての洞察も含むので、購入を検討されている方の参考になれば幸いです。

前提

簡単に、FuelBandの性能や筆者の使用状況などを箇条書きします。

FuelBandの機能

  • 主な機能は運動量(Fuelという独自単位)、歩数、消費カロリーの測定/表示。
  • 時刻を表示できる。
  • 睡眠判定、脈拍計の機能はない。
  • iOS/Android端末から通知を受け取る機能はない。
  • 生活防水。

筆者の状況

  • 筆者はFuelBandをほぼ毎日腕時計の代わりとして装着している。
  • 基本的には毎日入浴時に充電している。
  • 日常的にスポーツはしていない。
  • 運動不足や肥満には特に悩んでない。

わかったこと

充電切れになることは殆ど無い

1日のどこかに充電するタイミングを用意していれば充電切れになることはまず有りません。筆者の場合は入浴するときに外して充電しています。生活防水なので装着したままの入浴も可能ですが、体洗ったりするときに邪魔なので。友人宅に外泊した場合などは充電できませんが、それでも充電が切れたことはほとんど有りません。

まとめると、ウェアラブルデバイスのバッテリーの要件は以下のようになります。

  • 追加充電なしで2日間連続使用可能(欲を言えば3日間)
  • 10~30分程度で満充電できる

逆に、「連続使用5日間可能」とか言われても5日に1回だけ充電みたいな生活習慣を作るほうが大変でしょう。ウェアラブルデバイスは毎日充電、これをベースに多少余裕が有るくらいで十分です。逆に、バッテリーのためにデバイスが大きくなったり重くなったりするほうが損でしょう。

測定結果はほぼ直感通り

簡単に言うと、歩けば数値が増えます。出社日の運動量のほぼ全ては通勤時の最寄り駅への徒歩です。以下、細かい気づきを箇条書きにします。

  • エスカレータやエレベータを使わずに階段を使うのは効果的。
  • 昼はオフィスでお弁当食べるよりも、外に出て飲食店で食べるほうが運動になる。
    • 歩いて外に出るから考えてみれば当たり前。
    • 1日の総量から見ても数値的な差はかなり大きい。
  • 同じ距離を走っても歩いてもそんなに運動量は変わらない。
    • FuelBandの測定方法の問題かもしれない。
  • 太鼓の達人をプレイするとめっちゃ歩数が増える。

数値だけ見ても行動は変えられない

測定結果を見て実際の行動に反映できるかは、個々人の知識や意思に依存します。私はFuelBandをつけて運動する気になったかと言われるとNoです。月に1回位は数値の確認をしていますが、特に何も思うことはありません。

ただ、休日に沢山歩いたりした時に数値をみると嬉しくなるのは確かです。そういう時の話の種にはなります。

おわりに

やはり、”収集した値を専門知識と掛けあわせて具体的なアドバイスをしてくれるサービス”が必要だなぁというのが現時点の感想です。あと、実際はおしゃれな万歩計にしかならないので、お安く済ませたい人は万歩計を買えばいいと思います。

この話題を載せるのにちょうどいいアドベントカレンダーがあったら教えて下さい。

 

RailsのActiveJobからurl_helperを呼ぶ

RailsのActiveJob内から*_urlヘルパーを呼ぶ方法です。

どんなときに使う?

Jobから何かしらのAPIにアクセスして、そのパラメータにcallbackアドレスを設定する場合など

やり方

  1. url_helpersをinclude
  2. default_url_optionsをoverride(これをしないとhost名がわからないよって怒られる)
  3. お好みでBaseJobを作ってそれを継承する形でHogeJobを作成する
# app/jobs/base_job.rb
class BaseJob < ActiveJob::Base
  include Rails.application.routes.url_helpers

  protected

  def default_url_options
    { host: ENV['HOST_NAME'] }
  end
end
# app/jobs/hoge_job.rb
class HogeJob < BaseJob
  queue_as :default

  def perform(*args)
    # something
    # foobar_urlが呼べる
  end
end

ウェアラブルには専門家の洞察が必要

Xiomiが1300円のウェアラブルデバイスを発表した。
http://japanese.engadget.com/2014/07/23/xiaomi-1300-mi-band/

私はnike fuelband SE+を愛用しており、2013年の12月からほぼ毎日欠かさず着用して活動量を図っている。
しかし、数字を見てもその数値が実際に自分の健康にどのように影響しているかがわからない。

わかることは以下程度。
  1. 1日の平均値
  2. ランニングなどの意識して行っている運動の運動量がわかる。
  3. 多めに歩く機会があると数字が上昇していることがわかる。
活動量計は、家計簿などと違い数字を視覚化してもその効果が読み取りにくいため、達成感は得られても実際の健康管理には役立て辛い。専門的な知識がなければ、自分が健康であるために必要な運動量もわからない。

やはり、専門家の洞察が必要である。

現実的な案としてはこんな感じか。
  1. 医療関係者がロギングして、健康診断時や医療行為の際の参考にする。
  2. スポーツトレーナーが数値を元にメニューの作成や提案に役立てる。

1300円程度であれば、会社の福利厚生として配布することもできるし、そこから得られるデータを(産業医等を使って)社員の健康管理に利用するのは悪くない考えのように思える。
スポーツジムも入会特典で配るのは難しくないだろう。

今後、単にデバイスを作るだけでなく、それから得られるデータを活用するところまで含めたサービスを作ることが求められることは間違いない。

スケジュールのバッファを食いつぶしてしまう人へ

後輩が「作業をふられた時にいつも期限ギリギリまで作業してしまう。どういう心持ちでやれば余裕を持って作業を完了できるようになるか?」と言っていたのに対して、とりあえず返答した内容を書きます。以下の内容を意識すれば少しはマシになるかと思います。

あくまでも業務上での作業を前提として話していますので、私生活とかでは参考にならないと思います。あしからずご了承下さい。

作業時間は測定されている

通常、業務上の作業時間は管理簿に記録されます。もし、あなたが期限直前に終わるように調整して作業すれば、記録上にはその時間が残ります。
同じような内容の作業を再度行う場合、それは作業時間の見積りが本来の時間とずれる原因になります。

バッファは特定の目的があって作られている

スケジュールにはバッファを用意します。バッファは作業上で発生する不測の事態に対応するためのものであり、トラブル、バグ、認識齟齬などのために用意するものです。
あなたがバッファを食いつぶしている場合、原因の報告が求められる筈です。何も起こってないのであれば予測時間からバッファを差し引いた時間で作業が完了する筈ですから。

蛇足:「できるだけ前倒し」は無意

この手の相談に対して「できるだけ前倒しで作業したほうが何か問題が生じたときに対応できる。(だからできるだけ前倒しで作業しよう)」という旨の返答する人がいますが、この意識は無意味だと思います。「できるだけ早く」という曖昧な目標設定では人の行動は変わりません。

Facebookのアカウントを簡単に交換する方法

プログラミングとは関係ない話ですが、便利な機能のわりにあまり知名度が高くないようなので、記事として書いてみることにしました。

想定するシーン

イベントや勉強会などで、そこで初めてあった人と連絡先を交換しようとすることがあるかと思います。その際に、電話番号やメールアドレスではなく、FacebookなどのSNSアカウントを交換しようとしたことはありませんか?

人にもよるかと思いますが、今では電話やメールよりもFacebookTwitterやLINEのようなSNSので連絡しあう事のほうが多いという人もいるかと思います。

この方法はそういった「実際に対面してる人とFacebookアカウントを交換しあう」という言ったシチュエーションを想定しています。

今、みなさんは「その場で名前を聞く」→「その名前をFacebookで検索」→「検索結果一覧から相手のアカウントを探す」って感じでやってるかと思います。

名前を入力するのが結構面倒くさいですよね。名前を打ち間違えたりなんかしょっちゅうです。あと、案外似た名前の人がいて、検索結果から探すのも一苦労だったりします。

やり方

実はAndroidiOSFacebookのアプリには、(多分)最初からそういったシチュエーションを想定した機能が搭載されてます。

QRコードという名前のFacebookアプリです。
(Androidの画面です。モザイクかけてます)
f:id:kazasiki:20131201172827p:plain:h400

このアプリを開始するとこんな画面に行きます。 (モザイクかけてます)
f:id:kazasiki:20131201174220p:plain:h400

このQRコードを読み取ると、そのユーザのプロフィールページに飛べるという寸法です。また、アプリ画面の右下に『コードをスキャン』という項目がありますが、これを押すとQRコードのスキャンモードに移行します。

プロフィールページにさえ行ければあとは友だち登録するだけですね。

応用編

この方法自体はTwitter等のアカウントを交換するときにも使えます。要はプロフィールページのURLをQRコードにしておいて、それをQRコードスキャナでスキャンするというだけですからね。

自分のプロフィールページのURLを事前にQRコードの画像にしておいて、ショートカットをホーム画面上においておくと便利かと思います。ただ、相手がそういった準備をしてくれていることは殆ど無いと思うので、最初に自分を相手に登録してもらって、それに対して登録を返すという形になることが多いかと思います。

おわりに

便利な機能を利用して、よりよいFacebookライフを!

この分岐をどうやって書く?

1.今回の問題

複雑な分岐の書き方で迷ったことはありますか?
今回皆さんに試しに書いていただきたい分岐の処理はこちら。簡単だけどちょっと面倒くさいものです。
f:id:kazasiki:20130615100507j:plain
2,3分で書いたので少し汚いけど、許して(^_^;)

文章で説明すると、変数flagの値によって処理を分岐させます。
flagの値が1の場合は、judge()関数を動かし、結果がtrueであれば、doSomething()を実行します。
flagの値が2の場合は、judge()関数を動かさず、ただdoSomething()を実行します。
flagの値が上記以外の場合はなにもしません。
簡単な処理です。

2.実際に書いてみましょう

さて、では以降の文章を読む前に、皆さん各自実際にプログラムとしてこの処理を書いてみましょう。
チラシの裏にペンで書いてもいいし、テキストエディタに書いてもいいです。
簡単でしょ? 1分もかからないかと思います。
書いた?
ちゃんと書いた?
書いた人は下に読み進めて行きましょう。

3.答え合わせ

さて、どんな感じになりましたかね?

ちなみにこんなかんじの回答パターンを用意してみました。

private void hoge(int flag) {
    // flag = 1 or 2 or 3

    // Pattern1
    if (flag == 1) {
        if (judge()) {
            doSomething();
        }
    } else if (flag == 2) {
        doSomething();
    }

    // Pattern2
    boolean temp = false;
    if (flag == 1) {
        temp = judge();
    }
    if (temp || flag == 2) {
        doSomething();
    }

    // Pattern3
    if ((flag == 1 && judge()) || flag == 2) {
        doSomething();
    }

    // Pattern4
    switch (flag) {
    case 1:
        if (!judge()){
            break;
        }
    case 2:
        doSomething();
    default:
        break;
    }
}

細かいバリエーションは抜かして思いつく限りのパターンを書いてみたのですが、皆さんの回答はどれかに当てはまってでしょうか?
動作確認はしたので、正しくは動くかと思います。

4.どれが好き?

上に挙げた4つのパターンはそれぞれ長所と短所のようなものがあります。
読みやすいかどうかとか、正規化されている(処理が冗長でない)かとか、汎用性があるかとか。

まず、パターン1はそれぞれのflagの値による動作が追いやすいです。
プログラムの中でflagが処理制御用の変数であるならば、それ毎に処理が追えたほうが良いという考え方もあります。
ただし、見て分かる通りdoSomething()が2回書かれており、無駄があります。あと「要するにflagが2の時はjudge()しなくいい」という見方はしにくいですね。

次に、パターン2は処理に無駄はありませんが、パッと見た感じがわかりにくいかなと思います。何より一度判定結果をboolean変数に代入しているので、直感的でなくなってしまっています。

パターン3も処理に無駄はありませんし、行数も少なく、見た感じは一番スマートですね。
ただ、一行に固めて書いた影響で、flagとなっている変数名が長い名前に変更になった場合などに見難くなる可能性が高いです。judge()に関しても、本当はもっと長い関数名にするでしょうし、実際にはflagはintではなくStringでequals()を使った判定をするかもしれません。例えば、

// Pattern3
if ((myMostFavoriteArtist.equals("ももいろクローバーZ") && judgeDoSomethingRunning()) || (myMostFavoriteArtist.equals("私立恵比寿中学") ) {
    doSomething();
}

みたいな。

パターン4はswitch文を使った用法で、直感的に理解しやすいかもしれません。
ただ、このプログラムを理解するには「javaのswitch文がラベルジャンプ的に動作していて、breakしない場合はどんどん下の行を実行していく」ということを知っている必要があります。switch文は一般的(?)には、case毎に処理を記述してbreakするような用法が多く、このことを理解していない人は意外に多いです。プログラミング言語によってはこういうふうになってないものもあった気がします。
また、javaのswitch文はswitch条件に入れられる変数の型が決まっています。私の記憶だとenumとString以外の参照変数は入れれません。実数も入れれません。条件も必ず一致条件で、比較演算子は使えません。今回のケースは「int型の一致判定」だったので、switch文を使えましたが、言語的にswitch文は案外制約が多いのです。

5.まとめ

分岐処理はいろんな書き方があって、それぞれ長所短所があって、適切に使いわけなければいけません。
コードは皆の共同所有物なので、他の人のレベルに合わせる必要もあります。
設計上の思想や業務上の要件によって、どう書いたほうが見やすいか、変更に耐えうるかも変わります。
万能の回答はありませんが、各自気をつけて書いて行きましょう。
この記事が何かのヒントになれば幸いです。

Javaの配列に関するちょっとややこしい話

昨日、現場の人のソースを読んでて気になったので指摘したのがあって、それがどんなソースだったのかご紹介。
実際に修正してもらおうとしたところ、その人がしどろもどろになってたのが面白かったので。


私が見たソースはこんなかんじでした。もちろん色々端折ってます。
要するに、「分岐させた先で配列変数に値を設定して、その後に配列変数の値を参照してなんらかの処理をしたい」のです。

private void myMethod(boolean foo){

  // 分岐
  if(foo){
    // 配列変数に値を代入する
    String bar[] = {"月", "Mon" };
		
    // 変数の値を使って何かする。
    System.out.println(bar[0] + "曜日は英語で" +  bar[1] +"です");
  } else {	
    // 配列変数に値を代入する
    String bar[] = {"火", "Tue" };
		
    // 変数の値を使って何かする。 
    System.out.println(bar[0] + "曜日は英語で" +  bar[1] +"です");
  }
}


ぱっと見でわかりますが、上に書いた処理の『// 変数の値を使って何かする。』の部分は同じ処理が分岐の両方に書いてあり無駄があります。
そこで私は実装者にこのような指摘を行いました。


『// 変数の値を使って何かする。 』の部分をif文の下に出してください。


ぱぱっと実装者の人が書いたのはこちら。
分かる人はわかると思いますが、コンパイルエラーがでます。
配列変数barのスコープはif文の各分岐内で切れてしまっているため、分岐の外では使えません。

private void myMethod(boolean foo){

  // 分岐
  if(foo){
    // 配列変数に値を代入する
    String bar[] = {"月", "Mon" };
  } else {	
    // 配列変数に値を代入する
    String bar[] = {"火", "Tue" };		
  }

  // 変数の値を使って何かする。 
  System.out.println(bar[0] + "曜日は英語で" +  bar[1] +"です");
}


ここからは私が順を追って説明しました。
まず、配列変数barのスコープを変えるため、宣言をif文の前に出します。

private void myMethod(boolean foo){

  // 分岐の前に変数を宣言する
  String bar[];

  // 分岐
  if(foo){
    // 配列変数に値を代入する
    bar = {"月", "Mon" };
  } else {	
    // 配列変数に値を代入する
    bar = {"火", "Tue" };		
  }
  // 変数の値を使って何かする。 
  System.out.println(bar[0] + "曜日は英語で" +  bar[1] +"です");
}


一見妥当なように見えますが、まだコンパイルエラーがでます。
分岐処理内で行なっている配列変数への代入は、正常にコンパイルできません。


理由を説明すると、Javaでは配列を生成できるタイミングが限られています。

  1. 配列変数を宣言する時
  2. 配列をnewする時

この2つのタイミングでしか配列を生成することが出来ません。

従って、処理の途中に下のような処理を書き込んでもコンパイルエラーになります。

bar = {"月", "Mon" };


Javaでの配列は int などのプリティブ型と違いオブジェクトとして扱われます。
なので、本来newを使わずにオブジェクトを生成することができません。


「じゃあ配列変数を宣言する時に初期化する場合はなんでnewいらないの?」と言われると、Javaが特別に気を効かせてくれているとしか言えません(笑)
(Stringなんかも特別扱いされてますね)


ということで、Javaで配列を生成したい場合はこうなります。

bar[] = new String[] {"月", "Mon" };

先ほどのプログラムは正しくはこうなります。

private void myMethod(boolean foo){

  // 分岐の前に変数を宣言する
  String bar[];

  // 分岐
  if(foo){
    // 配列変数に値を代入する
    bar = new String[] {"月", "Mon" }; // newを追加
  } else {
    // 配列変数に値を代入する
    bar = new String[] {"火", "Tue" }; // newを追加
  }
  // 変数の値を使って何かする。 
  System.out.println(bar[0] + "曜日は英語で" +  bar[1] +"です");
}


Javaの配列の扱いは特殊なので、詳しい仕様を押さえてない人は
プログラミングをそれなりにやっててもちょっとつまずくのかなと思います。


以上、Javaの配列に関するちょっとややこしい話でした。