リプレイスの手段と効果

# リプレイスとは

[リプレース（リプレイス）とは - 意味をわかりやすく - IT用語辞典 e-Words](https://e-words.jp/w/%E3%83%AA%E3%83%97%E3%83%AC%E3%83%BC%E3%82%B9.html)

<details>

> リプレース 【replace】 リプレイス
> リプレースとは、交換（する）、置換（する）、元に戻す、後を継ぐ、などの意味を持つ英単語。
> 
> ITの分野では、古くなったり破損したシステムやハードウェア、ソフトウェアなどを新しいものや同等の機能を持った別のものに置き換えることを指す場合が多い。部品やソフトウェアなどの部分的な入れ替え、交換を意味する場合も、機器やシステム全体を新しくすることを指す場合（システムリプレース）もある。

</details>

# 本記事で書きたいこと
Webアプリケーション開発業は改修との闘いかと思います。
他の開発業と比べ、一度作ったものが変化する頻度が段違いです。
なので、既に改修しづらくなっているプロダクトではリプレイスの検討がしばしば入ります。

本記事では、リプレイスの各手段と効果を、具体例を交えて言語化できればと思います。

<img width="400" alt="esa-リプレイス-健全度.drawio.png (38.9 kB)" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2728467/21994cc6-b824-62ff-620c-51b23e591e88.png">

※
FE＝フロントエンド
BE＝バックエンド
健全度 ≒ 改修しやすさ

※
健全度は目的で変わります。
仮に中身のコードが大変なことになっていたとしても、ビジネス要件を全て満たしていて何の改修も必要ないなら右上に属します。

# 前提
MVC2＋(JQuery|VanillaJS)
なRailsアプリケーションをリプレイスする前提とします。

# 何もしない

## 内容

- 容易性 ★★★★★
- コスパ ★★★★★
- 健全度 ★★★★★

リプレイスもリファクタも必要ない理想形の状態です。

# リファクタ

## 内容

- 容易性 ★★★★☆
- コスパ ★★★☆☆
- 健全度 ★★★★☆

既存アプリケーションコードの修正で間に合っている状態です。

# FEリプレイス：Vue/ReactをHTMLの一部分に導入する

## 内容

- 容易性 ★★★★☆
- コスパ ★★★☆☆
- 健全度 ★★☆☆☆

(JQuery|VanillaJS)のままメンテ・改修していくことが困難な局面で検討するアプローチです。

### できること
- Vue/Reactのスモールスタート
    - 「ページ全部をリプレイスする工数はないが、このコンテンツだけ機能開発が盛んなのでVue/Reactに置き換える」が可能
    - FE負債チョット返せる

### できない・難しいこと
- SSR
    - 仮想DOMで描画になります。
    - Vue/Reactで描いた部分を検索エンジンに評価されない可能性があります。

### 例

```erb
<div>
  <ul id="item-list">
    <% @items.each do |item| %>
      <li><%= @item.name %></li>
    <% end %>
  </ul>
</div>

<script>
$(function() {
  $('#item-list').xxx
  // ...
});
</script>
```

↓

```erb
<div id="item-list"></div>
```
```js
import { createApp } from 'vue'

createApp({
  // ...
}).mount('#item-list')
```

### 補足

[レガシーフロントエンド安全改善ガイド (インプレスR&D, NextPublishing)](https://nextpublishing.jp/book/11098.html)
という本が（たしか）こんなアプローチでした。

# FEリプレイス：Next.jsを導入する

## 内容

- 容易性 ★★★★☆
- コスパ ★★★★★
- 健全度 ★★★★☆

**自分が知っている中で、リプレイスの銀の弾丸と思います。
安全にリプレイスできて弱点がないので最強です。**

```plantuml
@startuml
node LoadBalancer
host -> LoadBalancer
note bottom of host
    app.example.com
end note
package クラスタ {
    node Railsコンテナ
    node Next.jsコンテナ #EEBBBB
}
LoadBalancer -> Next.jsコンテナ
note bottom of Next.jsコンテナ
    ・GET以外はRailsに流す
    ・GETでNextのルーターに掛からないパスはRailsに流す
end note
Next.jsコンテナ -> Railsコンテナ
@enduml
```

- [Next.jsのrewrites機能](https://nextjs.org/docs/api-reference/next.config.js/rewrites)
    - （GETでNextのルーターに掛からないパスはRailsに流す に必要）
- [Next.jsのmiddleware機能](https://nextjs.org/docs/advanced-features/middleware)
    - （GET以外はRailsに流す に必要）
- （いずれも、Webサーバ級の仕事をするスゴい機能。）

を使うことで、既存の動きを損なうことなく特定ページのみNext.jsで描画することが可能です。

### できること
- Next.jsのスモールスタート
    - インフラさえ正しく移行できれば、リプレイスしたページにしか影響しません。
- SSR
    - SEO対策できます。

### できない・難しいこと

- Next.jsをマネージドサービスで運用すること
    - [Next.jsのstandaloneモード](https://nextjs.org/docs/advanced-features/output-file-tracing#automatically-copying-traced-files)を使い、自前でNext.jsコンテナ(orプロセス)を建てる必要があります。
    - そのため、VercelやAmplifyなどの定番サービスに乗せられません。
        - （自分の案件ではダメだったのですが、インフラ要件しだいではいけるパターンもあるかもです。）
    - 自前でnodeプロセスが走るサーバを運用しないといけないリスクは一定あると思います。

### 疑問
Vue側（Nuxt.js）は調べていないのですが、同じことは出来るんでしょうか。

# BEリプレイス：新規アプリケーションを建てる

## 内容

- 容易性 ★☆☆☆☆
- コスパ ★☆☆☆☆
- 健全度 ★★★☆☆

ここまでくると、ほぼほぼフルリプレイスです。
既存コードと並行して全く新しいアプリケーションコードを作ります。

インフラで
「特定パス/特定ホストのリクエストだけ新サーバに向ける、それ以外は従来サーバに向ける」
のようにして移行を実現します。

### できること
- 既存コードから完全な解放
    - 設定ファイル、基底クラス、共通クラス、モンキーパッチなどから完全に解放されます。
    - （外部設計＝外向きの振る舞いは踏襲する必要があります）

### できない・難しいこと
- 既存コードの再利用
    - 当然ですが、できません。
    - 既存のテストコードで担保されていた部分も改めてテストコードを書く必要があります。
    - （良し悪しやそれで動くかどうかを置いておくと、コピペである程度持ってくることはできます）
- DBschemaの共有
    - かなり工夫が要ります。

# BEリプレイス：新規エンドポイントを建てる

## 内容

- 容易性 ★★★☆☆
- コスパ ★★★☆☆
- 健全度 ★★★☆☆

/api/v2 のように新しいエンドポイントを切って実装します。

### できること
- 既存コードからある程度の解放
    - 設定ファイル、基底クラス、共通クラス、モンキーパッチなどとは向き合う必要があります。
- 既存コードの再利用
    - 既存のブラックボックス化しているロジックがあっても、呼び出しやすいです。
    - 既存のテストコードで担保されているビジネスロジックをそのまま呼び出しやすいです。

### できない・難しいこと
- 既存コードから完全な解放
    - 設定ファイル、基底クラス、共通クラス、モンキーパッチなどとは向き合う必要があります。

# フルリプレイス

## 内容

- 容易性 ★☆☆☆☆
- コスパ ★☆☆☆☆
- 健全度 ★★★☆☆

既存アプリケーションと並行して全く新しいアプリケーションを作ります。

インフラで
「特定パス/特定ホストのリクエストだけ新サーバに向ける、それ以外は従来サーバに向ける」
のようにして移行を実現します。

DBもリプレイスする場合、計画停止や移行バッチを書いたりする必要が出てきます。

# まとめ

プロダクトの改修が難しくなってきたら

FEリプレイス：Next.jsを導入する
BEリプレイス：新規エンドポイントを建てる

でOK

# おわり

(冒頭より)

> Webアプリケーション開発業は改修との闘いかと思います。
> 他の開発業と比べ、一度作ったものが変化する頻度が段違いです。

Web開発職は「変化に強いか？」をものすごく気にします。
変化に強い設計には及第点があり、図の赤線のラインがそれだと思います。

赤線を超えているのといないのとで改修難易度は段違いで、赤線を超えているシステムでは改修ごとに状況が悪くなる一方です。

<img width="400" alt="esa-リプレイス-健全度.drawio.png (16.9 kB)" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2728467/f6b072c2-bb79-be86-5d08-a083f6599303.png">

「いかに赤線を超えないか？」を日々学びつつ、
「赤線を超えたときに戻ってくる方法」を取り揃えたいと思います。