未来を見据えるのは簡単だが、数年先を見通すことは難しい

簡単といったら言い過ぎかもしれないが、将来的にいつかこうなるということをいうのはそんなに難しいことじゃない。

自動運転はいつか普及するだろうし、世界中の生産性がものすごく高くなり、人手が不要になれば経済システムは大きく変わるだろう。そうなるとベーシック・インカム的なものが現実になるはずだ。

民間宇宙旅行が普及すれば間違いなく巨大産業になるだろうし、金融業界における技術革新はどんどん進んでいくだろう。

これらのことはまあぶっちゃけ誰にでも言えるようなことで、言われれば「まあそうだろうね」というようなことだと思う。

しかし、例えば自分が生きている時代において、5年先を見通すことはできるだろうか。

スタートアップを立ち上げようと思ったら、この能力こそが重要なんだろうと思う。理論的には可能なんだけど、まだ誰もやっていなくて、なおかつやろうと思ったら数年以上かかるような事業。

これこそがスタートアップに必要な視点なんだと思う。20年後を見据えるのもいいかもしれないが、それまでに利益が上がらなくては破綻してしまう。そんなの待ってくれる投資家はいないはずだ。

それをやったからすごい、というスタートアップはたくさんある。Amazonなんかそうなんじゃないか。Amazonはある意味で10年以上先を見通して始まったような気はするが、売り上げ自体はすぐに立ったはずだ。

そうか。10年以上先を見通しつつ、すぐに利益の上がる事業こそが最もいい事業プランなのかもしれない。

未来を予測するために一番いいのは自ら未来を創り出すことだ、という言葉を思い出す。

昨今におけるプログラミングの本質

一般的な範囲において、理系的な素養(数学の知識とか)以上に、いわゆる当然の論理をしっかりと組み立てられること、すなわちある種文系的な能力の方がプログラミングには役にたつ。

つまり、最も重要なことは「そのソースコードはどういう構造をしていて、どういう風に振る舞うのか」がしっかりと整理されており、説明可能ということだ。

その際に毎度のように考えることは、実際のところ2つしかない。「登場人物」と「ふるまい」の定義である。

最初に登場人物の方であるが、もちろん人物とは限らない。オブジェクト指向における「オブジェクト」と言っていい。あるいはドメイン駆動設計におけるドメインモデル、またある時は一つのUIコンポーネントかもしれない。

肝心なのは、一つの(仮想的な)形のある物体としてのオブジェクト。これをプログラミングにおける「登場人物」と俺は考えている。

登場人物を定義する際に必要とされるのは、彼らがどう言った性質を持っているかをしっかりと洗いだすことである。

「ブログ投稿」という登場人物がいたとしよう。彼は「タイトル」「文章」「公開時刻」という3つの情報を持っているとすれば、それが彼の特徴である。

次に、「ふるまい」の定義だ。

当然ながら、先に述べた登場人物は特定のふるまいをすることが期待されている。それは、単に全ての情報を表示することかもしれないし、何かをきっかけとして他の登場人物に影響を及ぼすことかもしれない。

先に例で言えば、「ブログ投稿」は「編集」「保存」というふるまいを実行することが可能だ。それにより、「ブログ投稿」は自分自身を変えていくことができる。
あるいは、「ユーザー」という登場人物がいたとして、彼らが「他のユーザーをフォローする」というふるまいを実行すると、フォローされたユーザーは「フォローされているユーザーが増える」という影響を受ける。また、それによって「ユーザー」のタイムライン自体も影響を受ける。

プログラミングではこのように、誰がどう振る舞ったら他の誰かの状態がどう変わるのか、それをしっかり明確に定義する必要がある。
その上で、実際に検証する際には期待通りになっているかを明らかにすることができる。

ここまでがこのエントリにおける主旨だ。以降は補足。

実際にプログラミングをする際、以上の2つ(登場人物とふるまい)を実現する方法は割とたくさんあるし、様々なレイヤーで様々な登場人物(とふるまい)が存在するだろう。

例えばMVCという一般的なアーキテクチャでは、モデル層に定義された各クラスが登場人物であり、それらで定義されたメソッドがふるまいである一方、コントローラを中心に考えると、モデルが登場人物であるのは変わらずとも、ふるまいとしての単位はコントローラごとになる。

また、最近のReact – Reduxというフレームワークの場合、各コンポーネントが登場人物となって、アクションが定義されるが、コンポーネントの状態はコンポーネントそれ自体には保存されない。あくまでもreducerという関数が働いて、アプリケーション全体の構造を間接的に変えていく。

とはいえ、仮想的に区分される登場人物がいるのはどの場合でも変わらないと思うので、そこをしっかり考えておくと作業に取り掛かりやすいと思う。

もっと簡単にチャートを生成するためのAPI

D3.jsを使えばなんでもチャートを生成できるので勉強中なんだが、なんかいつまでも慣れない感じがする。そもそもなんでこんなに書かないといけないんだろう。

このライブラリは、既存のDOMに対してちょっとずつ重ねていく、という記述方法になっているので、その全てを明確に定義しないといけないからだと思う。

もっとシンプルに欲しいチャートを生成するフレームワークがあっていい気がする。どんなAPIがあれば便利だろうかと考えてみよう。

まずは、最もシンプルなPieチャート。

var dataSet = [10, 20, 30, 10, 24];
var colors = ['#98abc5', '#8a89a6', '#7b6888'];
// jQuery Style
$('#chart').pieChart({
  dataSet: dataSet,
  colors: colors,
  // other options...
});

// React Style
<PieChart dataSet={dataSet} colors={colors} ... />

こんな感じでかけそうなもんだ。Bar Chartも同じような感じでいけるな。

var dataSet = [10, 20, 30, 10, 24];
var colors = ['#98abc5', '#8a89a6', '#7b6888'];
// jQuery Style
$('#chart').barChart({
  dataSet: dataSet,
  colors: colors,
  // other options...
});

// React Style
<BarChart dataSet={dataSet} colors={colors} ... />

LineChartはどうだろう。こちらも基本的には値の連なりだから、値またはオブジェクトの配列を渡すだけでかける気がする。

ただ、実際にチャートを扱うとなると重要なのは色々組み合わせられることだと思う。ラインチャートを複数重ねたり、バーチャートを組み合わせてみたりということが柔軟にできる必要がある。パイチャートが遷移したりというアニメーションも重要だ。

それを定義するには、結局のところD3.js自体のやり方が一番柔軟なのかもしれない。要は手書きの絵と同じようなもんで、重ねて行きさえすればいい。その中でどの形が本当に必要で、何を型として切り取っていくかが分かれ目になるのかもしれない。

ちなみに、既存のラッパーライブラリはいっぱいあるんじゃないかと思って検索したらいくらでも出てくる。
http://matome.naver.jp/odai/2138966107937611601
http://scottlogic.github.io/d3fc/

ここら辺色々といじってみつつ、どんなやり方がいいのかを考えていきたい。

Once Upon a Time in America

前々から観たいと思っていたOnce Upon a Time in AmericaがNetflixに追加されたので、早速観た。4時間近くてかなり長い映画。

3つの時間を行き来しながら進んで行くストーリーが特徴的で、その中で主演のロバート・デニーロはやはりすごかった。子供時代、若者時代、老年時代とありが、後者の2つは共に40歳のデニーロが演じていて、両方の世代を見事に表現していたと思う。

ストーリー的には多くの謎を残しながら進んで行くので、そのうちまたもう一度観たいとは思うが、いかんせん4時間は長いので難しいかもしれない。

疑問をストックしておくことの重要性

知的生産活動とは何なのかということを改めて考えてみたい。

ざっと思い浮かぶ範囲での具体例は、「文章や論文を書くこと」「企業の戦略を考えること」「複雑なシステムを設計すること」などである。

これらに共通しているのは、何か解決するべき(あるいは解決したい)テーマや課題がすでにあり、それに対して必要な材料(知識や論理、裏付けなど)を集め、全体の筋が通るように組み立てる問いう流れである。

さらにざっくりと言えば、「問いを見つける」「解決の材料を集める」「まとめる(あるいは、組み立てる)」というサイクルの繰り返しこそが知的生産活動の本質だと思う。

このプロセスはある意味、企業活動や生命活動と共通している。企業は資金を投資して利益を得ることの繰り返しによって会社を維持・拡大していくことが根本的な性質である、生命活動において最も優先されるのは、持っている能力を利用して必要な栄養分を手に入れ、維持していくことである。
もし十分な利益を得ることができなければ、あるいは生物が必要な栄養素を得ることができなければ、そのまま死に向かうことになる。

そして、前述の「知的生産サイクル」にこの原則を当てはめれば、問いを見つけることができなければ(ストックしている問いの数が枯渇すれば)、その人の知的生産は停止する。解決するべき問いがないから、考えることもない。

つまり、もし人が何かを考えることで人生を楽しみたいのであれば、常に疑問をストックしておくことが、何よりも大事なのではないかと思うのである。

疑問を持つ能力は人によってとても大きな隔たりがあるし、他のあらゆる能力と同様、疑問を持つことをやめれば、どんどん落ちていってしまうだろう。別に疑問を持たなくても現代を生きていくことはまあある程度可能だからだ。このことがいわゆる「技術の進化によって人間がアホになる」ということの一つの原因だと思う。

だから、もし「考えること」を止めたくないのであれば、自分が手に入れた疑問を、あたかも珍しい宝石を拾ったかのように大切にし、いつでも見られるような形でためておくことが必要だと思う。
それを続けていくことで、疑問を見つける力は研ぎ澄まされ、その人の知的生産能力も長きに渡って向上させていくことができるのではないだろうか。

Testing React App written with ES6 with Mocha

npm install --save-dev mocha babel-register

Also make sure that you have valid .babelrc file.

{
  "presets": ["es2015", "react"],
  "plugins": ["transform-object-assign"]
}

And in the package.json,

...
"scripts": {
  "test": "mocha --compilers js:babel-register --recursive",
...

And just run npm test command.

Clamav installation to mac os x

brew install clamav
cp /usr/local/etc/clamav/clamd.conf.sample /usr/local/etc/clamav/clamd.conf
cp /usr/local/etc/clamav/freshclam.conf.sample /usr/local/etc/clamav/freshclam.conf
vim /usr/local/etc/clamav/freshclam.conf # comment out 'Example'
freshclam

ReduxでTrello風UIを実装する(試行錯誤編)

さて、トレロUIを実装してみる。2016/4/6 19:48スタート。何時間でできるかな。
 
まずはCSSというか見た目の構造をざっくりと考える。
 
リストを、左から追加していくようにする。リストにはタイトルがあり、編集可能。
リストの中にカードがあって、上から追加していく。カードはもちろん編集可能で、リスト間をドラッグ・ドロップで移動できる。
 
まずはリストのCSS。縦の長さは画面の100%ということでいいだろう。もしはみ出した場合はその中でスクロールする必要がある。
横幅は決めておこう。

次に、カード。横幅は100%だけど、高さは文字数次第でアジャストされる必要がある。角を丸めて適当に色をつけておこう。

リストの下にはカードを追加するためのボタンが必要。

以上を実際にブラウザで実験しつつ、Trelloを参考にしつつ考えたら次のような感じになった。
 

body {
  background: #0079bf;
  color: #4d4d4d;
  font: 14px "Helvetica Neue",Arial,Helvetica,sans-serif;
  line-height: 18px;
}
.list {
  float: left;
  width: 250px;
  height: 100%;
  padding: 0 10px;
  overflow-y: scroll;
  background: #e2e4e6;
  border-radius: 3px;
}
.list > .list-title {
  font-size: 15px;
  line-height: 18px;
  margin: 0;
  padding: 10px 0;
  min-height: 19px;
  min-width: 30px;
  overflow: hidden;
  text-overflow: ellipsis;
  word-wrap: break-word;
}
.list > .add-card {
  margin: 10px 0;
}
.list > .add-card > a {
  text-decoration: none;
  color: #8c8c8c;
}
.card {
  min-height: 40px;
  background: #fff;
  padding: 5px;
  border-radius: 3px;
}

 
Screen Shot 2016-04-06 at 20.16.03

おお、だいぶリアルだ…こんなに似せていいんだろうか。

さて、JavaScriptをどう書いていくかもざっくりと考えておこう。

必要となるnpmパッケージはreact reduxで使う一色の他に、ドラッグアンドドロップのためにreact-dndを使う。

ソフトウェアの機能をアクションとデータ構造の点から整理すると次のようになるだろう。
 
アクション

addList() — カラムを追加する
editList(listID) — リストのタイトルを編集開始
saveList(listID, newTitle) — リストの変更を保存
cancelEditList(listID) — リストの変更をキャンセル
destroyList(listID) — リストを削除
addCard(listID) — カードを追加する
editCard(cardID) — カードの編集開始
saveCard(cardID, newText) — カードの変更保存
cancelEditCard(cardID) — カードの保存をキャンセル
destroyCard(cardID) — カードを削除
moveCard(cardID, listID) -- カードをlistIDに移動

 
データ構造(ストア)

listOfList = [
  {
    id: 1,
    title: ‘list 1 title’,
    isEditing: 
    cards: [
      {
        id: 1,
        title: ‘card title’,
        isEditing: 
      }
    ]
  }
]

ストア層は全体としては配列になり、その中にリスト、リストの中にカードが入っているという構造。
それぞれのリスト・カードはIDを持っていて、作るたびにインクリメントされる。

これらの構造をreducerを通して定義していくことになるので、reducerも考えよう。

list, cardが主なデータモデルなので、それぞれについて2つずつ(リスト用と、各アイテム用)のreducer関数を用意する。

reducers/list.js

let nextListID = 1;
const listItem = (state, action) => {
  switch (action.type) {
    case 'ADD_LIST':
      return {
        id: nextListID++,
        title: action.title,
        isEditing: false
      };
    case 'EDIT_LIST':
      if (state.id !== action.id) {
        return;
      }
      return Object.assign({}, state, { isEditing: true });      
    case 'SAVE_LIST':
      if (state.id !== action.id) {
        return;
      }
      return Object.assign({}, state, { title: action.title });      
    case 'CANCEL_EDIT_LIST':
      if (state.id !== action.id) {
        return;
      }
      return Object.assign({}, state, { isEditing: false });
    default:
      return state;
  }
}
const lists = (state = [], action) => {
  switch (action.type) {
    case 'ADD_LIST':
      return [...state, listItem({}, action)];
    case 'EDIT_LIST':
      return state.map(item => listItem(item, action));
    case 'SAVE_LIST':
      return state.map(item => listItem(item, action));
    case 'CANCEL_EDIT_LIST':
      return state.map(item => listItem(item, action));      
    default:
      return state;
  }
}
export default lists;

reducers/card.js

let nextCardID = 1;
const card = (state, action) => {
  switch (action.type) {
    case 'ADD_CARD':
      return {
        id: nextCardID++,
        text: action.text,
        isEditing: false
      };
    case 'EDIT_CARD':
      if (state.id !== action.id) {
        return;
      }
      return Object.assign({}, state, { isEditing: true });      
    case 'SAVE_CARD':
      if (state.id !== action.id) {
        return;
      }
      return Object.assign({}, state, { text: action.text });      
    case 'CANCEL_EDIT_CARD':
      if (state.id !== action.id) {
        return;
      }
      return Object.assign({}, state, { isEditing: false });
    default:
      return state;
  }
}
const cards = (state = [], action) => {
  switch (action.type) {
    case 'ADD_CARD':
      return [...state, listItem({}, action)];
    case 'EDIT_CARD':
      return state.map(item => card(item, action));
    case 'SAVE_CARD':
      return state.map(item => card(item, action));
    case 'CANCEL_EDIT_CARD':
      return state.map(item => card(item, action));      
    default:
      return state;
  }
}
export default cards;

こうしてみると結構ワンパターンだし簡単だな。
さて、いよいよ実際の作業に突入する。まずはプロジェクト作成から。

mkdir redux-trello-ui; cd redux-trello-ui
npm init
npm install --save react react-dom redux react-redux react-dnd react-dnd-html5-backend
npm install --save-dev babel-core babel-loader babel-preset-es2015 babel-preset-react webpack

webpackとかの設定は省略。

まずはアプリのエントリーポイントから。Providerにreducerを読み込んだstoreを渡して、トップのコンポーネントを包むことで、reduxとreactをつなぐことができる。

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import { todos } from './reducers';

import Root from './containers/Root';

let store = createStore(todos);

ReactDOM.render(
  
    
  , document.getElementById('react-app')
);

先ほど用意したreducerをまとめる。

import { combineReducers } from 'redux';
import list from './list';
import card from './card';

export default combineReducers({
  list, card
});

っと、、、ここまで書いたのだが、想定しきれてないことが多くてスマートにまとまらなかったので、今日はここまでにしておこう。

ReduxとObject.assignの罠

Reduxと伝統的Fluxの大きな違いの一つはStore層の扱いかたである。

FluxではすべてのStoreを定義する必要があったのに対し、ReduxではStoreはアプリケーション全体に一つ存在するのみで、reducerと呼ばれる関数を使って、間接的に変更していく。これによって、冗長になりがちであったStoreを書かなくていい分、全体のコード量が減る(まさにreducer)。

reducerは通常のJavaScript関数であり、ステートとアクションを受け取って、アクションのタイプごとにステートをアップデートして返す、という振る舞いをする。

export default function sugoiReducer(state, action) {

  switch (action.type) {
  case 'SUGOI_ACTION_TYPE':
    return Object.assign({}, state, { change: 'value' });
  default:
    return state;
  }
}

その際に、なぜかは知らないがステートを変更するのではなく、新しいオブジェクトを作って返せ、問いうルールがある。上記のコードで言えば「Object.assign」を使わないといけないのだ。これを

export default function sugoiReducer(state, action) {

  switch (action.type) {
  case 'SUGOI_ACTION_TYPE':
    state.change = 'value';
    return state;
  default:
    return state;
  }
}

とすると、ステートの値自体は変更され保持されるが、Reactのコンポーネントには反映されないことになる。ちゃんと理解してないがイミュータブルなオブジェクトがなにかしているんだろう。今度調べたい。

もう一つのハマリどころとしてあったのが、Object.assign関数それ自体である。BabelでトランスパイルすればこちらもよろしくES5に変換してくれるんだろう、くらいに思っていたが、この関数はそのまま出力されるようだ。これを解決するにはbabel-plugin-transform-object-assignをプラグインとして入れる必要がある。

今回はCIで回してるphantomJSがこけてくれたのですぐに気づくことができたが、Chromeだけで開発しているとこういうのが怖いなあと思った。

データの視覚化

今後の個人的な取り組みについて、データの視覚化にもっとチャレンジしたい。統計とか。

そのためにはそもそもデータを集める必要があるので、そのノウハウや参照元リストを自分なりに作り上げていく必要がある。