書けらぁっ!
やりたいことは9割終わったので、以下余談として読んでください。
この記事は# 「レガシー」を保守したり、刷新したりするにあたり得られた知見・ノウハウ・苦労話 by Works Human Intelligence Advent Calendar 2025 シリーズ2 21日目の記事です。
本編という名の余談
皆さん、フロントエンドのスクリプト、何で書かれてますか?
Vanilla? React? Vue?
この記事ではjQueryを軸としたフロントエンドを保守するうえでしんどいなと思った点を書いていきます。
まるで令和の時代ではjQueryが時代遅れみたいなタイトルですが、フルリプレイスされない限りは全然現役を張る気がします。
「レガシー」という単語が示す意味合いは解釈によって異なるかと思います。
この記事では主に「時代遅れ」、「技術負債」といった比較的ネガティブなニュアンスで使用しますので予めご了承ください。
チームの未熟さがレガシーになったケース
誰か有識者がいれば「そうはならんやろ」というツッコミが入るべきだったケース。
有識者がチームにいなかった(あるいはいなくなった)か、チーム内のコミュニケーションが不十分な場合に起こり得るのでしょう。
一つのリポジトリが同じライブラリを複数バージョン使用している
jQuery UIなど、jQueryを使ってさえいればライブラリの導入は比較的楽でした。
だからこそ、特に考えることなく「とりあえずこのライブラリ入れておけば動く」みたいな状況が乱立した結果、同じライブラリを別々の実装者が(時を越えて)導入してしまうことがあります。
私はjQueryの1.x系と3.x系が併存しているリポジトリに遭遇したことがあります。
同一目的で別ライブラリが使用されている
特にモーダルやスライダーを実現するためにはライブラリを利用するのが楽でした。
結果、同じような効果を持つライブラリがいろんな画面で活躍してしまいます。
教訓: ライブラリの導入は慎重にしましょう!
時代とともにレガシーになってしまったケース
書いた当時は問題なかったか、他に選択肢がなかったが時代が勝手にレガシーにしてしまったケース。
フロントエンド全体の流行り廃りのサイクルが良くも悪くも早いのが一因なのかもしれません。
非同期処理の書き方が違う
非同期処理を実現するための標準が存在しなかったことが一因として有るのでしょうが、
チーム内での作法が定まっていなかったためか ajax, deferred, fetchAPI が入り乱れる事態に…。
また、Ajaxはコールバックの書き方も success/error/complete と done/fail/always の混在を見て個人的には博物館に来たみたいな気分を味わっています。
IE対応の名残で変数の宣言が var になったままになっている
特に悪名高いIEでは長らく対応がされなかったために let, const といったキーワードを使用することができなかったのでしょう。
ただ、きちんと宣言しているならともかく場合によっては変数巻き上げが起きていることに気づかずエラーに遭遇することも…。
サービスの名称や機能の変化に取り残されている
年月が経つに連れて、外部サービスが変動するのですが、特にSNSなどクリティカルでないものの場合、見過ごされることがあります。
個人的には機能の提供有無はともかくサービスの名称が変わるのはちょっと勘弁してほしいと思ってしまいます。
X こと Twitter というかイーロンマスク、てめーのことだよ
jQueryオブジェクトが格納された変数名の先頭に $ がついている
私がjQueryを触り始めたときにはすでに廃れた慣習ではありました。
が、既存コードには多く残っており当時私は新人だったこともあり、愚直につけていました。
あの頃の私に言いたい。「jQueryオブジェクトであることが、わかることで嬉しいことって実はそんなにないよ」、と。
教訓: 最新のトレンドは常に追いましょう!
コード/レビュー品質の低さがそのままレガシーになったケース
コード変更時の品質だけでなく、レビュー品質が低い(あるいはレビューそのものを実施していない)ケース。
記述が全く意味をなしていない
いわゆるデッドコードと呼ばれる、絶対に実行されることはないコード。
一方で、下手に削除するとぶっ壊れる可能性だけを大いに秘めていることも多いです。
そのためか「触らぬ神に祟りなし」で放置されるケースもよくあるのではと思います。
同期/非同期通信で行う処理の境界が曖昧になっている
Ajaxで処理を行っている前後でエラーチェックしているのにメッセージが出ていない事象に遭遇しました。
理由をよくよく見ると、メッセージ表示処理に呼ばれるAjaxに謎の async: false の文字が…。
メッセージを出す処理はAjaxの後に出すか async: true にすべきなのでは…?と思わざるを得ません。
逆に、 onsbumit などの後にエラーメッセージを表示しようとしているケースもありました。
処理がまるまる呼ばれなくなってしまうので preventDefault が必要そうだけど…?
といった、実装者の同期/非同期通信への理解の不足か、あるいは長年保守していくうえで見過ごされてきたコードの数々が散見されます。
「可哀想に…今直してあげるからね…」という気持ちで向き合っています。
命名規則がカオスになっている
- キャメルケース、スネークケース、ケバブケースの使い分けができていない
- 何をチェックするのか不明な
check関数と何の結果なのか不明なresult変数 - バラバラなクォーテーションルール
は見ていて頭が痛くなってくるのでやめてほしいなと思います。
また、 : 前後のスペースを整えている箇所もたまに見掛けますね。
var obj = {
key : key,
value : value,
};
全体的にそうなっているのであれば、「まあ面倒だけど合わせるか」といった気持ちにはなります。
ただ、大抵の場合ファイルの中で特定の改修した箇所だけが整形されているのです。
そのため、「見やすいけど維持・横展開されないからやめてほしいな」と個人的には思います。
なお、先のコードは後に別の人間によって案の定こんな形になってしまっていました。
var obj = {
index: index,
type: 'boolean',
key : key,
value : value,
};
ただただ、悲しい気持ちになりました。
DOM操作が最適化されていない
ループの中で都度 jquery.append(DOM) が実行されているコードについては appendは一回でいいのでは…?と思ってしまいますし、
その追加するDOM文字列に <div style="color: red">重要な項目</div> などと、
スタイルが書かれているとちょっとイラッとしてしまうのは私だけではないはずです。
教訓: 新しいレガシーを生み出さないように品質には気をつけましょう!
レガシーから脱却するために気をつけること
ここまで散々レガシーに対する 愚痴 苦労話をしてきましたが、
では自分はどうすればいいのかを考えるうえでは反面教師として一定の学びがあるのではとも思っているため、
個人的にはレガシーから脱却することは苦ではありません。
ここまでの教訓も踏まえながら、他にも自身で気をつけていることを記載します。
いずれは誰のコードもレガシーになりうる
システムを長期間保守・運用していくと変更からは避けることができません。
そうなると当時の最適解は今の最適解とは限らない、という事態になりえます。
コードの見やすさと性能は紙一重
特にリファクタリングを行う際に気をつけています。
最近ではスプレット構文や構造分解など便利な構文が生まれていますが、
楽に書けるからこそ、性能にはより気を使う必要があるなと感じています。
特に配列や一度に大量のメモリを使う処理は昔ながらの記法の方が早かったりするから困りますね。
まとめ
この記事ではjQueryをベースに苦労話を書きましたが、今の主流であるReactやNode.jsなども
いずれは同じ扱いになるのかもしれません。
大事なのは時代の流れを見極め続けることなのかもしれませんね。