すずけんメモ

技術メモです

YAPC::Asia Tokyo 2015 前夜祭に行ってきた

YAPC::Asia Tokyo 2015 の前夜祭に行ってきました。仕事終わりに埼京線からりんかい線に乗り継ぎ、国際展示場へ。ビッグサイトはちょっと時間がかかるかなと思っていましたが、空いていたので渋谷から30分ほどで着きました。

聴いたトークは3つ。メモがてらツイートしたことをはっておきます。発表者のみなさまありがとうございました。

PHP帝国の逆襲!(を願うPHPerが話す最近のPHPについてのクイックツアー PHP7対応版) - YAPC::Asia Tokyo 2015

YAPCなのに前夜祭はPHPRubyのセッションから始まったようです。私はuzullaさんのトークを聴きにいきました。去年も聴きたかったのですが機会を逃してしまったので1年経て聴けたことになります。会場が盛り上がってて最高でした。最近HHVMをいろいろ手元で試していたのでトピック的にも面白かったです。PHP7でまたいろいろ良くなりますし、今後も楽しみです。あと「負債のない言語があるか?ないだろ。」的な流れが最高でした。

はてなブックマークのトピックページの裏側 - YAPC::Asia Tokyo 2015

Elasticsearchのaggregationをごりごりと活用している事例でした。はてなブックマークは日々使っているので中のお話が聴けて新鮮でした。トピックの生成、Elasticsearch 6ノードで実現されているのが最も驚いたところです。2時間ごとの生成とおっしゃっていたけれど、日によってトピックの量が変わるとジョブの時間も伸びていくのだろうか・・・など思いつつ、興味ぶかいセッションでした。

我々にできるOSSとそのコミュニティの育てかた - YAPC::Asia Tokyo 2015

前夜祭最終セッションはモリスさんのセッションを見に。モリスさんの経験あってこそのセッションだなあと思いました。私は利用者になってしまうことがほとんどなので、こうしてもっと自分でごりごりとOSSとして出している話を聴くと、ああもっと姿勢を変えていかないとなあと思いました。最後t-wadaさんがQ&Aで質問されていたソフトウェアがコンパクトで美しいことと、ツールの実用性との両立というのは興味深い話でありました。

その他

前夜祭には初めて行ったのですが、ビールが出るのですね!おいしくいただきました。ビッグサイト、広くて明日から人もたくさんくるでしょう。運営の方には頭が上がりません。明日からも楽しく、無事に3日間が終えられることを祈りつつ、楽しんでいきたいと思いました。

JAWS-UG Meguro #0 でAWS SDK for Goについて発表してきました

「カジュアルなAWSの集いをやりますよ!」というお誘いをいただいて、行ってきました。

connpass.com

私からは最近触り始めたAWS SDK for Goの紹介をしました。

www.slideshare.net

Gist版: https://gist.github.com/suzuken/0a7f64a6016b3edfe2c4

AWS SDK for Goはまだ開発版で、プレビューの段階です。インタフェースはわりとカジュアルに変わってしまう段階では有りますが*1、ひとまず雰囲気だけでも掴んでもらえれば、と思い紹介してみました。

発表中でも触れたように、内部ではJSONで書かれたAWSapi仕様に則り、 go generate をつかってコードが生成されるようになっています。また、Exampleをうまくつかうようにしていたりと、このあたりも面白いところです。

Testable Examples in Go - The Go Blog

AWSのみなさま(と、 @kani_b 氏)、会場・運営どうもありがとうございました。

*1:実際にサンプルとして書いてきたコードが、発表前日の変更で壊れたりもしました・・

Arduinoをはじめよう、をやってみた

GWだし普段やってないことをやってみよう、ということでArduinoを触ってみた。Arduinoをはじめようという本と、それに合わさったキットをつかっている。*1

  • Arduinoをひとまず起動する
  • LEDをつけてみる
  • スイッチをon/offしてLEDをつけたり消したりしてみる
  • Cdsセルをつかって、LEDをつけたり消したりする
  • Cdsセルをつかって、LEDの光る強さを変えてみる
  • ブログから本文読み取って、単語数をもとに3つのLEDの光る強さを変える

ということをした。所要時間5時間くらい。組み立てつつ、写経しつつ進めた。たぶんProcessingとかこういう部品組むのとか慣れてる人だったらもっと早く終わると思う。

つかったもの

環境はOSX 10.9.5のMBP。

Arduinoをはじめようキット

Arduinoをはじめようキット

Arduinoをはじめよう 第2版 (Make:PROJECTS)

Arduinoをはじめよう 第2版 (Make:PROJECTS)

ここからIDEを落とす。Processingで書けるらしい。Cに変換されるとのこと。

Arduino - Software http://www.arduino.cc/en/main/Software

ArduinoIDEが付属している。こんな感じ。

f:id:suzu_v:20150504185604p:plain

ArduinoをはじめようキットだとArduino Unoというボードがついている。これをPCとUSBでつなぐと、Arduinoに電力が供給されて動くようになっている。ちなみに本には設定が必要だと書いてあったんだけど、USBでつないでArduinoIDEを起動したら勝手に設定が終わっていた。簡単。接続されているデバイスの中からArduinoを勝手に認識してくれているらしい。

f:id:suzu_v:20150504190012p:plain

コード書いてチェックボタンでverify、→ボタンでコンパイルとデプロイされる。便利。

まずLEDをつけたりスイッチをつけたり

Arduino IDEで新規ファイルを作成するとSTUBの手続きが生成される。

void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}

setup()マイコンボードに書き込まれた際に実行される処理。 loop() はその後繰り返し呼び出される。LEDをつけるには

void setup(){
  pinMode(13, OUTPUT); // LEDのポート番号
}

void loop(){
  digitalWrite(13, HIGH);
}

これだけでいい。ちなみに読み込みはINPUT用のpinをつくって、digitalRead()すればいい。するとボタンを押してLEDをつけたり消したりするのは以下のようにかける。

int val = 0;

void setup(){
  pinMode(13, OUTPUT); // LEDのポート番号
  pinMode(7, OUTPUT); // 例えば、ボタンのポート番号
}

void loop(){
  val = digitalRead(7); // ボタンの値を読み込む
  if (val == HIGH) {
    digitalWrite(13, HIGH); // LED on
  }
  else {
    digitalWrite(13, LOW); // LED off
  }
}

といったような感じでコードを書いていく。だいたいArduino側がapiを用意してくれているので、単純なdigitalRead()digitalWrite()だとさくさく書けるようだ。

こういった例がいくつかあって、以下の様に部品を組んで動かしていく。

f:id:suzu_v:20150504190456j:plain

f:id:suzu_v:20150504190506j:plain

微妙にはまったところ

6章にクラウドとの会話という章がある。ここで、ブログのフィードからテキストをもってきて、LEDライトのそれぞれの明るさに反映するという例になっている。

ブログのフィードを持ってきてシリアル通信でボードに送るところはProcessingで書かれている。ただこのままだと動かない。

  • そもそも http://blog.makezine.com/index.xml が403
  • Processingをインストールしてもそのままでは動かない。processing-java を入れる必要があり、それらの import 宣言が抜けている。

ということでちゃちゃっと直した。https://processing.org/download/からProcessingを落としてきてインストール。Tools -> Install "processing-java" でprocessing-javaをインストール。あとは以下のimport文をスケッチに足す。

import java.net.*;
import java.io.*;
import java.util.*;

あとはURLを適当に変えてあげる。私は代わりに String feed = "http://blog.arduino.cc"; とした。また、ここで例にあげられているlove, peace, arduinoの単語はブログによって頻度が違うので適当に選ぶといい。私はそれぞれwindows, make, arduinoとした。

で結果として以下のようになった。

f:id:suzu_v:20150504192155j:plain

ちゃんと光った。

感想

面白かった。シリアル通信できればProcessingで処理した部分は他の言語でも書けるだろうし、もっといろいろできそう。あと色んなセンサーを集めて遊んでみたくなった。

*1:2つともwishlistからプレゼントとしてもらったもの。harukasan, amacbeeありがとう!

dummyデータをつくる

dummyデータつくるのになんかスクリプト書くかーといっていっつも使いまわしている気がしてきたのでとりあえず簡単なライブラリにしておいた。

github.com

似たようなツールはいろいろあるけど、シンプルなのが欲しかった。もうちょっとまとまったら使い方を書きたい。

  • Goで適当な文字列が欲しい
  • cliツールとしても使いたい
  • 適当なフォーマットで指定したらよしなに出力して欲しい

みたいときに使えるようになる、予定。TODOとしては、

  • 固定長以外でも出力
  • JSONフォーマットで出力
  • LTSVのようなフォーマットで出力
  • delimiterをoptionalに
  • 大きいサイズ生成する場合には並列に

あたりだろうか。DBのテストするために書いたので、CREATE TABLE から適宜そのテーブルにいれられるダミーデータをつくれるように・・・とか一瞬思ったけど面倒そうだったのでやめた。

ローカル作業でのgitリポジトリ管理とコーディング環境の話

gitを改めてちゃんと使おうという人がまわりで増えてきたのでメモとして貼っておく。

現状の設定はこんな感じ。1年くらい変わってなかった。

https://github.com/suzuken/dotfiles/blob/cbf8e7168c96029d535d69f981337d23aacfa51c/gitconfig

特にaliasまわりは普段つかっているのであげておく。

[alias]
# http://oli.jp/2012/git-powerup/
# http://blog.blindgaenger.net/advanced_git_aliases.html
alias = !git config --list | grep 'alias\\.' | sed 's/alias\\.\\([^=]*\\)=\\(.*\\)/\\1\\\t => \\2/' | sort
b = branch -a
br = browse-remote
ci = commit
co = checkout
current-branch = rev-parse --abbrev-ref HEAD
d = diff
dc = diff --cached
di = diff
dic = diff --cached
f = fetch --prune
fs = !git f && git su
ignore = !([ ! -e .gitignore ] && touch .gitignore) | echo $1 >> .gitignore
info = remote show origin
l = log --graph -n 20 --pretty=format:'%C(yellow)%h%C(cyan)%d%Creset %s %C(green)- %an, %cr%Creset'
ll = log --stat --abbrev-commit
ln = log --graph -n 20 --pretty=format:'%C(yellow)%h%C(cyan)%d%Creset %s %C(green)- %an, %cr%Creset' --name-status
lp = log --oneline -n 20 -p
ls = log --stat --abbrev-commit -n 1 # display previous log
s = status --short --branch
st = status
su = submodule update
delete-merged-branches = !git branch --merged | grep -v \\* | xargs -I % git branch -d %
fetch-pulls = fetch origin +refs/pull/*:refs/remotes/pull/*

特によく使うのは delete-merged-branchesfetch-pulls。remoteでbranchがマージされてfetchしてきたときに既にmergeしてるものだけどlocalブランチから消す。これをやると現在mergeされていないブランチのみが残るので便利。 fetch-pulls はcodeをレビューするときとかにつかっていて、これをつかうと対象プロジェクトのPull Requestをまとめてfetchできる。するとローカルでdiffもとりやすいし便利。

あとはマージにはvimdiffを使ってる。それと git cloneghq clone motemen/ghq でつかっていて、全部GOPATHっぽく入るようになってる。これを peco peco/peco で探すようにしているので、大分ローカルでのリポジトリの移動が楽になった。普段はvimでコーディングしているので mattn/ctrlp-ghq でプロジェクトを行ったり来たりしている。だいたい新しいtab開いて ctrlp-ghq でcurrent directoryを移動して Dirvish justinmk/vim-dirvish でそこのrootを開く、ということをしてることが多い。基本的に全部動作が軽いのを選ぶようにしてる。

気が付くとvimの話になってしまったので反省している。

参考

React.jsをもくもくと触り始めた

とりあえず触ってみないとわからないのでもくもくとチュートリアルをなぞっていく。

A JavaScript library for building user interfaces | React https://facebook.github.io/react/

Starter Kit 0.13.1でさわる

wget https://facebook.github.io/react/downloads/react-0.13.1.zip
unzip react-0.13.1.zip

Getting Started | React をひたすらなぞる

https://facebook.github.io/react/docs/getting-started.html

これをなぞっていく サンプルが下のとおり

<!DOCTYPE html>
<html>
  <head>
    <script src="build/react.js"></script>
    <script src="build/JSXTransformer.js"></script>
  </head>
  <body>
    <div id="example"></div>
    <script type="text/jsx">
      React.render(
        <h1>Hello, world!</h1>,
        document.getElementById('example')
      );
    </script>
  </body>
</html>

text/jsxとなっているのがJSXと呼ばれているXML

JSX in Depth | React https://facebook.github.io/react/docs/jsx-in-depth.html

Reactを使う場合に普通のplainなJSをつかってもいいらしい

var myDivElement = <div className="foo" />;
React.render(myDivElement, document.body);

このようにJSの構文の中にXMLでの記述ができる これをそのまま React.render でオブジェクトをつくり、レンダリングできる。

ひとまず簡単にReactを利用したコードを書いて最初のhelloworld.htmlに食わせる。 src/helloworld.js として保存する。

React.render(
    <h1>Hello, world!</h1>,
    document.getElementById('example')
);

buildのためにツールを入れる

-> % npm install -g react-tools
/usr/local/bin/jsx -> /usr/local/lib/node_modules/react-tools/bin/jsx
react-tools@0.13.1 /usr/local/lib/node_modules/react-tools
├── jstransform@10.1.0 (base62@0.1.1, source-map@0.1.31, esprima-fb@13001.1001.0-dev-harmony-fb)
└── commoner@0.10.1 (private@0.1.6, commander@2.5.1, graceful-fs@3.0.6, install@0.1.8, q@1.1.2, mkdirp@0.5.0, iconv-lite@0.4.7, recast@0.9.18, glob@4.2.2)

これで jsx コマンドがつかえるようになる。buildをしてみる。

jsx --watch src/ build/

すると src/ にさっき配置した helloworld.js がビルドされる。同名のファイルが build/ に配置される。

-> % cat build/helloworld.js
React.render(
    React.createElement("h1", null, "Hello, world!"),
    document.getElementById('example')
);

また、これに応じてhtmlを書き換える。

<!DOCTYPE html>
<html>
  <head>
    <script src="build/react.js"></script>
  </head>
  <body>
    <div id="example"></div>
    <script src="build/helloworld.js"></script>
  </body>
</html>

これでHelloWorldが無事表示される。さきほどHelloWorldのDOMを貼り付けていたところに、scriptを貼り付けていることがわかる。ちなみに、下のようにheadに貼っても表示されない。

<!DOCTYPE html>
<html>
  <head>
    <script src="build/react.js"></script>
    <script src="build/helloworld.js"></script>
  </head>
  <body>
    <div id="example"></div>
  </body>
</html>

Tutorial | React をなぞる

次はtutorialを読めと書いてあったのでなぞる https://facebook.github.io/react/docs/tutorial.html

まずこれを型として、text/jsxのところに演習内容をいれていく

<!-- index.html -->
<html>
  <head>
    <title>Hello React</title>
    <script src="https://fb.me/react-0.13.1.js"></script>
    <script src="https://fb.me/JSXTransformer-0.13.1.js"></script>
    <script src="https://code.jquery.com/jquery-1.10.0.min.js"></script>
  </head>
  <body>
    <div id="content"></div>
    <script type="text/jsx">
      // Your code here
    </script>
  </body>
</html>

まずコンポーネントをつくってみる

var CommentBox = React.createClass({
  render: function() {
    return (
      <div className="commentBox">
      Hello, world! I am a CommentBox.
      </div>
    );
  }
});
React.render(
<CommentBox />,
document.getElementById('content')
);

レンダリングされ、divができている。ちなみにレンダリングされているDOMをみてみると以下のようになっている。 data-reactid というプロパティがある。これでreactが生成したDOMを管理しているのだろうなと想像。なんで0じゃなくて.0なのかはしらない。

<div id="content">
    <div class="commentBox" data-reactid=".0">
        Hello, world! I am a CommentBox.
    </div>
</div>

次にこれをplainなJavaScriptでやる方法も書いてる、が面倒なので飛ばす。JSXで書いたほうがDOMつくるのはシンプルに書けるっぽさ。ああでもコメントに書いてあるけど、Reactでの div は実際のDOMのノードとは違うらしい。なんのことだろ。

次にcomponentをつくることを学んでいく。ちなみに下のコードのままでは書きかけなので動作しない。

var CommentList = React.createClass({
  render: function(){
    return (
      <div className="commentList">
        Hello, world! I am a CommentList.
      </div>
    );
  }
});

var CommentForm = React.createClass({
  render: function(){
    return (
      <div className="commentForm">
        Hello, world! I am a CommentForm.
      </div>
    );
  }
});

// CommentListとCommentFormを含んでいる
var CommentBox = React.createClass({
  render: function() {
    return (
      <div className="commentBox">
      <h1>Comments</h1>
      <CommentList />
      <CommentForm />
      </div>
    );
  }
});

// propsでpropertyを取得できるらしい
// props = properties だと思われる
// こうすることで、`Comment`で`CommentList`からのデータを読むことができる
// this.props.childrenでnestした要素をとれるらしい
var Comment = React.createClass({
  render: function() {
    return (
    <div className="comment">
      <h2 className="commentAuthor">
        {this.props.author}
      </h2>
      {this.props.children}
    </div>
    );
  }
});

次にpropsを利用していく。

// CommentListのなかでCommentを利用している。かつ、propとしてauthorを設定している。
var CommentList = React.createClass({
  render: function(){
    return (
      <div className="commentList">
        <Comment author="Pepe Hunt">This is one comment</Comment>
        <Comment author="Jordan Walke">This is *another* comment</Comment>
      </div>
    );
  }
});

var CommentForm = React.createClass({
  render: function(){
    return (
      <div className="commentForm">
        Hello, world! I am a CommentForm.
      </div>
    );
  }
});

var CommentBox = React.createClass({
  render: function() {
    return (
      <div className="commentBox">
      <h1>Comments</h1>
      <CommentList />
      <CommentForm />
      </div>
    );
  }
});

// これはmarkdownへの変換器
var converter = new Showdown.converter();

// `{}` のなかでは普通にJavaScriptのmethodが使えている
// 普通にconvertしたHTMLを表示しようとしても<em>が文字列として出力されてしまう
// なので、ReactによるXSS対策を無効にするために、innerHTMLをつかうようにしている
var Comment = React.createClass({
  render: function() {
    var rawMarkup = converter.makeHtml(this.props.children.toString());
    return (
    <div className="comment">
      <h2 className="commentAuthor">
        {this.props.author}
      </h2>
      <span dangerouslySetInnerHTML={{__html: rawMarkup}} />
    </div>
    );
  }
});

markdownの表示のところはイレギュラーかも知れないが、Reactのレンダリング方針がかいま見える。

次に外部からデータを当て込んでいく。

var data = [
  {author: "Pepe Hunt", text: "This is one comment"},
  {author: "Jordan Walke", text: "This is *another* comment"}
];

var CommentList = React.createClass({
  render: function(){
    var commentNodes = this.props.data.map(function (comment) {
      return (
        <Comment author={comment.author}>
          {comment.text}
        </Comment>
      );
    });
    return (
      <div className="commentList">
        {commentNodes}
      </div>
    )
  }
});

// CommentListに対してdataのプロパティを渡すことができるのか
var CommentBox = React.createClass({
  render: function() {
    return (
      <div className="commentBox">
      <h1>Comments</h1>
      <CommentList data={this.props.data} />
      <CommentForm />
      </div>
    );
  }
});

React.render(
  <Commentbox data={data} />,
  document.getElementById('content')
);

こうすると data をrender時にCommentBoxに渡すことができる。dataをオブジェクトとして渡していたのを外部から渡すには以下のようにする。

React.render(
  <Commentbox url="comments.json" />,
  document.getElementById('content')
);

comments.jsonは以下のとおり。

[
  {"author": "Pepe Hunt", "text": "This is one comment"},
  {"author": "Jordan Walke", "text": "This is *another* comment"}
]

で、apiとして返せば連携できるようになるはず。

// getInitialStateでprops.dataを初期化している
var CommentBox = React.createClass({
  getInitialState: function() {
    return {data: []};
  },
  // ここは単純にserver sideリクエスト
  // ひさびさにjQueryみた
  loadCommentsFromServer: function() {
    $.ajax({
      url: this.props.url,
      dataType: 'json',
      success: function(data) {
        this.setState({data: data});
      }.bind(this),
      error: function(xhr, status, err) {
        console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
  },
  // componentがレンダリングされると呼ばれる
  componentDitMount: function() {
    this.loadCommentsFromServer();
    setInterval(this.loadCommentsFromServer, this.props.pollInterval);
  },
  // this.state.dataで参照できる
  render: function() {
    return (
      <div className="commentBox">
      <h1>Comments</h1>
      <CommentList data={this.state.data} />
      <CommentForm />
      </div>
    );
  }
});

// sleepのためのintervalもわたしてる。
// 2000をintでわたしたいから{}にしてるのか
React.render(
  <Commentbox url="comments.json" pollInterval={2000} />,
  document.getElementById('content')
);

これでサーバサイドに問い合わせて、componentにデータを引き渡しレンダリングするところまでできたことになる。

次にコメントを投稿できるようにする。

var CommentForm = React.createClass({
  handleSubmit: function(e) {
    e.preventDefault();
    var author = React.findDOMNode(this.refs.author).value.trim();
    var author = React.findDOMNode(this.refs.text).value.trim();
    if (!text || !author) {
      return;
    }
    React.findDOMNode(this.refs.author).value = '';
    React.findDOMNode(this.refs.text).value = '';
    return;
  },
  render: function(){
    // refのプロパティをつけておくと、上でReact.findDOMNodeでDOMを参照できる
    return (
      <form className="commentForm" onSubmit={this.handleSubmit}>
        <input type="text" placeholder="Your name" ref="author" />
        <input type="text" placeholder="Say something..." ref="text"/>
        <input type="submit" value="Post" />
      </form>
    );
  }
});

onSubmitのイベントをhandleSubmitで受け取っている。実際の送信処理を下のように書く。

var CommentForm = React.createClass({
  handleSubmit: function(e) {
    e.preventDefault();
    var author = React.findDOMNode(this.refs.author).value.trim();
    var author = React.findDOMNode(this.refs.text).value.trim();
    if (!text || !author) {
      return;
    }
    this.props.onCommentSubmit({author: author, text: text});
    React.findDOMNode(this.refs.author).value = '';
    React.findDOMNode(this.refs.text).value = '';
    return;
  },
  render: function(){
    // refのプロパティをつけておくと、上でReact.findDOMNodeでDOMを参照できる
    return (
      <form className="commentForm" onSubmit={this.handleSubmit}>
        <input type="text" placeholder="Your name" ref="author" />
        <input type="text" placeholder="Say something..." ref="text"/>
        <input type="submit" value="Post" />
      </form>
    );
  }
});

var CommentBox = React.createClass({
  getInitialState: function() {
    return {data: []};
  },
  loadCommentsFromServer: function() {
    $.ajax({
      url: this.props.url,
      dataType: 'json',
      success: function(data) {
        this.setState({data: data});
      }.bind(this),
      error: function(xhr, status, err) {
        console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
  },
  // コメントをしたらここでコメントをサーバにおくる
  handleCommentSubmit: function(comment) {
    // コメントが返ってくるに空でも表示しておく
    var comments = this.state.data;
    var newComments = comments.concat([comment]);
    this.setState({data: newComments});

    $.ajax({
      url: this.props.url,
      dataType: 'json',
      type: 'POST',
      data: comment,
      success: function(data) {
        this.setState({data: data})
      },
      error: function(xhr, status, err) {
        console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
  },
  componentDitMount: function() {
    this.loadCommentsFromServer();
    setInterval(this.loadCommentsFromServer, this.props.pollInterval);
  },
  render: function() {
    return (
      <div className="commentBox">
        <h1>Comments</h1>
        <CommentList data={this.state.data} />
        <CommentForm onCommentSubmit={this.handleCommentSubmit}/>
      </div>
    );
  }
});

これでひと通りコメントの追加、表示などができるようになったことになる。

新社会人エンジニアに向けて

新卒一年目の時にやっておけばよかったこと、というネタ振りで社内日報に書いた。こっちにも貼っておく。

  • 毎日コードを書こう。業務では様々な事情で打合せが増えたりして悶々とすることもある。良いコードを書けない人はコードを書いてる絶対量が少ない。コードを書こう。
  • 全部やろうとしなくていい。自分の関わっているシステムについて全部やらなくていい。でも、どれくらいの広さがあるのかを知ることはやったほうがいい。それで、自分がどこの領域で価値を出せるかを見定めて、相談して、コードを書こう。
  • 幸いなことに、続けていると仕事は面白くなる。長く取り組める環境をみつけて、じっくり問題に取り組もう。研究と似て非なる部分は、これは仕事のコードで、様々な人達が関わっているということだ。チームで仕事をするのは楽しい。また、大勢でいろんな思惑をもって動いているというシステムに携わるというのは、なかなか得がたい経験である。この環境を楽しもう。

新卒一年目のときから変わった習慣もあるけど、そんなに入社当時から変わっていないなと思った。新社会人のみなさん、おめでとうございます。