iT邦幫忙

2026 iThome 鐵人賽

DAY 6
0
Software Development

下載器不是寫完就能跑:一個 HLS 分段式串流工具的架構與測試修練系列 第 6

Day 06:這層抽象值得嗎?三個來源 vs 十個來源,成本轉折點在哪

  • 分享至 

  • xImage
  •  

前言:只有一個來源站的時候,需要 Template Method 嗎?

前幾天講的 Template Method、Factory,聽起來都是「顯然正確」的設計。但如果今天這個工具從頭到尾只打算處理一個來源站,這些抽象層是不是就變成過度設計?

答案是:要看的不是「現在有幾個來源」,是「這個抽象要解決的重複,實際上重複了幾次」

今日目標

  • 認識抽象化不是免費的,它本身也是一種需要維護的成本
  • 看清楚判斷「該不該抽象」的具體依據,不是憑感覺
  • 反思這個系列自己案例裡的抽象層,是不是也有沒抽對的地方

抽象化的成本,跟它省下來的成本要放在天秤兩邊

只有一個來源站時,Template Method 多出來的抽象類別、@abstractmethod、介面定義,全部都是純粹的額外複雜度——沒有第二個實作可以驗證「這個抽象切得對不對」,很容易切出一個「看起來通用,實際上只服務單一情境」的介面,日後真的要加第二個來源站時,才發現介面切錯了地方,還得重構一次。

三次法則是一個常被引用的經驗法則:出現兩次重複可以先容忍,出現第三次再考慮抽象化——不是因為數字 3 有什麼魔力,而是兩個樣本不足以判斷「哪裡會變、哪裡不會變」,第三個樣本出現時,才比較看得出真正的變動邊界在哪。

❌ vs ✅:過早抽象 vs 等重複出現再抽象

❌ 反例:只有一個來源站,就先切好一層抽象

class Crawler(ABC):
    @abstractmethod
    def get_items(self, soup, url): ...

class OnlySite(Crawler):
    def get_items(self, soup, url):
        return soup.select(".only-site-list a")

這個抽象類別目前只有一個子類別,Crawler 這一層完全沒有驗證過「哪些邏輯真的共用、哪些其實是 OnlySite 專屬」。如果第二個來源站出現時結構差異很大(例如不是靠 CSS selector,而是要解析內嵌 JSON),現在切的這層抽象可能整個用不上。

✅ 正例:先讓具體實作跑起來,等第二、第三個來源出現,重複顯現出來再抽出共用骨架

# 只有一個來源站時,先寫成一支具體、不帶抽象層的類別
class OnlySiteCrawler:
    async def collect(self, url):
        html = await self._get_html(url)
        soup = BeautifulSoup(html, 'html.parser')
        return [item['href'] for item in soup.select(".only-site-list a")]

今日思考題

回想你維護的專案裡有沒有「只服務一個情境,卻已經先切好抽象層」的程式碼?如果拿掉那層抽象,程式碼會變簡單還是變複雜?

今日重點回顧

  • 抽象化本身有成本,只有一個樣本時很難判斷抽象切得對不對
  • 三次法則:容忍前兩次重複,第三次出現時再考慮抽象化
  • 判斷該不該抽象的依據是「重複實際出現的次數」,不是「感覺以後會需要」

明日預告

明天是第一部的回顧:把這五天累積的爬蟲層設計原則收斂成它的責任邊界,以及它不該負責的事。


上一篇
Day 05:項目編號解析裡的例外,不是每個項目標題都乖乖是數字
下一篇
Day 07:第一部回顧——爬蟲層的責任邊界,跟它不該負責的事
系列文
下載器不是寫完就能跑:一個 HLS 分段式串流工具的架構與測試修練11
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言