PCウェブのTweetDeckでハッシュタグ付きで呟いたらツイートフォームにハッシュタグを保持するChrome拡張書いた
仕事とゲームの共通点、あるいはコーポレートビジョンとは
まえがき
【前編】大先輩のフリークアウトCTOが語ってくれた、マネジメントの深くてイイ話 / 飲み会で探るエンジニアのホンネ #naoya_sushi 編
【後編】大先輩のフリークアウトCTOが語ってくれた、マネジメントの深くてイイ話 / 飲み会で探るエンジニアのホンネ #naoya_sushi 編
この記事を読んで色々得られるもの、考えさせられることがあったので、つらつらと書いてみる。
エンジニアが頑張れば売上が上がる仕組み
『グーグル』がエンジニア天国みたいな環境を築いて、すごくハッピーだねって言われてますけど、あれはエンジニアにとってハッピーな会社をつくったから成功したんじゃなくって、エンジニアが頑張って検索のスピードを速くすることで会社が儲かって利益も生み出せるっていう構造をつくったから、必然的にエンジニアの生産性を上げるために、彼らがハッピーになる会社になったって思ってるんです。
これは今まで考えたことがなくて、新しい発見だったし、なるほど感がすごかった。
エンジニアってモチベーションと生産性が他の職種よりも顕著にリンクしていて、ムラの多いいきものだと感じてる。だから、エンジニアのモチベーションを上げることが会社が成功する大きなキーの一つになるわけで、それを実現する要因として技術的に面白いかどうか、というところが大きい。特に出来るエンジニアほど技術的なところとモチベーションが連動している気がする。
で、検索のスピードや、広告表示のスピードを上げるというのは技術的に面白いチャレンジだし、それが会社の売上に直結するアドテク業界が盛り上がっているのも納得できる。
エンジニアの目標達成に対するモチベーションは高い
この記事の話ではないが、CODE COMPLETEにエンジニアは目標を提示されるとそれを達成するように動く、という当たり前だが重要な話が書いてあったことを思い出す。これは「複数のエンジニアチームに同じプログラムを書く課題を出し、ただ評価軸としてそれぞれ別の軸を伝える。そうするとそれぞれ与えられた評価軸では他のチームより優秀な結果を残した。」というもの*1。エンジニアの目標達成に対するモチベーションは高い。その目標が技術的に面白ければなおさらモチベーションは高くなるだろう。
ゲームの話
突然だが、やればやるほど自分の技術・知識レベルが上がってスコアが上がるゲームは面白い。自分はタイピングゲーム, beatmania IIDX, super hexagon, etc...今までいろんなそういうゲームをやってきた。
また、ゲームをやっているユーザは与えられた条件の中で最善を尽くさずにはいられない、という話がある *2。
仕事とゲームの共通点
仕事もゲームもやるのは人なわけで、その人を突き動かすものとして共通なところは大きい。つまり、仕事も「やればやるほど自分の技術・知識レベルが上がってスコアが上がるゲーム」として捉えられるんじゃないかと思う。「自分の技術・知識」が自分の業務ドメインの技術・知識であり、「スコア」がKPIだ。乱暴な見方をすればGoogleの検索チームからしたら検索速度を上げるゲームが仕事だと言える。そういう視点で見ると、そこのエンジニアのモチベーションが高く、つまりはパフォーマンスも高くなることは当然のように思える。
仕事とゲームの共通しない点
ゲームユーザは「与えられた条件の中で最善を尽くさずにはいられない」と書いたが、現実においては条件というのはほとんど存在しない。もちろん法律や社内規則などはあるが、社員に共通する条件というのはそれくらいしかない。
対談の記事に
僕は一番ビックリした話が、KPIってあるじゃないですか。あれを決めると、時としてモラルハザードが起こるんですよ。
というなおやさんの発言があるが、人を動かす根源が仕事もゲームも同じなら、ゲームと同じく与えられた条件の中で最善を尽くさずにはいられず、モラルハザードが発生するのはむしろ当然なことのように思えてくる。
つまり、現実世界でも「与えられた条件」を明示的に設けないと、モラルハザードが発生する。そしてこのエントリで語られているものがコーポレートビジョンと別のKPIである。
「モラルハザード」を定量的に定義することは難しい。つまり、モラルハザードを防ぐ別KPIを設定するにはケースバイケースに適切に設定する必要がある。しかし、設定したKPIの値を落とさずに「モラルハザード」が起きてしまう抜け道がないことは保証できない。
コーポレートビジョンは違う。もっと抽象的なもので社員の思考の根底にあるものだ。抽象的であるがゆえに、社員に浸透させるのが難しいし、抽象的であるがゆえに浸透すればその会社にとっての「モラルハザード」の認識が根本から共有され、社員は無意識にそれを起こさないよう仕事をするようになる。
会社の文化
コーポレートビジョンを浸透させる、という表現を使ったが、それは会社の文化を浸透させる、あるいは作ることにほかならない。重要なのはいかに会社の文化、つまり社員が持つべき共通認識を持たせるかということだ。
今まではモラルハザードを防ぐという文脈で書いてきたが、コーポレートビジョン、ないしは会社の文化というは浸透していれば悪いことを発生させないということ以外にも効果がある。その会社らしいプロダクトを作る土壌になったり、一種の権限委譲にもなる。権限委譲については会社の文化が浸透していれば、社員が意思決定に迫られた時に、上司に聞かずともこの会社の文化としてこうするべきだ、という判断が可能になるということだ。
そもそも会社の規模が小さければコーポレートビジョンはいらないだろう。数人しかいなければそんなものなくても会社の文化、共通の認識というのは持っているだろうし、そういう価値観が近い人しか採用しないだろう。コーポレートビジョンが重要になってくるのは会社の規模が大きくなった時だ。起業した初期メンバーが持っていた共通認識をいかに社員全体に浸透させるか。ここが一番難しく、かつ成功すれば効果は絶大だと思う。
正直ここに書いているコーポレートビジョンと会社の文化の話は、理想論に近いかもしれないと思う。実際にこうやって成功した、と言う話はなかなか聞かないし、そもそも抽象的すぎてそれを人に伝えるのは難しい。
そんな中成功した1つの実例としては、やっぱりGoogleがあるんじゃないかと思う。How Google Worksの中で、広告に修正を加えるための会議で、一人の社員が拳でテーブルを叩きながら「こんなことはやるべきじゃない。邪悪になるぞ」と言って、修正が見送られたという逸話が紹介されている*3。まさにコーポレートビジョンが、文化が共有されていなければ起こらなかった現象だと思う。
最近そういう取り組みをしているところとしてグリーがある。
従業員に、グリーという会社のアイデンティティを明確にメッセージしてこなかったこともあり、グリーらしさとは何かを意識してメッセージを出しています。従業員それぞれが思っているところはあると思いますが、それがそろっていないことに少しもったいなさを感じているのも事実です。グリーは本来、モノ作りの会社です。それを、プライドを持って言えるようになれば楽しいし強いと思います。
これがどうなるか興味深いと思ってる。もちろん他でやってるだろうけど知らないだけというのもあると思う。
こういう文化を浸透させたら成功する、というのを自分で実証したいところだが、人の上に立つ予定がないので誰か実際にやって成功したという話を聞かせて欲しい*4。
関数型プログラミングの話
まえがき
最近関数型プログラミングについての話題をよく耳にするので、その波に乗って自分も関数型プログラミングに対する理解を書いてみる。
コード例はscalaで書く。知らない人にも分かるよう努力する。
関数型プログラミングってなに?
関数型プログラミングを一言で言い表すとすれば「関数を第一級オブジェクトにする*1ことにより可能になったモジュール性の高いプログラミングスタイル」だと思う。
つまりどういうことだってばよ?
関数型プログラミングの話をする時に僕はよくこう質問する
ユーザオブジェクトの配列があったとして、ユーザIDの配列が欲しいとどう書く?
例えば、以下の様な状況の時、getUserIdsの実装をどう書くか?
case class User(id: Int) // ???は未実装なことを表す def getUserIds(userArray: Array[User]): Array[Int] = ??? var userArray = Array( new User(1), new User(2), new User(3) ) getUserIds(userArray) // Array(1,2,3)が返ってきて欲しい
手続き型プログラミングしてる人の答えとして、こういうのを想定してる*2。
def getUserIds(userArray: Array[User]): Array[Int] = { var userIdArray = Array[Int]() for (user <- userArray) { userIdArray = userIdArray :+ user.id } userIdArray // scalaではreturn書かなくても最後の値が返る }
これを、関数型っぽく書くと、こうなる
def getUserIds(userArray: Array[User]): Array[Int] = userArray.map(v => v.id)
v => v.id
はv
を受け取ってv.id
を返す無名関数。map
は配列内の全ての要素に対して引数の関数を実行した配列を返すので、これでidの配列が手に入る。
少なくともこの例では関数型の方が簡潔であることは多くの人が同意してくれるんじゃないかと思う。
ここで、どうしてこう書けるのか?というのを考えてみる。ここのmap
の定義を見ると
def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = { def builder = { // extracted to keep method size under 35 bytes, so that it can be JIT-inlined val b = bf(repr) b.sizeHint(this) b } val b = builder for (x <- this) b += f(x) b.result }
https://github.com/scala/scala/blob/e2fec6b28dfd73482945ffab85d9b582d0cb9f17/src/library/scala/collection/TraversableLike.scala#L237-L246 *3
配列以外にも使えるように汎用的に書かれているため分かりづらいが、肝はここ
val b = builder for (x <- this) b += f(x) b.result
これはまさにgetUserIdsの手続き型版にそっくりだ。関数型版では手続き型版のコードを分解し、この面倒なところだけmap
に押し込めている。そして、これは関数を引数に取れる、つまり関数が第一級オブジェクトでないと不可能だ。
関数型プログラミングでは、map以外にも関数が第一級オブジェクトでなければ不可能だったコードの分解・モジュール化を数多く行い活用している。
そんなわけで
最初の話に戻って、自分は関数型プログラミングとは「関数を第一級オブジェクトにすることにより可能になったモジュール性の高いプログラミングスタイル」だと思っている。もちろん関数型プログラミングはそれだけじゃないけど、これを軸に説明がつく特徴が多いと思ってる。
Chromeのタブを選んで別ウィンドウにしたり2つのウィンドウを1つにまとめるChrome拡張作った
皆さんChrome使っててこことこことのタブだけ別ウィンドウにしたい、とか、この2つのウィンドウ一つにまとめたい、とか思ったことありません?あれ面倒なんですよね結構。
だからそれが出来るChrome拡張書いたお!
スクショ見たら使い方分かるようにしたつもりだけど、日本語で説明すると
- タブ選んでボタン押すと選んだタブが別ウィンドウに切りだされる
- タブを選ぶやり方はshift + click or command + click(windowsだとcontrol + click?)
- タブを選ばずボタンを押すと、最後にフォーカスしてたウィンドウのタブが今使ってるウィンドウに移動する。
という感じ。コード量は大したことないけど結構便利なものが出来たんじゃないかと思ってわりと満足してる
ちなみにあんまり知られてない気がするんだけど、タブを選ぶのはもともとChromeに備わってる機能で、複数選択してcommand + w押すと選んだタブを全部閉じたり出来る。
あと、2つのウィンドウを1つにまとめるところのインタフェースは妥協した。本当ならウィンドウを複数選んでそれをまとめる、ってのをやりたかったけど、それを分かりやすく作りこむのは難しそうだったんで最後にフォーカスしてたウィンドウとまとめる、という形にした。 *1
というかアイコン作る能力なくてつらい。誰か教えてください。
php conference 2014に行ってきた
まえがき
PHPカンファレンス2014 行ってきた。それに関する感想とかメモ的な何か。
基調講演 PHPの今とこれから2014
- PHPの歴史知れてよかった。
- PHP6がアレだったのは知ってたけど、正式にすっ飛ばすことが決まってたのは知らんかった。
- PHP7の新機能良い
- 非同期プログラミング
- タイプヒンティング
- とは言えここらへんHHVMでサポート済み
PHPコアから読み解くPHP5.5
内容的には
- phpは、実行するときphpプログラムをオペコードという命令に変換してから実行される。
- 5.5の変更点のyield追加、boolval()追加についてオペコードの観点から分析する。
- 5.5の変更点のzend_execute()のオーバーライド負荷についてphpの実装から分析する。
というお話で、結論は
- yield→積極的に使おう!
- boolval→コールバックする時以外は使わなくていい
- zend_execute()→結構変わってるから取り扱い注意
- こういう風にphpの中身を知るとどう書くべきかも分かるので、皆中身にも興味持ってね!
という感じ。
個人的には
- 中身を知ったとして得られるものが少ないので、ここらへんはPHPのエキスパートになるつもりじゃないと勉強する気にならない。
- 使い方だけ知れればいいや。
- yieldの便利さを知らなかったので、ループ処理とかを部品化出来て便利なのが分かって良かった。
- ただ、yield使うと純粋関数にならなくて複雑になるので使うとしても本当に効果的なところでしか使う気がしない。
- というかループ処理の部品化に関しては関数を渡せるようにしたら解決するっぽいから、そっち方向に進化してほしい
と思った。最近Scala書いてて、気づかないうちに自分の頭が関数型脳になってきてるのに気づいた。
フリマアプリ「メルカリ」の超高速開発を支える PHP
資料見つからなかった。タイトルどおり超高速開発をどう実現したか、という話。
- 話を聞くまでは超高速な性能を持つプロダクトをどう開発したのか、という話だと勘違いしてた
- 「PHPのいいところは身近であること」
- すごい共感出来る。
- 最近、仮に「完璧なプロダクトを作れるけど使える人はほとんどいない言語」と「誰でも使えるけどバグも入りやすいしメンテがきつい言語」があったとして、どっちがいいのかと言うのによく思いを馳せる。
- 「最高だと思うものの6割で出す」
- よく聞く話。はてなの中の人もそんなこと言ってた気がする。
- 「迷ったら単純な方を選ぶ」
- これあんまり知らなかったけど、よく聞く話らしい*1
- なるほど、って思った。
- 確かにとにかくものを作らないといけない段階だと特に使い方が簡単な方がさくっと使えて良い。
- 「最初から大人数に使ってもらうことを想定して準備しない。ヒットしなかったらその分のコストが無駄。」
- ほんまそれ。
- とは言えスケールする設計にしておくのは大切だと思った。
- 「テストはコスパの良いエンドツーエンドを書く」
学生・新卒エンジニア向け講演 〜パーフェクト成長戦略
徳丸さんの話と迷ってこっち聞きに行った。内容というかsotarokさん目当て。
- 「オープンソースとかのコード嫁」ってのはその通りと思いつつ実践出来てなくて耳が痛い話
- 特に大きいプロダクトだと、どこから読んだらいいのか分かんなかったりするんですけど、皆どうしてるんですか。
- 「人をdisらずコードをdisる」ってマジ大事。
- ただ、自分はコードをdisってるのに、受け手が自分をdisられていると感じてしまうこともあるので、難しい話ではある
PHPにおけるI/O多重化とyield
I/Oの多重化をyield使って実現する話。
- やっぱりyieldは性に合わない...
- それをライブラリ側で全部隠蔽してくれればいいんだけど。
- ただ、思わずHHVM/Hack使えばいいんじゃね?って思ってしまった
HHVM + Hack == PHP++
http://dl.hhvm.com/resources/conf/2014/OSCON/Include%20Hack.pdf
目玉講演。Facebookの中の人がHHVMとHackについて話してくれた。
- 「PHPの今とこれから2014」にもあったとおり、非同期プログラミングとタイプヒンティングのサポートが魅力的すぎる。
- 各種コレクションも用意してるの素晴らしい。
- 型があるおかげでIDEの強力なサポートが可能なのめっちゃ良い(まだないっぽい
- 「単純なベンチマークじゃあんまり意味が無いから、プロダクトに近いベンチマーク作った」
- まさにHHVMが速いという自信の現れだと感じた
- 公表するのがこの講演が初めて
- っていうのを本人が英語で言った時と通訳さんが日本語に訳した時に拍手がばらけたのが面白かった*2
- あと単純にプレゼンめっちゃうまかった。
- 最後の質疑応答で「CentOSでパッケージ提供してくれないの?」って質問に、通訳さんが英語に訳す前から発表者の人頭抱えてて笑った。
- この講演ではないけど、本人に「関数型要素はHackに入れないの?」って聞いたら「mapとかfilterは入れたい」って答えてたってツイート見かけてテンション上がった*3
- yield使ってループ処理を部品化する、ってところがmapあれば(おそらく大半は)解決出来る。
Webアプリのデプロイ今昔物語
- 資料わかりやすい
- エンジニアになって2,3年なので、こういう昔話聞くと知らないこと多くて面白い。
おわり
当日聞けなかった分も資料見て書こうと思ったけど思いの外長くなったからやめとく*4
*1:https://twitter.com/yuma_iwasaki/status/520768690891935744
*2:もちろん僕は後者で拍手しましたが...
*3:https://twitter.com/okapies/status/520887859692052481
*4:別エントリで書くかも
お前らの並行(concurrent)/並列(parallel)の説明は分かりづらい
まえせつ
こないだakka meetup行った時に並列・並行の話がちょっと出て、今までこの2つが違うらしいことは知ってたけどどう違うのかは曖昧なままだったのでこの機会に調べてみた。 で、いろいろ調べた結果*1、要はこういうことだろ、という自分の理解を書いてみる。
せつめい
ここにコンピュータに実行させるタスクが2つあるじゃろ。
これを順番に処理するのが逐次処理じゃ。
ここで、タスクをそれぞれコマ切れにして
こう処理するのが並行(concurrent)処理じゃ。
むつかしいこと考えずにこう処理するのが並列(parallel)処理じゃ。
以上じゃ。
*1:書籍とか読んだわけじゃなくてぐぐって出てきた情報がソースなんですけど