泪目~卷王已经在想怎么实现代码可视化了?

2023-10-20 19:30

本文主要是介绍泪目~卷王已经在想怎么实现代码可视化了?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文最初发布于 Alex Ellis 的个人博客。

有一天,我正在阅读关于个人电脑和桌面 GUI 发展的内容,我就想,我们都已经非常习惯个人电脑“桌面“这个类比。我们把文件放在文件夹里,并把它们放在桌面上。这个过程有很多物理动作发生。

人类非常善于理解空间,尤其是在记忆物理空间的时候,这让我联想到了我们通常如何将代码可视化。在思考和可视化代码的时候,有没有什么好的方法可以利用这一点?

如何可视化代码?

这让我想到了我往往如何可视化代码,有点难以描述。我认为,它通常以不同的方式存在于我的脑海中,这取决于抽象和特殊性水平,而且同时存在若干不同方式的组合。根据需要,我可以很好地在它们之间切换,特别是当我对代码库非常熟悉的时候。例如,当我想象各种微服务之间的交互时,在每个服务的周围画个大方框是很有帮助的,把每个服务视为一个大的工作单元,彼此之间通过 RPC 交互。

一个简单的面向微服务的汽车租赁服务架构图,以及代表一条执行路径的分布式跟踪。

另一方面,如果对于计算机如何读取我给它的东西,我想知道微末的细节,那么把所有东西放大到物理内存表示是有帮助的。

我曾经做过的一个 Google Sheets 页的截图,上面有内存地址和汇编指令。这对于非常仔细地了解整个过程很有帮助。

幸运的是,我把大部分时间都花在了中间的某个地方,在阅读实际的代码(比汇编高级),把大块的代码作为一个个大的单元来思考,和研究架构图及系统间通信之间做一些平衡。即使是代码本身也已经有了很多物理关系;想想目录路径、命名空间、行缩进以及代码行的线性排序。

这些可视化的效果如何?

对于这个问题,我考虑了一些不同的可视化技术,每一种技术都有不同的应用场景。考虑一下下面这个不完全的清单:

  • 架构图

  • 依赖图

  • 分布式跟踪

  • 序列图

  • 类图

  • 打印语句

  • 火焰图

  • 阅读源代码

怎么对它们进行比较呢?首先,似乎有一个天然的抽象等级轴线,从低级的代码阅读到高级的架构图。似乎还有一些其他的轴线,我们也可以对它们进行排序。

也许我们可以根据它们在多大程度上代表了更大的系统来对它们进行排名?架构图在这方面做得很好,但火焰图只能代表单个执行路径。也许是变化的频率?这是一个有趣的问题,虽然源代码经常变,但架构图(有望)保持稳定。

让我们想一下,可视化如何很好地表示整个系统实际的代码执行情况呢?在这种情况下,高级的架构图得分也许不会很高,因为它抽象掉了服务框内的许多细节。分布式跟踪可以做得更好,不过具体程度取决于有多少个跟踪点。类图虽然有助于可视化类之间的关系,但可能并不表示实际的路径。火焰图可以显示清晰的执行路径,但只能显示单条代码路径,而不能为更大的系统提供可见性。

画到图上可能会像下面这样,不过上面的这些点表示为一个范围可能更好:

这让我思考,右上角的部分会是什么样子。一个能让我们洞察细节的、有用的可视化该是什么样子?有没有一种方法可以在较低的层次上,将整个系统的路径可视化?

如果我们也使用空间会是什么样子?

看图的感觉仍然像看地图。在那一刻,你把在代码中看到的东西在空间上转化为图表,就像你在一个不熟悉的地方用地图确定方向。就像电脑上的东西,我们用了桌面隐喻一样,我想知道是否有另一种方式将代码可视化为实际存在的东西,以便让翻译过程变得更容易。

如果我们用“玩具型可视化(toy visualization)”在物理空间中表示代码,会怎么样?

看下面这个基本的例子,我们有一个 Counter 类,它有一个私有的 count_ 变量并提供了各种访问方法。也许它会在一个简单的 main 函数中被访问,做一些计数。

#include <iostream>class Counter {
public:void reset() {count_ = 0;}  int get() {return count_;}void incr() {++count_;}void set_count(int x) {count_ = x;}
private:int count_;
};int main() {Counter counter;counter.reset();counter.incr();counter.incr();  std::cout << counter.get();
}

复制代码

如果我们把代码的不同部分表示为三维结构,会怎么样?如果我们把 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 中)。

如果你了解到其他类似的项目,欢迎和我联系,我非常乐意听到更多这样的项目!

有趣的想象

显然,这个概念并不是什么突破性的东西,但我认为,对于我们使用的工具,这是一个有趣的思考方式,重要的是,我们如何做得更好。一定有更好的方法存在,设想下它们可能的样子会很有趣。

查看英文原文:

How do you visualize code? · Caffeinspiration

这篇关于泪目~卷王已经在想怎么实现代码可视化了?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/249262

相关文章

C++使用栈实现括号匹配的代码详解

《C++使用栈实现括号匹配的代码详解》在编程中,括号匹配是一个常见问题,尤其是在处理数学表达式、编译器解析等任务时,栈是一种非常适合处理此类问题的数据结构,能够精确地管理括号的匹配问题,本文将通过C+... 目录引言问题描述代码讲解代码解析栈的状态表示测试总结引言在编程中,括号匹配是一个常见问题,尤其是在

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

如何通过Python实现一个消息队列

《如何通过Python实现一个消息队列》这篇文章主要为大家详细介绍了如何通过Python实现一个简单的消息队列,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录如何通过 python 实现消息队列如何把 http 请求放在队列中执行1. 使用 queue.Queue 和 reque

Python如何实现PDF隐私信息检测

《Python如何实现PDF隐私信息检测》随着越来越多的个人信息以电子形式存储和传输,确保这些信息的安全至关重要,本文将介绍如何使用Python检测PDF文件中的隐私信息,需要的可以参考下... 目录项目背景技术栈代码解析功能说明运行结php果在当今,数据隐私保护变得尤为重要。随着越来越多的个人信息以电子形

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景