關於

你好,我是 NSS 江口。
不久前我寫了一篇關於《穩健的 Python》的文章,這次我將從中探討依賴關係的主題。
不知不覺中 Python 已經不再是軟性語言了~穩健的 Python~

依賴關係

02.依賴圖像.png

依賴關係是指代碼運行所需的其他代碼之間的關係。
一般而言,依賴於少數組件的代碼被認為是優良的代碼;另一方面,依賴項的增加往往來自於模組的重用,這也被視為優良代碼的特徵。在這種相對立的優勢之間找到合適的平衡點是非常困難的。
SonarLint 等工具常常會進行依賴關係檢查。(有時會要求依賴關係維持在 15 個以下。)
在小規模的專案中,自己和他人可以協商以遵守依賴關係的上限,但隨著參與者的增加,達成共識變得困難,很多時候不得不放棄機械化的判定。

依賴關係的類型

依賴關係主要有物理依賴、論理依賴和時間依賴三種類型。

  • 物理依賴
    • 當 import 或繼承關係不存在時,源代碼將無法編譯(無法通過構建),比較容易掌握。
  • 論理依賴
    • 雖然在源代碼上並不存在依賴關係,例如 WebAPI,但若服務端接口發生變更(如端點變更或數據格式變更)將會影響運行,這使得掌握變得困難。
  • 時間依賴
    • 與論理依賴類似,源代碼上沒有依賴關係,但在接受服務時需要進行必要的處理(如必須在使用前調用 configure 方法等)。

所謂靜態代碼分析僅針對物理依賴進行。
其他依賴關係的機械化檢測相當困難,但在構建過程中,儘量保持友好和明確的接口是必要的。
在 WebAPI 方面遇到論理依賴關係的問題,包括以下幾點:

  • 在新增項目時,提供方可能認為只需不使用即可,但由於使用者側對 JSON 字符串進行簡單的差異檢查,結果出現了誤檢。
    {
    "code": "xxxx",
    "price": 10000
    }
    // ↓修改為如此。根據簡單字符串差異邏輯可能會出現誤檢。
    {
    "code": "xxxx",
    "price": 10000,
    "tax": 1000
    }
  • 為了減少流量,將 JSON 數據中的 "name": null 宣告中的項目刪除時發生錯誤。
  • 將無效數字從 -9999999 更改為 NaN 時發生錯誤。
  • 根據 API 規範未特別說明的記錄順序對使用者非常重要,使用者必須通過代碼值進行排序。

提供方可能會認為自己的規範並沒有偏離,但實際上存在許多隱含要求,這些要求往往是相當重要的。
作為對策,可能需要提前發布詳細的公告,或在 UAT 等過程中讓實際使用者使用。
我以前設計 WebAPI 時參考的最佳實踐書籍是:Web API: The Good Parts

說到時間依賴,我想起一些事。
以前在 Java 中進行 JDBC 連接時,需要按照以下方式進行類聲明並註冊 JDBC 驅動:

Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/test?user=xxx&password=yyy");

只有在類加載時執行靜態初始化器後,JDBC 驅動的註冊才會生效,從而獲得連接。此後,由於 SPI (Service Provider Interface) 的出現,這種聲明不再必要。
從現今的角度來看,這次變更不僅消除了時間依賴,且即使存在現有的類加載處理也能正常運行,這是一個非常好的變更。

依賴關係的可視化

論理與時間依賴的可視化可能相對困難,但我們希望能夠盡可能容易地掌握物理依賴。
因此,為此目的的工具在穩健的 Python 內有提及,這裡想介紹幾個。

套件的可視化

通過使用 pipdeptreeGraphViz,我們可以整理(可視化)套件之間的依賴關係。
首先從 https://graphviz.org/download/ 下載 GraphViz 並安裝。(因為是由 pipdeptree 執行,因此 GraphViz 的安裝目錄需添加到 PATH 中。)
接下來使用 pip 進行安裝。

pip install pipdeptree graphviz

然後執行 pipdeptree,並使用 GraphViz 生成圖像。

pipdeptree --graph-output svg --packages pydantic > deps.svg 

image.png

如果不設定 --packages,則所有套件都將作為目標。此外,還可以用 --exclude 設定排除的套件。

引入的可視化

這可能是最常使用的工具對吧?使用 pydeps 可以將源代碼中的 import 依賴關係進行可視化。
首先進行安裝。

pip install pydeps

接下來使用以下命令創建圖像文件。

pydeps --show-deps qiita_aggregator.py -T svg -o deps.svg

image.png

在這裡設定的 qiita_aggregator.py 是一個自製工具,用來統計一定期間內發表的文章的瀏覽數和讚數。雖然程式大約只有 80 行,但意外地發現它有不少依賴關係。

函數調用的可視化

與引入的可視化不同,在函數調用的可視化中,可以看到特定函數的重複使用程度。這可以通過 pyan3 進行確認。

首先是安裝。

pip install pyan3

順便提一下,在我的環境中,由於與 graphviz 的兼容性問題,在運行時出現以下錯誤。

TypeError: CallGraphVisitor.__init__() got multiple values for argument 'root'

如果出現這種情況,將 pyan3 降級可能會有所幫助。

pip install pyan3==1.1.1 

接著使用相同的文件進行運行。

pyan3 *.py --grouped --annotated --html > deps.html

image.png

以上便可以知道哪些函數被調用。
從許多函數被調用的函數,代表其影響力較強,因此在進行修正之前應該先進行單元測試等對策。

總結

我學到了有關提升 Python 可靠性的依賴關係。
尋求對於許多人而言的最佳解是非常困難的,但如果過於輕視,可能會對我們自身造成困擾,因此我希望持續追求這方面的探索。


原文出處:https://qiita.com/NSS_FS_ENG/items/1a7b7c48b36782145016


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝10   💬8   ❤️12
442
🥈
我愛JS
📝1   💬6   ❤️4
92
🥉
酷豪
📝1   ❤️1
54
#4
AppleLily
📝1   💬4   ❤️1
43
#5
💬3  
10
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次