如何運用「區隔關注」原理讓你的前端程式堅不可破

Ben Lue
5 min readJun 18, 2019
Photo by Markus Spiske on Unsplash

區隔關注(Separation of Concerns)是屬於比較進階的軟體議題。在前端設計上,「區隔關注」的原則可以提高程式碼的可讀性,同時將程式修改時的破壞性降低。網路上關於「區隔關注」的文章往往過於抽象。這篇文章將用一些實際的例子,來說明如何在前端程式開發導入「區隔關注」的原則,讓你的程式慢慢進入「堅不可破」的境界。

以前端程式來說,新手工程師可能會把樣式描述直接寫在 HTML 的標籤屬性上,像這樣:

<div style="margin: 0 auto;">
<h3 style="color: red;">My Big Title</h3>
...
</div>

經歷過畫面不斷的被要求修改,最後將程式改成一團漿糊的痛苦後,這時新手工程師會開始善用 css ,將樣式的設定抽離,甚至會喜歡上 bootstrap。此時程式碼可能變成:

<div class="mx-auto">
<h3 class="text-danger">My Big Title</h3>
...
</div>

漂亮多了。不過公司裡如果有大神級的人物,這樣的程式碼還是會在 code review 時被檢討。問題出在哪裡?

Separation of Concerns

問題就出在小標所寫的幾個字:separation of concerns(誤)。在上面的範例碼中,還是將樣式的資訊嵌入了 HTML 代碼中。如此一來,至少會有二個潛在的問題:

  1. 如果你調整了樣式的規則(例如上述範例中的 .mx-auto 這個 css class),那麼所有參考到這條樣式規則的 HTML 代碼都會因而受影響。這樣的副作用也許是你要的,但更多時候可能是你不想要或根本沒有預期到的。
  2. 在上面範例中所使用的 css class 名稱有助於了解所使用的樣式的作用為何,但卻無法幫助我們了解這段 HTML 代碼的目的或作用。這是弔詭甚或矛盾的。因為我們在 HTML 代碼中應該要提高的是 HTML 本身的可讀性,而不是去解釋樣式的作用。樣式的說明應在 CSS 代碼中進行。

上述第二點可能有點抽象,我們用個實際的例子來幫忙了解。讓我們將原來的範例程式改寫成這樣:

<div class="article">
<h3 class="article-title">My Big Title</h3>
...
</div>

如此一來我們就可以很清楚的知道這段 HTML 代碼原來是要用來顯示一篇文章的。這也是「區隔關注」這個原則所要達成的目的:它就是我們平常說一碼歸一碼的意思。它的明顯好處是減少我們去過度混用 css class,避免程式因為一個小小的修改就掛點。

這件事我也想過

看到這裡,有些讀者可能會心理想著:這事我也想過,但是實務上真要這麼寫會比較麻煩、對負責設定 CSS 的工程師也會有困難,因為他不見得清楚程式的邏輯。

這其實是 HTML 語言本身的特性所造成,因為 HTML 和 CSS 從一開始就像是個孿生兄弟。雖然多年來經過許多軟體工程師的努力,要將二者做乾淨的區隔 (decoupling) 仍是不容易的。

不幸的是,目前可用來解決這個問題的軟體工具不多。其中一個解決方法就是用 Sass 的 extend 的功能。以我們使用的範例來說,用 Sass 可以這樣來解決:

.article
@extend .mx-auto

如此一來,.article 就可以完全借用 .mx-auto 的樣式屬性。一方面省掉複製 .mx-auto 樣式屬性到 .article 的工作,另一方面達成提高 HTML 代碼可讀性的目標。但是 .mx-auto 是 bootstrap 所定義,要這麼做就必須從 import Bootstrap 的 Sass 代碼開始改起。如果你所引用的 CSS 根本不是 Sass 代碼產生的呢?那只好直接 import CSS 代碼檔了。

coServ 提供了類似的功能,但更簡易好用。針對我們的範例,在 coServ 上可以這麼處理:

.article: {
'!extend': '.mx-audo'
}

而且 coServ 還允許你同時繼承多個 class 並加上新的屬性:

.article: {
'!extend': '.mx-auto .my-3 .border .border-primary',
'font-size': '1.2rem'
}

厲害的是,你不用擔心所要繼承的 class 當初是如何定義的、更不需要匯入 Sass 或 CSS 檔。只要網頁有定義的 css class,你都可以直接引用,十分方便!

以上說明了 coServ 如何幫助你簡單有效的運用「區隔關注」的原理,讓你的程式如同從磚造房子變成鋼筋水泥。coServ 還有許多功能,例如 CSS 封裝 (CSS encapsulation),可以讓你的 CSS 只在元件或你所定義的 HTML片段中可見,不會四處擴散。如果你對這些主題有興趣,歡迎多關注 coServ 的發展。

coServ github 網址:https://github.com/benlue/coServ

--

--

Ben Lue

CEO of Gocharm Inc. and father of two amazing children. Love programming since teen and still loving it.