關閉
0
0 件商品
總計NT$ 0
前往結帳
會員登入
驗證碼
忘記密碼?
建立專屬帳號

CodeSmell - Primitive Obsession

描述

程式碼的好壞在於能不能解決問題跟夠不夠容易理解

有一天,我接觸到程式碼的壞味道(Code Smell) 時,恩!Long Method, Large Class 好像還行,滿容易理解的!下一個:Primitive Obsession ?! 這…因為對我來說太難懂,所以就寫一篇來幫助自己練習.

Primitive Type 基礎型別

一個程式語言提供的最基礎程式碼型別,以 C# 來說:int, string, decimal…

Obsession 痴迷

我查到一個滿貼切的中文描述:念念不忘的事

那麼 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; }
}

乍看之下好像沒有什麼問題,但接下來就會發生一些事情

username:

  1. 可能需要做驗證使用者帳號格式
  2. 可能需要驗證是否重名

password:

  1. 可能需要做密碼的驗證
  2. 針對密碼會需要做加密
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();
}

Request 傳送到 Service 後,可能不知驗證過的的情況下

//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; }
...

有沒有什麼比較好的解決方法呢?

.

.

.

閱讀更多

 

文章引用自 https://hwchw.medium.com/