HTML5Experts.jp

Qiitaのスライドモードは、mizchiが勝手に作った!?─Incrementsの縛られない開発スタイルを聞いてみた

及川卓也さんや田中洋一郎さんをはじめ、著名なエンジニアが次々と入社していることで話題のIncrements。8月にはさらにCSSのコードフォーマッターであるStylefmtの作者・morishitterこと森下雅章さんを迎えるなど、さらに開発陣営を強化しています。

今回はさっそく森下さんにも加わっていただき、白石俊平編集長を聞き手に、CTOの髙橋侑久さん、フロントエンドエンジニアmizchiさん、デザイナーの東峰裕之さんに、「Qiita」の開発環境や開発スタイルなどについて聞いてみました。

特定領域でとんがってるスペシャリストが増えてきた

白石:まずは、自己紹介とQiitaの開発チームでの役割についてお聞かせください。

髙橋:IncrementsのCTOを務めている髙橋です。メンバーの中では一番古株ですね。Qiitaは最初、CEOの海野が開発していたのですが、それを引き継ぐかたちでQiitaのプロダクト開発からインフラまでのすべてを見てきました。

最近はJavaScriptのエキスパートであるmizchiのように、特定領域でとんがってるメンバーも増えてきているので、エンジニアの組織作りや環境整備に注力する時間が増えています。

白石:Qiitaはもともと海野社長がコードを書いてたんでしたっけ。

髙橋:はい。Incrementsは代表の海野が大学時代にビジネスコンテストで知り合った3人で創業したんですが、その共同創業者の1人が海野にプログラミングの相談をしたことがQiitaを開発し始めたきっかけでした。

Qiitaはプログラマのための情報共有のプラットフォームで、解決しようとしている課題は明確なんです。プログラムを書く時ってGoogleで検索したり技術書で調べず、頭の中の情報だけでコードを書く人はほとんどいないじゃないですか。

でも結局自分が知りたい情報が見つからなくて、時間を無駄にしている人は多いですよね。誰もが使える情報共有基盤を作って、そういう検索時間を圧縮できたら、日本のソフトウェア開発の生産性を高めていくことができると考えたのが、Qiita誕生のきっかけです。

Qiitaの開発は2011年に始まって、2012年に起業しているんですけど、最初は3人で始めたということもあって、リーンスタートアップみたいなかんじで開発していたんですよね。僕が入社したのは2013年4月。その時にエンジニアのコミュニティに支えられながら、自分が必要だと思っていたQiitaの下書き機能を開発しました。

白石:なるほど。当時も技術系の情報を発信するブログサービスは存在していたと思うんですが、Qiitaが大ブレイクしたことから考えても、まだ不十分だったところがあったんでしょうね。

mizchi:僕は基本的にはフロントエンドの人間で、2年前に教育系のベンチャーから転職してきました。最初は「Kobito」のWindows版をElectronで作ったり。SPA(Single Page Application)とネイティブAPIをたたくアプリを作ってたんですけど、去年の9月からQiitaの開発にも関わるようになりました。

Qiitaは2011年末くらいに開発されたものなので、ちょうどそのくらいの時期にフロントエンドのフレームワークに激動の技術進化があったりして、いろいろ古くなってしまったところをどうにか秩序をもたらせないかと対応してきました。最近やっと落ち着いて、機能開発などもかなりやれるようになってきたかなあという感じです。

例えばQiitaのホーム画面のフィードや編集画面、この前足したスライド機能など、どうしても局所的にJavaScript的な密度が高くなる箇所があるので住み分けし、モジュールとしてAPIがちゃんとお互い交流できるようにきれいに設計しています。

さらに、コンポーネントで密度を厚くし、複雑化したところからはみ出さないように作っていく。でもかなり行数も多いんで、できる範囲でとにかくきれいに区切って、ひたすら分割していくみたいなことをやってました。

東峰:デザイナーの東峰です。Incrementsではデザイナーの業務範囲が結構広くて、PMに近いことからデザインの実装まで一通り行います。ユーザーヒアリングも行くし、エンジニアとコミュニケーションとりながら企画やディレクションなども行うし、GitHubにPull Requestも出すという感じです。

前職はサイボウズでグループウェアを作っていたので、入社した頃は「Qiita:Team」を担当していましたが、最近はQiitaをメインに担当しています。

森下:8月にIncrementsに入社しました。前職はサイバーエージェントで、新卒で入社してフロントエンドエンジニアをやってました。UI周りの実装だったり、CSSの設計が得意領域で、自分でCSSのフォーマッターとかスタイルガイドジェネレーターを自作したりもしてます。

縛りをつけず、最新技術もいろいろ試す

白石:では、さっそく開発環境などの話を聞いていきたいと思います。まずは、Qiita全体のアーキテクチャについて教えてください。

髙橋:アーキテクチャとしてはオーソドックスにRuby on Railsを使っています。バージョンはまだ5にはしてなくて、4.2です。データベースはMySQLを使っています。

白石:フロントエンドの開発ツールやエディタは何を使っているんですか?

mizchi:エディタには特に縛りがないですね。最近はBabelを使ってるんですけど、FlowTypeというTypeAnnotationを付けるやつを部分的に足しています。全部ではないんですけど、新規で書いた分は型を付けながら進めている部分が多いです。世間的にはTypeScriptの方がメジャーだと思うんですけど、TypeScriptはスクラッチの開発じゃないとなかなか導入が難しいので。

最初CoffeeScriptで書かれていたものをJSに変換するコンパイラとかをかけながら、ガリっと書き換えた時期があって、その頃にBabelにして、RailsのSPRocketsを使ってビルドしてました。去年はそれもできるだけ捨てて、書き直してっていうのを延々やってましたね。

白石:たしかmizchiさんって、ブログでCoffeeScriptってヤバいみたいな記事を書かれてませんでしたっけ?

mizchi:CoffeeScriptはあまりメンテされなくなってきたのと、ES2015(ES6)がすごい進化してて、新しい機能を使う時にCoffeeScriptに縛られるのはかなりのリスクがあるなと。CoffeeScript好きな人は全然いいと思うんですけど、自分のようなフロントエンドを一応攻めないといけない人は、CoffeeScriptを使うのはリスクであると認識してます。

白石:先ほどTypeAnnotationを使っていると言ってましたね。型がないのがJavaScriptのいいところでもありますが、やっぱり規模が大きくなってくると型が欲しくなってきたというところでしょうか?

mizchi:これはいろいろ考え方はあると思うんですけど、JavaScriptってとてもテストが書きづらい言語なんですよね。End to End(E2E)だったり、独立させたNodeでユニットテスト書くなりしても、なかなか書きづらい。最近はとても分量が多くなってしまっている中で、その動作を担保するものとして、静的解析っていうのは有用なんじゃないかと。まあもちろん、静的解析するからといって、テストを全く書かないというわけではないんですけれど。

白石:FlowTypeで書いたものをテストケース書くとなったら、テストケース側は何で書くんですか?

mizchi:今はNodeでユニットテストできるようにしています。Reactのサーバーサンドレンダリングは基本的にテンプレートのテストやユニットテストならできるんで。E2Eが足りないのは分かっているんですが、決め手のフレームワークが今ちょっと足りてなくて…(今現在E2Eを導入してないのは)反省しているところがあります。

白石:フロントエンドのほうは、Reactを採用してるんですね。

mizchi:はい。昔はBackbone.jsで書いたものも大分残ってはいるんですけど、新規で書く部分に関しては、Reactで書いています。Reactがいいというよりはここが古くなったから捨てるということが密結合にならずに、個別のモジュールで一気に捨てられるような、代謝のしやすい設計をすることが大事だと思っています。

白石:CSSとReactあたりって、興味がある人が多いと思います。CSSモジュールとかいろいろ聞かせてください。

森下:前職でReactを使っていてたんですが、Reactアプリの中でCSSを書いていくことに対しては自分なりの意見を持っています。CSS Modules等のCSS in JS系ツールを触ってみたりしたんですけど、僕はJSのコンポーネントの単位とCSSのコンポーネントの単位って、1対1で対応するものではないと考えています。

それはデザインの再利用する単位と機能の再利用する単位が異なるからで、よくあるcomponentsディレクトリ配下に、index.jsとindex.cssがあるみたいな構成は結構難しいのかなと思っています。

CSS in JS系ツールは、CSSそのものやその設計手法にあまり詳しくない人が、なんとなくJSのコンポーネントの単位でスタイルの影響範囲を閉じたい、という場合は良いものだと思います。QiitaとQiita:TeamはHTMLのレンダリングを全てReactが行っているわけではないので、部分的にCSS in JSを導入するのもおかしいので使いたくないです。

白石:じゃあ、もうコンポーネントにスタイルは閉じない?

森下:そうですね、Reactのコンポーネントの単位ではCSSのコンポーネントは作らない。

白石:Web ComponentsでCSSを閉じさせられる、例えばShadow DOMとかだと思うんですけど、それはちょっとどうかなって思ってるかんじですか?

森下:Shadow DOMでスタイルの影響範囲に抑られるのはいいことだと思ってますが、そもそも装飾と機能を合わせたものをコンポーネントとしていろんなところで再利用していこうという考え自体が僕にはイマイチ…。

mizchi:そういえば昔、Web Componentsでピアシングってスペックがありましたね。

白石:ピアシング、それ知らないなあ。

mizchi:ピアシングって、外から中に対してCSSをかけるんですよ。でもそれがなんか難しすぎるからなくなったらしいんですよね。やっぱりそこの複雑さよりは、単純な方をWeb Componentsは取ったんだろうなっていう気はします。

白石:なるほど、scope属性みたいな感じで書いていけるんでしたっけ?

森下:あれも今は仕様が変わってて、scoped属性はなくなって、@scopeっていうアットルール(@規則)に変わりました。(注: このあと@scopeルールもなくなった)

白石:そうなんですね。勉強になります。じゃあもうCSSは別に出しちゃって、WebとかそういったものでCSS付けるっていうみたいな感じなんですかね。

デプロイはAWS、ログ収集はBigQueryを利用

白石:ちなみに、バックエンドのほうの話も聞いてみたいです。

髙橋:デプロイ関係はAWSを使ってますね。あんまりAWS固有にベッタリみたいな感じにはしたくないと思っているので、データの収集などはGoogleのBigQueryを使っています。

白石:僕もBigQueryを使いたいんですが、使っているクラウドサービスはAWSなんですよね。Googleのほうはインターネット回線を通じて送っているんでしょうか?

髙橋:今は各アプリケーションサーバーごとにFluentdがあって、それを集約するFluentdサーバーからGoogleのBigQueryに一部分をバックアップとして保存しています。

よくデータ量が多そうですねって言われるんですけど、Qiitaの場合はユーザーがほぼエンジニアなので、トラフィック量という意味では、マスを相手にしているサービスと比較すると少ない部類です。実験しやすい環境なので、いろいろとやっています。

mizchi:監視はDatadogとNewRelicっていうアメリカのサービスを使っています。その2つを使って各種サービスのサーバーモニタリングをしています。

白石:Datadogは知らなかったです。範囲的にはNewRelicみたいなことを?

髙橋:NewRelicはどちからというとアプリケーションそのもののパフォーマンスを見るのが強いんですが、Datadogはサーバーのメトリクスの監視などをします。はてな社のMackerelとかなり近いです。

mizchi:本番環境をDockerによるコンテナベースの環境に移行しようというロードマップがあります。開発環境も本番環境と同じようにVagrantからDockerベースのものに移行しようと取り組んでいます。

白石:仮想環境あたりの話は詳しく聞きたいですね。

mizchi:最近Node.jsのネイティブバイナリをガンガン使ってます。今まで開発環境で使っていたCentOSに引きずられて使いたいツールが導入できないことがありました。例えば、FlowTypeのバイナリがCentOSというかRed Hat系のものがないからできなかったんですよね。Dockerになったことでミドルウェアを更新しやすくなったので開発しやすくなりました。あとVagrantではローカルのファイル変更を仮想環境側でうまく検知できない問題があったのですが、Docker for Macのファイル検知が賢いから、ファイル監視みたいなこともやってます。

本番環境がクラシックなEC2を使っていたので、ミドルウェアの更新はサーバー台数が増えてくるとなかなか簡単に行えなくなってきてたんですよね。そこの本番環境に引きずられて開発環境にも悪影響が出てたんですけど、それをDockerに持っていくことによって本番環境が切り替えやすくなるので、その分開発環境にも新しいコンポーネントを入れやすくなりました。

白石:ちなみに、そのVagrantからDockerへの切り替えていうのは、もう結構苦労しましたか。それとも割とすんなり?

mizchi:そうですね。Dockerなどに強いインフラエンジニアが入ってきたので、その人が主導してガンガン進めてくれている感じです。

白石:なるほど、まさに専門に特化してる方にどんどん移譲していってる段階なんですね。

試行錯誤を繰り返しながら、リモートワークを模索

白石:次は開発体制についてお聞きしたいのですが、そもそもQiitaは何人ぐらいのチームで開発しているんですか?

髙橋:エンジニアが10人、デザイナー3人、PM1人、バックオフィス4人と社長で、社員は現在19人です。社長の海野もエンジニアなんですが、現在は経営に集中しています。開発チームは大きく言うと3つで、QiitaとQiita:Team、そしてKobitoです。Kobitoはそれぞれのメンバーが兼任しています。Qiitaの開発チームは6人ですね。

東峰:QiitaとQiitaチームはかなりコードベースが共通なので、機能作り始めると両方考慮しなくてはいけないことも多いですね。

髙橋:Incrementsは全社的にリモートワークを導入しているのが、大きな特徴ですね。今日はインタビューがあるのでmizchiも来てますけど、基本的にはインターネットの向こうの人です。

白石:リモートワークは話題になっていましたね。実際、コミュニケーションとかうまくいくものですか?ツールなどはどんなものを使っているのでしょうか。

東峰:Google Hangoutsをベースにしています。多人数で繋ぐとどうしても重くなったりとか、回線状況によって接続がうまくいかないこともあるので。いくつかサービスを試しているところです。

白石:やはり常時接続にしているのでしょうか。

東峰:いえ、オフィス側だけですね。モニターとカメラがオフィスの真ん中にあるんですけど、それがHangoutで常にオフィスを映しています。そのチャンネルに入ってくれば、オフィスの様子が見えるように作っています。

白石:なぜ、オフィスだけ見せておくんですか。

東峰:実は社長の海野や髙橋、僕といったメンバーは学生時代にはてなでアルバイトしていた時期があるのですが、当時はてなでは東京と京都のオフィスを常時ビデオ会議で接続していたんですね。何かあるとそこにみんなが集まってくるという状態ができていて、その体験がすごくよかったからなんです。

リモートワークについてのリリースを出したのはつい最近なんですけど、2年近くトライアルはしてきました。週1だけリモートとか2週間スポットでフルリモートやってみたりとか。常に接続して定期的にキャプチャーを撮ってくれるSqwiggleというツールを使ってみたりもしました。でも常に見られてる感じがして嫌だっていう声があったり、マシンスペックもかなり使うので、最終的にはみんなが集まる場所としてのオフィスHangoutを作る形に納まりました。

mizchi:常時接続ってバッテリーの消費が激しいので、外に出歩いてる人にはかなり難しいんです。まあそれと別に僕は個人的にSqwiggle大嫌いだったのはあるんですが。

東峰:まあ実際、そういう人は多いと思うよ。

白石:リモートワークといっても、みんな自宅で仕事しているわけではないんですね。

東峰:そうですね。基本的に場所は自由なので、自宅以外にもカフェやコワーキングスペースとか、地方の実家に帰って作業してみたり、自由度は高いですね。

髙橋:リモートワークは各個人がベストパフォーマンスを発揮できる場所を自分で選んで仕事できるようにすることが目的であって、離れ離れになることが目的ではないので、あくまでも集まれる場所が必要なんですよね。そのために、オフィスのバーチャルな集会場みたいなかんじで常に開放し続けています。

白石:なるほど。リモートから見るとオフィスが全部映ってるんですね。これはHangoutじゃないですよね?

東峰:これはappear.inでやってます。スマホでも見れるんですよ。まるでオフィスにいるみたいな感じで話せるんですが、実際のオフィスには誰もいないということもあります(笑)。

白石:それシュールでいいですね。

東峰:髙橋が言った通り、やはり各自がベストパフォーマンスを出しているかということが大事なんですよね。振り返りもパフォーマンスがどれだけ上がったのかを見ていきたいと考えています。Incrementsはオンラインのコミュニケーションに慣れているメンバーが多いので、(リモートワークでも)できちゃうのはできちゃうんですね。特に大きな問題はないように見えるんですけど、本当に上手くいってるのかちゃんと検証したいので、あえてネガティブな面の洗い出しをするようにしています。

白石:オンラインコミュニケーションというものに対する経験値がみんな高いわけですね。Slackとかも使ってますか?

東峰:使ってますね。SlackとGoogle Hangouts、あとはQiita:Team。

髙橋:リモートワーク取り組み始めた目的の1つには、これから社会がリモートワークにシフトしていくなかで、率先して自分たちがその環境に身を置くことによって、リモート環境で働く組織の情報共有に必要な課題は何か、身を持って体験できることがあります。それをQiita:Teamの開発に還元していきたいですね。

東峰:我々はエンジニアを支援して世界を良くするっていうの社是なんで、新しいことにはどんどんチャレンジしていって、あまり保守的になりたくないと思っています。

OKRで組織目標を設定し、コミュニケーションを効率化

白石:ちなみにタスク管理のツールは何を使ってますか?

東峰:開発に関するものはGitHubとZenHub、Trelloを使ってます。

髙橋:あと最近では及川が入ってきたタイミングで、OKR(Objectives and Key Results)という取り組みを始めました。もともとはGoogleなどで使われていたフレームワークなんですが、会社に導入しようとしてもいきなりうまくはいかなかったんです。四半期単位でゴール設定するんですけど、1クオーター目、2クオーター目はもう全然ダメでしたが、3クオーター目の今になってようやくまともにOKRが回り始めてきました。

白石:では最後に、今後の課題や取り組んでいきたいことをお聞かせください。

mizchi:すごく根本的なことなんですけど、RailsとJavaScriptって相性が良くないんですよ。Railsから内部データ読んでJavaScriptをコードの自動生成するとか、いろいろ試しに作ってはみたんですけど、まあ言語が違うから。turbolinksが独立したJSパッケージもあるんですが、まだしっくりこないですね。個人的にはそこを突き詰めたいと思っています。

白石:言語の違いっていうところの問題が根源なんですかね。サーバーサイドがNodeだったらもっと上手くいくとか。

mizchi:僕はあんまりサーバーサイドにNode使いたいとは思ってない人間なんです。もちろんNode使えばReactのサーバーサイドレンダリングとかはすんなりいくんですけど、シングルスレッドを管理するコストの方が重いし。

髙橋:今のそのJavaScriptとRailsの繋ぎこみの部分というのは結局インターフェイスがRails側で統一できていないので、JS側で試行錯誤しなきゃならないっていうのが一番の問題点なんです。Facebookが最近公開したGraphQLみたいに、中間の緩衝地帯みたいなものを作ることによって、JSクライアントとバックエンド側がもっと上手くインテクレードできるような環境が作ることを考えたりしています。

mizchi:その2つの間で共通するハッシュや配列のフォーマットなどで会話しようと心掛けてるうちは多分上手くいくんですけど、そこからはみ出した瞬間上手くいかないなって感じがします。日付とか困りますね。Unixtimeにしてほしい。Datetimeのフォーマットは信用ならない(笑)。

髙橋:Incrementsの自慢はメンバーの質が高いこと。結局できる人を連れてくることが、最高の環境改善方法だと思っています。JavaScriptで迷ったらmizchiに聞けば、何でもかなりクオリティの高い回答が返ってくる。社内Slackで質問すれば社内の有識者からすぐにコメントをもらえるのがいいですね。

mizchi:僕としても多少無茶してもあんまり止められないっていうのは楽しいですね。勝手にこの前作ったスライド機能も、勝手に作って勝手に出したら、めちゃくちゃ評判良かったっていう。

白石:あれ勝手に作ったんですか?

mizchi:業務中に勝手に作ったんです。ベースは2時間で作りました。

白石:森下さんは入社してチャレンジしていることはありますか?

森下:BootstrapベースのCSSフレームワークを消して、Qiita独自のUIパーツなどを作っておきたいですね。そのスタイルガイドやメンテナンスみたいなことをやっていきたいと思っています。

白石:Qiitaのデザイン言語を作っていきたいみたいなかんじですね。

東峰:さすがに規模も大きくなってきて、多くのメンバーが協働でUIを作っていくのにBoostrapがあるだけではクオリティを保つことが難しくなってきましたから、Bootstrapを捨てるのがメインというよりは、ちゃんとうちに合ったフローやガイドラインを整理して、見た目も含めてトータルのUIデザインを管理できる状態にしていきたいと思っていて。その仕組み作りについては、森下を中心に一緒にチャレンジしていきたいですね。

白石:Qiitaはこれからもまだまだ成長していきそうですね。今日は興味深いお話をありがとうございました!