読者です 読者をやめる 読者になる 読者になる

Sketchglass Blog

respassのデベロッパーチームsketchglassの公式ブログ

オープンソースなリアルタイムチャットシステム "respass" を3週間で作った

WebSocketを用いたオープンソースなリアルタイムチャットシステムrespassをリリースしました。

f:id:sketchglass:20160716045054p:plain:w64

TL; DR

無職2人が3週間で https://respass.sketch-glass.io/ を作りました。 f:id:sketchglass:20160717003920p:plain

ソースコードGitHub上で公開されています。

github.com

自己紹介

@minamorl

@seanchas_t

  • 無職
  • C++/TypeScriptエンジニア
  • GitHub

はじめに

この記事は主に技術者に向けて書かれていますが、そうでない方にも読めるような表現を重視しています。難解な用語にはなるべく注釈をいれました。技術的な話よりも「無職2人がいかにして3週間で作り上げたのか?」という開発フローの話に重きをおいたので、非技術者の方にも楽しく読んでいただけると思います。

なぜ作ったか

オープンソースなチャット

近年、TwitterやSlackの普及に伴い、リアルタイムなチャットシステムというのは広く普及しました。このようなリアルタイムなチャットシステムには大変需要がありますが、オープンソースな実装は非常に選択肢が限られています。 そこで、私たちはMITライセンスのもとで誰もが自由に使うことが出来るリアルタイムチャットシステム、respass を開発しました。

開かれたチャット

respassは、誰でも自由に閲覧でき、Twitterでログインすることですぐに共有スペースにコメントを書き込めるチャットです。 フォローしている人のコメントしか見られないTwitterや、明示的にチームに参加しないとチャットに加われないSlackとはひと味違った体験を実現しています。

リアルタイムなチャット

respassでは、ブラウザ側からサーバー側に一定周期で接続して新しいメッセージはないか確認する代わりに、WebSocketという技術を採用してサーバーとクライアント(ブラウザ)を常時接続した状態に置くことにしました。 これによって、遅延のないユーザー同士のメッセージのやりとりを可能にしています。

わかりやすくシンプルなUI

respassは、誰もが一目見て使い方を理解できるモダンなUIを実現するために、無駄を省き可能な限りシンプルでクリアになるようにデザインされています。

f:id:sketchglass:20160717003920p:plain f:id:sketchglass:20160717003931p:plain:h400

使われている主な技術

  • Node.js
  • TypeScript
  • React + webpack

いかにして3週間による開発を可能としたか?

ここからが本題です。

はじまり

@minamorlと@seanchas_tはほぼ面識がありませんでした。

私たちが最初に共同開発を決定したのはもくもく会(一部のエンジニア同士の文化で、カフェなど一箇所に集まって黙々と作業すること)の最中です。お互いにほとんど面識はありませんでしたが、Twitter上である程度お互い技術的な知識があるのは知っていたので、なにか共同開発をしてみたいな、と思っていました。その段階では何かを一緒に作りたいですね、という雑談をしただけでした。

はじめに@minamorlがWebSocketによる簡単な通信システムを作りました。白黒の画面で、片方が文字を打つともう片方に反映されるというただそれだけのシステムです。

f:id:sketchglass:20160717003852j:plain

この時点で双方で何を作るのかという具体的な合意はありませんでした。単純に趣味のプログラミングとしてWebSocketという技術に興味があったので、触ってみたというのが事の発端です。TypeScriptでの開発経験はありませんでしたが、WebSocketを用いたリアルタイムチャットシステムを実装するにあたり、必要なPythonのライブラリが見つからなかったためTypeScriptでの開発を決定しました。

@minamorlは漠然と「数カ月したらそのうちフロントエンドも作ろうかな」と思っていました。しかし開発を始めて最初のコミットから数時間後、@seanchas_tが簡単なフロントエンド実装を用意しました。

f:id:sketchglass:20160717003908p:plain f:id:sketchglass:20160717003857j:plain

こうして双方の打ち合わせも特にないまま、一瞬のうちにサービスの初期段階が完成しました。

意気投合する間もなく、必然的に私たちは共同開発の道を歩むことになりました。

高速な意思決定プロセス

基本的に対面でのやりとりというのは最初の開発方針の決定時以外ほとんど行われませんでした。

私たちは数回程度現実世界で会話しましたが、会った時点で話したのは大まかなビジョン程度でした。「なんとなくこういうものを作りたい」「じゃあ作りますか」で話が進みました。開発の進行も、会話より動くコードが優先されました。私たちの間ではアイデアではなく実現したものが全てでした。これは上から下まで設計したあとにサービスを作る、いわゆる商業的な開発手法とは全くかけ離れたものです。

会話の中心はSlackで行われ、技術面においてはTypeScriptで行うという点で一致しました。@seanchas_tはTypeScriptでの経験が長かったため、開発をするのは容易でした。

私たちは開発のかなり早い段階でTrelloとCircleCIを導入しました。これは開発速度の向上へ大いに役に立ちました。

GitHubで単にissueを建てて頑張るより、Trelloのほうがタスク管理全体に向いているなと感じました。Trelloというのはオンラインのタスク管理ツールです。

私たちはボードを次のようなリストに分割しました:

  • 最終目標
  • 改善案
  • タスク
  • doing
  • done
  • 今はやらない

f:id:sketchglass:20160717003913p:plain

この中でもタスク一覧とdoingが果たした役割が大きかったです。現在進行形の作業が見えることによって重複した作業をするのを防げました。いちいちチャットでうっとおしい確認もしなくて済みました。

もしTrelloを導入していなかったらどうなっていたでしょうか。重複した作業をしないために、お互いがどのような作業をしているのか知るためにいちいちチャットを飛ばし、相手のレスポンスを待たなくてはいけません。そういったストレスがない環境で開発することによって、高いモチベーションを保てたまま完成させられたのは素晴らしかったです。

プルリクエストベースの開発

これも非常に大きな役割を果たしました。プルリクエストベースの開発というのは、簡単に言うと、正式リリース用のソースコードに直接変更を反映させるのではなく、一旦別の場所で開発したもののリクエストを送り、assignee(任命された人)に承認してもらって初めて本番反映するという仕組みのことです。 お互いをassigneeに設定することでコードのバグを防ぐ効果もありましたし、なによりその場しのぎのコードは許されないという強い意識が生まれました。また、master(本番のソースコードそのもの)に直接コミットしないことによってバグが混入しても戻せばいいという安心感は大きかったです。

一方でデザインなどの微調整に関してはいちいちプルリクエストを送らず直接修正していました。ちょっとここの余白を4pxずらしたいな、と思ったら勝手にずらす、といった形で行われました。これは開発速度の向上に寄与しました。

全体的に、突き詰めるポイントは妥協せず会話しあい、徹底した調整が行われましたが、それ以外は思いつきや即興によって行われました。

TypeScriptの貢献

TypeScriptをバックエンドとフロントエンドの両方に導入したのは正解でした。複数のプログラミング言語を使うというのは案外脳がつかれます。同一のプログラミング言語を用いるということは、脳内でコンテキストを切り替える手間が省けますし、JSONの型定義が共有されてたので、フロント・サーバを行ったり来たりして整合性を考える必要がありませんでした。isomorphicなアプリケーション開発(サーバーサイドのプログラムとフロントエンドのプログラムでまったく共通のコードを利用すること)は新鮮であると同時に効率的な体験でした。

ドッグフーディング

自分たちの作ったサービスを自分たちで使うことによって効率よくデバッグ作業が進められました。また知人のTwitterユーザに手伝ってもらってバグ探しをしてもらったのも大いに貢献したと思っています。ことさら@saki7による厳しい品質テストは大いに役立ちました。彼もまた優れた無職です。

鉄を熱いうちに打つ

昔から鉄は熱いうちに打てといいます。あらゆるものごとがそうです。熱が冷めないギリギリのラインを見積もって、私たちは開発スパンを早期に3週間に設定することを決めました。

だらだらと先延ばしすることなく、3週間、昼夜問わずの開発を行いました。私たちは完全に熱に浮かされていたといえるかもしれません。とにかく、アイデアにのめり込んでいました。開発初期のぼんやりとしたこのチームなら上手くいきそうだという感覚は、時間を経つにつれて強まり、いまのプロダクトに対する情熱がピークに達するころ、私たちは完全な結束感を感じました。

それはいままでどんな仕事でも得たことのない感動でした。

相手の意見を尊重する

これは非常に大きなトピックです。

基本的に私たちが繰り返したコミュニケーションの基本は尊敬と妥協です。お互いコードの面で異議がある場合でも、動いているものが優先されましたし、不必要に見えるコードも無視して、容赦のないデバッグリファクタリングも甘んじて受け入れました。

相手の意見を尊重する、というのは非常に難しい行為です。ことにそれがクリエイティブなプロセスともなると悪夢のようです。才能のある尖ったクリエイター同士が衝突して破滅する場面を私たちは何度も目にしてきました。画家が二人いたとして、お互いの個性をぶつかり合わせず作業するということについて考えてください。プログラマーも同じです。私たちは互いの技術力に敬意を払うことで、深い検討が不要な部分については妥協を受け入れ、それを回避することが出来ました。

課題と展望

今回3週間本腰をいれて二人で開発してみた結果、予想以上に相性は良かったです。すでに私たちは膨大なプロダクトの改善案を抱えながら、更により長期的なタスクにとりかかろうとしています。

3週間の開発を通して課題として浮かび上がってきたことがいくつかあります。

まずこのやり方は確実にスケールしない、ということです。つまり私たちはたまたま運よく相性が合ったので成り立っただけで、そこに新たに開発者を加えるとなるとやはりバランスの均衡は崩れてしまうことが予想されます。

次に、抱えている様々なissueに対する優先順位付けができていなかったのは大きな課題でした。GitHubのissue trackerもTrelloも、問題を優先順位付けて解決するにはあまりにも簡素すぎます。

最後にですが、やはりリモート開発には限界があるということを書いておきます。これは@minamorlと@seanchas_tとの共通見解です。二人の意見が対立したとき、どうしても文章では誤解を招いてしまいます。今回、開発の基盤においては大きなヒビは入りませんでしたが、物事の進め方に対しては若干の見解の対立が生じてしまいました。コミュニケーションロスを防ぐためには、リモート開発よりも口頭で共有することのほうが伝わるものは大きいのかもしれません。

私たちは今後、週に数回集まって会議しながらより大きなプロダクトに挑んでいくつもりです。

以上、無職が2人で3週間で https://respass.sketch-glass.io/ を作ったお話でした。

感想

@minamorl

TypeScriptは初の体験だったが、バックエンドとフロントエンドの共通化は非常に効率的で新しい体験だった。言語のイディオムに関しては@seanchas_tの真似をすることによって効率よく吸収することが出来た。あと朝(昼過ぎ)にプルリクエストで目が覚めるのが面白かった。

@seanchas_t

労働以外での複数人での本格的なサービス開発は今回が初めてだった。メンバーそれぞれのアイデアや実装が相乗効果になってサービスが出来上がっていくのが刺激的な体験だった。 また、サーバ/フロントエンド、コーディング/デザインなどの役目を分けず開発を行ったのが効率やチームの一体感を生み出して良かったと思う。

@saki7

メンバー間の意思決定プロセスが単純明快だったのが見てて爽快感があった。今後の発展に大いに期待している。

連絡先

sketchglass.team@gmail.com