YAMAGUCHI::weblog

菊池桃子に憧れてこの桃の世界に入りました。

腰痛になる前に良いマットレスに変えるべき

はじめに

こんにちは、Go界の中村鴈治郎です。GW真っ只中ですが、みなさんはいかがお過ごしでしょうか。僕は家でコード書きつつ、連休明けの出張の準備などをしています。 さて、今日はテクノロジーとは一切関係のない、ベッドマットレスの話です。

結論:マットレスは良い物を買うべきである

今日の結論からいいます。ITエンジニア、あるいはデスクワーク中心の方々は、マットレスは良い物を買うべきです。

「なにを今更言ってんだ、当たり前だろ」という話です。ですが、最近知人で腰痛や睡眠に悩む人がちらほら出てきていて、そういったマットレスを買い換えそうな人に僕が毎回いま上で紹介したマニフレックスのマットレスを紹介してきました。で、そろそろ紹介がテンプレ化してきたので、まとめておこうと思って書きました。

マニフレックスのマットレスを買って9ヶ月経った感想

そもそも僕がマットレスを買い換えたきっかけも腰痛でした。実際自分が運動不足もあって腰痛気味になったときにマッサージ師の方に「マットレスを買い換えたほうが良い」と言われ、@kotarokに相談したところ、マニフレックスのマットレスが大変良いと聞いたので、聞いた当日に即購入したのでした。

それから9ヶ月このマットレスで寝てみたら、もう快眠の毎日で、正直旅行や出張でホテルに泊まってもなかなかこのクオリティのマットレスに出会えていないので本当にレベルが高いんだなと実感しています。 そして、マットレスを買い換えてから1ヶ月もしないうちに腰痛はすっかりなくなりました。(正確にはマッサージで腰痛がほぐれたのですが、マットレスによる腰痛の影響が無くなったのと、多少の筋肉の張りは睡眠で解消できるようになった、ということです。)

良さそうだ、とはいえ購入は躊躇う、という方へ

実際に新宿や渋谷に行けば、無印と東急ハンズがあるので両方試し寝ができると思います。毎日使うものですし、簡単には入れ替えが出来ないものなので、ぜひ実際に試して下さい。(東急ハンズにはマニフレックスのマットレスが展示してある)

マニフレックスのマットレスは「高反発」を売りにしたウレタンマットレスなので、体重がある程度ある人にはお勧めです。ウレタンマットレスというとまず連想されるのがテンピュールですが、テンピュールは「低反発」を謳っています。テンピュールのマットレスに寝たことがある人ならわかると思いますが、低反発ウレタンは体が沈み込みますよね。しかし高反発ウレタンは、体のラインに沿って凹みはするものの、体は沈み込まず、非情に心地よい支えを得られます。このへんが多少好みがわかれるところで、人によっては「ちょっと固いかも」と感じるかもしれません。ただ、一度試してみる価値は確実にあると思います。

良いマットレス=高いマットレスなのか

例えば上で紹介したマットレスはマニフレックスの中でも上位のシリーズなんですが、シングルサイズで42000円です。42000円と聞くと高いと感じるかもしれませんが、このマットレスはスプリングではなく高反発ウレタンなので経年でのヘタリがスプリングマットレスよりも穏やかです。 例えばとても短く見積もって5年で寿命が来るとして、5年毎日使うものなので、日割りで考えるとおよそ23円。毎日23円で快眠を買えるなら安いものです。世の中にはRedBullを毎日飲んでいる方もいるそうですが、1本200円以上しますね。これで考えたらこのベッドの1週間分以上の価格です。高い。そう考えると、良いマットレス=高いマットレスというわけでは無さそうです。

実際大塚家具などに行けば、キングサイズで180万円のベッド&マットレスを売ってますが、そのレベルまでとは言わなくても、このような良いマットレスは買えます。

比較対象として同じ価格帯の無印のポケットコイルマットレスはシングルサイズで31500円です。しかしマニフレックスのマットレスと比較して1万円の差でこの程度のクオリティだとしたら、申し訳ないですが、もう買おうとは思わないでしょう。

また、いま見たら、新しいラインナップが出てました。こちらはセミダブルで僕の買ったものと同じ価格帯で買えるようです。僕のモデルは通気性も考慮したモデルなので吸湿性の高いカバーだったのに対して、こちらのモデルは純粋にマットレスのみの提供なので価格は無印のポケットコイルスプリングマットレスと同等になっています。

おわりに

良いマットレスを買って、快眠を得ましょう。

Go Conference 2013 spring開催しました

はじめに

こんにちは、Go界の山本礼三郎です。タイトルのとおり、昨日Go Conference 2013 springを開催しました。

正直ネタドリブンで始まったイベントではありますが、1.0リリース前の印象を拭いきれていない現状をなんとか打破したいと思い、僕が聞いてみたいプレゼンターにお話してもらいました。グローバルで見ても非常に密度の濃いイベントになったと思います。特に鵜飼さんとDerekのプレゼンは、美辞麗句だけでない、本当のGoの姿を表現したものだったのではないでしょうか。 また半年後くらいに開催したいと思っていますので、次回も楽しいイベントにしましょう!

御礼

会場を提供してくださったオラクルの @yokatsuki さん、有難う御座いました。大人数収容できる会場などなかなか無い中、快諾してくださったのは大変有り難かったです。 また受付とドアマンを引き受けてくださった @nuki_pon さん、@RicoImazu さん、@tennten さん、有難う御座いました!おかげで大変スムーズに進行出来ました。

ハンズオン講師をしてくれた、@tenntennと@IanMLewis、DanとAlfonsoもお疲れ様でした。次回はA Tour of Goの人数を減らして、もっとハンズオンBやCを増やしたいですね。 最後にプレゼンターの皆様、素晴らしいプレゼンを有難う御座いました。正直Goの情報は英語/日本語にかぎらず少ない状況ですので、非常に貴重なものとなりました。今後のイベントでもぜひ発表をお願いします!

発表資料

感想等

ブログエントリ

Togetter

お知らせ

もしGoに興味が湧いたらGoogle+コミュニティに参加してみてください!

名言集botをTwitter API 1.1に対応&GAE/Goに載せ替えた

Go

はじめに

こんにちは、Go界の左卜全です。出張で韓国に来ています。アニョハセヨ。 「Twitter API 1.0が廃止になるよ」というアナウンスがあってからぼーっとしていたのですが、よく考えたら、それで動かしている @wisesawTwitter API 1.1に対応させなきゃまずいなと気づきました。さらに、なんと恐ろしいことにこのbotPython 2.5で動いていたのです。GAE/PythonももうPython 2.5のサポート打ち切りですよ。 ダブルパンチでサポート打ち切られちゃうんで、コードを書きなおそうと思い立ち、GAE/Goで動かすことにしましたよ。

はまったところ

結構詰まっちゃうかなあと思ったけど、3rd partyライブラリ使ったらさくさく書けてしまいました。はまったところは2つくらい。

  • code.google.com/p/go.net/html を使うときはnetレポジトリに入ってる他の余計なパッケージのディレクトリを消し去らないと、bad import "syscall"のエラーがでてデプロイ出来ない。(ipv4パッケージがsyscall呼んでる)
  • appengine/urlfetch経由で生成されたhttp.Clientを使わないといけないので、勝手にhttp.DefaultClient使うようなライブラリは全滅

あとは普通に、app.yamlとcron.yaml書いて、30分おきに特定のURL(下のコードでは/hoge)を叩くようにしただけ。楽ちん。

コード

とりあえず動かせばいいや、ということで書いたのがこんな感じ。Twitterの場合Access TokenとAccess Token Secretをダッシュボードで生成出来て、しかもずーっと使いまわせるので下のようなハイパー適当なコードが動かせてしまう。 他のサービスだったら、oauth.ClientのRequestTokenメソッドを使ってちゃんと取得しないとダメです。しかしいい加減TwitterもOAuth 2.0に移行してくれないかな。。。そうすればもっと楽に実装できるんだけど...

package wisesaw

import (
    "fmt"
    "io/ioutil"
    "net/http"
    "net/url"

    "code.google.com/p/go.net/html"
    "github.com/garyburd/go-oauth/oauth"

    "appengine"
    "appengine/urlfetch"
)

const (
    MeigenURI                     = "http://www.meigensyu.com/quotations/view/random"
    TemporaryCredentialRequestURI = "https://api.twitter.com/oauth/request_token"
    ResourceOwnerAuthorizationURI = "https://api.twitter.com/oauth/authenticate"
    TokenRequestURI               = "https://api.twitter.com/oauth/access_token"
    StatusesUpdateURI             = "https://api.twitter.com/1.1/statuses/update.json"
    UserAgent                     = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.31" +
        " (KHTML, like Gecko) Chrome/26.0.1410.43 Safari/537.31"
)

var IndexPageText = []byte(`<!doctype html>
<html>
<head><title>名言集.com bot on GAE/Go</title></head>
<body>
<h1>名言集.com bot on GAE/Go</h1>
<p><a href="https://twitter.com/wisesaw/">Follow me on Twitter</a></p>
</body>
</html>
`)

var oauthClient = oauth.Client{
    TemporaryCredentialRequestURI: TemporaryCredentialRequestURI,
    ResourceOwnerAuthorizationURI: ResourceOwnerAuthorizationURI,
    TokenRequestURI:               TokenRequestURI,
    Credentials: oauth.Credentials{
        Token:  "xxxxxxxxxxxxxxxxx",
        Secret: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    },
}

var accessCredentails = &oauth.Credentials{
    Token:  "xxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    Secret: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
}

// TweetStatus posts status using http.Client generated from utlfetch.Client(c).
func TweetStatus(c *http.Client, cred *oauth.Credentials, status string) ([]byte, error) {
    data := url.Values{
        "status": {status},
    }
    resp, err := oauthClient.Post(
        c,
        cred,
        StatusesUpdateURI,
        data)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, err
    }
    return body, nil
}

// FetchWisesaw fethes wisesaw text and its author.
func FetchWisesaw(c *http.Client) (string, string) {
    req, _ := http.NewRequest("GET", MeigenURI, nil)
    req.Header.Set("User-Agent", UserAgent)
    resp, err := c.Do(req)
    if err != nil {
        return "", ""
    }
    defer resp.Body.Close()

    node, err := html.Parse(resp.Body)
    if err != nil {
        return "", ""
    }

    var meigen func(n *html.Node, text, author *string)
    var f func(n *html.Node, text, author *string)
    f = func(n *html.Node, text, author *string) {
        if n.Type == html.ElementNode && n.Data == "div" {
            for _, a := range n.Attr {
                if a.Key == "class" && a.Val == "meigenbox" {
                    meigen(n, text, author)
                    break
                }
            }
        }
        for c := n.FirstChild; c != nil; c = c.NextSibling {
            f(c, text, author)
        }
    }

    meigen = func(n *html.Node, text, author *string) {
        if n.Type == html.ElementNode && n.Data == "div" {
            for _, a := range n.Attr {
                switch {
                case a.Key == "class" && a.Val == "text":
                    *text = n.FirstChild.Data
                case a.Key == "class" && a.Val == "link":
                    ul := n.FirstChild
                    li := ul.FirstChild
                    a := li.FirstChild
                    *author = a.FirstChild.Data
                }
            }
        }
        for c := n.FirstChild; c != nil; c = c.NextSibling {
            meigen(c, text, author)
        }

    }

    var text, author string
    f(node, &text, &author)
    return text, author
}

func init() {
    http.HandleFunc("/", rootHandler)
    http.HandleFunc("/hoge", wisesawHandler)
}

func rootHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "text/html; charset=utf-8")
    w.Write(IndexPageText)
}

func wisesawHandler(w http.ResponseWriter, r *http.Request) {
    c := appengine.NewContext(r)
    client := urlfetch.Client(c)
    text, author := FetchWisesaw(client)
    if text != "" && author != "" {
        status := fmt.Sprintf("%v (%v)", text, author)
        body, err := TweetStatus(client, accessCredentails, status)
        if err != nil {
            http.Error(w, err.Error(), 500)
        }
        fmt.Fprintf(w, "%v", body)
    } else {
        http.Error(w, "No contents", 500)
    }
}

OPAMを使い始めた

はじめに

こんにちは、Python界の情弱です。OCamlをしばらく書いていなかったのですが、久々に書こうと思い、環境を再セットアップしました。 もうOCaml 4.00.1が出ていたり、そもそもセットアップはOPAMでするのが楽ちんだったりするらしいので、試してみました。

OPAMのインストール

基本的には本家のチュートリアルにある通りにやればいいだけなんで、簡単。

% wget http://www.ocamlpro.com/pub/opam_installer.sh
% sh ./opam_installer.sh /usr/local/bin

ずーっと最新版のOCamlのビルド&インストールを /home/$USER/.opam に対して行ってるログが流れてきますが、最後に設定ファイルへの書き込みを聞いてきます。

=-=-=-= Configuring OPAM =-=-=-=
Do you want to update your configuration to use OPAM ? [Y/n] Y
[1/4] Do you want to update your shell configuration file ? [default: ~/.zshrc]
[2/4] Do you want to update your ~/.ocamlinit ? [Y/n] Y
[3/4] Do you want to install the auto-complete scripts ? [Y/n] Y
[4/4] Do you want to install the `opam-switch-eval` script ? [Y/n] Y
User configuration:
  Generating ~/.ocamlinit.
  Updating ~/.zshrc.
Global configuration:
  Updating <root>/opam-init/init.sh
    auto-completion : [true]
    opam-switch-eval: [true]
  Updating <root>/opam-init/init.zsh
    auto-completion : [true]
    opam-switch-eval: [true]
  Updating <root>/opam-init/init.csh
    auto-completion : [true]
    opam-switch-eval: [true]

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

To complete the configuration of OPAM, you need to run:

    . /home/ymotongpoo/.opam/opam-init/init.zsh > /dev/null 2> /dev/null || true

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

To use OCaml installed by OPAM, use
eval `opam config env`

追加された諸々のファイルを見て、各種設定を書き換えました。(.zshrcから各種OS用設定ファイルに書き換えたり、ユーザ名が直に入っているものやホームディレクトリのものを$USERや$HOMEに書き換えたり、など)

基本操作

OMakeをインストールしようと思ったらビルドがこけて困っていたところ、「OPAMなら入るよ」という情報を聞いたのが、そもそものきっかけだったのでOMakeのインストールを例にしてやってみます。

% opam search omake
Available packages for 4.00.1:
omake        --  Build system designed for scalability and portability
omake-mode   --  Omake Emacs integration
spotinstall  --  A tool to facilitate the installation of OCaml annotation files (.cmt, .cmti, .spot, .spit).

OPAMによりインストールしたOCamlが4.00.1(執筆時最新)なので、それに対応したパッケージが表示されています。すばらしい。

% opam install omake
The following actions will be performed:
 - install ocamlfind.1.3.3 [required by omake]
 - install omake.0.9.8.6-0.rc1
2 to install | 0 to reinstall | 0 to upgrade | 0 to downgrade | 0 to remove
Do you want to continue ? [Y/n]
...

依存パッケージを見て、全部自動でビルド&インストールしてくれている。すばらしい!無事OMakeが入りました。 そういえばProject EulerCSVファイルを扱うことがちょいちょいあるので、関連パッケージが無いか見てみます。

% opam search csv
Available packages for 4.00.1:
csv  --  Library to read and write CSV files

% opam info csv
             package: csv
             version: 1.2.2
             depends: ocamlfind & oasis = 0.3.0
   available-version: 1.2.2
         description: Library to read and write CSV files

This library can read and write CSV files, including all extensions
used by Excel - eg. quotes, newlines, 8 bit characters in fields, "0
etc. The library comes with a handy command line tool called csvtool
for handling CSV files from shell scripts.

パッケージの内容も確認できてすばらしい!

OCaml自体のインストールは?

異なるバージョンを入れる

そういえばOPAMでOCamlの最新版は入れたけど、古いOCamlや今後バージョンが上がったらどうするの?ということで3.12.1も入れてみたり、バージョンを切り替えたりしてみる。

% opam switch list
4.00.1  C 4.00.1                     Official 4.00.1 release
--     -- 3.11.2                     Official 3.11.2 release
--     -- 3.12.1                     Official 3.12.1 release
...
--     -- 4.01.0dev+short-paths      latest trunk snapshot with short type names
--     -- 4.01.0dev+trunk            latest trunk snapshot
--     -- system                     System compiler (4.00.1)

なんかいっぱい出てきた!3.12.1があるのでそれを使ってみよう。

% opam switch 3.12.1
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 3574k  100 3574k    0     0   295k      0  0:00:12  0:00:12 --:--:--  767k
200Configuring for a x86_64-unknown-linux-gnu ...
gcc found
The C compiler is ANSI-compliant.
Checking the sizes of integers and pointers...
Wow! A 64 bit architecture!
...
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

To complete the configuration of OPAM, you need to run:

    eval `opam config env`

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

まだインストールされてないバージョンを指定したら、勝手にインストールが始まりました!

% eval `opam config env`
% ocaml -version
The Objective Caml toplevel, version 3.12.1
% opam switch list
4.00.1  I 4.00.1                     Official 4.00.1 release
3.12.1  C 3.12.1                     Official 3.12.1 release
--     -- 3.11.2                     Official 3.11.2 release
--     -- 4.00.0                     Official 4.00.0 release
--     -- 3.12.1+mirage-unix-direct  Mirage compiler for unix
...
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

To complete the configuration of OPAM, you need to run:

    eval `opam config env`

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

インストールされたあとにちゃんと指定したバージョンに切り替わっています。4.00.1も手元にあることが見て分かります。

% opam search omake
Available packages for 3.12.1:
omake       --  Build system designed for scalability and portability
omake-mode  --  Omake Emacs integration

3.12.1でOMake関連パッケージを探すと4.00.1の時とは違う結果が返って来ますね。4.00.1に戻してみます。

% opam switch 4.00.1
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

To complete the configuration of OPAM, you need to run:

    eval `opam config env`

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
% eval `opam config env`
% ocaml -version
The OCaml toplevel, version 4.00.1

戻りました。しかし、毎度evalするのはめんどくさいですね...

同じバージョンで複数の環境を作りたい

Pythonであればvirtualenv、Goであればgoenvなど、開発環境ごとにモジュール/パッケージの依存を切り分けたい時は次のオプションを使えばいいようです!

opam switch install <alias> --alias-of <version>

たとえば、いま既に4.00.1を入れてますが、ここで開発用に別の4.00.1の環境を用意してみます。

% opam switch install dev4.00.1 --alias-of 4.00.1
...
% eval `opam config env`
% opam switch list
dev4.00.1  C 4.00.1                     Official 4.00.1 release
4.00.1     I 4.00.1                     Official 4.00.1 release
3.12.1     I 3.12.1                     Official 3.12.1 release
--        -- 3.11.2                     Official 3.11.2 release
--        -- 4.00.0                     Official 4.00.0 release
--        -- 3.12.1+mirage-unix-direct  Mirage compiler for unix

おおおお!dev4.00.1という名前で4.00.1が新たに追加されました!先ほど4.00.1ではomakeパッケージを入れましたが、新しい環境では入ってないことを確認します。

% opam list -i
Installed packages for dev4.00.1:
base-bigarray  base  Bigarray library distributed with the OCaml compiler
base-threads   base  Threads library distributed with the OCaml compiler
base-unix      base  Unix library distributed with the OCaml compiler

% opam switch 4.00.1
% eval `opam config env`
% opam list -i
Installed packages for 4.00.1:
base-bigarray           base  Bigarray library distributed with the OCaml compiler
base-threads            base  Threads library distributed with the OCaml compiler
base-unix               base  Unix library distributed with the OCaml compiler
ocamlfind              1.3.3  A library manager for OCaml
omake          0.9.8.6-0.rc1  Build system designed for scalability and portability

ちゃんと環境が切り分けられていますね!

OPAMすばらしい!

すばらしいので、OCaml使う時は今後はOPAMから入れることにします。

「The Non-Designer's Design Book」はエンジニア必読の書籍だった

はじめに

こんにちは、Python界の情弱です。もうかれこれ5年くらい「僕にウェブデザインのセンスがあったら、いやせめてデザインのセンスがあったらどんなによかったことだろう」と思っていたわけですが、半ば諦めていました。しかし先日同僚の@kotarokパイセンに勧められるがままに「ノンデザイナーズ・デザインブック」を読んだら、これが素晴らしい書籍で、もう一度僕にやれば出来るかもと思わせてくれたわけです。

ノンデザイナーズ・デザインブック [フルカラー新装増補版]

ノンデザイナーズ・デザインブック [フルカラー新装増補版]

本書が良いのは、多くのデザイン例があり、それも原則の適用後だけではなく、その前後でどれだけデザインが変化するかを目にすることが出来るところ。 特に第3版はフルカラーなのですが、2008年以前に読んだ人、あるいは第2版までしか読んでない人も絶対に第3版をもう一度読むべきだと思いました。やはりカラーに関する記述はカラーの書籍で読むべきでしょう。

感想

文法が違っていた瞬間に動かなくなるプログラムとは違って、デザインというのは、ある程度雰囲気でそれっぽいことが出来てしまい、逆に何が良いデザインで何が悪いデザインなのか、という問題をなあなあで過ごしてしまいがちです。少なくとも僕はそうでした。 また同時に、「良いデザイン」とされているものは「良いセンス」という、感性に依存するものであるとも勘違いしていました。

しかし本書を読んで一番に実感することは「デザインはある程度までは技術である」ということ。本書は本当に少ない原則に基づいて、印刷物やウェブを綺麗にデザインする「考え方」を身につける本でした。この本を読み終えてから、自分なりに「なぜ良く見えるのか」「なぜ違和感を感じるのか」を言語化するための理論が身についたことを実感します。現に今は、これまでと違って、あらゆる印刷物やウェブページが材料となり、自分なりにそれらの良い点、改善したい点を挙げられるようになりました。

デザイナーと雰囲気ではなく「ひとりよがりではない自分の理論を持って」ウェブのレイアウトやデザインについて話をしたいと感じるエンジニアは多いのではないかと思いますが、そのための書籍としては、まさに絶好の一冊ではないかと思います。

推薦してくれた@kotarokも言っていましたが、この程度の内容は義務教育で触れておくべきだと心から思いました。

読書メモ

大原則

本書は「協調」と「強調」こそがデザインの大原則であるということを首尾一貫して主張していて、それらを様々な視点から取り上げている。この大原則を言語化するための4つの視点が以下。

  • 近接
  • 整列
  • 反復
  • コントラスト

近接

関連が近いものは近づけ、関連が無いものは離す。重要なのは中途半端な空白を作らずに、近づけるか離すか、きちんとした意識を持つこと。行き場のない空白は悪。

整列

アラインメントは統一する。中央揃えは整列の線が弱いため、できるだけ左揃え/右揃えを使う。整列をすることで、近接していなくとも一体感を得ることが出来る。(例: レポートのタイトルと氏名欄)

反復

区切りや改ページなどがあっても、近接/整列の方法が視覚的に一致していれば、人間はそこに関連性を見出す。見出しのフォント、罫線のパターン、ロゴなどを統一することで、異なる場所でそれを見た時に統一感を得ることが出来る。

コントラスト

中途半端な違いはデザインの衝突として受け止められ、違和感を覚えさせる。意味を切り離す、注意を引く、などの好意的な差異は、意図的に大きく違いを付けること。

カラー

4つの大原則はほとんどがレイアウトに関する話だったが、カラーも同様の原則を当てはめることができる。ただしカラーに関しては上記原則に当てはめるための材料がある。

カラーホイールによる配色パターン

原色である赤、黄、青を120度毎に置き、さらにその2次色である緑、紫、橙を各々の中間に置く。この6色の中間にあるのが3次色で、これらの12色でカラーホイールが完成する。

f:id:ymotongpoo:20130328074218g:plain

カラーホイールを使って色を選ぶ際は次のパターンを使うと良い

  • 補色:カラーホイールで向かい合わせ同士の色2色
  • トライアド:120度の位置にある3色
  • スプリット・コンプリメント・トライアド:1つの色とその補色の両側2色の計3色

シェードとチント

カラーホイールに乗っている色をヒュー(純色)と呼び、それに黒が加わるとシェード、白が加わるとチントと呼ぶ。カラーホイールによる配色パターンに加え、シェードとチントを用いることで同じ配色パターンにおいてもバリエーションが生まれる。

寒色と暖色

寒色は青を含むもの、暖色は赤や黄を含むものを指す。寒色は引っ込んだ印象に、暖色は飛び出た印象に受け取られるので、各々を適切な場所で使うべき。

活字

同じ文字でも書体一つで大きく印象が変わる。英文フォントでは次の6つの書体に分類出来る。

  • Oldstyle
    • 手書き文字を手本としていて、セリフ(ペン入れ角度)が斜めになっている。また曲線部の"thick/thin transition"は一番細い部分をつなげた直線(ストレス)が斜めになっているのも特徴。
  • Modern
    • 新し目なので、セリフは真横で細い、ストレスも垂直。
  • Slab selif
    • thick/thin transitionがほぼない。セリフも真横で太い。
  • Sans selif
    • 「セリフがない」という意味の如く、セリフがない。通常はthick/thin transitionはない。
  • Script
    • 伝統的なカリグラフィーの書体。
  • Decorative
    • 上記に属さない、おもしろ書体全般。

コントラスト

活字は大原則でいうコントラストを作るための方法と考える。コントラストを生むための性質は以下の6つ。

  • サイズ
    • 違いを付けるときははっきり付ける。14ptと16ptでは衝突となる。
  • 太さ
    • RegularとSemi Boldでは違いは生まれない。様々なウェイトがあるフォントを手元に用意しよう。
  • 構造
    • 書体を選ぶ。近い書体同士は衝突になる。ScriptとSans selif、DecorativeとModernなど違いを強調すること
    • 同じ書体でもRomanとItalicではやはり違う。大文字だけの場合と、大文字小文字混在でもやはり違う。
  • 方向
    • 長体、斜体など、文字の方向もコントラストとして捉えよう
    • 文字色ももちろん大事な要素。先の配色パターンを意識する。

今挙げた6つの活字におけるコントラストを生む性質のうち2つ以上を組み合わせることで、強いコントラストを作ると良い。

追記 (2013.03.28 00:00)

@kotarok先輩にエントリを書きましたと報告したら、次のスライドを紹介してくれました。前半の内容がまとまった素晴らしいスライドです!