🏠

マチマチとOSSの関わりをGitHubで振り返る

2019/02/26に公開

ご近所SNS「マチマチ」を作っている武者(@knu)です。今回はマチマチとOSSとの関わりについて紹介したいと思います。

マチマチのエンジニア達はもっぱらRuby/RailsやReactのコードを書いていますが、そうしたフレームワークや周辺ライブラリ、そして言語実装はすべてOSSとなっていますし、データベースエンジン(PostgreSQL/PostGIS)、RedisやMemcached、それらを稼働するOS、ビルドやテストに使うツール、エディタ、等々に至るまでの多くがOSS、またはOSSをベースとしたものとなっています。今や、OSSなくしてはこの世界で何もなし得ないと言っても過言ではありません。

私自身も長らくOSS開発に携わっており、前世紀からFreeBSDRubyのコミッターを務め、自作のOSSもたくさん書き、周辺のエコシステムにパッチをフィードバックしたりしてきました。そんな中で強く感じるのは、近年ますますOSSと仕事のコードに境目がなくなってきているということです。

受託であろうが自社製品の開発であろうが、OSSを使って何かを書いている限りは、日々不具合や改善したいと思う点が必ず出てきます。ソフトウェアの開発の動きが活発な現代では、改善を自分達で独占すべく手元で抱え込もうとしても、長期的にはメンテナンスコストで持ち出しになる、よほどのコアコンピタンスでもなければ公開して開発元にフィードバックして後を任せた方が楽である、という考え方はごく普通になっています。

マチマチでも、社内での成果を社外に出すことについていちいち許可を求めるような手続きはなく、逆に「貢献だ!恩返しだ!」と肩肘張ることもなく、淡々と、よりよい世界を目指す一住人としてOSSを公開したり開発元にフィードバックしたりしてきました。

私がジョインしてからまだ2年足らずですが、主にGitHub上の活動から改めて振り返って、我々の足跡をまとめてみました。

ドキュメント関係

BigQueryのDash用docset

https://github.com/Kapeli/Dash-User-Contributions

BigQueryのSQLを書くときに、構文や関数についていちいちググるのがつらいことから、ドキュメントブラウザーDash用のオフラインドキュメントを作ってメンテナンスしています。SQL文は一般的な英単語の組合せですし、世の中には無数のSQLエンジンがあるので、検索ワードを調整するコストが高いのです。

これは私が前職時代に作ったものですが、現職ではますますBigQueryを多用するようになったので、引き続き更新を続けています。(設定画面の「Downloads」→「User Contrubuted」からインストールできます)

Dashのドキュメントはdocsetという形式で、ダウンロードしてきたオンラインリファレンスに、命令や関数を抜き出して作ったインデックス(SQLiteデータベース)を付加して同梱することで作成します。生成スクリプトはRubyで書いています。コードは豪快にRakefile一つで完結しており、正常にビルドできたかのチェックや前バージョンとの差分出力など、メンテナ目線で必要な機能を備えています。

https://github.com/knu/docset-bigquery

ちなみに私はPrestoのdocsetも同様にメンテナンスしていますが、前職ではAmazon Athenaで必要だったものの、現職では出番がありません。AthenaやTreasure DataなどでPrestoを使っている方は、活用していただければと思います。

https://github.com/knu/docset-presto

これらの定期更新のためのPR作成手順は自動化しており、それぞれ、オンラインドキュメントの更新を検知するとビルドが走り、自分のレポジトリにcommitしてpushし、ビルドログとともにプッシュ通知しつつ、TodoistにToDoとしても登録するワークフローを組んでいます。ToDo項目からはリンクを辿ってすぐにPRを出せるようになっています。

これには私が主要開発者の一人を務めるワークフローエンジンHuginnを使っているのですが、それの話はまた改めて紹介します。古くはYahoo! Pipes, 最近だとIFTTTやZapierのようなもの、というと通じるでしょうか。

https://github.com/huginn/huginn

いささかがんばりすぎ感はありますが、前回ビルドからの差分をいち早く目にすることで新しい機能や変更に気づける(Be the first to know)のは、一ユーザとしても大きなメリットだと思っています。

コードの健全性

マチマチのコードベースは、PrettierRubocopでソースコードの大部分を自動フォーマットしており、余計なスタイルのブレを排除しています。

これの良いところは、スタイルについての議論やレビューで余計な時間・ストレス・軋轢を生まない、というのがひとつ。瑣末なスタイルについてだらだら(自動で)指摘するなら(自動で)修正までやれよ、というのは誰しも思うことでしょう。

また、癖の強い書き手がいたとしてもその「におい」を消すことができるので、「ここは○○さん独特のスタイルのコードだからいじるのが憚られる」のような不健全な縄張り意識と属人化を防ぐメリットもあります。

https://twitter.com/knu/status/1095330025530830848

「誰がどこをいじってもいい」を当たり前にすることで、プロダクト・チームは強くなります。

Rubocop

Rubocopには好みが分かれるcopが多くあり、かつ余計なお世話と思いたくなるものも日々追加されていきますが、マチマチでは自動修正をopt-inしていくだけなのであまり気にしていません。ただ、自動修正が壊れているのに気づいたときはすぐにフィードバックしています。

https://github.com/rubocop-hq/rubocop/pull/4688
https://github.com/rubocop-hq/rubocop/issues/5641

Rubocopのデフォルトは癖が強すぎるので、マチマチでもかなりカスタマイズした上で使っています。周りを見回しても、onkcopのような有名な設定例をベースに各現場でカスタマイズしていたりするところが多いようですね。

StandardRB

そもそも細かい設定ができすぎるのが混乱の元である、と喝破したのがPrettier(rubyプラグインも開発中!)やrufoですが、少し前に、皆が使い慣れたRubocopをベースにしたフォーマッタStandardRBが登場し、1.0に向けてフィードバックを呼びかけていました。

https://github.com/testdouble/standard

そこで、私も軽く試していくつかフィードバックしておきました。

https://github.com/testdouble/standard/pull/38
https://github.com/testdouble/standard/pull/40

最終的にどのフォーマッタが天下を取るのかはわかりませんが、もしStandardRBが本当に「スタンダード」になったらここはつらい、と思ったところはみなさんもフィードバックしておくといいと思います。

SQLの自動フォーマット

マチマチでは、プロダクトの内外を問わず、PostgreSQLやBigQueryで大きなSQLをたくさん書いて使っています。先に触れた通り、Ruby, JavaScript, CSS, JSXなどのソースファイルはすでに自動フォーマットを行っているのですが、SQLについてはまだ適用できていません。

すべて完璧にとは言わずとも、8割方を読みやすく整形してくれるものが見つかればいいのですが、マチマチではPostgreSQLやBigQueryのSQLをそれぞれ使い倒しているので、なかなか満足の行くフォーマッタが見つからないのです。SQLは他のプログラミング言語にはあまり類を見ない自然言語寄りの平坦な構造をしており、方言や拡張も無数にあるため、それらを広くカバーする実用的なフォーマッタの作成は困難なのでしょう。

個人的にはPythonのsqlparse(コマンド名はsqlformat)を試していますが、グローバルに適用するにはちょっと足りない感じです。たとえばSELECTの式リストを途中でいい感じに区切ってくれない、複文を食わせるとおかしい、などの問題を確認していて、直すためにはどういうルールを設ければいいのかもにわかには思いつかないことが多いです。今のところは、このツールでフォーマットしたものを手直しする運用で今は我慢しています。

私はEmacsを使っているので、簡単に使えるようにformat-allパッケージにSQL設定を追加してもらいました。

https://github.com/lassik/emacs-format-all-the-code/pull/11

名前の一括置換

Rubyコミュニティにおいては、まつもとさん(Matz)の座右の銘「名前重要」が広まっていますが、マチマチも開発においてモデルや機能の命名にはこだわっています。

また、開発を進める中で、ある機能が始めに命名されたときとは役割が異なってくることがあります。そういうとき、マチマチでは躊躇せずに実体に即した名前に変更してしまうことが多いです。

弊社藤村(id:fujimuradaisuke)の作ったgit-gsubコマンドは、そういうときにファイルの中に現れる名前やファイル名自体を一括置換するのに便利なツールです。

https://github.com/fujimura/git-gsub

私の方は、Emacsの中で置換する際に便利なパッケージを作りました。

https://github.com/knu/replace-with-inflections.el

Railsでよくある命名規則に則って FeedEntry / feed_entriesFeedItem / feed_items に置換したい、みたいなことが簡単になります。名前の変更だけでなく、あるモデルのCRUDを既存の他のモデルのそれからコピペで作る、というのも管理画面などでありがちなので重宝しています。

おわりに

一記事に全部含めるには数が多かったので、本記事は一旦ここで区切りとします。次回をお楽しみに!

マチマチでは、空気のようにOSSを吸ってOSSを吐くエンジニアを募集しています。武者にお気軽にお声掛けください!

Discussion