Typography

活版印字


  • Home
  • Archive
  • Categories
  • Tags
  •  

© 2020 alincode

Theme Typography by Makito

Proudly published with Hexo

controller vs service

Posted at 2016-03-11 pattern 

大家都在談 MVC,但我想先談談更基本的東西,那就是 controller 和 service 的職責,不管寫了幾年的 code,總是會不停看到,應該寫在 service 的邏輯放在 controller 中,應該寫在 service 的 code 寫在 controller 中。

大多數的人都說 controller 就是負責流程控制,service 負責商業邏輯,但什麼是流程控制,什麼是商業邏輯,老實說剛寫個幾年程式哪聽的懂,有些事呢,就是要自己受過折磨,才能深刻體會。

controller 的責任

做值的檢查

  • xxx != null
  • xxx > 0

決定走哪個 view 或 response http code,接 Error

1
2
3
4
5
6
7
8
9
10
11
12
13
create : async(req,res) => {
try{
// 略...
if(product){
return res.view("success_view");
}else{
return res.view("fail_view");
}
} catch(e){
return res.serverError(e);
}
},

呼叫 service

並只傳內容物(Object Data 或 簡單型別值) 給 service。除了一些特例,牽涉到 session、cookie、request header 特定的邏輯,但大多遇到的情況都不需要,誤用居多。

1
2
OrderService.create(req); // (X)
OrderService.create(req.order); // (O)

service 的責任

商業邏輯

(e.g. 寄信、訂單計算、與第三方平台溝通…)

1
2
3
4
5
6
7
8
getServiceFee : async(user, order) => {
let isVip = UserService.isVip(user);
if(order.paymentTotalAmount > 1000 || isVip ){
return 0; // 免運
}else{
return 70;
}
}

複雜的物件生成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
getNewUser : async(...略...) => {
let newUser = {
username: newUserParams.username || email,
email: email,
fullName: newUserParams.fullName,
gender: newUserParams.gender || 'none',
RoleId: role.id,
mobile: newUserParams.mobile,
city: newUserParams.city,
region: newUserParams.region,
zipcode: newUserParams.zipcode,
address: newUserParams.address,
privacyTermsAgree: newUserParams.privacyTermsAgree || false,
subscription: newUserParams.subscription || false,
}
return newUser;
}

與資料庫溝通

如果有 Dao 的架構的話,可以呼叫 Dao 的 method,如果沒有 Dao 的架構,那 Dao 所做的事,就可以在這裡做。

略…

這樣做的好處是什麼?

職責分明,減少重複的code

如果 controller 跟 service 都要做值的檢查,那不是重工?如果有時候把檢查放在 controller,有時候放在 service,那有沒有哪一天,根本忘了做值的檢查,所以遊戲規則要先講好。

減少重工的部分,可以看看 Clean Code 這本書,如果沒看過 Clean code,可以先看看 Kent Beck的實作模式,比較薄,而且談的東西,好像都可以馬上運用在工作中,Clean Code 有些例子真的有點太極端,即使了解了,也很難完全實行,而且看完後,你會覺得兩本書提到的理論,有會相衝突的地方很有趣。

易於測試

如果 controller 把 request 當參數傳給 service,那你 service 的測試 code,不就要寫得跟 controller 一樣?(重工) 所以只傳 Object data 跟 簡單型別值,你的測試會比較好寫。在者,並不是只有HTTP一種協定,如果現在變成接 Socket,那 service 不就不能共用。

結論

每個 Pattern 都是為了解決一些前輩的問題,而演變而成的,多多讀讀 Pattern 就可以少踩一些雷,多希望我能更早領悟這個道理。

Share 

 Previous post: SPA SEO (1) Next post: javascript var 作用域 

© 2020 alincode

Theme Typography by Makito

Proudly published with Hexo