フロントエンドとバックエンドのどちらも担当

三田英一氏(以下、三田):「息の長いサービスのフロントエンドを少しずつ改善していく営み」というテーマで発表したいと思います。よろしくお願いいたします。

まず自己紹介です。三田英一と申します。TwitterとかGitHubはこのアカウントでやっています。ラクスには、中途入社で2014年に入りました。以来、フロントエンドとバックエンドのどちらもやっています。

あと、今日の話とはあんまり関係ないのですが、アジャイル開発も好きなので、認定スクラムマスターを取ったりしています。あと、ちょっとサイドワークというか、15パーセントの稼働ではあるのですが、技術調査的な仕事も最近やっています。

写真は、自分の今の席を写したものです。どんだけキーボードがあるねんとか、ディスプレイを何枚使うねんとかってすごく突っ込まれますが(笑)。分割キーボードが使いやすかったりするんですよね。あとちょっと見づらいですが、スプラトゥーンが好きなので、武器を並べたりとかしています。

本日お話しする内容ですが、なぜ改善が必要なのかという話と、あと現状のフロントエンドの問題点がどんなものなのか、実際に取り組んでいることについて紹介しようかなと思っています。

逆に今日お話ししないことは、Reactを導入しているんですが、この話は以前のミートアップでしているので、今日はReact以外の改善を中心に話しをしたいと思っています。

なぜ「楽楽明細」の改善が必要なのか

楽楽明細の紹介を軽くします。帳票か請求書か支払明細かなどの種類は問いませんが、それらをWebで発行して、お客様のところに届けるサービスになっています。こちらのサービスは導入社数が年々増えていて、これまでに1600社の導入実績があるような……先ほど古いサービスと紹介がありましたが、今なおすごく利用者が増えている、勢いがあるサービスになっています。

開発当初からのシステム構成について軽く紹介します。まず楽楽明細の開発が始まったのは、だいたい2010年ごろです。私は入社していないのでちょっとわからないのですが、これくらいのころです。

MVCモデルを使ったWebのアプリケーションで、サーバー側はJSPを動かしていて、HTMLを介して、フロント側はjQuery、みたいな。当時はすごくよくある構成だったものです。

なぜこのサービスに改善が必要なのかを続けてしたいと思います。楽楽明細は今後10年続くサービスだと思っているから、というのが一番の理由かと思っています。追加したい機能がまだまだあって、開発はこのあと何年もアクティブに続く予定になっています。

これが大きいのかなと思っていて、このあとはもうメンテナンスモードだよみたいなサービスだったら、それほど改善はいらないのかなと思っていますが、楽楽明細はそういうサービスじゃないですと。

今まではバックエンドを中心に改善してきましたが、フロントエンドはあんまり改善していないというのが現在の状況です。今から10年後も続くということは、開発開始から数えると20年経っているということなので、たぶん使っているものも、OSSの保守などは終わっちゃっているのかな、とか思ったりしますし。

あとエンジニアとしては、20年前のシステムをメンテナンスするのは、モチベーションもつらいし、採用面でもキツイのかなと思っています。なので、改善が必要だと思っています。

ちなみに、20年前ってこんな感じですというのを挙げました。私がちょうど就職してエンジニアになったころですが、思い出していたら、調子に乗っていろいろなものを挙げてしまいました。

クラサバって言って、クライアントでVBのアプリ動かして、サーバー側でOracleDBが動いていて。技術的に仕事と関係ないですけど、テレホーダイで夜11時になったらインターネットに一斉につないで、ISDN速ぇとかって言っていたころですね。何が言いたいかというと、20年って相当昔ですねという感じです。

現状のフロントエンドの問題点

現状のフロントエンドの問題点です。あの構成だったら想像つくと思うのですが、あるあるで4つ挙げました。DOM操作が複雑です。パフォーマンスも悪い。特に画面の要素数が多いところに、$()でjQueryを使ってDOM検索すると、死ぬほど遅くて画面固まっちゃうとか。

あとHTMLの見た目変えようとすると、JSまで波及しちゃうのがあったりとか。class属性変えたいだけなのに、そのclassに引っ掛けてjQueryを動かしていたので、動かなくなるというのもあるあるかなと思います。

3つ目は、JSファイル間で依存関係がぜんぜんわからないっていうのがあって、なにか変えたときに、影響箇所がどこに出るかが全然わからない。4つ目は、型やIDEの支援がないから、ほとんどメモ帳で、根性で検索してから直すみたいな、そんな世界になっているというのが、現状の問題点です。

では、それをどのように改善していくかという話ですが。システムを作り直せば話が早いんですが、当然そういうわけにはいかないです。なので、機能追加もやりながら、少しずつ行っていく必要があります。改善もするし、技術要素も新しいやつをちょっとずつ取り入れていきたいねっていうのがあったり。それを安全にやるためには、テストが必要だよねっていうのがあります。

なので、少しずつ日常の開発に溶け込ませてやっていくっていうのが重要なのかなと思っています。

実際に取り組んでいること

実際に改善として取り組んでいることについてお話しします。まず1個目がモジュール化です。IE11とかサポートしなければいけないので、ES5が動かないといけないのですが、ES5はモジュールの概念がないので、これがけっこうフロントエンドを改善するうえではつらいのかなと思っています。個人的には、フロントエンドを改善したかったら、モジュール化が一番重要なんじゃないかと思っています。

これはモジュール化していないコードの例なんですが。これもあるあるだと思うんですが、HTMLにこういう感じでScriptタグが並んでいて、common.jsはjquery.jsに依存しているから、jquery.jsより下に書かなきゃいけないし。

app.jsは、common.jsに依存しているからその下に書かなきゃいけないことがコードとして表現されていないので、よくわからない人が順番入れ替えちゃうと動かなくなるような世界になっています。

依存関係がわからないと何が起きるかと言うと、よくわかんないから闇雲に全部テストしなきゃみたいな感じで、非常に効率が悪い。あと修正するのが怖いというのは、わりと慎重な人ほど、コードで直せばいいのにコードを追加したりとかし出して、本当にカオスな状態になったりすることが、あるあるなのかなと思います。

Webpackの導入

具体的な解決策として、Webpackを導入しています。WebpackはSPAとかがよくサンプルで出ますが、複数のエントリーポイントが、下にコードでサンプルで書いていますが、エントリーのところにたくさん書けば、その分複数のファイルをバインドしたJSにできるので、こういった書き方でやっています。

出力のほうもこういう感じで、output filename [name]としてるんですが、こういう感じで書いておくと、エントリーで書いた名前そのままでファイルを吐き出してくれるので。この例だとcommon.js、gamen1.js、gamen2.jsみたいな感じで、今までのJSと同じ単位でファイルを出力できます。

これは単位を変えないということで、わりと影響が小さく実現できるのがいいのかなと思って、こういうやり方をしています。

モジュール化したあとの状態なんですが、common.jsという共通のものについては、exportでどれを外部に公開しているかが明示できたりとか。

あとapp.jsのほうは、common.jsの中の、例えばこの例だとmessageっていう関数を使いますよっていうのがちゃんとimportで明示できて、依存関係が明確になります。

モジュール化することのメリットをまとめて挙げていますが、これはわりと一般的に言われていることですね。コードの再利用性が高まったりとか、あとはうちのサービスだと1JSP=1jsみたいな構成になっていて、ゴチャゴチャに書かれているのが、モジュールを意識して……そういうふうに書かなきゃいけないんですが……書くことでコードの凝集度が上がっていったりとか。

それによって、パーツで開発するようになるので、作業分担がしやすくなったり、テストコードが書きやすくなったり、あとグローバルになんでも置かなくてよくなるので、そこらへんの問題が解決されると思っています。

TypeScriptの導入

2個目が、TypeScriptを導入しました。TypeScriptは、AltJSっていうJavaScriptの代替となる言語の一種です。平たく言うと、型を定義できるJavaScriptです。TypeScriptで特徴的なのは、実行環境をもってなくて、JSに変換するまでが仕事です。

下に、1~6でTypeScriptのソースが実際に動かされるまでを書いているんですが、TypeScriptが絡んでいるのは1~3番までのところまで。TypeScriptのソースをASTに変換して、JavaScriptでソースを出すところまでです。

4番から6番は、今までどおりJavaScriptのソースで実行されるということで、何が言いたいかというと、JSファイルを吐き出すだけなので安全です。実行環境が変わるわけじゃないので、わりと敷居低く導入できるのかなと思っています。

TypeScriptは、今現在だとほとんどデファクトなので迷う必要はなくて、ほかの選択肢はないかなというのと。あとJavaの開発者には、構文がなじみやすいかなと思っていて。Genericsとかと一緒だったりするし、わりとスッと入れるのかなと思っています。

あと一番大きいのが、ゆるく導入できるというところで、これがうちみたいなレガシーの改善にはすごく向いているかなと思っています。

ゆるく導入できるというのは、(TypeScriptは)型を指定していくのですが、any型っていうのがあるので、どうしても難しいときにはany型というのもありだよ、というふうにしてあげれば、一応ゆるくは導入できるのがいいかなと思っています。

そこらへんも、どれくらい厳密にしたいかは、自分たちの現状というか、事情があって決めたいと思うのですが、これはtsconfig.jsonの中でいっぱい項目があって、どれを厳密にチェックするかを自分たちで決められるので、ここでさじ加減を調整できるかなと思います。

だいぶ慣れてきたら、1つずつチェックを厳しくしていくみたいなやり方は、わりと現実的なのかなと思っています。

あとは、チェックでエラーになっても、トランスパイルすることが可能なので、どうしてもエラーを外せないなということがあっても、トランスパイル自体はできたりするのも、ちょっとゆるくていいな、と個人的には思っていて。

それをずっと放置しちゃうのは問題だと思いますが、導入当初はいいかなと思っていたり。なのでちょっとずつ、1ファイルずつ徐々にtsみたいなこともやりやすいのが、TypeScriptのいいところです。

Jestの導入

続いてテストコードです。もともとフロントエンドのテストは書く習慣がありませんでしたが、安全にリファクタリングするためには、当然テストコードが必要ということで、テストコードも導入しています。

導入したのはJestです。JestはFacebookが開発しているツールで、何がいいかと言うと、よく言われていますが、Jestだけ入れれば、なんでもできるというオールインワンなところがよいです。とはいえ、現状使っていますすが、ブラウザに依存するテストは書けていないので、やり方を調べてやらなきゃいけないところです。

まずは書きやすいようなユーティリティみたいなところから導入して。このテストもゆるく導入しています。ここらへんのテストのやり方については、『レガシーフロントエンド安全改善ガイド』っていう本があって、そこに載っていたのでちょっと実践したいなと思っています。この本はすごくいい本だったので、フロントエンドを改善したい人は、ぜひ読んでみるといいかなと思っています。回し者じゃないですよ(笑)。

技術選定のポイント

次は毛色がまた変わりますが、技術選定の話をしたいと思います。技術選定は、自分は選定する立場にいるので、ちょっとこういう話をしますが、ミスると数年単位で痛いっていうことになるので、けっこうこれは慎重にやっています。新しすぎるものは避けていて、個人的にはアーリーマジョリティくらいを目指そうと思ってやっています。

アーリーマジョリティについては、下のグラフで書いてますが、何かを採用する人が100人いたらだいたい50人、半分くらいの人が採用、使い始めるときがアーリーマジョリティとかって言われていて。そのくらいのときに使い始めるのがベストなのかなと思っています。

ただ、いつがアーリーマジョリティかなんて、「今ですよ」っていうのは言ってくれるわけじゃないので(笑)。自分の肌感で鍛えていくしかないので、けっこうウォッチするのが大事かなと思っています。

それについて参考にしているものがいくつかあって、1個目が、GitHubにWEB DEVELOPER - ROADMAPっていうのをあげてくれている人がいて。これを見たりしています。これ毎年更新されていて、今貼っている画像はこれを一部切り取っただけですが、すごく網羅的にいろいろな技術要素に対して書かれていて。

凡例はありませんが、紫が今一番流行っているよというやつで。緑がその次で、グレーはちょっと避けたほうがいいよ、みたいな感じになっています。こういうのも、一応軽く見て参考にしたりとかはしています。

あともう1個が、ThoughtWorks社が出しているTECHNOLOGY RADARですね。これもちょっと参考にしていて。同じような感じなんですが、これも各分野でAdoptが一番いいよっていうやつで、その次はTrialで、みたいな感じになっていて。今フロントエンドだと、React HooksとReact Testing LibraryとVue.jsがいいよ、というような感じになっています。

1個前のサイトもそうですが、日本のトレンドとちょっと違ったりするので、これは参考までと思っています。

あともう1個大事なのがあって、社内の技術ロードマップです。これはラクスの開発組織として現在保有している技術の棚卸しと、あと今後5年で身につける必要があるよねっていうような技術をロードマップ的に書いてあるものです。

なにか採用するときには一応これを見て、基本はこの方針に従うような感じでやろうとしています。TypeScriptもこれに従っているので、全然問題ないです。

学習はあまり欲張らない

続いて、学習についてです。新しいものをやっていくんですが、当たり前ですが、実際に開発するメンバーにその技術を覚えてもらわなきゃいけないので。なので、自分としては一気にやりたいときもあるんですが、誰もついてこないと意味がないので、みんながついてきてくれる感じで、少しずつやっていく必要があるかなと思っています。

あんまり欲張らないで、年に1個でも2個でも新しいものを取り入れたらオッケーみたいな感覚がいいのかなと思っています。

そのためには、僕がすごくいいと思ってもそれだけじゃダメなので、どんなメリットがあるかをみんなに知ってもらう必要があります。ここの温度差があると、本当にうまくいかないと思っていて、僕がすごく「めっちゃいいぞ!」って言っても、みんなが「ふーん」という感じだとダメなので。

これはどんなメリットがあるのか、みんなにどんないいことがあるのかを一生懸命説明したり。あとメンバーにも、どうせだったらよい開発経験をしてほしいのでっていうのを伝えて、わかってもらうのがすごく大事かなと思っています。

あとは、学習をサポートするということで、メンバーのスキルレベルもマチマチだし、新しい技術要素をウォッチしている人がいたり、新しい技術というよりかは既存の技術を高めたいっていう人もいたりします。興味がある領域もマチマチなので、入門レベルまではサポートしてあげたほうが絶対いいかな、と思っています。

やるのはそんなに奇をてらったことじゃなくて、要点をまとめて勉強会を開催して、入門レベルまで引き上げてあげるのがすごく大事かなと思います。その中で、やっていてちょっとよかったのが、「モブ写経」と僕が呼んでいるやつで。サンプルコードがあったときに、これを複数人でプログラミングします。

要はモブプログラミング形式ですね。1人がタイプして、周りの人はサポートするようなかたちで書いていきます。初めて書くため、たいていはスラスラ書けないので、周りの人がガヤというか「カッコ足りないよ」とか「カンマがないよ」みたいに教えてあげる感じで書いていって。

手を動かしてやるので、座学でやるよりかは絶対理解が進むし、コミュニケーション面ではわりとオススメかなと思っています。これはずっとやるわけではありませんが、部分的に取り入れるといいかなと思っています。

あとは実地でやってもらうしかないのですが、初めて担当するときは、知っている人とペアで作業をしてもらったり。あと当然学習時間がかかるので、スクラムで開発しているんですが、スプリントプランニングのときにそれを考慮してスケジュールしてもらったりしています。

あとやっていることとして、「スキル星取表」というのを作っていて。これを全員でやっているのですが、それぞれどの技術がわかる、得意なのかっていうのを印として書いていって。これがあることで、誰が得意なので誰に聞けばいいのかが新規参加メンバーにもわかると。

これを見ると、ReactだったらCさんだなっていうのがパッとわかるとか。あと計画的なスキルアップにも使えるかなと思っていて、これを作ったことで、自然とメンバーの中で「私〇〇に印がないですが、やってみたいです」とか、けっこう前向きな会話が発生したりしています。

あと心理的な効果として、これ、印を埋めたくなってくるので、そういうのもちょっと期待しています。学習については以上です。

フロント専任チームを作りたい

最後は、組織についてです。現在の組織なんですけども、フロントとバックという分けがなくて、今は1人のエンジニアがフロントもバックも担当しています。現状を見ていると、CSSやHTMLが苦手なバックエンドエンジニアはすごく多いです。

僕も両方やっていて、実際両方ハイレベルなスキルをもつのはけっこうつらいので、極端な話、バックエンドエンドを改善しているときはバックエンドしか見ていません。今はフロントエンドに寄っているので、フロントエンドって感じで。両方見るのはけっこうキツイと思っています。

なので新しい試みとして、さっきの楽楽勤怠の話にもありましたが、フロントエンド専任のメンバーを今立ち上げようとしています。餅は餅屋に任せたいなと。作業分担して並行作業してやりたいねとか。ゆくゆくはもっと人数を増やして、フロント専任チームを作りたいという計画もあります。

ただそのために、もうちょっと分離しやすいように、SPAやBFFをいろいろやっていかなきゃいけないのかな、とは漠然と思っています。

最後、まとめになります。改善していった結果、現状はこんな感じになっています。フロント側をやっと改善する基礎ができてきたかなと思っています。今のシステムがハイブリッドな感じになっていて、Reactが動いているところもあったりするのですが。

今回、上のところのレガシーなところ、青いとこが改善されて、ここは安心して開発できる状態になっていったかなと思います。銀の弾丸はないので、少しずつ改善を続けていきたいと思っています。レガシーなフロントエンドは改善できるということで。ご清聴ありがとうございました。

質疑応答

藤澤貴之氏(以下、藤澤):三田さんありがとうございました。

池田智裕氏(以下、池田):ありがとうございました。けっこう反応がありまして。質問としては、「Webpackを利用しているとNode.js、npmを利用していると思いますが、Javaプロジェクトの構成にどうやって組み込んだのでしょうか?」という質問が。

三田:今はプロジェクトは1個のまんまでやっていますね。本当にJavaとJSと、昔ながらの感じですね。フォルダ分けして入っている感じで。プロジェクトのルートにpackage.jsonがあって、Javaのビルドをするbuild.gradleがある感じで今は、やっています。

池田:あとは「フロントエンドの情報収集はどういうふうに、情報アンテナをどのように張っていますか?」という質問が。さっきお話にありましたけれども。

藤澤:資料上に出てないもの以外であればという感じですね。 

三田:特にフロントエンドだからというのはあんまりないですけどね。普通にみんなと一緒だと思います(笑)。Twitterを見てとか、はてブを見てとか。そんなくらいしかしてないですね。

藤澤:あと定番だとJSer.info、ニュースまとめてくださっているサイトとかですかね。

三田:そうですね。わりと僕もさっき話したとおりで、けっこうバックエンドも見なきゃいけなかったりとかするので、フロントエンド集中みたいな感じじゃなくて、わりとあらゆる方向にアンテナを張っているような感じではあります。

池田:あとは新技術の話ですが、「メンバーにわかってもらう際に工夫しているところが知りたい。どうしても対立してしまうときはありますよね」という質問が。

三田:うちのメンバーはあんまないんですよね。そういうの。すごく楽なんですよね(笑)。

池田:「じゃあやろう」ってなるんですか?

三田:やろうってけっこうなりますし。選定しているものもそんなに……さっきも流行っているものみたいな感じで言ったんですけど、わりと異論があんまり出ないようなものを選んでいる感じもあるので。

池田:これは技術だけの話じゃなくて、どうしても今までの枠組みでやってると、それに慣れてきたところで、なぜ新しいものをやって、新しいものを覚えなきゃいけないのっていうようなのはあるとは思うんですけどね。それがない?

三田:それもあまりなくて。わりとよさは伝えようとはしていますね。これ入れるとメッチャいいよっていうのは、わりと普段から言っている感じですかね。それであんまり「これ入れるの反対です」とかって言われたことはないし。

あとは、絶対無理なスケジュールではやらないので。負担をかけるようなことはなるべくやらないようにしている。さっき言ったんですけど、今年はTypeScriptやりましょう、来年は別のところやりましょうみたい感じで。

池田:あらかじめ先の話を言っておいて、みんなに準備をさせているみたいな感じですね。

池田:もうひとつ質問。「ちょっと答えにくいかもしれないですが、スクラムだとクロスファンクショナルが注目されていますが、難しかったんでしょうか?」と。「なんでフロント専任を作っていこうという決断をしたのでしょうか?」というような。

三田:もともとスクラムをチームでやっていたんですけど、サービスが成長してきてどんどん新しいものを作ってみたいな感じでメンバーがすごく増えてきて。今1チームで入らなくなっていて、2チームになっていて。もっとどんどん増える予定があるので。

理想はやっぱり僕もクロスファンクショナルなチームかなと思うんですけど、規模的な問題でそう分けざるを得ないかなと思っていて。分けるやり方として、フロントとバックというのが分けやすいのかなと思っているので、ちょっとそこらへんをやっています。

池田:早さについていくためにはそうせざるを得ないだろうということですね。

三田:そうですね。

藤澤:三田さん、どうもありがとうございました。

三田:ありがとうございました。