CSSの@importを例にプログラムにおけるメンテナンス性の重要性を解説してみる

前置き : メンテナンス性の重要性を知ろう
---

プログラミングを初めてしばらく経ッッた時、例えば先輩があなたの書いたプログラムについて

* 『このコードはメンテナンスしづらいなぁ』
* 『これリファクタリングしてもっとカンタンにしよう』

と言っていたら、それは**『ちゃんと動くけれど変更しづらいね』**という意味だと捉えて下さい。

この言葉は*動くコードを書けるようになったという意味では喜ぶべきこと*です。
しかしプログラミングをする現場ではたいていの場合**単に動くだけではダメで、様々な変更を加えてもきちんと動き続けるようコードが要求されます。**

CSSを例にすると

* ある`<div>`のスタイルをいじったら、ヘッダーのスタイルまで変更されてしまったよ、なんで :question: 
* このclassの名前を変えたいんだけど、呼び出した場所も全て書き換えないといけないのは面倒だなぁ :sweat: 

ということがあると困ってしまいますよね。
つまり**ちょっとした変更にも必要以上に多くの時間や労力がかかってしまうようでは運用していけません**。

ここでの**「変更のしやすさ」**や**「変更を加えてもバグが発生しない度合い」**のことを、**エンジニアたちは『メンテナンス性』と呼んでいます** :wrench: 

とは言え、ここまで読んでも「じゃぁどうやってメンテナンス性を上げればいいの :question: 」という疑問は解決されないと思います。
実際には**より具体的なコードを書くときの手順や経験則がある**ので、それらも知っておかないとメンテナンス性の高いコードを書くことはできません。

あくまで今回は**初心者向けにメンテナンス性を上げることを体感してもらうポストとしたい**ので、初歩の初歩として、**『呼び出し箇所をまとめる』**という法則を、CSSの`@import`を例に説明しようと思います。
これを行うと、スタイルシート名を変更した時の修正箇所を減らすことができて便利です

プログラミングを始めたすぐはとにかく動くことを優先するべきですが、メンテナンス性について知っておくとより効率的にコードを書くことができるのでぜひ読んでトライしてみて欲しいです。

補足
---

通常のプログラミング言語(JavaScriptやRuby)の変数や関数を使ったほうが説明しやすいのですが、今回はあえてCSSの`@import`を例にしてみました。
これは**「プログラミング言語は知らないけれどHTMLやCSSは書けるよ」という初心者も多い**と思ったからです。

また詳しい方からの「いやいや、`@import`は読み込みが遅いからつｋ(ry」的なツッコミは受け付けません。あくまでも入門者の説明のために使うので。


たたき台にするコード
---

前置きが長くなりましたが、今回は以下のHTML(2つ)とCSS(3つ)を使って説明します。
全てのファイルは同じフォルダ内にあるものとします

```html:index.html
<!DOCTYPE html lang="ja">
<html>
  <head>
    <meta charset="UTF-8">
    <title>トップページ</title>
    <link rel="stylesheet" type="text/css" href="./style-a.css">
    <link rel="stylesheet" type="text/css" href="./style-b.css">
    <link rel="stylesheet" type="text/css" href="./style-c.css">
  </head>
  <body>
    <div class="my-style-a my-style-b my-style-c">
      トップページです。<br>
      <a href="./about.html">ABOUTページヘ</a>
    </div>
  </body>
</html>
```


```html:index.html
<!DOCTYPE html lang="ja">
<html>
  <head>
    <meta charset="UTF-8">
    <title>トップページ</title>
    <link rel="stylesheet" type="text/css" href="./style-a.css">
    <link rel="stylesheet" type="text/css" href="./style-b.css">
    <link rel="stylesheet" type="text/css" href="./style-c.css">
  </head>
  <body>
    <div class="my-style-a my-style-b my-style-c">
      ABOUTページです。<br>
      <a href="./index.html">トップページヘ</a>
    </div>
  </body>
</html>
```
```css:style-a.css
.my-style-a {
  color: white;
}

```

```css:style-b.css
.my-style-b {
  background-color: black;
}

```

```css:style-c.css
.my-style-c {
  font-size: 18px;
}

```

これらの読み込み関係を図にするとこうですね。

![sample1.png](https://qiita-image-store.s3.amazonaws.com/0/17214/392784a5-b201-682e-516e-3eac7318d6f5.png)

問題 : CSSファイル名を変えたら
---

前述のHTMLでは、`index.html`でも`about.html`でも、`style-a.css` `style-b.css` `style-c.css`の3ファイルを共通して読み込んでいます。

ここで`style-b.css`のファイル名を`style-x.css`へ変更しなくてはならなくなりました。
そこであなたはファイル名を変更たところ、背景色が白に戻ってしまいました。

なぜなら**CSSの読み込み元であるHTMLファイル側でもファイル名の変更が必要だから**です。

```html:index.html
<!DOCTYPE html lang="ja">
<html>
  <head>
...(中略)...
    <link rel="stylesheet" type="text/css" href="./style-a.css">
    <link rel="stylesheet" type="text/css" href="./style-x.css"> <!--"style-b"を"style-x"に変更-->
    <link rel="stylesheet" type="text/css" href="./style-c.css">
  </head>
  <body>
...(中略)...
  </body>
</html>
```

```html:about.html
<!DOCTYPE html lang="ja">
<html>
  <head>
...(中略)...
    <link rel="stylesheet" type="text/css" href="./style-a.css">
    <link rel="stylesheet" type="text/css" href="./style-x.css"> <!--"style-b"を"style-x"に変更-->
    <link rel="stylesheet" type="text/css" href="./style-c.css">
  </head>
  <body>
...(中略)...
  </body>
</html>
```

つまりこのようにファイル名の変更をする場合、**読み込み元が増えたらその分だけ修正箇所も増える**ということです。

![sample2.png](https://qiita-image-store.s3.amazonaws.com/0/17214/e39c55b4-467d-e1f2-f0d0-42f211820a8a.png)

このように変更箇所は**`style-x.css`だけではなく、それを読み込む場所の合計3ファイルにまたがります。**

ここでもし

* 今回は`index.html`と`about.html`だけだけど、もし`products.html`や`links.html`など、同じCSSを読み込むHTMLがもっと増えたら
* 他のスタイルシート`style-a.css`や`style-c.css`も名前を変更したくなったら
* 追加のスタイルシート(`style-d.css`や`style-e.css`など)も読み込む必要が出てきたら

...もうおわかりですね、その数に比例した箇所の修正をしなければならず、大変な手間がかかるのです :scream: 

解決法: `@import`でスタイルシートをまとめる
---

ではどうしたら良いのでしょうか :question: 
ここで登場するのが**`@import`の使用**です。
CSS内で`@import 'xxx'`と記述すると (xxxはスタイルシートの場所=URLやパスを指定)、CSS内で他のスタイルシートを読み込む事ができます。
例えば前述のスタイルシートに加えて、新しく`main.css`を作成して以下のように記述してみましょう。

```css:main.css
@import "style-a.css";
@import "style-x.css";
@import "style-c.css";
```

また`main.css`内で前述の3つのスタイルシートを読み込んだので、HTML側から重複する`<link>`読み込みを削除しましょう。
これでも読み込んだ結果は以前と同じままです。

```html:index.html
<!DOCTYPE html lang="ja">
<html>
  <head>
...(中略)...
    <!--style-a.css と style-x.css と style-c.css の読み込みを削除-->
    <link rel="stylesheet" type="text/css" href="./main.css">
  </head>
  <body>
...(中略)...
  </body>
</html>
```

```html:about.html
<!DOCTYPE html lang="ja">
<html>
  <head>
...(中略)...
    <!--style-a.css と style-x.css の読み込みを削除-->
    <link rel="stylesheet" type="text/css" href="./main.css">
  </head>
  <body>
...(中略)...
  </body>
</html>
```

上記の`main.css`は結局のところ以下と等価のCSSになります。

```css:main-expanded.css
.my-style-a {
  color: white;
}
.my-style-b {
  background-color: black;
}
.my-style-c {
  font-size: 18px;
}
```

すると読み込み関係は

![sample3.png](https://qiita-image-store.s3.amazonaws.com/0/17214/da4fd123-d345-f6ad-e788-f3e85f806982.png)

このようになります。

するといくらHTMLが増えても **`@import`したファイルの名前を変えても、変更箇所は常に1箇所で変わりません!!**

![sample4.png](https://qiita-image-store.s3.amazonaws.com/0/17214/dd661232-f534-4d8f-5594-be89e479fefd.png)

別の視点から考えると、元々`style-b.css`の読み込み(=呼び出し)は各HTMLの`<link>`で行われていましたが、それを`main.css`内の`@import`一箇所にまとめた事になります。

これが**『呼び出し箇所をまとめる』**ということです。
これができると、変更があってもそれが影響する範囲が狭いため、結果としてメンテナンス性が向上します。

名称変更はもちろん

```css:main.css
@import "style-a.css";
@import "style-y.css"; /* ファイル名変更 */
@import "style-c.css";
```

削除や追加も楽です

```css:main.css
@import "style-a.css";
/* style-x.cssの読み込みを削除 */
@import "style-c.css";
@import "style-d.css" /* 追加 */
```

まとめ
---

いかがでしょうか :question: 

他の一般的なプログラミング言語やフレームワークでは

* 処理を関数にまとめる
* テンプレートファイルを使う
* 外部ライブラリを利用する

などのテクニックが、今回の**『呼び出し箇所をまとめる』**に関連しています。

このポストで、感覚的にでも「効率が上がりそうだな」「無駄な作業が減りそうだな」ということが分かってもらえれば幸いです。