有一天,我接觸到程式碼的壞味道(Code Smell) 時,恩!Long Method, Large Class 好像還行,滿容易理解的!下一個:Primitive Obsession ?! 這…因為對我來說太難懂,所以就寫一篇來幫助自己練習.
一個程式語言提供的最基礎程式碼型別,以 C# 來說:int, string, decimal…
我查到一個滿貼切的中文描述:念念不忘的事
那麼 Primitive Obsession ,就會是:念念不忘基礎型別!
在想什麼叫念念不忘基礎型別的時候,以過往經驗來說,寫進資料庫之前,會先換成基礎型別來做資料傳遞,既然如此,常用到基礎型別應該也是滿正常的吧?而如果用癡迷來說的話,也就是說不該用的地方也用的意思
上網查詢這個 CodeSmell 時,很常出現一個例子: URL
URL 是由樣東西構成的 :
當我們使用一個基礎型別 string 來接取 URL 的當下,我們就失去了對他裡面的元件存取的權利了.而過後如果要再存取就必需寫下些解析的程式碼,才能再把想要的元素讀取出來,不過我還是沒有很理解影響的程度會有多大.
在我過往的工作當中會遇到需要建立使用者的情境,如果開發的是一個帳號管理服務API 的話,可以想像會長這樣:
//Controller
public CreateUserResponse CreateUser (CreateUserRequest req)
{
//do something;
}
而這個創建使用者的內容通常包含有帳號密碼:
public class CreateUserRequest
{
public string username { get;set; }
public string password { get;set; }
}
乍看之下好像沒有什麼問題,但接下來就會發生一些事情
public class CreateUserRequest { public string username { get;set; } public string password { get;set; } public ErrorCode Validate() { if(username.length<10) ... if(checkAlreadyHaveUsername(username)) ... if(password.length<10) ... } }//Controller public CreateUserResponse CreateUser (CreateUserRequest req) { req.Validate(); }
//Service
public CreateUserResponse CreateUser(CreateUserRequest req)
{
if(username.length<10) ...
if(checkAlreadyHaveUsername(username)) ...
if(password.length<10) ...
因為基礎型別的關係,沒辦法有效率的得到驗證結果,但還是必須要驗證,就會開始衍生出更多的驗證管道了:Helper, ExtentionMethod, UserValidationClass…,壞味道就漸漸產生了,能想像可能還有 update-password, search-member… 等等傳入參數類似的 API 嗎?
如果再放大這個 Primitive Obsession 直接在 CreateUserRequest 裡面加,這樣也會導致 CreateUserRequest 變成一個很大的 Class, 就會面臨到,另外一個 Request 也長得差不多,但卻不能沿用,又得重新寫一次驗證了
public class CreateUserRequest{
public string username { get;set; }
public string password { get;set; }
public string contact { get;set; }
public bool isTestingUser { get;set; }
...
.
.
.