天天看點

如何将你的代碼可視化?

作者 | Alex Ellis

譯者 | 平川

策劃 | 闫園園

本文最初釋出于 Alex Ellis 的個人部落格。

有一天,我正在閱讀關于個人電腦和桌面 GUI 發展的内容,我就想,我們都已經非常習慣個人電腦“桌面“這個類比。我們把檔案放在檔案夾裡,并把它們放在桌面上。這個過程有很多實體動作發生。

人類非常善于了解空間,尤其是在記憶實體空間的時候,這讓我聯想到了我們通常如何将代碼可視化。在思考和可視化代碼的時候,有沒有什麼好的方法可以利用這一點?

如何可視化代碼?

這讓我想到了我往往如何可視化代碼,有點難以描述。我認為,它通常以不同的方式存在于我的腦海中,這取決于抽象和特殊性水準,而且同時存在若幹不同方式的組合。根據需要,我可以很好地在它們之間切換,特别是當我對代碼庫非常熟悉的時候。例如,當我想象各種微服務之間的互動時,在每個服務的周圍畫個大方框是很有幫助的,把每個服務視為一個大的工作單元,彼此之間通過 RPC 互動。

如何将你的代碼可視化?

一個簡單的面向微服務的汽車租賃服務架構圖,以及代表一條執行路徑的分布式跟蹤。

另一方面,如果對于計算機如何讀取我給它的東西,我想知道微末的細節,那麼把所有東西放大到實體記憶體表示是有幫助的。

我曾經做過的一個 Google Sheets 頁的截圖,上面有記憶體位址和彙編指令。這對于非常仔細地了解整個過程很有幫助。

如何将你的代碼可視化?

幸運的是,我把大部分時間都花在了中間的某個地方,在閱讀實際的代碼(比彙編進階),把大塊的代碼作為一個個大的單元來思考,和研究架構圖及系統間通信之間做一些平衡。即使是代碼本身也已經有了很多實體關系;想想目錄路徑、命名空間、行縮進以及代碼行的線性排序。

這些可視化的效果如何?

對于這個問題,我考慮了一些不同的可視化技術,每一種技術都有不同的應用場景。考慮一下下面這個不完全的清單:

架構圖

依賴圖

分布式跟蹤

序列圖

類圖

列印語句

火焰圖

閱讀源代碼

怎麼對它們進行比較呢?首先,似乎有一個天然的抽象等級軸線,從低級的代碼閱讀到進階的架構圖。似乎還有一些其他的軸線,我們也可以對它們進行排序。

也許我們可以根據它們在多大程度上代表了更大的系統來對它們進行排名?架構圖在這方面做得很好,但火焰圖隻能代表單個執行路徑。也許是變化的頻率?這是一個有趣的問題,雖然源代碼經常變,但架構圖(有望)保持穩定。

讓我們想一下,可視化如何很好地表示整個系統實際的代碼執行情況呢?在這種情況下,進階的架構圖得分也許不會很高,因為它抽象掉了服務框内的許多細節。分布式跟蹤可以做得更好,不過具體程度取決于有多少個跟蹤點。類圖雖然有助于可視化類之間的關系,但可能并不表示實際的路徑。火焰圖可以顯示清晰的執行路徑,但隻能顯示單條代碼路徑,而不能為更大的系統提供可見性。

畫到圖上可能會像下面這樣,不過上面的這些點表示為一個範圍可能更好:

如何将你的代碼可視化?

這讓我思考,右上角的部分會是什麼樣子。一個能讓我們洞察細節的、有用的可視化該是什麼樣子?有沒有一種方法可以在較低的層次上,将整個系統的路徑可視化?

如果我們也使用空間會是什麼樣子?

看圖的感覺仍然像看地圖。在那一刻,你把在代碼中看到的東西在空間上轉化為圖表,就像你在一個不熟悉的地方用地圖确定方向。就像電腦上的東西,我們用了桌面隐喻一樣,我想知道是否有另一種方式将代碼可視化為實際存在的東西,以便讓翻譯過程變得更容易。

如果我們用“玩具型可視化(toy visualization)”在實體空間中表示代碼,會怎麼樣?

看下面這個基本的例子,我們有一個 Counter 類,它有一個私有的 count_ 變量并提供了各種通路方法。也許它會在一個簡單的 main 函數中被通路,做一些計數。

如果我們把代碼的不同部分表示為三維結構,會怎麼樣?如果我們把 Counter 類表示為一個大房間,牆上寫着咒語,會怎麼樣?你可以想象代碼的可能路徑,變量和它們所代表的事物之間的聯系,就像下圖中的粉紅線:

如何将你的代碼可視化?

我們可以從中看到什麼?首先,作為私有變量,count_ 的用法顯然沒有什麼不當,因為沒有任何粉紅線從它那裡離開房間。公共方法也很清楚,它們與房間外的事物有粉紅色的連接配接。

更有趣的是,這個房間與另一個房間相連,會是什麼樣子?main 函數可以是另一個房間,其符咒線也做了相應的連接配接:

如何将你的代碼可視化?

現在,我們可以跨房間對話了;在 main 函數調用 counter.reset() 的地方,我們可以有一個從調用者 main 到被調用者 Counter 類的連接配接。你甚至可以想象有一個調試器單步周遊這個過程,觀察這條線路上的參數和傳回值。想象一下,我們可以放大不同的區域來檢視本地狀态和數值,然後沿着調用路徑傳回到活動區域。

這有用嗎?

像這樣的東西有用嗎?我不确定。用這樣的方式走查一個熟悉的代碼庫會很有趣,特别是當你能在 3D 表示(或是 VR 環境)中做空間探索,并可以根據需要縮小和放大時。當第一次探索一個新的代碼庫,檢視事物之間的連接配接關系時,不知道它是否會特别有用。不過,我确實處理過一些代碼庫,如果這樣看會非常吓人。我很想看看這樣看會有什麼不同,每新引入一個類,這兒那兒就會引入新的連接配接。

話雖如此,我認為在制作這樣的東西時,你至少會遇到以下問題:

複雜的代碼很難推理。把意大利面代碼中的意大利面可視化可謂大快人心,但是對于非常複雜的代碼來說,這樣做不知道會有多繁瑣?

如何表示出像線程同時執行這樣的東西?

如何表示是引用傳遞而不是值傳遞?

如何表示異步工作?如何表示遞歸?房間一直嵌套下去?

如何防止裡面的東西變得陳舊和過時?至少,這個需要能夠自動生成。

問題

有幾個考量因素使這個問題變得棘手。一個是實體位置的變化比代碼的變化耗時通常長得多。使用熟悉的實體位置作為記憶宮殿,一部分原因是它在你的記憶中每次出現都是一樣的。如果你在記憶一副撲克牌,你可以把梅花 A 暫時存放在櫥櫃門後面,下次你需要存放撲克牌時,櫥櫃門仍然在那。

如果你的代碼庫經常變化,反映事物空間布局的地圖就可能會發生變化,不管這些地圖是 3D 生成的還是純意識的。這就像回到一個你曾經熟悉的地方,想象一下,不隻是地标變了,路也改道了。即使我們天生具有記憶空間事物的天賦,如果那個空間發生了變化,如果我們不得不重新學習,我們還能從空間可視化受益嗎?

看看這樣的東西對于探索一個新代碼庫(就像使用地圖探索一座新的城市),以及随着時間推移再次回到該代碼庫(就像離開很長時間後回到自己的家鄉),有多大幫助,這會很有趣。

代碼可視化項目

我對這一領域的資料可視化不是很熟悉(其他領域的也不熟悉),但經過簡單的搜尋(也就是 30 分鐘的 Google 搜尋),我發現有幾個項目似乎在做類似的事情:

SoftVis3D:其中的“代碼城市”視圖提供了項目層次結構的可視化。

Code Park:一款新的 3D 代碼可視化工具(2017),“在類似三維遊戲的環境中可視化代碼庫”,其中,代碼被表示為 "代碼室",代碼在牆上(現在讀到這個,感覺和我的想法非常類似)。

使用 3D-Flythrough 實作代碼結構可視化(2016),提供空間隐喻和第一人稱代碼探索。

Primitive:一家 VR 合作初創公司,擁有矩陣式的“沉浸式開發環境”,包括“面向 3D 視覺分析軟體的新工具”。

下面是讀者指出的一些項目:

AppMap:一個自動化代碼分析工具,包括依賴關系圖和跟蹤視圖。

plurid:一個用于在三維可探索結構中可視化和調試代碼的架構。

fsn(檔案管理器):一個實驗性的應用程式,支援以 3D 方式檢視檔案系統(出現在 Jurassic Park 中)。

如果你了解到其他類似的項目,歡迎和我聯系,我非常樂意聽到更多這樣的項目!

有趣的想象

顯然,這個概念并不是什麼突破性的東西,但我認為,對于我們使用的工具,這是一個有趣的思考方式,重要的是,我們如何做得更好。一定有更好的方法存在,設想下它們可能的樣子會很有趣。

檢視英文原文:

https://alexanderell.is/posts/visualizing-code/?

繼續閱讀