# Python Clean Code 概念以及淺談(1) 此文章主要講述 - **何謂 Clean Code?** - **Python 結構化、格式化、統一程式碼與該如何落實Code style規範與工具** ## 何謂Clean Code? 何謂Clean Code? 其實沒有一定的答案也沒有絕對,但Clean Code不限語言有這幾種常見特性 - **簡潔明瞭**:程式碼應該易於理解,避免不必要的複雜性。 - **可讀性**:良好的命名、適當的註解和結構化的代碼有助於其他開發者快速理解程式碼的功能。 - **可維護性**:程式碼應該易於修改和擴展,能夠適應未來的需求變更。 - **一致性**:遵循一致的編碼風格和規範,保持程式碼的一致性。 專業的軟體工程師寫程式不是寫給機器的,目的除了給機器跑能動以外還要人能看的懂才是好Code ## Clean Code重要性 可維護性和可閱讀性直接影響開發速度和專案的可行性。如果收到需求後需要花時間進行重構,並且每次收到新需求時都要重構,不僅會浪費時間,還可能導致重構的成本超過重新設計的成本。更糟的是,如果在重構過程中引發了錯誤,可能會導致服務中斷或產品無法使用。這些情況是軟體工程師最不希望遇到的。這樣的情況充分說明了 Clean Code 的重要性。 # Python結構化、格式化、統一程式碼 ## Python PEP8 Clean Code 也包含格式化與結構化,可利用官方推薦的PEP8程式撰寫標準,可設定在IDE上,在寫code時會出現hint幫助你寫出符合PEP8規範的code PEP8能帶來什麼好處? - 程式碼一致性(縮排、命名等等) - 更好除錯(基本上會建議你寫法避免如大量使用try catch) - 增加程式碼品質(結構化程式碼) > 💡pep8 https://peps.python.org/pep-0008/ ### 為何要做這件事情? 在一個專案中,撰寫風格的統一性是至關重要的。想像一下,如果一個專案有五個工程師,而每個人都有自己獨特的程式碼風格,那麼這個專案將會擁有五種不同的風格。當發送 PR 時,就會浪費時間在爭論這些主觀的風格問題(如縮排、命名規則和語法糖用法)上。由於風格問題本質上是主觀的,因此很難確定哪種風格是絕對正確的或錯誤的。統一風格可以減少這些不必要的爭論,使團隊能夠專注於更有價值的工作。 因此團隊應該擬定code style規範,在團隊上才能 - 聚焦複雜的業務邏輯 - 快速review程式碼 - 建立團隊結構化閱讀方式 > 💡如果團隊每次PR一直再爭論所謂的code style,那麼請團隊一定要花時間重新審視或擬訂規範 ## 程式碼註解 一般來說要減少寫註解,可以透過明確的命名,以及利用設計來明確歸納權責,一眼看出能清楚知道程式碼想要表達的,如果程式碼大多數都有註解我才不信這段Code會寫多好,除非是很特殊的情境 以下列舉我開發最常遇到的情境 1. **複雜的業務邏輯或算法** **情況**:當程式碼包含複雜邏輯或計算時,需要註解來解釋。 **例子** ``` python 註解:在使用者到達某區域時計算兩點間的距離 def distance(x1, y1, x2, y2): return ((x2 - x1)**2 + (y2 - y1)**2)**0.5 ``` 2. **臨時解決方案或熱修復(Hotfix)** **情況**:當需要快速修復問題時,註解可以解釋這段程式碼的臨時性。 **例子** ``` python 註解:臨時解決方案:當用戶年齡不明時預設為18 if user.get("age") is None: user["age"] = 18 ``` 3. **跨團隊協作或團隊標準** **情況**:當需要其他團隊成員或跨團隊協作時,註解可以幫助快速理解程式碼。 **例子** ```python 註解:與前端協商好的 API 返回格式,不要隨意修改 def get_user_data(user_id): return {"id": user_id, "name": "Example"} ``` ### 總結 註解是一門學問在特殊情況下再使用,而且註解也是需要被維護的,所以不要隨便亂用註解 ## Docstring Docstring 是 Python 中用來記錄程式碼功能和使用說明的字串,通常放在函數、類別或模組的開頭,用於描述這些程式碼的用途、參數、返回值等。它在撰寫文檔、自動生成 API 文檔,以及讓其他開發者理解程式碼時特別有用。 python使用方式 ``` python def add(a, b): """ 將兩個數字相加並返回結果。 參數: a (int): 第一個加數。 b (int): 第二個加數。 返回: int: 兩個數字的和。 """ return a + b ``` 當這段程式碼執行時會透過 __doc__ 是 Python 中的一個特殊屬性,用來存取函數、類別或模組的 docstring。這個屬性可以讓你在程式碼執行時動態地查看或操作文檔字串。每當你為函數、類別或模組編寫 docstring 時,Python 會將這些字串儲存在 __doc__ 屬性中。 > 💡Docstring通常要看專案性質,畢竟需要人力維護,如果沒有實質商業需要或人力請不要做這件事情,對團隊又是另一種負擔 > 💡Docstring與程式碼註解差異 兩者在於程式碼註解是說明程式原因(為何),而Docstring是解釋程式(如何) ## Annotations 註解(Annotations) 是一種用來添加元數據到函數參數和返回值的機制。這些註解通常用於提供額外的資訊或對函數的參數和返回值進行類型提示。Python 的註解機制讓你可以在函數定義中使用 : 來指定參數的類型,以及使用 -> 來指定函數的返回類型。 ``` python def add(a: int, b: int) -> int: """ 計算兩個整數的和。 參數: a (int): 第一個數字。 b (int): 第二個數字。 返回: int: 兩個數字的和。 """ return a + b ``` 如果有碰過fastapi的人應該最熟悉pydantic來做 Annotations ``` python from fastapi import FastAPI from pydantic import BaseModel class Item(BaseModel): name: str description: str | None = None price: float tax: float | None = None class Response(BaseModel): result list[Item] app = FastAPI() @app.post("/items/", response_model= Response) async def create_item(item: Item) -> Response: get_result = create(item=item) return get_result ``` 而Annotations有些地方可能要注意 - 非強制性:Python 的註解不會強制檢查類型。它們僅提供提示,實際的類型檢查需要工具或手動檢查。 - 靜態分析工具依賴:要充分利用類型提示功能,通常需要額外的工具或 IDE 支持。(靜態工具 mypy、PyLint、pytype等等) ### 關於Annotations個人看法 在 PEP-484 中,作者提到 Python 仍然是一種動態語言,並不希望類型提示成為強制性要求。這段話的目的是為了保持語言的彈性。早期在 Python 2 和 Python 3 剛推出時,許多套件沒有使用註解(Annotations),這不會影響程式碼的維護性和可讀性。只要設計職責明確、命名清晰,再搭配 Docstring,其實也能夠很好地表達程式碼的意圖。 然而,個人比較支持使用註解(Annotations),如果有需求或人力支持,可以與 Docstring 配合使用。註解對於指定參數類型和返回值類型非常方便,而對於異常情況無法使用註解表示的部分,可以用 Docstring 進行說明。結合良好的命名和清晰的職責設計,基本上能夠充分理解程式碼的功能。 ## 該如何落實Code style規範與工具 ### 工具 - **靜態分析工具**: - **mypy**:提供靜態類型檢查,幫助檢查類型錯誤。 - **PyLint**:檢查代碼質量,標準化代碼風格,發現潛在的錯誤。 - **Flake8**:結合了多種檢查工具,檢查代碼風格、錯誤和複雜性。 - **Bandit**:檢查代碼中的安全漏洞。 - **自動化測試**:使用測試框架如 `unittest` 或 `pytest` 來編寫和運行測試,確保代碼的正確性。 ### CI與落實方法 為了強制執行程式碼風格規範,可以通過工具和 CI 流程來實現。例如,可以使用 pre-commit 來檢查代碼風格,或者在雲服務的 CI 流程中加入檢查,以確保在發 PR 時會執行 Code style 規範檢查。這些自動化工具有助於確保程式碼符合規範。 然而,需要與團隊進行溝通,以確保所有成員都遵循這些檢查流程。通常,有些人可能會因為懶惰而跳過檢查,或者因為加快發布速度而省略這些步驟。因此,實施這些流程時應避免過於嚴格,應確保團隊達成共識,以便長期有效地維持規範。
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up