你好,我是 NSS 江口。
不久前我寫了一篇關於《穩健的 Python》的文章,這次我將從中探討依賴關係的主題。
不知不覺中 Python 已經不再是軟性語言了~穩健的 Python~
依賴關係是指代碼運行所需的其他代碼之間的關係。
一般而言,依賴於少數組件的代碼被認為是優良的代碼;另一方面,依賴項的增加往往來自於模組的重用,這也被視為優良代碼的特徵。在這種相對立的優勢之間找到合適的平衡點是非常困難的。
SonarLint 等工具常常會進行依賴關係檢查。(有時會要求依賴關係維持在 15 個以下。)
在小規模的專案中,自己和他人可以協商以遵守依賴關係的上限,但隨著參與者的增加,達成共識變得困難,很多時候不得不放棄機械化的判定。
依賴關係主要有物理依賴、論理依賴和時間依賴三種類型。
所謂靜態代碼分析僅針對物理依賴進行。
其他依賴關係的機械化檢測相當困難,但在構建過程中,儘量保持友好和明確的接口是必要的。
在 WebAPI 方面遇到論理依賴關係的問題,包括以下幾點:
{
"code": "xxxx",
"price": 10000
}
// ↓修改為如此。根據簡單字符串差異邏輯可能會出現誤檢。
{
"code": "xxxx",
"price": 10000,
"tax": 1000
}
"name": null
宣告中的項目刪除時發生錯誤。-9999999
更改為 NaN
時發生錯誤。提供方可能會認為自己的規範並沒有偏離,但實際上存在許多隱含要求,這些要求往往是相當重要的。
作為對策,可能需要提前發布詳細的公告,或在 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 內有提及,這裡想介紹幾個。
通過使用 pipdeptree
和 GraphViz
,我們可以整理(可視化)套件之間的依賴關係。
首先從 https://graphviz.org/download/ 下載 GraphViz
並安裝。(因為是由 pipdeptree 執行,因此 GraphViz
的安裝目錄需添加到 PATH
中。)
接下來使用 pip
進行安裝。
pip install pipdeptree graphviz
然後執行 pipdeptree
,並使用 GraphViz
生成圖像。
pipdeptree --graph-output svg --packages pydantic > deps.svg
如果不設定 --packages
,則所有套件都將作為目標。此外,還可以用 --exclude
設定排除的套件。
這可能是最常使用的工具對吧?使用 pydeps
可以將源代碼中的 import 依賴關係進行可視化。
首先進行安裝。
pip install pydeps
接下來使用以下命令創建圖像文件。
pydeps --show-deps qiita_aggregator.py -T svg -o deps.svg
在這裡設定的 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
以上便可以知道哪些函數被調用。
從許多函數被調用的函數,代表其影響力較強,因此在進行修正之前應該先進行單元測試等對策。
我學到了有關提升 Python 可靠性的依賴關係。
尋求對於許多人而言的最佳解是非常困難的,但如果過於輕視,可能會對我們自身造成困擾,因此我希望持續追求這方面的探索。
原文出處:https://qiita.com/NSS_FS_ENG/items/1a7b7c48b36782145016