Upgrade to Pro — share decks privately, control downloads, hide ads and more …

有效結構化你的 Rails 專案

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.
Avatar for tsechingho tsechingho
August 02, 2020

有效結構化你的 Rails 專案

將使用數種實際的範例,講述如何結構化專案邏輯與 UI 畫面。

建議使用多層的 Namespace 來結構化專案的業務邏輯,每個業務流程須講究獨立運作。

當不同角色的業務邏輯 UI 畫面不一樣時,該如何使用前後端技術有效率實作,並保留容易擴充的彈性,將是本次探討的重點。

使用 Rails 開發專案,務必不要死守 MVC 架構,Presenter、Form Object、Query Context 等都是你的好朋友。Rails 的 Form Builder 是很有彈性的,可以串接 ActiveRecord 以外的物件,重點是如何做好表單驗證、錯誤處理、巢狀表單。將會示範如何靈活運用這些物件。

最容易將專案越搞越複雜的方式,大多發生於

1. 相似的業務流程,直接使用同一個流程,加上很多 if else 條件。
2. 不同的角色,有類似的 UI,使用很多 if else 條件去 render 不同的 patial 檔案。

以上無視眾多的小差異積累的威力,就會造成牽一髮動全身,讓專案變得難以維護。將會示範幾項手法來處理這問題。

使用 Rails view 或 React 實作 UI 端(Server / Client Side Render)的基本守則是類似的,因此可以做到遊走於兩種實作方法的。將會示範基本做法。

Avatar for tsechingho

tsechingho

August 02, 2020
Tweet

More Decks by tsechingho

Other Decks in Technology

Transcript

  1. 複合式商店 - 購物⽅式 • 購物⾞ • 可放置多樣商品+型號 • 可移除商品 •

    可選數量 • 可放置加購商品 • 所有商品⼀起結帳 • 智能購物⾞ • 主動折扣(符合條件) • 即時拆單(分批結帳)
  2. ⼀⾴式商店 - 單品購物 • 單品+立即結帳 • 各型號獨立 • 不可選數量 •

    不可搭配加購商品 • 樣式:按鈕 • 單品選購+立即結帳 • 型號可單選 • 可選數量 • 可搭配加購商品 • 樣式:選項+按鈕
  3. ⼀⾴式商店 - 系列商品購物 • 系列商品+立即結帳 • 各商品+型號獨立結帳 • 不可選數量 •

    不可搭配加購商品 • 樣式:分區(按鈕) • 例:劃位售票 • 系列商品選購+立即結帳 • 可多選商品+型號⼀起結帳 • 可選數量 • 可搭配加購商品 • 樣式:分區(選項+按鈕) • 例:冷凍鍋物(⽺⾁爐 )
  4. ⼀⾴式商店 - 綑綁商品購物 • 綑綁商品+立即結帳 • 各綑綁商品獨立結帳 • 不可選數量 •

    不可搭配加購商品 • 樣式:分區(按鈕) • 例:限量公仔 • 綑綁商品選購+立即結帳 • 可複選綑綁商品⼀起結帳 • 可選數量 • 可搭配加購商品 • 樣式:分區(選項+按鈕) • 例:募資商品
  5. 線上商店 - 結帳流程 • 折扣 • 抵⽤(點數) • 優惠(合作) •

    ⾦流 • ATM、超商條碼 • 信⽤卡、線上⽀付 • 發票、電⼦發票 • ⼆聯式、三聯式、捐贈 • 載具 • 物流 • 超商取貨、超商付款取貨 • 郵寄、宅配、貨到付款
  6. 複合式商店 - ⾏銷 + 結帳 • 免費領取 • 零元兌換 •

    等價兌換 • 折價兌換 • 全站折扣碼 • 指定商品折扣碼 • 分類(館)折扣碼 • VIP 卡 • 活動折扣 • 經常性、季節 • 特惠、廠商合作 • 加購優惠
  7. 依照角⾊ - 所需⾴⾯組成不同 • 線上課程平台 • 訪客 • 學員 •

    講師 • 學院 • 平台 • 外送平台 • 顧客 • 外送員 • 店家 • 平台
  8. 依照流程 - 呈現元素排列不同 • 貨運單(送件 -> 收件) • 空運 -

    ⾶機, 空港, 轉運站 • 海運 - 貨船, 海港, 海關 • 陸運 - 卡⾞, 集貨中⼼, 收貨點 • 購物 • 購物⾞ • ⼀⾴購物
  9. 學會 Rails 不只是 … • 只會 MVC 架構 • 只會在

    Model 做 Validation • 只會寫⼀⼤串 ActiveRecord 的 where 條件查資料庫 • 只會⽤ view helper 簡化 view 取得資料的複雜度 • 只會拿 Form Builder 串接 ActiveRecord 或 Ransack 物件 • 只會⽤ if … else … 切割流程
  10. 至少要活⽤ … • ActiveHash / ActiveYaml / ActiveJson 當作資料物件 •

    Query Context 作為跨資料物件查詢的仲介層 • Presenter / Decorator 作為 view 的資料來源 • Form Object 作為表單驗證的把關者 • Service Object 作為串接外部服務的⿊盒⼦ • Operator / Flow Object 作為控制流程的中⼼物件
  11. 善⽤ Route 切割業務邏輯 • Admin 和 API 都知道要切成 namespace,為何其他功能不切 namespace?

    • 除了切出 namespace,也能切成 subdomain 做到獨立。 • 既然會掛 rails engine 的 routes 到專案,為何 routes.rb 不切割成數個檔案?
  12. Rails View 層越簡潔越好 • 多點 Layout 不是壞事,仿照 AMP 只放該⾴⾯需要的 JS、CSS

    和資料 • 同個 namespace 的 partial file 不要放到其他 namespace 資料夾 • 改⽤ Presenter 為主、Decorator 為輔,少⽤ view helper • 資料要遵守 Single Source of True 原則 • 避免多層的 if … else …,儘量只⽤ if 就好 • 最後⼤概只剩 HTML + CSS classnames + methods + Loops + if 的結構
  13. Namespace 是業務邏輯⼿段 • 每個業務邏輯都要有⾃⼰的 module ( namespace ) • 流程控制邏輯

    / UI 呈現邏輯 / 資料存取邏輯 • Controller / View / Model => web page • Operator / Presenter / Query Context => page section (components) • 放 app 或 lib 資料夾 • 寫成 rails engine 放專案內,或發佈成 ruby gem
  14. Namespace 依類型區分 • app/contexts • carts/query_context.rb • orders/query_context.rb • app/forms

    • carts/update_form.rb • orders/create_form.rb • app/presenters • carts/popup_presenter.rb • orders/details_presenter.rb • app/services • payments/create_service.rb • callbacks/update_service.rb
  15. Namespace 依需求區分 I • app/learning • carts • query_context.rb •

    update_form.rb • popup_presenter.rb • app/teaching • orders • query_context.rb • create_form.rb • details_presenter.rb
  16. Namespace 依需求區分 II • app/components/learning • carts • popup_presenter.rb •

    app/objects/learning • carts • query_context.rb • update_form.rb
  17. React.js + Rails • 不做需要 SEO 的 web page 或

    page section 才⽤ React • 需要 SEO 的⾴⾯⽤ AMP (in rails view) • React 資料夾切割以⾴⾯為單位 • API 端點依需求 namespace 切割 (例:learning vs teaching) • Presenter -> json.jbuilder -> React component props