閒談軟體設計:Client Server

更新於 發佈於 閱讀時間約 11 分鐘
本來本周是想寫跟最近工作有關的 library vs. framework,不過前幾日中午休息時間時,在 FB 上看到一個開發者在某個社團分享他開發的 library,想了解大家對於用這來設計 Restful API 的想法,我沒有直接留言 (不想節外生枝去筆戰,不過,基本上那已不是 Restful API,詳見閒談軟體設計:休息時間),只是在我的 FB 簡述自己的想法,沒想到引起一些討論,真的是蠻有趣的,所以今天的主題就來聊聊 client server 吧!

講古

什麼!?client server 有什麼好聊的?首先,先想想看為什麼要用 client server? ㄟ… 作者傻了嗎?現在不都是這樣嗎?因為程式要跑在雲端 (要說成雲端才夠潮) 上啊,這樣不就是 client server 了。這裡要來講古一下了,在大型主機的年代 (這裡要澄清一下,本人沒有歷經那個年代,不然都把自己講老了),就已經有 clent server 的概念:由 client (計算能力較差的終端機) 向 server (計算能力較好的大型主機) 請求服務,幫助理解與管理分散式系統程式的複雜度

當時終端機與大型主機之間確實是不同的機器以區網連接,例如:X Window System 便是 client server 的架構,但由於個人電腦的運算能力越來越好,client 與 server 不見得一定得在不同的機器,一般來說 client 和 server 在抽象上會是獨立的執行實體 (process 或 thread),但之間不一定是透過網路或 HTTP 溝通,可以用像是 IPC 的方式溝通。若真要說 client server,其實可視為 multitiered 架構的一個只有 2-tier 的特例,所以使用 client server 和使用 multitiered 的用意,可以說是一樣的:separation of concerns

Separation of concerns

既然是 separation of concerns,整個應用程式的程式碼,哪些該放在 server 上,哪些又該放在 client 上,在網頁應用程式變熱門之前,其實就有這方面的討論,在《Distributed Systems: Principles and Paradigms》一書中有個有趣的圖,討論在一個分層 (layered) 的系統中,哪些層放在 client 哪些層放在 server 所帶來的優點與缺點:

圖片來源:《Distributed Systems: Principles and Paradigms》

圖片來源:《Distributed Systems: Principles and Paradigms》

圖中的 (a),所有的商業邏輯與資料庫則在 server,甚至 presentation model 都是由 server 提供,終端機只須根據 presentation model 顯示使用者介面,這樣的優點是 client 的運算能力不需要很好,但缺點是 client 與 server 之間的溝通會很頻繁 (連 presentation model 都在 server 上),若溝通成本 (網路速度) 太高,使用者的體驗會很差,如果要以現在的網頁應用程式類比,早期 server-rendered page 技術就屬於這個類型,所有動作都需要以換頁的方式進行

隨著終端機的能力越好,漸漸就將完整的使用者介面程式都放到 client 上,即上圖的 (b),像是很多早期的桌面應用程式都是屬於這個類型,大多數與使用者介面有關的邏輯都能在 client 上處理,在體驗上比什麼都要詢問 server 要好,當時的表單系統都是送往 server 才能處理,但若有錯還是要整個流程再來一次,因此像圖中的 (c),漸漸有一些商業邏輯的程式搬到 client 上,像是直接在 client 檢查使用者輸入的內容,以提升使用者體驗。在大量 JavaScript 框架的協助下,目前大多數網頁應用程式都屬於 (c) 類型,同樣,大多數網路遊戲也是屬於這個類型

由於後來個人電腦的運算能力實在太好了,所以 server 只剩下資料庫或檔案伺服器的責任,像圖中的 (d),其他商業邏輯都搬到 client 上,後期的桌面應用程式大多是這類,像是企業用的倉儲系統等。甚至,為了加快儲存速度,如圖中的 (e) 一樣 client 自己本身有儲存能力,在離線時或是用非同步的機制與 server 同步。一般來說,會把 (a) 到 (c) 稱之為 thin client,而 (d) 和 (e) 則稱為 flat client,就過去部署程式需要到每台機器安裝來說,確實 thin client 會是較好管理的,因此 Sun 曾提出過 thin client 的企業解決方案,但在個人桌面環境,還是操作體驗較好的 flat client 較受歡迎。

不過,現在部署程式已經不像過去那樣需要安裝,只要打開瀏覽器,點選某個網站,大量的 JavaScript 程式就部署到 client 端,也因此能提供更好的體驗,但和過去桌面應用程式不同的,網頁應用程式較少是屬於 (d) 或 (e) 類型 (可能是我孤陋寡聞,若有例子歡迎提供),我覺得主要的原因是安全性,在專屬的應用程式協定的保護下,server 比較能放心 client 要儲存到資料庫的資料完整性與正確性,但 stateless 的 HTTP 協定,則比較難確保這件事,因此,大多數的商業邏輯還是放在後台,避免 client 直接操作資料庫竄改 (自己或別人的) 資料

Server 的設計

另外,server 只是一個概念上提供服務的實體,可能是由多個執行中的個體組成,其組成可能是水平的擴展,以 load balancer 提升 server 的負載能力;也可能是垂直的擴展,變成更多 tier 的組成,每個 tier 提供特定的功能;或是混合的微服務組成。因此在設計 server 端的 API 時,個人還是以提供什麼服務為主,而不是提供什麼資料,當然這些服務的結果是以資料的形式送到 client 端,但不會是設計時主要的考慮目標,就如同《建構微服務》一書提到的:

這些功能可能需要資訊交換 — 共用模型 — 但我見過太多以資料的角度思考而導致貧血的 CRUD 服務,因此,請先詢問『這個上下文是做什麼的?』然後才問,『他需要什麼資料?』

簡單說,還是從商業邏輯的角度出發去設計 API。除此之外,設計 API 時,還需要考慮什麼嗎?其實還蠻多的,像是怎樣的資料格式傳輸是比較有效率的,或是可以減少 request 次數,又或者是安全性控管等等,不過大體上,不管是不是設計微服務的 API 或單體是服務的 API,我都蠻贊同《建構微服務》書中提到的原則:

尋找理想的整合技術

  • 避免破壞性變更
  • 讓你的 API 保持技術無關
  • 讓服務消費者覺得你的服務很簡單
  • 隱藏內部實作細節

基本上,讓 client 直接操作資料庫 (上圖中的 (e) 類型) 違反上述四個原則,因為若調整資料庫的 schema 就可能導致 client 的程式需要修改,這構成破壞性變化,當然即使是將商業邏輯擺在 server 端也是要修改,程式的修改是無法避免的,但 API 可以扮演隔離改變的角色,由於 client 直接操作資料庫,變成 API 與特定技術綁死 (SQL),此外,使用上也不直覺,使用 API 的人需要知道資料庫設計的細節。個人覺得比貧血的 CRUD API 還要糟糕。

混淆的術語

由於使用 client server 主要目的是 separation of concerns,那在寫 API 程式的時候,是否也要考慮 separation of concerns 呢?其實也是需要的,過去擔任 OOAD 助教時,曾經在某次全班的 design review 時,老師對著學生畫的 sequence diagram 問:這個 xxx controller (其實是 MVC 中的 controller) 是 main controller 嗎?當時一起 design review 的我,並沒有意會過來,也覺得 controller 確實可以當作是 main controller 啊,但後來考慮到 MVC 的 controller 主要是處理 UI 事件,main controller 則是處理系統事件,確實不合適在一起。

類似事件後來有再發生,一次是在 code review 學弟的程式碼時,發現大多數的商業邏輯被分散在用 Strust @Action加註的函式中,於是我建議他將商業邏輯抽出來。另一次則是前陣子 code review 同事寫的後台程式,商業邏輯也是被放在用 Spring @RestController 加註的類別函式中,同樣,請同事再 refactoring 一下。老實說,在軟體設計的術語中,model 和 controller 恐怕是被用得最多的字眼,但也常常被搞混的,像 @RestController 本身有 controller 字眼,可能聯想成 MVC 的 controller,也可能想成處理系統事件的 main controller,但對我來說,它只是處理的 request 的 handler 而已。

所以,以 separation of concerns 的角度,API 的 request handler 該處理什麼事呢?簡單來說,就是商業邏輯以外的所有事:

  • 安全性控管
  • 資料格式檢查與轉換成 domain 物件
  • 呼叫 main controller 對應的函式
  • 處理例外與轉換成對應的狀態碼和錯誤訊息
  • 將 domain 物件轉成合適的輸出格式

總結

當然,像 Spring framework 有提供蠻多的 filter 協助開發者處理像是安全性控管、資料格式檢查與資料轉換、例外的對應和資料輸出格式轉換,所以看起來好像只剩下一件事:呼叫 main controller 對應的函式,那不就只剩下商業邏輯的部分了?既然如此,不需要獨立一個類別,直接把商業邏輯的程式放到 request handler 中似乎也是可以?老實說,不是不行,對我來說就只是少了點跟框架的友善距離罷了,自己的習慣,@RestController 中的函式都蠻短的,大部分是 Spring framework 無法幫忙的格式檢查或資料轉換,然後就是呼叫 main controller 了,所以寫測試時,也相對輕鬆。

這次 client server 就談到這裡,不管是網頁應用程式或是 Andorid/iOS 上的 App 大多是 client server 的架構,也需要 API 的設計,希望大家都能設計出好的 API,有任何想法歡迎一起討論。

留言
avatar-img
留言分享你的想法!
Spirit-avatar-img
發文者
2023/09/16
閒談軟體設計:Offline first (Server 篇)提及了這篇文章,趕快過去看看吧!
avatar-img
Spirit的沙龍
54會員
107內容數
這是從 Medium 開始的一個專題,主要是想用輕鬆閒談的方式,分享這幾年軟體開發的心得,原本比較侷限於軟體架構,但這幾年的文章不僅限於架構,也聊不少流程相關的心得,所以趁換平台,順勢換成閒談軟體設計。
Spirit的沙龍的其他內容
2024/03/23
這篇文章探討了在軟體開發中的技術債可能來自哪些原因,以及如何自動化偵測與修復技術債。作者透過分享不同情境下的技術債選擇,提供了對於技術債的思考與建議,針對開發人員在需要做出無奈的技術決策時,提供了一些建議。此外,還提供了一些在做出技術決策時的方法,如保留抽象層和避免vendor lock-in。
Thumbnail
2024/03/23
這篇文章探討了在軟體開發中的技術債可能來自哪些原因,以及如何自動化偵測與修復技術債。作者透過分享不同情境下的技術債選擇,提供了對於技術債的思考與建議,針對開發人員在需要做出無奈的技術決策時,提供了一些建議。此外,還提供了一些在做出技術決策時的方法,如保留抽象層和避免vendor lock-in。
Thumbnail
2024/03/09
今天來聊個最近很夯的主題 DDD,但不是 DDD 的本尊 Domain Driven Design,而是無所不在的 Database Driven Design,Database Driven Design 不是不好,只是你的模型容易變成貧血模型,邏輯都集中在 service 層等等。
Thumbnail
2024/03/09
今天來聊個最近很夯的主題 DDD,但不是 DDD 的本尊 Domain Driven Design,而是無所不在的 Database Driven Design,Database Driven Design 不是不好,只是你的模型容易變成貧血模型,邏輯都集中在 service 層等等。
Thumbnail
2024/03/02
有趣的是,Model 其實沒什麼嚴格的定義,所以每個人對 Model 的解讀也不盡相同,有人覺得資料怎麼儲存屬於 Model 的一部份 (受 ORM 工具的影響),有人覺得工作流程 (workflow) 是 Model 的一部份,我個人也有自己的想法,而且隨專案的規模和特性,也不是總是一樣的。
Thumbnail
2024/03/02
有趣的是,Model 其實沒什麼嚴格的定義,所以每個人對 Model 的解讀也不盡相同,有人覺得資料怎麼儲存屬於 Model 的一部份 (受 ORM 工具的影響),有人覺得工作流程 (workflow) 是 Model 的一部份,我個人也有自己的想法,而且隨專案的規模和特性,也不是總是一樣的。
Thumbnail
看更多
你可能也想看
Thumbnail
孩子寫功課時瞇眼?小心近視!這款喜光全光譜TIONE⁺光健康智慧檯燈,獲眼科院長推薦,網路好評不斷!全光譜LED、180cm大照明範圍、5段亮度及色溫調整、350度萬向旋轉,讓孩子學習更舒適、保護眼睛!
Thumbnail
孩子寫功課時瞇眼?小心近視!這款喜光全光譜TIONE⁺光健康智慧檯燈,獲眼科院長推薦,網路好評不斷!全光譜LED、180cm大照明範圍、5段亮度及色溫調整、350度萬向旋轉,讓孩子學習更舒適、保護眼睛!
Thumbnail
創作者營運專員/經理(Operations Specialist/Manager)將負責對平台成長及收入至關重要的 Partnership 夥伴創作者開發及營運。你將發揮對知識與內容變現、影響力變現的精準判斷力,找到你心中的潛力新星或有聲量的中大型創作者加入 vocus。
Thumbnail
創作者營運專員/經理(Operations Specialist/Manager)將負責對平台成長及收入至關重要的 Partnership 夥伴創作者開發及營運。你將發揮對知識與內容變現、影響力變現的精準判斷力,找到你心中的潛力新星或有聲量的中大型創作者加入 vocus。
Thumbnail
無論是企業的資訊科技環境,還是個人數據儲存需求,雲端技術都逐漸融入我們的生活。本文將帶領讀者深入了解雲端服務、主機代管,以及雲端平台。透過運用雲端技術,我們可以省去在自家機器上費心管理實體伺服器或執行軟體應用程式的煩惱,不論是個人使用者或企業都能輕鬆體驗雲端帶來的便利。
Thumbnail
無論是企業的資訊科技環境,還是個人數據儲存需求,雲端技術都逐漸融入我們的生活。本文將帶領讀者深入了解雲端服務、主機代管,以及雲端平台。透過運用雲端技術,我們可以省去在自家機器上費心管理實體伺服器或執行軟體應用程式的煩惱,不論是個人使用者或企業都能輕鬆體驗雲端帶來的便利。
Thumbnail
在大型主機的年代 (這裡要澄清一下,本人沒有歷經那個年代,不然都把自己講老了),就已經有 clent server 的概念:由 client (計算能力較差的終端機) 向 server (計算能力較好的大型主機) 請求服務,幫助理解與管理分散式系統程式的複雜度。
Thumbnail
在大型主機的年代 (這裡要澄清一下,本人沒有歷經那個年代,不然都把自己講老了),就已經有 clent server 的概念:由 client (計算能力較差的終端機) 向 server (計算能力較好的大型主機) 請求服務,幫助理解與管理分散式系統程式的複雜度。
Thumbnail
企業常常有代理人機制, 當我們有重要的事情需要請假時, 就會有代理人幫我們處理公司事務, 相當於「我們授權代理人處理什麼事情」,而這樣的代理機制在軟體世界也是常見的一種機制, 尤其是在分散式運算的架構下。 那代理能為我們帶來什麼好處呢? 又為什麼非用不可? 這也是我們今天著重探討的主題。 其實代理就
Thumbnail
企業常常有代理人機制, 當我們有重要的事情需要請假時, 就會有代理人幫我們處理公司事務, 相當於「我們授權代理人處理什麼事情」,而這樣的代理機制在軟體世界也是常見的一種機制, 尤其是在分散式運算的架構下。 那代理能為我們帶來什麼好處呢? 又為什麼非用不可? 這也是我們今天著重探討的主題。 其實代理就
Thumbnail
什麼是集中式系統架構 簡單來說就是,應用程式和數據庫都集中在一台中心端Server身上,而使用者通過終端設備來訪問這個中心化系統。
Thumbnail
什麼是集中式系統架構 簡單來說就是,應用程式和數據庫都集中在一台中心端Server身上,而使用者通過終端設備來訪問這個中心化系統。
Thumbnail
介紹 分層架構模式,是將一個軟體系統進行分層,每個軟體系統都去要通過層來隔離不同的關注點,其中最為經典的就是三層架構以及領域驅動設計提出的四層架構。 📷 三層式架構 下面會介紹每一層專門要處理的事情 最常是用的分層方式 至於每層模組的命名方式,每間公司都不太ㄧ樣 📷 參考資料 鐵人賽文章
Thumbnail
介紹 分層架構模式,是將一個軟體系統進行分層,每個軟體系統都去要通過層來隔離不同的關注點,其中最為經典的就是三層架構以及領域驅動設計提出的四層架構。 📷 三層式架構 下面會介紹每一層專門要處理的事情 最常是用的分層方式 至於每層模組的命名方式,每間公司都不太ㄧ樣 📷 參考資料 鐵人賽文章
Thumbnail
這篇分享希望能讓你了解 目前企業在資訊基礎設施上有哪些常用架構,彼此之間又有甚麼樣的差異, 而企業又要如何選擇出適合自己的架構呢? 本篇會分享三種主流架構: 1.三層式架構 2.超融合架構 3.非聚合式超融合架構 4.總結
Thumbnail
這篇分享希望能讓你了解 目前企業在資訊基礎設施上有哪些常用架構,彼此之間又有甚麼樣的差異, 而企業又要如何選擇出適合自己的架構呢? 本篇會分享三種主流架構: 1.三層式架構 2.超融合架構 3.非聚合式超融合架構 4.總結
Thumbnail
前言 近幾年很常聽到雲端服務、雲端運算,許多工作職缺也會寫雲端工程師之類的,一直以為雲端相關的事務涉及到分散式運算系統,所以它的技術門檻應該是非常高的,如果一般大眾大概很難理解它。 雲端是甚麼 接下來就用三個面向來讓大家稍微了解雲端服務的優勢和種類有哪些,我們日常使用的雲服務又是屬於哪個類型。
Thumbnail
前言 近幾年很常聽到雲端服務、雲端運算,許多工作職缺也會寫雲端工程師之類的,一直以為雲端相關的事務涉及到分散式運算系統,所以它的技術門檻應該是非常高的,如果一般大眾大概很難理解它。 雲端是甚麼 接下來就用三個面向來讓大家稍微了解雲端服務的優勢和種類有哪些,我們日常使用的雲服務又是屬於哪個類型。
Thumbnail
隨著軟體規模、性能要求的不斷提升,分散式系統得到快速發展。分散式系統透過許多低成本節點的協作來完成原本需要龐大單體應用才能實現的功能,在降低硬體成本的基礎上,提升了軟體的可靠性、擴充性、靈活性。
Thumbnail
隨著軟體規模、性能要求的不斷提升,分散式系統得到快速發展。分散式系統透過許多低成本節點的協作來完成原本需要龐大單體應用才能實現的功能,在降低硬體成本的基礎上,提升了軟體的可靠性、擴充性、靈活性。
Thumbnail
前陣子剛好聽了 AWS(Amazon Web Service,亞馬遜的雲端服務)介紹他們的雲端服務,簡單來說就是從「硬體思維」轉換到「軟體思維」的方式,以軟體方式去思考就可以看作是「雲端」
Thumbnail
前陣子剛好聽了 AWS(Amazon Web Service,亞馬遜的雲端服務)介紹他們的雲端服務,簡單來說就是從「硬體思維」轉換到「軟體思維」的方式,以軟體方式去思考就可以看作是「雲端」
Thumbnail
踏入工程師生涯也十幾個年頭了,這些年工作主體逐漸從開發轉向諮詢規劃。遊走於兩者之間總會碰到一些相持不下的時刻,比如 PM 覺得某某功能很重要,可工程部門一直想要說服說這個做不了。處理得好就是雙贏,處理得不好往往就是不歡而散。 當一個新的產品及服務放到你面前的時候,你是怎麼去理解一個產品的?
Thumbnail
踏入工程師生涯也十幾個年頭了,這些年工作主體逐漸從開發轉向諮詢規劃。遊走於兩者之間總會碰到一些相持不下的時刻,比如 PM 覺得某某功能很重要,可工程部門一直想要說服說這個做不了。處理得好就是雙贏,處理得不好往往就是不歡而散。 當一個新的產品及服務放到你面前的時候,你是怎麼去理解一個產品的?
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News