HTML
CSS
リファクタリング
初心者

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

More than 1 year has passed since last update.

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

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

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

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

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

CSSを例にすると

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

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

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

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

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

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

補足

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

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

たたき台にするコード

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

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>
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>
style-a.css
.my-style-a {
  color: white;
}

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

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

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

sample1.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ファイル側でもファイル名の変更が必要だからです。

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>
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

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

ここでもし

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

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

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

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

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

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

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>
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になります。

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

すると読み込み関係は

sample3.png

このようになります。

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

sample4.png

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

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

名称変更はもちろん

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

削除や追加も楽です

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

まとめ

いかがでしょうか :question:

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

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

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

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