LINEヤフー Tech Blog

LINEヤフー株式会社のサービスを支える、技術・開発文化を発信しています。

This post is also available in the following languages. Korean

LINEアプリのクライアントサイドの開発者が作る「コードレビュー文化」

LINEヤフー株式会社の開発組織では、開発文化を改善するためにさまざまな試みを行っています。今回は、LINEのクライアントアプリの開発プロセスを改善を担うMobile Developer Experience Devチームでの「コードの可読性」向上の取り組みについて、Munetoshi IshikawaさんとGiuk Jungさんのインタビューを通じて紹介します。

左からGiuk Jung、Munetoshi Ishikawa

Giuk Jung:LINEのiOSアプリ開発を担当しています。特にiOSのビルド環境の改善や、ビルドに使われるツールの開発などに取り組んでいます。簡単に言うと、「開発者をサポートする開発」をしています。iPhone3GSが発売された2009年から日本で働き始め、今年で15年目になります。

Munetoshi Ishikawa: LINEのAndroidアプリの開発を担当しています。Jungさんと同じチームで働いており、全社的なソフトウェアエンジニアの教育も行っています。9年前に入社して以来、機能開発だけでなく、コードレビューの品質向上、採用プロセスの改善などの業務にも携わっています。

開発者体験を担当するチームの「開発文化」

Q:Mobile Developer Experience Devチームとは、どのようなチームですか?

Ishikawa:1つのチームではなく、組織全体の開発文化と原則を改善することが、Mobile Developer Experience Devチームの特徴で、特に生産性やコード品質の向上に取り組んでいます。例えば、変更されたコードから開発者が行うべきテストを提案したり、自動的にレビュアーを追加するボットを作ったりします。「開発」のチームとしてこのような活動を行っているのは、独特だと言えますね。私たちの活動の一部はこちらのスライドでも紹介しています。

Q. チームの開発文化はどのような感じですか?

Jung:私たちのチームでは、プルリクエストを出すときは、チームメンバー全員をレビュアーに指定するという原則があります。LINEアプリのクライアントサイドの開発組織では、AndroidチームとiOSチームが分かれていません。そのため、iOSの開発者がAndroidのコードを、逆にAndroidの開発者がiOSのコードをレビューすることもあります。両方のプラットフォームのコードを比較しながら読むことで、モバイル開発環境に対する理解が深まります。

同じような流れで、ボットを使った「ランダムレビュー」も行っています。プルリクエストの1次レビュアーが承認すると、ボットがランダムに2次レビュアーを指定します。2次レビュアーは普段触れないコードをレビューすることで、プロジェクトをより広く理解でき、他のチームとの交流もできます。

コードレビューにルールを適用すること以外にも、健全な開発文化を形成するためにメンバーと積極的にコミュニケーションを取っています。コードレビューが放置されないように、デイリーミーティングで待機中のプルリクエストをみんなで確認します。規模が大きかったり、長期的な計画が必要な実装は、事前に設計文書を作成して議論します。その他にも、週1回の勉強会やカジュアルなテックトークの時間を設けています。

「ソフトウェアの構造は組織の構造に似ている」という「コンウェイの法則」というものがあります。「コンパイラを4つのグループで作れば、4パスコンパイラになる」という有名な命題ですね。通常、組織が大きくなり、チームが分割されればされるほど、ソフトウェアも同様に拡張性を失ってしまい、複雑になります。私たちのチームは、それを解決するための鍵は緊密にコミュニケーションを取る開発文化にあるという意見に賛同しています。

グローバル開発環境でより重要な「コードの可読性」

Q. このような文化は簡単には作れなかったと思いますが、特にお二人が共感しているのは「コードの可読性」だと聞きました。

Ishikawa:私が「コードの可読性」に注力しようと思ったのは、実は入社当時からなのです。入社前に前職の先輩エンジニアとカジュアル面談をする機会があったのですが、その先輩に「LINEのサービスが急成長している状況に合わせて、一緒に品質の改善しませんか」と提案されました。そして入社後に、コードの品質を向上する過程で数多くのコードレビューを行いましたが、同じようなフィードバックをすることが何度もありました。リンター(linter)などのツールを使って指摘を自動化するのにも限界があったため、コードを書くときやレビューするときに注意すべき点をスライドにまとめようと考えたのです。スライドはそれだけで有用だったのですが、前述の先輩エンジニアであり、当時の上長に「せっかくなら公開したら?」と提案されたので、バージョンアップしてこちらに公開しました。

Jung:プロジェクトの規模が大きくなればなるほど、そしてプロジェクトの期間が長ければ長いほど、コードの可読性について考えるべきことは多くなります。特にLINEアプリは、大規模で長期的なプロジェクトであることに加え、「グローバル環境」での開発という特徴もありますね。国や文化、言語、さらには勤務地が異なるメンバーと一緒に働く環境では、円滑なコミュニケーションが重要です。コードも一種のコミュニケーション手段なので、「コードの可読性」が高ければ、相手の意図を把握しやすくなります。

通常、コードは仕様をもとに作成します。しかし、開発期間が長くなり、仕様とコードが何度も更新されるにつれて、仕様を把握するために何度もコードやドキュメントを確認することになります。さらに、グローバルな開発環境であれば、言語の違いによって仕様を把握するのがより難しくなりますね。例えば、初期に特定の国に限定していた仕様を他の国に拡張する場合、そのドキュメントが外国語やつたない英語で書かれていると、理解するのが困難です。そのような場合、コードの可読性が高ければ、仕様を把握するのがはるかに容易になります。開発者にとって「読みやすいコード」こそ、最も明確なドキュメントと言えます。

もちろん、ドキュメントとコードはそれぞれの役割が違うので、ドキュメントの作成は必要ですが、ドキュメントだけに頼るより、コードから直接仕様を読み取れる方がスムーズに開発できました。

読みやすいコードを書くためのいくつかのヒント from『読みやすいコードのガイドライン』

名前に使う単語を選ぶとき、より意味が限定された単語を用いることで、誤解の可能性を下げられます。例えば、数値に対するlimitという単語は、それが上限であるのか下限であるのかが曖昧です。それよりはmaxやminという単語を使う方が、どちら側の限界かが明確になります。(2-3 |単語の選択)

直感的に理解できないコードがある場合、非形式的なコメントで補足をすることで、可読性を大きく改善することができます。誤解を生みやすいコードに対して注意点を明確にしたり、考えないと理解できないコードに対して説明を追加するとよいでしょう。特に、放置すると誰かが間違った方法でリファクタリングしてしまいそうな場合には、コメントで注意を促す必要があります。(3-3 |非形式的なコメント)

オブジェクトの取りうる状態の数が2 つ以下で、その状態を遷移させる関数が1つの場合、可能であればその関数を冪等(idempotent)にするとよいでしょう。冪等とは、操作を1回行ったときの結果と、操作を複数回行ったときの結果が同じという概念のことです。(4-3 |状態遷移の設計)

関数が複数の責任を負うと、その動作を抽象的に理解しにくくなります。さらに関数を再利用することも困難になり、コードのコピーの原因になるなど、設計にも悪影響を及ぼしかねません。関数が負う責任は1つにするべきで、そのためにも適切に関数を分割する必要があります。(5-1 |関数の責任)

抽象化は可読性を向上させる有効な手段の1つですが、同時に暗黙的な依存関係の原因にもなります。そのため抽象化を行う際は、何の目的で行うのかを考えなくてはなりません。(6-5 |依存の明示性)

Q. Ishikawaさんが「コードの可読性」について本にまとめ、それをJungさんが韓国語版に翻訳したそうですね

書籍

Ishikawa:先述のスライドを基にして、可読性についての考え方を『読みやすいコードのガイドライン』(日本語版韓国語版)という本にまとめました。このスライドを作り始めた理由は、コードレビューで楽をしたいというものだったのですが、レビューについての考えを整理したり、今のコードベースを振り返ったりするきっかけになりました。同じような問題を抱えている人は少なくなかったらしく、社内でも公開してからも、多くの方からポジティブなフィードバックをいただきました。そんな中、社内のSlackで「本が勝手にできてほしい」と何気なく呟いたところ、Developer Relationsチームの協力もあり、『読みやすいコードのガイドライン』の執筆に至ったという経緯です。

この本の韓国語翻訳の話を受けたとき、同じチームのJungさんを翻訳者として推薦しました。彼の母国語は韓国語であり、日本語も堪能なのですが、それだけが推薦理由というわけではありません。Jungさんは、技術的な能力が高いだけでなく、何よりもチームメンバー全員から信頼されています。これだけでも推薦理由としては十分なのですが、同じチームのメンバーなのでコミュニケーションについて不安がないのも大きかったですね。実際、Jungさんは、翻訳した文章が不自然でないか、韓国人にとってよりなじみのある表現に置き換えても意味が変わらないのかなど、非常に細かい部分まで考慮しながら多くの質問をしてくれました。私は韓国語が読めませんが、間違いなく高い完成度で翻訳されたと確信できます。

コードの改善が必要なのは分かっているけれど、それをうまく言語化できないとき、この本を手にとって頂ければと思います。

Jung:翻訳の経験はゼロでしたが、韓国語に翻訳することで、一緒に働いている他の開発者にも役立つということを期待していました。Ishikawaさんのスライドは社内の研修にも使われているのですが、それが日本語版と英語版しかないのが心残りでした。Ishikawaさんが日本の開発者のために『読みやすいコードのガイドライン』を出版したように、私も母国語に翻訳することで韓国の開発者のためになると思ったのです。

この翻訳版が、日韓両国に分散しているチームがお互いのコードをレビューする際に「共通のコード品質基準」として活用されることを期待しています。業務時間外や休日に翻訳作業をするのは大変でしたが、苦労した時間が有意義なことだったと実感する日がいつか来ると信じています。そのときは達成感に心ゆくまで酔いしれるつもりです。

Q. 他にコードを書くうえで重要だと思うことはありますか?

Jung:昨年から生成AIが本当にホットな話題になっていますが、開発環境にAIの導入が進めば進むほど重要になることがあると思います。設計と実装のシンプルさを強調するKISS(Keep It Simple, Stupid)原則がその一つです。AIシステムは、機械学習モデル、データの前処理、他のシステムとの統合などで複雑になりがちです。そのため、AIモデルとその統合の管理や解釈をよりしやすくするために、「シンプルさ」を保つことがより強調されると思います。

共通機能を再利用可能に抽象化し、コードの重複を減らすDRY(Don't Repeat Yourself)の原則もさらに強調されると思います。AIシステムは、事前に学習されたモデル、関数、パイプラインを再利用することで、時間とリソースを節約し、一貫して出力できるからですね。その他、TDD(Test Driven Development)のように、AIの信頼性を確保するための原則も浮き彫りになるのではないかと思います。

Ishikawa:一般的にコード品質の尺度には、可読性以外にも、柔軟性、拡張性、再利用性、パフォーマンスなど、さまざまな基準があります。もちろん、それらの基準はどれも重要ですが、時には相反することもあります。ある動作のパフォーマンスを上げようとして、かえってコードの可読性や再利用性が低下してしまうこともあります。そのとき、優先順位をどのように決めるかは非常に難しい問題であり、同時に非常に重要な問題でもあります。人によって優先する基準が違うので、開発者はコードレビューや対面での議論を通じて意見を出し合いながら調整していかなければなりません。私は、このようなプロセスこそが開発の大きな醍醐味(だいごみ)だと思います。そういう意味では、コード品質において最も重要なのは、コード自体の特性よりも、技術的な議論を楽しめるかどうかなのかもしれませんね。

私の場合、「可読性」と同じくらいコードの「頑健性」も重視しています。ここでの「頑健性」は、間違って使われにくい、間違って変更されにくい性質を指して言っていますが、これは時に「柔軟性」、つまり少ないコード変更でより広く使える性質と相反することもあります。機能を拡張する際には、たとえ少ないコード変更であっても、その変更にミスがあってはならないため、可読性や柔軟性よりも頑健性を優先することもあります。特に大規模なプロダクト開発では、コードの変更が安全であると保証することが非常に重要です。

さらに、プログラミング原則やテクニックが「なぜ」役立つのかを考えることも重要です。コードの品質を上げるはずの原則やテクニックも、乱用してしまうと、かえってコードの可読性を低下させたり、バグの原因になったりします。それがなぜ必要なのかを考えずには、「ハンマーしか持っていないと、すべてがくぎに見える」状況に陥ってしまうかもしれません。例えば、「早期リターン」は有名で分かりやすいテクニックなので、多くの解説ではさらっと紹介されています。一方で、「読みやすいコードのガイドラインでは」、どのようなときに早期リターンを使うべきなのかだけでなく、使うべきでない状況やその理由も丁寧に説明しています。原則やテクニックを適用する前に「なぜ使うべきか」を考える力が身につけば、言語のパラダイムやはやりの設計が変わったとしても、振り回されることなく追随できると思います。

コードレビュー文化を作りたいなら「このように」

Q. 多くの開発チームでコードレビュー文化を作ろうと努力していると思いますが、同じよう試みをした立場からアドバイスをお願いします。

Jung:私が最も重要視しているのは、技術的な側面ではありません。「感情的な摩擦による士気低下」が起こらないように注意する必要があると思います。そのためには、レビューに使う言葉遣いから気をつけなければなりません。特に、チームが分散していたり、国際的なチームであればなおさらです。「このコードは良くありません。修正してください」ではなく、「このようなコードに注意をうながす記事がありました。こちらにリンクがあるので参考にしてください」というような親切な言葉遣いが良いと思います。わざわざ褒めるコメントを残すのもいいですね。例えば、「この部分、気に入りました。バグが解決され、さらに読みやすくなりましたね」みたいな感じです。

また、コードレビューが行き詰まっている場合は、変更されたコードがレビュアーの基準に達していなくても、品質がある程度改善されていれば、承認を検討してください。私たちが求めているのは完璧ではなく、継続的な改善ですからね。そして、レビューを受ける側も、常に毅然とした態度で臨む必要があります。たった5行のコードに6つのコメントがつくこともあります。コードが間違っていると言われるのは不愉快かもしれませんが、レビューしてくれたメンバーは他の仕事をしながら時間を割いてくれたことを忘れてはいけません。助けようとするメンバーに十分に説明し、謙虚に耳を傾けてください。

Ishikawa:コード、設計、プロセス、その他開発に関することなら何でもいいので、議論を楽しんで、議論する人の範囲を広げてみてください。コードレビューも議論の形式と一つとみなせますが、そこで心理的安全性が担保されていないと、「コードや設計に対する指摘」を「コードを書いた人への攻撃」と捉えられかねません。普段からみんなで議論しながら、「議論の対象は人ではなくコードである」ことや「発言が間違っていても恥ずかしいことではない」ことをチームの共通認識にできれば素晴らしいと思います。そうすれば、コードレビューでも忌憚(きたん)なく意見を言うことができ、より良いコードを作るためにはどうすればいいのか、みんなで真剣に議論できるようになります。