The other day I was reading about the development of personal computers and the desktop GUI, and I was thinking about how comfortable we all have become with the analogy of the “desktop” for our personal computers. We place files in folders and keep them on our desktops. There’s a lot of physical action going on.
Humans are very good at understanding spaces, especially when it comes to remembering physical spaces, and it got me thinking about how we commonly visualize code. Is there any good way to tap into that when thinking about and visualizing code?
Featured Content Ads
add advertising hereHow do you visualize code?
This made me think about how I tend to visualize code, and it’s a little hard to describe. I think it usually lives in my head in a variety of ways, depending on the level of abstraction and specificity, and there’s some combination of all of them there at the same time. Depending on the need, I can jump between them pretty well, especially if I’m very familiar with the codebase.
For example, when I’m imagining the interactions between various microservices, it’s helpful to draw big boxes around each service, treating each one like a big unit of work with RPC interactions in between.
Featured Content Ads
add advertising hereOn the other end of the spectrum, if I’m worried about the minuscule specifics of how the computer is reading what I’ve given it, it’s helpful to zoom all the way in to a representation of the physical memory.
Luckily I spend most of my time somewhere in the middle, with some balance between reading the actual code (luckily higher level than assembly), thinking about chunks of code as large units, and working with architecture diagrams and inter-system communication. Even code on its own has a lot of physical relationships already built in; think of directory paths, namespaces, line indentation, and the linear ordering of lines of code,
Featured Content Ads
add advertising hereHow well do these visualizations do?
Thinking about this made me consider a few different visualization techniques, each of which is useful in different circumstances. Consider the following incomplete list:
- Architecture diagrams
- Dependency graphs
- Distributed traces
- Sequence diagrams
- Class diagrams
- Print statements
- Flame graphs
- Reading the source code
How would we compare these? First, there seems to be a natural axis of abstractness, ranging from low level code reading to high level architecture diagrams. There seem to be a few other axes we could order them on as well.
Maybe we could rank them on how well they represent the larger system? Architecture diagrams would do well there, but a flame graph would only represent a single execution path. Maybe frequency of change? That would be an interesting one, with architecture diagrams (hopefully) staying pretty static as the source code changes frequently.
What if we thought about how well the visualization represents the actual code execution through the system? In this case, maybe a high level architecture diagram wouldn’t score very high, as it would abstract away many of the details inside the service boxes. Distributed tracing could do better, though the level of specificity would depend on the number of tracepoints you have. Class diagrams, while helpful for visualizing the relationship between classes, may not represent the actual paths taken through. Flame graphs would show a clear execution path, but again they would only show a single code path without giving visibility to the larger system.
Graphing these might look something like the following, (though each of these dots may be better represented as a range):
Link to a larger version of the graph
This made me think about what that upper right section would be like. What would a helpful visualization look like that provided clear insight into the details? Is there a way to visualize the path through the larger system while staying at a low level?
What would it look like if we tried to use space as well?
Looking at a diagram still feels like reading a map. There’s that moment of spatially translating what you see in the code to the diagram, much like you’d orient yourself with a map in an unfamiliar area. Like the desktop metaphor for things on our computers, I wonder if there’s another way to visualize code as things that exist in the world to make the translation easier.
What if we had a toy visualization where we represented code in physical space?
Let’s say we have the following basic example, where we have a Counter
class that keeps track of a private count_
variable and allows various access methods. Maybe it’s accessed in a simple main
function to do some counting.
#include
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
NOW WITH OVER +8500 USERS. people can Join Knowasiak for free. Sign up on Knowasiak.com
Read More