Python寫業務邏輯的幾個編碼原則

作為一個寫業務邏輯的boy,我需要專註的就是把業務邏輯寫好。寫業務邏輯並不複雜,就是把編程最基礎的東西使用好,有變數循環流程式控制制函數資料庫等。
但是寫出的邏輯要通俗易懂、易於理解,避免炫技、晦澀。在目前團隊中待了一段時間了,根據 code review 和自己的理解整理出一些基本原則。

業務程式碼思想原則

第一:程式碼要足夠容易閱讀。

程式碼是給程式設計師閱讀的,首先要做到的就是邏輯清晰,易於閱讀。所以要避免毫無意義的變數名、嵌套過多的邏輯判斷、過於複雜的流程式控制制。在易讀性和性能兩者之間,首先要保證易讀性,當然兩者並不衝突。

第二:程式碼性能要有保證

python程式碼的執行速度比不上編譯性語言,所以要在程式碼層面上保證性能的可靠。通常解決一個主要降低性能的點,就能提升整體的性能。

業務程式碼編碼原則

變數

核心思想:清晰表示變數的功能
原則

  1. 變數命名統一,python推薦使用下劃線分隔命名法,即蛇形命名法,畢竟python就是蛇嘛。真實原因:Python 為什麼要推薦蛇形命名法
  2. 變數命名中可以帶數據類型,如 buy_user_listid_to_name_dict 。python的靈活性高,為了更加方便區分變數、函數、方法等,變數名加數據類型是個好方法
  3. 超過三個的常量都要用枚舉值。善用枚舉值,讓枚舉值的名字解釋常量,這是遵守第一條原則,容易閱讀
  4. 多使用局部變數少使用全局變數,命名空間中局部變數優先搜索

流程式控制制

核心思想:減少if else嵌套,邏輯越清晰越好
原則
減少if else

  1. 可以使用字典的key value特性,直接用key命中條件,避免if判斷。
  2. 使用裝飾器裝飾函數,裝飾器實現里用字典特性做if else判斷。可參考:如何簡化大量的 if…elif…else 程式碼?
  3. 用in操作替換if else判斷。
  4. 使用any 或 all 將多個判斷一起處理,減少if else的分支

無法減少if else時要讓邏輯清晰

  1. 存在複雜的判斷條件時,可以先將判斷條件處理一遍。如一個判斷(a and b) or (c and d)操作時,先單獨判斷出 a and b 和 c and d,然後再判斷兩者結果
  2. 減少if else之間的處理流程。if或else中處理的流程過長時要盡量簡化流程處理,抽象出函數。讓if else對齊,處理的邏輯看起來清晰。
  3. if條件的短路特性。if a or b 這種判斷中,如果a是True就不會判斷b,所以將True條件寫在前面可以節省判斷時間

簡單小例子:使用 all 減少 if else


have_opencourse = True if plan_id in [1,2] else False

user_info = bayuser.get_user_info(user_id)
register_time = pendulum.parse(user_info.created_at)
register_at_today = True if register_time.date() == get_local_today() else False

checkin_days = uc.get_user_checkin_days(user_id)
checkin_zero_day = True if checkin_days == 0 else False

ab_test_id = 414
ab_test_name = words_utils.get_user_plan(user_id, ab_test_id).user_plan
no_provide = True if ab_test_name == "no_provide" else False

# 使用if else判斷
if register_time.date() == get_local_today() and checkin_days == 0 and ab_test_name == "no_provide" and plan_id in [1,2]:
    return encoder.json_response(code=200)
    
# 使用all判斷
if all([have_opencourse, register_at_today, checkin_zero_day, no_provide]):
    return encoder.json_response(code=200)

循環

核心思想:減少for循環
原則

  1. 用for循環代替while循環,for循環比while循環快
  2. 使用隱式for循環代替顯式for循環。如sum,map,filter,reduce等都是隱式for循環
  3. 盡量不要打斷循環。打斷循環的放在外面。有判斷條件的語句和與循環不相關的操作語句盡量放在for外面
  4. 應當將最長的循環放在最內層,最短的循環放在最外層,以減少CPU跨切循環層的次數
  5. for循環和集合都可以處理的選擇集合解決,集合的效率遠高於循環

簡單小例子:集合替代for循環

# for循環
for user in pay_user_cet4_set:
    if user not in all_presale_user_set:
        cet4_push.append(user)

# 集合操作
cet4_push = pay_user_cet4_set - all_presale_user_set

函數

核心思想:功能單一,短小精悍
原則

  1. 函數設計要盡量短小,嵌套層次不宜過深
  2. 一個函數只做一件事,盡量保證函數語句粒度的一致性。
  3. 函數申明應該做到合理,簡單,易於使用。函數名合理,參數不宜過多。
  4. 函數參數設計應該考慮向下兼容。通過添加默認參數來實現。

小結

之前分享過一本如何優雅寫python的書,可以看之前寫的一篇文章:
改善python程式的91個建議

在每一個開發團隊都有會團隊的程式碼風格。優秀的程式碼風格讓團隊中龐大的程式碼井井有條,處處有規律可循,就像是一個人完成的。每一個人也要有自己的程式碼原則,缺少基本原則的指導會讓程式碼看起來不和諧,前後矛盾,這樣肯定是不利於個人成長的。

本文提到的原則並見得全部正確,只是我個人在實際工作中的真實總結,絕不是閉門造車,僅供參考,歡迎交流。後續總結的原則也會繼續更新到這裡。