2013-04-29

input type="datetime" で、ブラウザから素早く日時を入力する

ブラウザから日時を入力させたくて、どうすれば素早く入力できるのかなぁと、いくつか試しました。前提は Bootstrap の responsive を使って、PC とスマートフォンで同じHTML/CSS を使う、ということです。別に、PCとスマートフォンで分けてもいいんだけど、まずは動くものを作りたいので、ブラウザ判定とかしない方向で。一方で、自分が使っている環境、Chrome on Mac OS X と Safari/Chrome on iOS 6、動けばよいので他のブラウザでの互換性は気にしていない。Android とか危うい気がする。

いくつか試してみたところ、 HTML5 の input タグの属性に type="datetime" や type="datetime-local" を指定するのが、いちばん入力しやすく、11秒で入力できました。入力しやすさ、の指標は「iPhone の Safari を使って、テキストフィールドに『ビール飲むぜ』と入力し、さらに、今から1時間以上先のキリのいい時間時刻(今が19:30なら21:00)を入力するまでの時間」です。

他の方法は以下のとおり。

  • すべてテキストフィールド: 約30秒
  • select と option タグ。分は10分刻み: 約30秒
  • Bootstrap DateTime Picker
    • 日時をひとつのフィールドで: 約30秒
    • 日付と時刻を、別々のフィールドで: 約20秒

意外とどれを使ってもあまり変わらず。iPhone の場合、wheel scroller っていうんですかね、あれを、複数項目に対して使えるかどうか、が鍵なのかも知れません。

2013-04-27

Go で時刻から文字列を生成する

Go で時刻を文字列にフォーマットしたくなりました。結論から言うと、time.Time 型の Format 関数の引数に、「2006年1月2日午前3時4分5秒」を、どう表現したいのかを指定します。

t := time.Time.Now()
var x := t.Format("01/02 15:04")

とすると、現在時刻をこの書式で文字列になります。

最初、t.Format("%y") とか %Y とかしても、そのまま %y とか表示されてしまい、困惑していました。ドキュメントを、一瞥したら

The layout defines the format by showing the representation of the standard time,

Mon Jan 2 15:04:05 -0700 MST 2006

which is then used to describe the time to be formatted.

と書いてあって「だから年や月のフォーマットはどうやって指定するんだよ」と思ったわけです。

ソースをしばらく眺めていて、あーそういうことであったか、と、やっと分かりました。Parse() 関数も同じ方法で文字列から時刻に変換します。

時刻文字列の書式をこんな方法で指定するのは初めて知りました。知らなかっただけで、実はメジャーなのかも知れません。

明日の自分へ: ドキュメントを読めと、あれほど。

2013-04-26

定期的に連絡取りたい人の管理

Luper というアプリを知りました。毎月とか、半年ごととかに連絡とりたいコンタクトを登録しておくと、リマインドしてくれるというもの。

今じゃだめ、後でやる必要がある、というタスクの管理も有用であるなぁと最近思い始めました。いろんなアプリがあると同期や移行が面倒なので、Luper は使わないけど。

2013-04-25

8080 番ポートがいつも使われていた

Mac を使っていて、いつも再起動するとローカルの 8080 ポートが使われていて、Google App Engine のローカルサーバを立ち上げようとするとエラーがでました。それで Evernote にメモしてあるコマンドを叩いて終了させる、ということを繰り返していました。なんか、めっちゃバタバタしているとき(つまり、いつも)に、とりあえずやって、そのままだったのです。

自分のクビをしめるのはやめておこう。ってことで。動いていたのは Jenkins です。朦朧とした頭で、ビルド、インストール、設定したら自動で立ち上がるようになっていました。

  • /Library/LaunchDaemon/org.jenkins-ci.plist を削除する。これが起動時に呼ばれていました。
  • /Library/Application Support/Jenkins ディレクトリを削除する。この中に Jenkins 起動スクリプトが入っていました。
  • /Application/jenkins.war を削除する。本体。

2013-04-21

スクワットは続くのに、早起きはできないのはなぜか

生活や習慣を変えようと、もう38年くらい努力しているわけですが、なかなかうまくいいきません。Runtastic Squats というアプリのフリー版を使っています。1日おきくらいのスケジュールで、ちょっとずつスクワットの負荷が上がっていくプランを提示してくれるアプリです。加速度センサでスクワットの数も数えてくれます。気に入ってて、スケジュール通りに進んでいますが、もうすぐフリー版のレベル1が終わってしまうので、おそらく有料の Pro に乗り換えることでしょう。Pro になると通知もしてくれるそうです。

一方で、Lift というアプリで早起き習慣を身につけようとしていますが、一向にうまくいきません。Lift は身につけたい習慣を登録/選択して、できたらチェックするというアプリです。別にアプリ自体に大きな欠陥があるようには思えません。Squats に比べて扱う範囲が格段に広いわけですが、それが大きな問題とも思えないわけです。

そこで、早起きの時刻設定の敷居が高すぎる仮説です。Squats は設定がよくできていて、第1回目のセッションは、5回、4回、3回、3回 みたいなのです。こんなの余裕です。一方で、早起き設定は普段の起床時刻よりも、1:30くらい早くてこれは余裕とは言いがたい。いきなり敷居が高いわけです。何かのライフハック記事で「習慣を変えたいなら、最初は damn easy な変化にしておけ」と書かれていました。

というわけで、普段の起床時刻から、5分早くするみたいな damn easy なところから始めようと思います。今夜、酔ってるんで、明日はちょっと厳しいかも知れません。


requests でテストした、その後ですよ

Web API をもつアプリケーションのテストを、Python と requests ライブラリを使って書いています。それはよいのですが、テストが通らなかったときですよ。酔ってますよ、もう、休日に仕事してぜんぜんはかどらなくて。それと、これとは別ですけど。

アプリケーションが Python で書かれていない場合、開発者が Python 環境を自由に使えない場合があります。テストのレポートを再現するためだけに、Python モジュールをインストールしてもらうのも気が引けます。

というわけで、requests を使ったアクセスを、 curl で再現するように hooks に追加することにしました。最初から curl 使えよとか、いろいろあると思いますが、すでにレイヤをまたいで requests 使ってたもので。

import curledrequests as requests
requests.debug = True
requests.post('http://example.com/', auth=("foo", "bar"), data={"hoge":"moge"})

のように書くと、

$ curl http://example.com/ -u 'foo:bar' -w '\n%{http_code}\n'
... ここに body が入る ...
200

と表示されます。これを Web API 開発者に渡して、再現してもらうことができます。gist においてあります。

2013-04-13

Go Conference 2013 Spring

Go Conference 2013 Spring 略して GoCon に行ってきました。

A Tour of Go

公式チュートリアルであるところの A Tour of Go というのがあります。1ページにコードと文書があって、Run ボタンをクリックすると実行結果が見られます。以前にこれを読んだことがあったのですが、よく分からないまま Run ボタンを押して、どんどんページを送っていって、結局何も分かっていない、という状態になりました。そこで今回は写経することにしました。

ダウンロードサイト から、OS X のバイナリをダウンロード、インストールして写経をしていたら、主催者の @ymotongpooGo Playground を教えてくれました。ブラウザで Go のコードを書いて、その場で実行できます。実行時間が短く、サードパーティのライブラリを必要としないコードであれば、これで簡単に実行できます。そういうわけで、Go Playground でチュートリアルをやっていきました。

ついでに書いたコードを簡単に共有するための URL も生成できます。

変数とポインタ

Go では変数とポインタが明確に区別されます。普段つかっている Python では名前にオブジェクトをバインドするモデルで、事実上すべてがポインタみたいなものです。ここはちょっと注意が必要でした。Go では x = y と書くと x に y のコピーを代入します。ポインタ(というか参照というか)は明示的に & を使います。

package main
import "fmt"

type Foo struct {val int}

func main() {
     f := Foo{0}
     g := f   // 変数なので f のコピー
     h := &f  // ポインタ
   
     f.val++

     fmt.Println(f.val)  // => 1
     fmt.Println(g.val)  // => 0
     fmt.Println(h.val)  // => 1
}

一方 Python では x = y と書くと、x に y のポインタ(というか参照というか)を代入します。コピーを代入するには明示的に copy モジュールを使うという考え方です。

from copy import copy

class Foo(object):
    def __init__(self, val):
        self.val = val

f = Foo(0)
g = copy(f)  # copy
h = f        # pointer

f.val += 1

print(f.val) # => 1
print(g.val) # => 0
print(h.val) # => 1

goroutine

並列処理/並行処理を Go は言語レベルでサポートしていて、go foo(..) と書くと、foo() 関数の呼び出しが非同期で実行できます。

トイレで「goroutine ってコルーチンなんだなぁ」と思っていたのですが、席に戻った瞬間 @Jxck_ さんの発表 で「goroutine はコルーチンではありません」と電撃発言です。どうやら OS のスレッド上で動作する並行ルーチンとして実装されているようです。

実装はおいといて、コルーチンを使ったトランポリンみたいなことが簡単に書けそうです。ちなみにトランポリンの理解は非常に曖昧です。

goroutine として呼び出す時でも、関数は通常の引数をとるので、ポインタを渡すことができます。ということは、複数の goroutine で同じオブジェクトを参照するという事態が起こるんだろうなぁと考えて、簡単なコードを書きました。

package main

import (
  "fmt"
  "time"
)

type Foo struct {
  value int
}

func main() {
  f := Foo{0}  // 初期値は 0
  fmt.Println(f.value)

  go Incr(&f, 1, 1)  // +1
  go Incr(&f, 2, 200) // +2

  time.Sleep(1 * time.Second)
  fmt.Println(f.value)  // => 2
}

func Incr(f *Foo, delta int, wait time.Duration) {
  oldValue := f.value  // 古い値を取得して
  time.Sleep(wait * time.Millisecond)  // しばらく休んで
  f.value = oldValue + delta  // 上書き
}

プロセスをまたいでいる時にどうなるかは不明です。こんなときにスレッドセーフじゃないようなコードを書くなという話なわけです。

並列処理といえば…

これは明らかに誤解なのですが、気分がよかったので、Twitter 上では訂正せずにいました。

以前の職場で開発環境/ツールのマーケティングをしていて、そのラインナップに FPGA 用にコードを書くツールが含まれていました。もともとグラフィカルに記述すると、PC 用に実行形式のバイナリを吐き出すというツールで、簡単に並列処理を記述できたのです。そこ発展して FPGA を搭載した I/O ボードの処理をデプロイできる、というツールです。

そんなわけでハードの設計は、まったくできません。ただFPGAを使うときにはプログラムの書き方が、大きく変わる、というのは感じています。Go も並列処理を念頭においた言語らしいので、あらためて並列処理を考える時期にきているようです。

2013-04-07

mock.patch() が置き換えする対象

mock.patch() の挙動について質問されて、即答できなかったので、簡単に調べ直してみました。

簡単なサンプル

まず以下のようなコードを想定します。

# foo.py その1
import random

def pickup(seq):
    return random.choice(seq)

random.choice() 関数は呼び出すごとに挙動が変わり、テストしにくいので、mock の出番です。

# test.py
from unittest.mock import patch
import foo

with patch('random.choice') as m:
    m.return_value = 0
    assert foo.pickup([1, 2, 3]) == 0

import の仕方を変えるとモックに失敗する

ここで foo.py の書き方を以下のように変えます。

# foo.py その2
from random import choice

def pickup(seq):
    return choice(seq)

pickup() 関数を外側から見た挙動は同じです。しかし、なんということでしょう、test.py を実行すると assert が失敗します。pdb や print を使って調べるとわかりますが、choice() 関数が Mock オブジェクトになっていません。

名前に対してパッチしている

with patch('random.choice') のコンテクストに入るとき、大雑把に以下のようなことが起こります。

import random
random.choice = Mock()

※ 実際には Mock ではなく、そのサブクラス MagicMock ですが、この議論の本質ではないので、Mock で話を進めます。

Python のプロセスでは、モジュールはシングルトンとしてふるまうため、プロセス内で random.choice という名前は、Mock オブジェクトを参照することになります。foo.py その1の中では random.choice という名前を使っているため、Mock オブジェクトを参照します。

ところが foo.py その2 は random.choice という名前を参照しているわけではありません。from random import choice すると、大雑把に以下のようなことが起こります。

import random
choice = random.choice
del random

patch() 適用後、名前の参照先は

  • グローバルな random.choice => Mock オブジェクト
  • foo.py の choice => 元の choice 関数

のようになっています。このため、foo.py その2では choice がモックにならないのです。

名前空間 foo 以下の名前に対して patch を適用する

じゃあ、どうするのかというと、普段は patch('foo.patch') としています。上記の問題が発生するような状況だというのが分かっていれば、これで解決です。しかしながら、foo.py を、その1からその2に実装を変えたとき、テストが fail するけれど、どこがどうなっているのか見つけにくいな、と思いました。

その1のときに、test.py に patch('foo.random.choice') と書くとよいのでしょうか。こうすると foo.py その2に書き換えてテストすると、fail ではなくて patch() 実行時にエラーが出るので、名前がおかしいことに気付くような気がします。

2013-04-06

Robin Williams / ノンデザイナーズ・デザインブック

文書デザインの考え方を紹介する本

今年、付きまとっている @ymotongpoo が読んでると聞いて、ノンデザイナーズ・デザインブックを再読しました。プログラミングでいうところの、デザインパターンとも言うべきプラクティスが解説されています。

この本自体は以前から持っていましたが、流し読みしただけで、実践したことはありません。使う機会がなかったのと、この本がパターンのカタログであると捉えていなかったからです。

再読したので、忘れないうちの実践として、このブログのデザインを変更しました。Blogger.com に最初から入っている「シンプル」というテーマをベースに、CSS だけを変えました。HTML は触っていません。

整列、近接、反復

あなたは文字揃えの扱いに慣れてきました。しかしいっそうの訓練を積むまでは、 1ページに1種類の文字揃えだけを使うようにしてください。つまりすべての文字列を、左揃えか、右揃えか、中央揃えかのどれか一つにするのです。

もとのデザインではタイトル、エントリのタイトル、本文が揃っていませんでした。そこで、これらの左端を揃えました。

右のカラムは元々揃っていたので、そのままです。

もし関連する項目がいくつかあるなら、それを近接させてグループにしましょう。直接的な関連をもたない項目は離しましょう。

ブログの論理的な構成は、以下のようになっています。


  • ヘッダ
  • 記事群
    • 記事
      • 日付
      • 題名
      • 本文
        • セクション
        • [セクションタイトル]
        • 文章


これまではセクションタイトルのフォントが小さくて、セクションを認識しづらい見栄えでした。大きくすると、まとまりが見えるようになりました。

反復は、一貫性をさらに強化したものです。約物、書体、線、色など、あなたがす でに繰り返し使っている要素を見つけて、そのうちの一つを強調して反復の要素と して使えないか考えてみましょう 

ブログの場合、似た構成要素が反復するつくりになっています。絵や文章を配置するのではなく、文書構造にスタイルを適用しているので、自動的に反復が適用できます。

コントラストが課題

コントラストは、染みを隠すために壁を塗るのに似たところかあります。染みの上に塗る色が周りの色とだいたい同じではだめで、正確に同じ色にするか、それが不可能なら壁全体を塗り直すしかないのです。

今回の作業ではコントラストを活用できていません。タイトルを目立たせていないため、全体的にメリハリがないのです。

広告なんかだと、読む気がなかった人に強制的に提示するので、タイトルが目立つことは重要かも知れません。このブログへの流入は、リンクか検索エンジンからのほとんどです。ブログのタイトルが目立ったから読む、という因果関係はまず成立しないでしょう。かといって本文との差がないと構造が分かりにくいものです。そんなわけで、ヘッダ部分はフォントを大きく、色を薄くしました。

そもそもブログ名が悪いのかも知れません。見栄えではなくて、コンテンツの問題なので、今回は保留。

また、色のセンスがないのでモノトーンにしていますが、本当は色を使わないほうが難しいはずです。marippe の「色彩センスのいらない配色講座」や、フルカラー新装増補版が助けになるのだと思います。

問題解決のフレームワーク

実践してみたところ、かなりマシになりました。特に整列の効果は絶大です。インデントが好きで Python を使っているのに、もっと早く気づかなかったのが不思議なくらいです。

これまで、漠然と気に入らないなあ、と感じていたことに対して、体系的に問題と解決を捉えられるようになったのが最大の収穫です。