蒼時弦也
蒼時弦也
資深軟體工程師
發表於

釐清脈絡 - 重新思考 Rails 架構

這篇文章是 重新思考 Rails 架構 系列的一部分。

我們繼續用「物流系統」作為案例,來探討將軟體架構設計完善時所需的前置準備,也就是去了解整個系統的脈絡(Context)或者說學習該領域(Domain)的知識。

這個過程大多還未進入到開發階段,因此不論語言、框架都是通用的,甚至可以說是否要使用某個語言或者框架,可能要再確認後才決定更加適合。

從案例學習

不論是設計文件(Design Document)或者產品需求文件(Product Requirement Document)如果只描述功能、規格層面的問題,對所有閱讀文件的人來說都是非常大的心理負擔,對新成員、初次接觸的領域來說,都會變得容易出錯。

舉例來說,在物流系統中有對於時區的特殊需求,以規格來描述會像這樣

當從站點出發時時,在 ATD 欄位以 MMdd 格式紀錄出發時間。抵達目標站點時,在 ATA 欄位以 MMdd 格式紀錄抵達時間,所有時間皆以當地時間表示。

以一份規格來說,已經算是相當清楚的資訊,將要填寫的數值、格式、換算等資訊都有描述出來,然而對於開發團隊仍要花時間理解完整的運作。

如果以案例的方式描述,那麼會像這樣

假設有一筆運送紀錄單號 O-1234 當從桃園(TPE)出發,在 ATD 欄位以當地時間(UTC+8) 1600 填入。 當抵達沖繩(OKA)時,在 ATA 欄位以當地時間(UTC+9) 1830 填入。

上述的案例看起來就會比規格容易理解很多,同時也會發現「規格」跟「案例」一定程度是互補的,我們可以從多個案例中推導出一個可能的規格,而案例也可以幫助對於規格的理解更加清楚。

除此之外,這些案例的撰寫方式實際上也很將近使用者故事(User Story)的描述方式,通常也會是描述使用者需求的一種呈現。

客戶下了一筆運送訂單 O-1234 從桃園(TPE)出發 當機場人員確認出發後,在 ATD 欄位以當地時間(UTC+8)1600 填入後送處 那麼在報表上可以看到 O-1234 的 ATD 呈現 16:00

客戶下了一筆運送訂單 O-1234 從桃園(TPE)出發 當機場人員確認抵達後,在 ATA 欄位以當地時間(UTC+9)1830 填入後送出 那麼在報表上可以看到 O-1234 的 ATA 呈現 18:30

出發跟抵達可能是兩個不同的流程(不一樣的步驟)因此我們會將使用者故事拆成兩件事情獨立描述,而且正好涵蓋了我們對於規格的理解。

這類型的案例就很適合用 Cucumber 撰寫文件進行測試

分類脈絡

正常狀況下,我們會不斷蒐集到各種需求、規格上的描述,然而如果只作為「單一系統」來看待,就可能把各種行為混合在一起處理,因此需要將脈絡釐清。

舉例來說,空運、海運等等都會是集中運輸的方式進行,也就是說我們除了透過案例了解系統時,也會發現一些預期外的資訊。

以大多數人的生活經驗來看,寄送包裹會是一個訂單加上貨品的組合。

1class Order < ApplicationRecord
2  # 一筆訂單可以同時運送多個貨品
3  has_many :products
4end
5
6class Product < ApplicationRecord
7  belongs_to :order
8end

然而,在空運或者海運的狀況下,運送的規模不會是一台車子,而是一整個貨櫃,因此還需要知道這些被寄送的商品被怎樣組合到其他運送單位上。

 1class Shippment < ApplicationRecord
 2  # 一個運輸單位有多個「貨櫃」
 3  has_many :containers
 4end
 5
 6class Container  < ApplicationRecord
 7  # 每個貨櫃以「棧版」為單位集裝
 8  has_many :pallets
 9  belongs_to :container
10end
11
12class Pallet  < ApplicationRecord
13  # 商品被打散到不同棧版上
14  has_many :products
15end

加入了運送資訊後,是否開始覺得整個系統變得複雜,如果要再加入不同類型的運輸單位(如:貨車可能是單一貨櫃或者棧版)我們可能還要做更多的處理。

同時,你可能還會發現 OrderPallet 同時都管理 Product 那麼其中一邊的物件做了修改後,是否會影響到另一邊的資料正確性,都會需要考量進去。

根據需求不同,會有不一樣的分類方式。在這個情境來看,我會選則分成三個不同的情境。

  • 訂單(Order)
  • 運送(Shipment)
  • 集裝(Container)

判斷的依據通常會根據使用者故事的描述可以找到線索,通常有對應的操作就表示我們會有類似的分組出現,至少在「運送」這件事情上我們可以從文章一開始的案例看出來。

那麼,訂單跟分配貨品,就有蠻高的機率是兩件不同的事情。

印象中當時「集裝」是被設計在運送的畫面上,不過那個畫面非常複雜,實際操作設定哪些貨櫃被送出去應該是可以在另外的畫面被處理的。