ブラックボックス化したJavaScriptコードを可視化
特定の人しか修正できないJavaScriptコードは、まさにブラックボックスであり、技術的負債といえる。長い目で見れば、機能追加や品質改善に大きな支障となることは明らかで、誰もが解決したいと考えるはずだ。しかし、多くの企業ではサービスの改善や機能追加が優先され、技術的負債の回収・改善は後回しにされがちだ。むしろ負債を返す作業こそ、新規開発の足かせと考えられていることすらある。
本セッションに登壇した鈴木潤氏も、そうした課題を感じていた。鈴木氏は、転職サイト「DODA」や求人情報サービス「an」を手がけるパーソルキャリア株式会社(旧社名:株式会社インテリジェンス)で、リファラル採用活性化サービス「MyRefer」といった新規サービスの開発を担当。迅速な新規機能の追加を業務成果としてきた。
「技術的負債の問題は明らかながら、MyReferはサービスとしてまだまだ成長段階にあり、顧客企業の業務を円滑に進めるためにも、急ピッチで新規機能を開発することが必須。『新規機能開発を止めずに』並行して技術的負債を返す取り組みを考える必要があった。そこで『課題の明確化』『どう解決するか』『改善の方針』の3ステップでアプローチした」と鈴木氏は語る。
鈴木氏以外の開発メンバーも「なんとなく開発しづらい」と漠然と感じながら、その原因がわからないストレスを抱えていた。そこで、メンバー全員が集まり「どのような問題が生じているか」を付箋で書き出すワークショップを開催。さまざまな声が上がる中で、JavaScriptに関するものをまとめていった結果、大きく以下2つの問題に集約されていったという。
- 複数のファイルをまたがっていることによる複雑さ
- DOMとイベントリスナが離れすぎている
二大課題をwebpackとReactの活用によって解決
【問題1】複数のファイルをまたがっていることによる複雑さ
この問題について、鈴木氏は関数処理時の手間を挙げる。例えば、ひとつの処理が複数のファイルにまたがって書かれており、そのどこかで定義されている「Hoge.fuga関数」を修正しなくてはならない場合、大量のタグの中から定義部分を探し出さなければならない。
この問題を解決するには、複雑な検索を行わなくとも、大量のScriptタグの中で「どこで定義しているのか」がわかる必要がある。具体的にはECMAScript 2015のimport構文で書くと、1~2ファイルに絞り込める。これを可能にするため「webpack」を導入し、依存関係を解決できるようにした。webpackとは、JavaScriptファイルの冒頭に記載されているimportをたどり、複数行のコードをひとつのファイルにして出力できるツールだ。
webpackが必要だった理由に、サポートブラウザの問題があった。MyReferではサポートブラウザとしてECMAScript 2015のimport構文に対応していないIE11を含めており、import構文を使用したコードをIE11上で実行しても動作しない。そのため、webpackを使用してimport構文を使用しているJavaScriptの依存関係を解決し、出力されたファイルをHTMLから読み込む方法をとった。
【問題2】DOMとイベントリスナが離れすぎている
そしてもうひとつ、「DOMとイベントリスナが離れすぎている」問題。例えば、よくあるHTMLとjQueryのソースコードでも、セレクタ「js-hoge-button」が変数に格納されていることや、動的に出力されていることがある。これではコードとしてわかりにくい。
そもそもHTMLとjQueryのクリック時の処理が、ひとつのファイルにまとめて書かれていればこの問題は解決できる。そこで、MyReferではReactを導入。ボタン要素とクリック時の関数をひとつのファイルに記載することによって解決を試みた。
さらにChromeのReact Developer Toolsであれば、ツリー状にコンポーネント名を確認できる。クラス名がわかるため「ボタンを押した際の挙動がわからない」問題が解決できたという。
そうなると「jQueryは完全にもう使わないのか」という疑問が生じるが、鈴木氏は「jQueryで書かれているソースコードは容易に捨てられない。MyReferではReactライフサイクルメソッドの中に閉じ込める形で利用している」と説明した。
ESLintの導入
さらに鈴木氏は、JavaScript用静的検証ツール「ESLint」についても言及。当時のMyReferのコードではグローバルに存在する名前空間があり、それを当事者以外誰も知らないといった状況が発生していた。それだけでなく「var」「let」「const」などをつけ忘れたことで、意図せずグローバル変数化してしまうこともあった。
この問題を解決するために導入したのがESLintだ。特別な理由がない限りグローバルな領域に変数を増やさないようにし、evalも禁止。また、実行時エラーを引き起こしかねないセミコロン忘れなども含めてチェックしている。