- インタビュイー
-
LINE フィナンシャル開発センター Front-endチーム フロントエンドエンジニア 鈴木僚太
(右)
LINE フィナンシャル開発センター Front-endチーム フロントエンドエンジニア 水牧稜太(左)
2020年11月に開催された
徐々に浸透した型安全の重要性
- ――LINE証券でフロントエンド開発に利用しているTypeScriptには、
どういったメリットがあると考えていますか。 鈴木:TypeScriptの魅力として、
まず挙げられるのはJavaScriptとの互換性です。もともと型のないプログラミング言語であるJavaScriptに、 型を付けたようなプログラミング言語がTypeScriptなので、 JavaScriptの経験さえあればTypeScriptでのプログラミングもそれほど難しくありません。実際、 LINE証券のプロジェクトでTypeScriptを採用したときも、 それ以前にTypeScriptを使ったことがないメンバーは結構いました。 TypeScriptを採用したメリットとしては、
型があることによる安全性が大きいと考えています。TypeScript以外の選択肢もありますが、 フロントエンド開発でそれ以外の言語を使って型の安全性を得ようとすると、 JavaScriptと大きく異なってしまいハードルが高くなってしまうという問題がありました。 - ――型の安全性に関する理解は、
すぐにチーム内に浸透したのでしょうか。 水牧:チーム全体の雰囲気として、
新しいものを抵抗なく受け入れるところがあり、 TypeScriptを用いて型を定義することについても、 「とりあえずやってみよう」 という雰囲気で始まりました。 ただ、
型の重要性は最初から理解されていたわけではなく、 それなりにコードを書いてから徐々に良さがわかってきたという感じです。しっかりと正確な型を書くように心がけコードを書き進めることで、 型の恩恵にあずかる場面が増え、 それによりさらに正しい型を書こうという意識が芽生えてくるといったイメージです。 それとTypeScriptに強い人ということでチームにジョインした鈴木の布教もあり、
チーム内に型の重要性が徐々に浸透しました。 - ――チームに型の重要性を伝えるために、
具体的にどういったことを行ったのでしょうか。 鈴木:最初はとにかく型をちゃんと書いたほうが良いということを重点的に伝えました。TypeScriptを使っていても、
その恩恵を100%享受できているかはどうかは別問題です。そこで、 たとえばコードレビューなどを通して、 TypeScriptを使っているのに恩恵を受けられていないといった場面があれば、 自分の考えを伝えて、 こういうふうにやるとTypeScriptの嬉しさがもっとも引き出せるんだということをチームのメンバーに共有してきました。 - ――コンパイルオプションで暗黙のany型をエラーにする
「noImplicitAny」 を有効にしたとのことですが、 これを決めたときのチームの反応はどうだったのでしょうか。 鈴木:新しいことはとりあえずやってみようというチームなので、
私が 「noImplicitAnyがオフになっているよ、 オンにしましょうよ」 と言ったときは 「とりあえずやってみよう」 という感じでした。 ただ、
それが即座に浸透したかどうかは別の話だとも思っています。実際に取り組み始めたとき、 noImplicitAnyによって発生したコンパイルエラーに対処してくれる人を募集したのですが、 そういったことに興味を持つかどうかはチームメンバーの中でも個人差があります。やれば確実に改善になるのですが、 直接的に新しい機能が増えるというような話ではないため、 どこまで興味を持つかは人によって違うなと感じました。
![例:TypeScriptなら型エラーの検知や入力補完が可能 例:TypeScriptなら型エラーの検知や入力補完が可能](/assets/images/dev/serial/01/line2021/0001/thumb/TH800_001.jpg)
![例:TypeScriptなら型エラーの検知や入力補完が可能 例:TypeScriptなら型エラーの検知や入力補完が可能](/assets/images/dev/serial/01/line2021/0001/thumb/TH800_002.png)
![悪い例(上)と良い例(下)。下のほうがより厳しい型定義で型の恩恵を受けやすい 悪い例(上)と良い例(下)。下のほうがより厳しい型定義で型の恩恵を受けやすい](/assets/images/dev/serial/01/line2021/0001/thumb/TH800_003.jpg)
![悪い例(上)と良い例(下)。下のほうがより厳しい型定義で型の恩恵を受けやすい 悪い例(上)と良い例(下)。下のほうがより厳しい型定義で型の恩恵を受けやすい](/assets/images/dev/serial/01/line2021/0001/thumb/TH800_004.jpg)
![noImplicitAny有効化によるコンパイルエラー。関数の引数を書かないとコンパイルエラーが発生し、危険なany型が推論されるのを防ぐことができる noImplicitAny有効化によるコンパイルエラー。関数の引数を書かないとコンパイルエラーが発生し、危険なany型が推論されるのを防ぐことができる](/assets/images/dev/serial/01/line2021/0001/thumb/TH800_005.jpg)
noImplicitAnyの有効化は“未来への投資”
- ――noImplicitAnyを有効にしたときの状況はどうだったのでしょうか。
鈴木:これからnoImplicitAnyを有効にすることを決めたとき、
エラーの数は550もありました。正直、 途方もない数だなと思いました。もう少し型の重要性が浸透しているのではと思っていたのですが、 今と比べるとまだまだ浸透していなかったのですね。 そこで、
3~4名のエンジニアで一気にコードを修正し、 エラーを減らしました。そのとき、 およそ半分ほどにまでエラーを減らしましたが、 そこで力尽きたというのが正直なところです。本当はそのまま一気にゼロまで修正できれば良かったのですが、 半分くらいやったところで 「ああ、 もうこれは無理だ」 と思いました (苦笑) 実際の修正で最も大変だったのは、
そのエラーを潰すことだけではなく、 修正した結果、 芋づる式に新たな問題が発覚することでした。anyはコンパイルエラーを抑制してくれる機構であり、 any型を修正することにより、 anyに頼っていたことで隠れていた別のコンパイルエラーが姿を現すことがあります。表面に出ているのは 「anyを使っていますよ」 というコンパイルエラー1つですが、 そのanyによって隠蔽されていた内なるコンパイルエラーまで解消して、 やっと数字上の1つのエラーを消したことになります。そのため、 1つのエラーであっても修正作業は重かったですね。 水牧:noImplicitAnyを有効にする前は、
そもそもanyに対する危機意識が低かったんです。そのため、 どれだけ潜在的にanyがあるのかといったことは意識していませんでした。おそらくチームメンバーのほとんどがそうだったのではないかと思います。やっぱりnoImplicitAnyを有効にしないと、 anyを意識せずにコードを書いてしまいますね。 ただanyが1箇所あると、
いろんなところがどんどんanyになっていきます。そのanyになる箇所は、 型の安全性が確保されない部分になってしまう、 つまりバグの危険性が潜在的にあるということになってしまいます。それをnoImplicitAnyを有効にすることで、 個々のエンジニアが意識するようになったことは良かったと考えています。 - ――noImplicitAnyを有効にした後、
どのような変化があったのでしょうか。 鈴木:チームメンバーの考え方が変化し、
JavaScript的ではなく、 TypeScript的な考え方に変わって、 最初から型安全なコードを書けるようになりました。 水牧:これから書く、
あるいは追加するなりリファクタリングするなりしたときに、 バグを生む確率が減るという意味で、 型を付けることは未来への投資だと思います。なので、 すぐにバグが減ったというよりも、 これから先で生まれるかもしれなかったバグが減ったということがメリットだと思います。 鈴木:生産性の観点では、
noImplicitAnyを有効にし始めた当初は多少手戻りが発生していました。コードを書いたけれどもnoImplicitAnyでエラーが出るという状況です。それによって多少は生産性が落ちたかなと感じましたが、 チームメンバーがTypeScriptの考え方に慣れるにつれて、 生産性のロスはほとんどなくなりました。今ではみんなが最初からnoImplicitAnyに適合したコードを書けるようになったので、 無効にしていたときと比べてコードを書く速度が落ちているということはないと思います。 水牧:コーディングスピードの観点で言えば、
型があるほうが確実に速く書けると感じています。しっかり型を書いていれば、 IDEの補完でポンポンポンと書いていけるためで、 その恩恵は大きいと感じています。
![noImplicitAny有効化の経過 noImplicitAny有効化の経過](/assets/images/dev/serial/01/line2021/0001/thumb/TH800_007.jpg)
LINE証券の開発におけるこれからのチャレンジ
- ――型安全以外の部分で、
トラブル回避のために意識していることはありますか。 水牧:すごく基本的なことですが、
ロジックとUIの分離はやはりすごく重要だなと思っています。そこがしっかり分離されていると、 リリースでバグが出たなどといったときの修正のしやすさがまったく違います。逆にロジックとUIがちゃんと分かれていないと、 見通しが悪くなり、 バグが発生したときに原因がどこにあるのかが特定しづらくなってしまうため、 しっかり分離することを意識しています。 鈴木:これも基本的なところですが、
もっとテストをしっかり書いていかなければならないと思っているところです。設計からテストが書きやすいコードにすることは、 やはり大事なことだなと思います。 このテストにおいても、
型安全と同様に意識が重要です。テストがなくても動くものは動いてしまいますから、 意識がないと本当にテストのないものができてしまいかねません。 またテストが理由でチームメンバーが不快にならないことも重要です。たとえばプルリクエストを出してCIによってテストが実行されたとき、
コードに問題があるわけではないのにE2E (End to End) テストで失敗してしまうといったことが時折発生します。そうすると、 E2Eテストはよく失敗するものだという意識がメンバーの中に芽生え、 E2Eテストの重要性が低くなり、 あまり重視されなくなったりテストが書かれなくなったりしまうということになりかねません。こういったことから、 チームメンバーから信頼される仕組みにすることは重要だと痛感しています。 - ――今後チャレンジしたいことはありますか。
鈴木:我々のLINE証券というサービスの開発には、
ちょっとしたバグで大きな影響が発生する可能性があります。そのため、 何か新しい機能をリリースするといったことに対して、 つねに高いリスクがつきまとうことになると感じています。そのリスクを下げるために、 マイクロフロントエンドに取り組みたいと考えています。 1つのアプリに見えていても、
その内部では複数のアプリが個別に動作しているマイクロフロントエンドであれば、 たとえば株の取引にかかわる部分などクリティカルなところには手を付けず、 別のところを新しくするといったことが可能になります。これによって新機能をリリースする上でのリスクを下げられるでしょう。こういった取り組みを今後進めていきたいですね。 水牧:今後やりたいのはコンポーネントの設計の見直しです。現状はデザインが多岐に渡っていて、
似たようなコンポーネントでもあまり共通化できていません。デザインに微妙な違いがあり、 それをコードに落とし込むのが難しいため、 別のコンポーネントとして作るということがあるためです。そこで何らかの手法を使ってピュアなコンポーネントを定義し、 それに対してバリエーションを作るといったことに挑戦したいと考えています。 - ――最後に、
LINE証券の開発において、 やりがいを感じるところ、 あるいは自分が成長できたことを教えてください。 水牧:このサービスで動くお金の額はものすごく大きいので、
そのためのサービスを開発しているというのはすごくワクワクします。またLINEということで多くのユーザーに利用されていて、 それを自分が作っているんだという満足感も大きいですね。 鈴木:我々のチームの成果物はQA
(Quality Assurance) のフェーズで、 実際に動かしてみて問題がないことを入念に確認されます。当初は、 なんでこんなにしっかりやるのかと思っていましたが、 金融にかかわるサービスのリリースや運用に携わる中で、 リスクを抑えながら運用していくことの大切さを学びました。なので、 バグを出さないことが重要だということを理解した上でリスクを下げていく、 あるいはコストを下げるということに関心が向いています。こういった考え方になったことが、 ファイナンシャルに携わることのチームに入って自分が成長できた証ではないかと思います。 - ――本日はありがとうございました。
![現状の構成(上)と目指す理想的な構成(下) 現状の構成(上)と目指す理想的な構成(下)](/assets/images/dev/serial/01/line2021/0001/thumb/TH800_010.jpg)
![現状の構成(上)と目指す理想的な構成(下) 現状の構成(上)と目指す理想的な構成(下)](/assets/images/dev/serial/01/line2021/0001/thumb/TH800_009.jpg)
![画像](/assets/images/dev/serial/01/line2021/0001/thumb/TH800_011.jpg)