I (ISP):介面隔離原則
今天有一個考模擬考的功能
班長 = OPS(大介面,擁有所有科目的模擬考卷)。
數學小老師、英文小老師、自然小老師 = U1Ops / U2Ops / U3Ops(小介面)。
考卷內容 = 各科的操作方法(op1 / op2 / op3)。
班長手上有「全科模擬考卷」大集合,但他不會自己做,而是把卷子分發給各科小老師。
所以
數學小老師只要處理數學卷(不用管英文或自然)。
英文小老師只要處理英文卷。
自然小老師只要處理自然卷。
在製作畫面的時候也有一樣的情形。
我發現「文章管理」這件事太複雜了,所以關於文章的功能放在一起畫面變很長。
所以我把它拆成兩部分:
雖然都是「文章」相關,但每個頁面只需要自己用得到的功能。
所以拆開來,各自服務需要的人(管理者或作者)。
今天,我成功把鐵人賽的第一篇文章放到部落格(歡呼!)
但在做的時候,發現還有好多地方需要改進:
我做了一個 AI 幫忙生文章的功能。(還在想怎麼整理 AI 提示)
我需要一個「預覽」按鈕,先看看文章長怎樣。
文章裡需要可以放程式碼的區塊(用 highlight.js、marked 來幫忙)。
就像蓋房子時,先把基礎做好,之後才會知道牆壁要不要加強、窗戶要不要改。
結果長這樣
來處理前端啦!
我將 AI 產制的內容跟編輯分開,然後在另一個步驟看是不是要套用。
但以後想要擴增更多關於 AI 不同 Prompt 的功能,例如格式化、給靈感、或是產生特定內容。
<!-- AI 協助面板 -->
<div
:class="[
'rounded-lg border-2 border-blue-100 bg-gradient-to-br from-blue-50 to-indigo-50 transition-all duration-300 ease-in-out overflow-hidden',
{
'p-4 max-h-96 opacity-100': aiPanel.show,
'p-0 max-h-0 opacity-0': !aiPanel.show,
},
]"
>
<h4 class="text-sm font-semibold text-indigo-700 mb-3 flex items-center">
🤖 AI 寫作協助
</h4>
<div class="flex flex-col sm:flex-row gap-2 mb-3">
<input
type="text"
v-model="aiPanel.prompt"
placeholder="輸入您的需求,例如:改善這篇文章的結構"
@keyup.enter="handleAiAssist"
class="flex-1 px-3 py-2 border border-gray-300 rounded-md text-sm focus:border-indigo-400 focus:ring-2 focus:ring-indigo-200 focus:outline-none"
/>
<button
type="button"
@click="handleAiAssist"
:disabled="!aiPanel.prompt.trim() || aiPanel.loading"
class="px-4 py-2 bg-indigo-600 text-white text-sm font-medium rounded-md hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center whitespace-nowrap"
>
<span v-if="aiPanel.loading" class="loading-spinner mr-2"></span>
{{ aiPanel.loading ? '生成中...' : '生成內容' }}
</button>
</div>
<div
v-if="aiPanel.result"
class="bg-white p-3 rounded-md border border-blue-200 mb-3 max-h-32 overflow-y-auto text-gray-700 text-sm leading-relaxed prose prose-sm max-w-none"
v-html="renderedAiResult"
></div>
<div v-if="aiPanel.result" class="flex flex-wrap gap-2">
<button
type="button"
@click="applyAiResult"
class="px-3 py-1 bg-green-600 text-white text-xs font-medium rounded hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2"
>
套用到內容
</button>
<button
type="button"
@click="appendAiResult"
class="px-3 py-1 bg-gray-600 text-white text-xs font-medium rounded hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2"
>
附加到內容
</button>
<button
type="button"
@click="clearAiResult"
class="px-3 py-1 bg-gray-600 text-white text-xs font-medium rounded hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2"
>
清除結果
</button>
</div>
</div>
「架構」是一種把事情分得清楚的方式。
它不只用在程式,也用在團隊合作。
想想看:
架構是一開始就把所有功能就想好嗎?
如何再慢慢擴展的過程中去拼湊架構,並為後面的功能增加彈性呢?