君たちは永遠にそいつらより若い

技術と音楽と日々のこと。

ロールモデルがなくなること

ふと気付くとロールモデルがなくなっていた。

僕には、とても尊敬している人がいる。その人のことを尊敬していることは、今も昔も何も変わらないのだが、その人のことを追いかけることをずっと前に止めていたことを、つい30分前に友人と電話をしていて、ふと気付かされてしまった。

 

昔の僕は、その人のことを追いかけていて、その人のことをロールモデルとして、道を歩んでいた。その人は、前職の上司で、とにかくいい意味で怪しいデキる人だった。僕は、純粋な専門職らしい専門職のキャリアではなく、どちらかと言えば様々な掛け算によって、自分の価値を生み出しているタイプなので、その奇妙な上司は、専門職らしい専門職の人たちの中で、自分のような人間でもキャリアを築いていけることを証明してくれる唯一のロールモデルだった。

先刻会話をしている中で、昔はあなたのことを目指していたけれど、今は違うのだ、ロールモデルが無くなってしまったのだ、という趣旨の内容を友人から聞かされた。それに対して僕は、実務の中で君は僕と君はこだわる部分が全く違うことがわかってきたから、それは当たり前だと受け答えをしていたが、自分のロールモデルについて答えようとしたときに、自分はかなり前からその上司のことを既にロールモデルとして扱っていないことに気付いてしまった。日々、今のボスと殴り合うためには、目の前の課題に集中し、日頃からあらゆる事象を熟考し行動するしか術がなく、ロールモデルを追いかけている場合ではなかったのだ。

元上司は、外国人の部下を現地で100人従えるとか、そういった経験はしていないし、彼には僕のしていることはできない――もちろん彼が今の僕のポジションなら、彼のやり方で彼の価値を築いただろうが――。では、僕は今のボスをロールモデルにできるのか?否。今の僕のボスも僕とは性質が異なるので、僕はボスのことを参考にはするものの、直接のロールモデルにはできないだろう。そして、僕たちは同じではないから、お互いを尊敬し合い、お互いの足りない部分を補いながら、この地で多くの課題を2人で解決できているのだ。

 

自分の道の不確実性を感じたとき、人はロールモデルを定めることで、足元を固め、前を向こうとする。しかし、流動的な社会の中で、自分の性質を知れば知るほどに、それが誰でも無い自分の道であることに気付いていく。そもそもロールモデルを定めたところで、近くはあれ全く同じ性質を持っている人などいないし、ロールモデルを追いかけている間に世界もものすごいスピードで動いていくので、全く同じ道を歩んでいくことはできない。そして、自分の性質の分析と活用が進むにつれ、ロールモデルはいつかいなくなってしまうのだ。

友人も僕も実際不安は感じておらず、目の前が開けたような気持ちでいる。自分を活かそうと思えば活かそうと思うほどに、僕たちはロールモデルという「型」を失っていく。それは、認知の有無に問わず、誰もが通っている道なのかもしれない。他でもない自分のためだけのスタートラインを引くときに、僕たちはやっとそのジレンマから開放され、自分の頭で学び、自分の足で自らの道を歩めるようになるのだろう。

GitHubのリポジトリをissueも含めてバックアップできるBackHub

What?

f:id:kuteken:20160317213910p:plain

  • BackHub というドイツ発のサービス
  • GitHubリポジトリをissueも含めてバックアップできる
  • バックアップしたものをダウンロードしてローカルに保存可能
  • リポジトリだけでなく、Issuesもまるごとリストア可能(ちょっと形式が変わるけど)
  • パブリックリポジトリをバックアップする場合は、無料
  • プライベートリポジトリをバックアップする場合は、有料

backhub.co

サービスに必要な権限

  • Githubからログインする
  • 以下、権限が必要
    • Read org and team membership
    • Full control of private repositories
    • Access user email addresses (read-only)
  • 大事な情報を持ってる場合、普通に恐ろしいから安易に試せない。
  • 大したもの入ってなかったから試した次第(一応、サービス評価とか、運営会社の存在や付加価値税登録番号とか調べたけど)

f:id:kuteken:20160317213851p:plain

使い方

  • ログインしたら、リポジトリリストが並ぶので、バックアップボタンでバックアップする
  • そのまま、リポジトリごとにダウンロードできる
    • metadata.zip のファイル名にリポジトリ名が入ってなくて、かぶるからムカつく
    • metadataの中身は見た感じ、GitHubAPIのjsonをそのまま突っ込んだように見える

f:id:kuteken:20160317213911p:plain

  • リストアするときは別名でリポジトリをつくる。作成時にはPublic/Privateを選べる

f:id:kuteken:20160317213935p:plain

  • リストアされたissueは、微妙に形式が変わる

    • issueのtagはちゃんと残っていた
    • 元データのjsonにはassign情報が入っているのに、assignは外れてた
  • Before f:id:kuteken:20160317220110p:plain

  • After f:id:kuteken:20160317220125p:plain

これを使いたい人ってリポジトリを休眠させるときに、リポジトリだけじゃなくて、コメントとかissueを残したいからだと思うんだけど、リストアしなおすと形式が変わったり、情報が落ちたりするので、頻繁にバックアップしてリストアしてお金を節約〜という利用イメージはあまりつかなかった。これなら、Githubをダウングレードする前に一度ローカルに落としてから、潔くLockして眠らせておくほうがいいかな。

GitHubの課金を止めたら(ダウングレードしたら)プライベートリポジトリはどうなるか

お金の面でも、公開状態の面でもGitHubさん超優しかった。公開になるのかなーと思って、プライベートリポジトリをBuckup取って 消したけど、消さなくても良かったorz まぁ、新しいサービス試せたのでいいです!!

Q.

  • GitHubの課金を止めたら(ダウングレードしたら)プライベートリポジトリはどうなるか

A.

f:id:kuteken:20160317213203p:plain

  • 公開状態

    • 無理やりPublicにされることはない
    • Privateのまま、Lockされて中身が見れなくなる。
    • もちろんPush/Pullもできなくなる
  • 復活or中身を見る方法

    • 再課金する
    • Publicにしちゃう
  • Githubの優しさ

    • 月途中だったらお金Refundしてくれる

補足: 各ページのメッセージ表示

こんな感じのメッセージが表示される。

  • Billing Overview
@XXX’s private repositories are locked because they have exceeded the account’s plan limit. To unlock, upgrade your plan or make repositories public.
  • Repository Page
This repository has been disabled.
Your repository is currently disabled due to a billing issue. Please see your billing page for more information.

Google said 'If users can’t spell, it’s our problem.'

先週末、 Tuyên に誘われて、日曜にSAIGON TECH STARTUP FESTに寄ってきた。カンファレンス3個くらい聴いて、いつもどおり MY SQUAR の Nicolas に声掛けて、すぐ帰った。どのTECHイベントに行っても、本当にいつでもどこでも Nicolas がいる。

www.getlinks.co

今回の登壇者は、ベトナミーズイングリッシュではなかったので、聞き取りやすくて、寝ずに済んだ。

Google said 'If users can’t spell, it’s our problem.'

さて本題。Google の Head of Marketing Vietnam の Anh Nguyễn さんのお話の中の Google の信念が心に響いたので、メモ。

If users can’t spell, it’s our problem.
If they don’t know how to form the query, it’s our problem.
Even if there’s not enough content, it’s our problem.
If content is there but in a different language they don’t speak, it’s our problem.
Even if the web is too slow, it’s our problem.

もし、ユーザが言葉を正しく綴れないなら、それは僕たちの問題だ。
もし、ユーザがクエリでの検索がうまくできないなら、それは僕たちの問題だ。
もし、検索した先のページにユーザの探したい情報がない場合でも、それは僕たちの問題だ。
やっと見つけた情報が、ユーザの読めない言葉であっても、それは僕たちの問題だ。
たとえ、WEBがとても遅かったとしても、それは僕たちの問題なんだ。
※日本語は僕の超意訳

2009年くらいから色々なところで話されてるから、パターンも色々あるみたい。もし、それがユーザが「問題として認識していない問題」であっても、僕たちにとってはそれは解決すべき問題である。表面的な解決ではなく、潜在的な問題をも救い上げる、好きな考え方だ。

ユーザが「問題として認識していない問題」

情報検索時には、ユーザが「問題として認識していない問題」を抱えることがある。これについては、R. S. Taylor による情報要求のレベルに当てはめると、その段階を把握しやすくなる。

R. S. Taylor による情報要求のレベル

  • 直感的要求 (visceral need)
    • 現状に満足していないことは認識しているが、それを具体的に言語化してうまく説明できない状態
  • 意識された要求 (conscious need)
    • 頭の中では問題を整理できるが、あいまいな表現やまとまりのない表現でしか言語化できない状態
  • 形式化された要求 (formalized need)
    • 問題を具体的な言語表現で言語化できる状態
  • 調整済みの要求 (compromised need)
    • 問題を解決するために必要な情報の情報源が同定できるくらい問題が具体化された状態

※以下書籍から引用

情報検索と言語処理 (言語と計算)

情報検索と言語処理 (言語と計算)

上に引用した R. S. Taylor の情報要求(information need)のレベルにあるように、Googleでクエリを入力して検索できる状態のユーザは、形式化された要求 (formalized need)若しくは調整済みの要求 (compromised need)を持っている状態と言える。しかし、クエリを入力して検索できないユーザは、意識された要求 (conscious need)や直感的要求 (visceral need)のレベルにいる。直感的要求 (visceral need)のレベルのユーザは、問題を問題として認識することさえできていない。しかし、Googleは彼らを救いたいと願う。

有名な「世界中の情報を体系化し、ユーザに適切に届ける」と言うフレーズで切り落とされてしまった心の部分を、感覚的にわかりやすい言葉に紡いだものが、件の言葉であると、僕は解釈している。この言葉がスクリーンに表示された時、会場では憧れのような眼差しと共に、いたるところでシャッターが切られた。僕は、こういった人の心が動く瞬間に立ち会うとき、いつも感動を覚える。


ちなみに、こちらのイベントの主催者は、 GetLinks というアジア向けの求人サイトだった。CyberAgent Ventures や 500 Startupsから出資を受けてるバンコクのスタートアップ。

www.getlinks.co

(アジア向けのサービスのくせに、なんでサラリー表示に通貨単位をつけないんだろうね…バーツなのか、VNドンなのか、USドルなのかわかんなかった…

はい、今日も僕は元気です。

現地の人に現地の人と間違われる話。

書かなすぎてだめだからどうでもいい話書こう。最近、かなりの確率でベトナム人にベトナム人と間違われるようになった。

バイクに乗ってたら道を聞かれ、「わかんねー(ベトナム語)」って言ってんのにひたすらベトナム語で話され、外国人慣れしている商売人にも素で間違われ、終いには普通に日本語で日本人と話してても「日本語お上手ですね!」と言われる始末。上手いよ、そりゃネイティブだからな!!!!!!!!!ベトナム人に韓国人に間違われるのは分かるけど、現地の人に現地の人と間違われたり、自国の人としゃべってるのに自国の人間と思われないあたりが、レベルが高い。

何が変わったか、自分ではわからないけれど、ベトナム人の友人にどの辺がベトナム人っぽいのか聞いてみたら「うーん!もう、全部ですね!だからとても親しみやすいです!!!」とキラッキラした目で言われた。だから通訳のみんな、年上年下問わず、俺にだけクッソタメ口なのかもしれない。よくわかんないんですけど、たぶん得してます。母上、ベトナム人っぽく見えるように産んでくれてありがとうございます。なにがかわったんだろほんと。アメリカ在住の友人曰く、「食が顔つきを変える」んだとな。たしかにそいつの顔は徐々に日本人離れしつつあるし、体の構成物質も変わってくだろう。

そういえば、日本人に「韓国人?」と聞いてもキレないけど、韓国人に「日本人?」と聞いたらブチキレられるので、どちらか迷ったら彼らは「韓国人?」と質問するらしいよ。アーハン。

Excelで式の区切り文字がセミコロンに変化して、更にエラーになる(グローバルな理由で)

現象

同じファイルを開いているのに、あるメンバー(ベトナム人メンバー)のExcelでだけ、以下のようになってしまう現象が起こって、ハマった。

  • 計算対象の値
    • 2014-09-06 10:58:48.0のような文字列でText型貼付け(案件の事情)
  • 現象
    • うまく数式が動かずエラーになる(#VALUE!になる)
    • 式の区切り文字がカンマでなく、セミコロンに変化する
      • 他の人: e.g. =IF(EXACT(1*U7,1*AP7),"○","×")
      • 問題の彼: e.g. =IF(EXACT(1*U7;1*AP7);"○";"×")

原因

  • Macの言語と地域の設定(Language & Region)で、数値の区切り記号(Number separators)の桁区切り(Grouping)が.、小数点(Decimal),になっていた
  • そのため、2014-09-06 10:58:48.02014-09-06 10:58:48,0にすると動く

ベトナムでは、数字の桁区切りにはピリオド.、小数点にはカンマ,を使う

f:id:kuteken:20150504145746p:plain

解決方法

  • Mac言語と地域の設定 > 詳細 (Language & Region > Advanced) から数値区切りの設定を変更し、Excelを再起動する
    • 書式の言語(Format language)をEnglishなどに変える

f:id:kuteken:20150504145749p:plain


他メンバーにとっては当たり前すぎて"I can't resolve!"とお手上げ。僕もまさか小数点が,であるなんて思いもしなかったので、ちょっと悩んだ。海外のメンバーと作業するときは、この辺の常識も疑ってかかろう。

MySQLのタイムゾーンの挙動差について調べた

作っている場所と使用される場所のタイムゾーンが違ったり、国際的なサービスを作っていたりする場合に、タイムゾーンまわりの挙動について気になったので、MySQLで実際に試したことのまとめ。

前提

mysql> SELECT @@global.system_time_zone, @@global.time_zone, @@session.time_zone;
+---------------------------+--------------------+---------------------+
| @@global.system_time_zone | @@global.time_zone | @@session.time_zone |
+---------------------------+--------------------+---------------------+
| ICT                       | SYSTEM             | SYSTEM              |
+---------------------------+--------------------+---------------------+
1 row in set (0.00 sec)

mysql> desc test_times;                                                                         
+-----------+-------------+------+-----+-------------------+-----------------------------+
| Field     | Type        | Null | Key | Default           | Extra                       |
+-----------+-------------+------+-----+-------------------+-----------------------------+
| type      | varchar(20) | YES  |     | NULL              |                             |
| timestamp | timestamp   | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| datetime  | datetime    | YES  |     | NULL              |                             |
| date      | date        | YES  |     | NULL              |                             |
| time      | time        | YES  |     | NULL              |                             |
+-----------+-------------+------+-----+-------------------+-----------------------------+
5 rows in set (0.00 sec)
mysql> SET SESSION time_zone = '+07:00';
Query OK, 0 rows affected (0.00 sec)

mysql> insert into test_times values ('2000-01-01 00:00:00', '2000-01-01 00:00:00', '2000-01-01 00:00:00', '2000-01-01 00:00:00', '2000-01-01 00:00:00');
Query OK, 1 row affected (0.00 sec)

mysql> insert into test_times values ('now()', now(), now(), now(), now());
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> insert into test_times values ('utc_timestamp()', utc_timestamp(), utc_timestamp(), utc_timestamp(), utc_timestamp());
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> SET SESSION time_zone = '+09:00';                                                              
Query OK, 0 rows affected (0.00 sec)

mysql> insert into test_times values ('2000-01-01 00:00:00', '2000-01-01 00:00:00', '2000-01-01 00:00:00', '2000-01-01 00:00:00', '2000-01-01 00:00:00');
Query OK, 1 row affected (0.00 sec)

mysql> insert into test_times values ('now()', now(), now(), now(), now());
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> insert into test_times values ('utc_timestamp()', utc_timestamp(), utc_timestamp(), utc_timestamp(), utc_timestamp());
Query OK, 1 row affected, 1 warning (0.00 sec)

結果

mysql> SET SESSION time_zone = '+07:00';
Query OK, 0 rows affected (0.00 sec)

mysql> select * from test_times;
+---------------------+---------------------+---------------------+------------+-----------+
| type                | timestamp           | datetime            | date       | time      |
+---------------------+---------------------+---------------------+------------+-----------+
| 2000-01-01 00:00:00 | 2000-01-01 00:00:00 | 2000-01-01 00:00:00 | 2000-01-01 | 00:00:00  |
| now()               | 2015-04-17 02:18:06 | 2015-04-17 02:18:06 | 2015-04-17 | 02:18:06  |
| utc_timestamp()     | 2015-04-16 19:18:06 | 2015-04-16 19:18:06 | 2015-04-16 | 19:18:06  |
| 2000-01-01 00:00:00 | 1999-12-31 22:00:00 | 2000-01-01 00:00:00 | 2000-01-01 | 00:00:00  |
| now()               | 2015-04-17 02:18:15 | 2015-04-17 04:18:15 | 2015-04-17 | 04:18:15  |
| utc_timestamp()     | 2015-04-16 17:18:15 | 2015-04-16 19:18:15 | 2015-04-16 | 19:18:15  |
+---------------------+---------------------+---------------------+------------+-----------+
6 rows in set (0.00 sec)

mysql> SET SESSION time_zone = '+09:00';
Query OK, 0 rows affected (0.00 sec)

mysql> select * from test_times;
+---------------------+---------------------+---------------------+------------+-----------+
| type                | timestamp           | datetime            | date       | time      |
+---------------------+---------------------+---------------------+------------+-----------+
| 2000-01-01 00:00:00 | 2000-01-01 02:00:00 | 2000-01-01 00:00:00 | 2000-01-01 | 00:00:00  |
| now()               | 2015-04-17 04:18:06 | 2015-04-17 02:18:06 | 2015-04-17 | 02:18:06  |
| utc_timestamp()     | 2015-04-16 21:18:06 | 2015-04-16 19:18:06 | 2015-04-16 | 19:18:06  |
| 2000-01-01 00:00:00 | 2000-01-01 00:00:00 | 2000-01-01 00:00:00 | 2000-01-01 | 00:00:00  |
| now()               | 2015-04-17 04:18:15 | 2015-04-17 04:18:15 | 2015-04-17 | 04:18:15  |
| utc_timestamp()     | 2015-04-16 19:18:15 | 2015-04-16 19:18:15 | 2015-04-16 | 19:18:15  |
+---------------------+---------------------+---------------------+------------+-----------+
6 rows in set (0.00 sec)
時刻関数
データ型

まとめ