刷新之間,藏著多少重來與等待 - 網頁快取
清晨七點半🔹X-Cache 是「快取結果的回報」🔹Cache-Control 是「告訴瀏覽器要怎麼快取」❔ 資源 Cache 在哪裡🕒 Expires:設定「絕對時間」🕒 Cache-Control:設定「相對時間」🕒 🔹快取過期後怎麼辦清晨七點半,你手捧著一杯還冒著熱氣的黑咖啡,筆電剛開機,PChome 的首頁已經靜靜等著。今天,是傳說中的限量開搶日 —— PS5 Spider-Man 2 限定版主機,早上八點整正式開賣。明明一個月前,你才下定決心要戒掉電動,結果看到廣告那一瞬間,理智直接下線:「反正只是收藏,不一定要打開來玩。」這麼說服自己之後,還特地設了三個鬧鐘,把商品頁加進書籤,信用卡也提前擺在桌上待命。
滑鼠懸停在「重新整理」按鈕上,指尖微微冒汗,內心默唸著:「這不算破戒,這叫做支持正版!」
當秒針跳到 7:59:59,你一口氣按下刷新,畫面瞬間閃動。那張帥氣的限量主機圖,早已從最近的新竹 CDN Edge Server 快取而來,商品庫存與折扣倒數,則剛剛從台北資料中心即時更新,因為你的瀏覽器在快取過期後,發送了 If-Modified-Since 的精確詢問。 ...
Cache - 從頭開始
Node🥥 第一階段:打造屬於自己的「最簡快取機制」🥥 關於 Thread-Safety🧠 鎖定ConcurrentDictionary🥥 過期機制🌟 總結村裡,有位小學徒 Yoyo,每天最常被叫去做的工作,就是幫村裡人查詢「住戶資料」。
「Yoyo,去問資料庫大師,這位用戶住哪裡?」「Yoyo,再去查一次,那筆我剛剛沒記住。」
一開始,Yoyo 也不以為意。畢竟這是學徒的日常
「欸,再去……」
可重複個幾百次後,他終於受不了了:「為什麼我每次查完,都要重跑一樣的路?而且連名字都懶得叫了內」,有天,他開始在口袋裡放一本小筆記本,把查過的資料寫在上面。從此以後,他只要看看自己的筆記本,就能直接回應問題,不必每次都跑一趟,這本小筆記本,就是 Yoyo 發明的「快取系統」
在這一階段,我們要實作一個最基礎、卻實用的快取系統
Lazy Load + Dictionary現在我們選擇兩樣工具
Dictionary 當作資料容器
一個 Func<T> 委派來延遲建立資料(Lazy Load)
實作規劃
元件
說明
Dictionary<string, ...
Array - Collection
Array(T[])是什麼?IEnumerable(IEnumerable)是什麼?為什麼 Enum.GetValues 回傳的是 Array(而且是非泛型)LINQ 不是「不能用在 Array」,是因為遇到「非泛型」問題選 Array 還是 IEnumerable選 Array 還是 IEnumerable當我們有一塊連續記憶體的資料結構(大小固定),就會有 Lengthf、values[i] 直接索引(O(1)),這是真正「已經全部在手上」的一批資料,適合需要高速索引、固定長度、確定要把資料一次放好的場景
它不是資料結構,它是「你可以被 foreach 一個個拿出來」的能力(介面),可能背後是 array / list / db query / 檔案讀取 / generator / yield return…,重點在於,它允許 deferred execution(延遲執行),也就是寫了 Select/Where 不代表立刻跑,是 foreach / ToList() / Count() 的那刻才真正開 ...
Host
ASP.NET Core 的誕生ASP.NET VS ASP.NET COREHostHost.CreateDefaultBuilderIHostEnvironmentIConfigurationGeneric Host 和 WebApplication Hosthost.Run / host.Start / 直接跑summary以前的 ASP.NET 只能跑在 Windows + IIS 的組合裡。換句話說,你想開發網站,就必須用 Windows Server,因為 ASP.NET 被「綁死」在那個環境。後來微軟想要讓它更自由,所以從頭開始重寫,這就是 ASP.NET Core 的誕生
它一開始用「ASP.NET vNext」這種暫時的名字登場,後來一度被叫做 ASP.NET 5,最後才定名為 ASP.NET Core。這裡的「Core」代表:
全新框架 → 不是 ASP.NET 4.x 的小改版,而是重頭設計。
精簡核心 → 把最必要的功能保留下來,刪掉複雜、不必要的包袱。
跨平台 → 不再侷限於 Windows,可以跑在 Linux、macOS,甚至容器(Docker)裡。
...
OAuth 2.0
OpenIDOAuthOAuth 2.0 (Open Authorization)為什麼中間會先回一個 Authorization Code,而且還暴露在 Url上資料分享summary讓我們想像一下,如果每次進入一個新的國家,都需要重新申請一個新的身份證會很麻煩,但這就是早期網路使用者的日常生活 —— 每個網站都需要一個新的帳號和密碼。於是,OpenID 的概念應運而生,它就像是網路世界的通用護照,為技術發展添加了人性化的一面
故事開始於 Blaine Cook 試圖在 Twitter 上實現 OpenID。這就像是試圖讓你的護照(OpenID)不僅能證明你的身份,還能授權別人代表你處理一些事務。但 Blaine 和他的朋友發現,OpenID 的核心價值,是讓「證明你是誰」這件事可以被重複使用,而不用每個系統都自己養一套帳密系統,而不是授權(允許別人做什麼)
使用者已經在某個可信任的地方有身分,例如一個 OpenID Provider(身分提供者),接著他嘗試登入另一個網站,這個網站不想自己管理帳密,而網站把「你是誰的驗證責任」交給 OpenID Provider,因此網站不碰你 ...
關於 host file ( Windows )
開始研究 host files 這東西的契機是,在看動畫瘋時一直被廣告煩得很不爽,然後就沒想說隨便 Google 看看有沒有什麼招,沒想到有人有一樣的想法而且還把心思動到 host file 上,覺得這個用法滿有意思的
host file網路就像一個巨大的城市,而每個網站都是這個城市中的一個建築物。在這個城市裡,每棟建築物都有一個獨特的地址(IP 地址)。但是,我們的頭腦無法記住地址,所以我們給每棟建築物起了名字(域名)。現在,想像你的電腦會幫你連接到你想去的建築物,有兩種方式來幫你找到正確的地址:
1.打電話給城市的訊息中心(DNS Server)詢問地址。2.查看一本特殊的私人電話簿(hosts 文件)。
hosts 文件的運作機制如下:
優先級:當你想訪問一個網站時,你的電腦首先會查看 hosts 文件(私人電話簿)。格式:hosts 文件中的每一行都像是電話簿中的一個條目,包含一個 IP 地址和對應的域名。覆蓋 DNS:如果 hosts 文件中有你要找的網站,電腦就會直接使用這個地址,而不會去詢問 DNS Server。
hosts 文件就像是一個可以自定義的、優先級很高的小型 ...
Asynchronous Programming - 第三章:非同步中的等待藝術
全自動咖啡機Task.Run(...) 的本質CPU-bound vs I/O-boundsummary小遙家裡有一台很貴的全自動咖啡機。只要放入咖啡豆,按下按鈕,五分鐘後,一杯完美的拿鐵便會端坐在托盤上,溫度與比例都恰到好處
但她還是習慣站在一旁等
她不相信機器;在咖啡流出前的幾十秒,她總會打開上蓋,觀察豆槽有沒有卡住,再輕拍一下;聽見磨豆的聲音時,也會試著微調參數、瞄一下壓力表。她甚至曾試著在機器運作時,手動幫忙攪拌牛奶。直到有一天,她打翻了一杯還沒加糖的咖啡,才驚覺:其實什麼都不做,才是真的在等那杯咖啡完成
有些事情,本質上就像 I/O-bound 的任務,對方的成長、一段關係的發酵、時機的成熟、情緒的消化,它們需要的是時間與環境,不是你額外派一個「焦慮的自己」去乾等
Task.Run 的本質不是「非同步」,而是把你原本會卡住目前執行緒的同步工作,轉交給 Thread Pool 的背景執行緒去扛,讓現在這條執行緒先活下來
12345678public static Task Run(Action action){ return Task.Fac ...
從克德族說起:繼承為何讓人生卡關?
好久好久以前,有兩個著名的家族——
克德族,是一個信奉血統主義的家族。他們深信純正血脈的力量,嚴格遵循世代傳承的家族傳統,認為唯有優良基因的延續,才能孕育出最優秀的後代。起初,這種方式的確造就了不少傑出人才。克德家的子女大多具備出色的音感,未來幾乎都走上了音樂的道路。
但隨著時間流逝,問題逐漸浮現。某一天,家族中一位孩子心懷成為機械技師的夢想,卻發現家族的傳統成了束縛。他無法脫離音樂的陰影,也難以獲得從事機械所需的技能,陷入深深的痛苦與迷惘。
海的另一端,是萊雅族。這是一個秉持開放思想的家族。他們相信卓越不僅來自血統,更來自個人的選擇與學習。他們鼓勵每位成員自由探索,組合各種不同的技能與知識。
這樣的理念帶來了極大的彈性。萊雅族的子女可以依興趣學習,不論是音樂、機械或其他領域皆不受限制。他們甚至可以同時成為音樂家與技師。
然而,自由也帶來困惑。因選擇過多,部分成員在成長過程中感到迷惘,沒有明確的方向。不僅如此,因為每個人都走著截然不同的路,外人甚至難以辨別他們是否屬於同一族群。
克德族的困境,就像物件導向中的繼承(Inheritance)。子類別(Subclass)往往難以擺脫父 ...
組合的力量與設計哲學
在上一篇文章中,我們看到繼承帶來的限制與設計陷阱。本篇將把鏡頭轉向另一個更自由、更靈活的設計哲學 —— 組合(Composition)。
組合就像是把系統拆解成可重組的積木,每個模組只負責一個任務,清晰、精準、可插拔,讓程式不僅易於擴充,也更能回應未來的變化。
🌸 組合怎麼解決問題?用組合代替繼承,解決行為歧義(Ambiguity of Behavior)讓戰鬥法師「擁有」戰士和法師的能力,而不是「繼承」它們。
12345678910public class Battlemage{ private Warrior _warrior = new Warrior(); private Mage _mage = new Mage(); public void MeleeAttack() => _warrior.Attack(); public void CastSpell() => _mage.CastSpell();}
用 Interface 來分離行為,避免多繼承,解決屬性重複(Duplicate State)讓 Warrio ...











