89 comments

[ 3.0 ms ] story [ 202 ms ] thread
I know it's filesystems and not code, but the SGI Irix "fsn" file system navigator, featured in Jurassic Park, seems worth mentioning:

https://en.wikipedia.org/wiki/Fsn_(file_manager)

It's in the OP
It is now. It was not when I posted the comment. The last bullet point there was "Primitive", so the author has added a few.
Whoops sorry about that, added a note to make it clearer. Thanks for the suggestion!
For run-time visualization, I use Chrome about://tracing it gives very good details, over a time horizon, synchronized over multilple threads/processes. Zoom into nanosecond detail or zoom out over seconds or minutes overview.

I have my own simple C++ code to generate those traces (json data), there is also an official sdk for it (Perfetto is the new shiny way)

For static code analysis, I use Doxygen, it parses the headers, can make high level module diagrams and fine grained dependency graphs. It uses Graphviz/dot for rendering the graphs.

Quite interesting application of tracing tools, I've only used it for build time optimizations. Do you perhaps have a screenshot to see how the end result would look like ?
Here is a quick video, where you can see all the frames when zoomed out, and detailed frame information when zoomed in https://www.youtube.com/watch?v=w2rz36aJUS4 This is just for a physics engine, with rendering. See also this page by Aras (formerly form Unity 3D) with his screen shots: https://aras-p.info/blog/2017/01/23/Chrome-Tracing-as-Profil...
Thanks for the effort of creating the video. It looks like it would be useful in a similar sense perf flamegraphs are.
For TypeScript I created a visualization of function calls - a function call graph:

https://github.com/whyboris/TypeScript-Call-Graph

this looks interesting, at my work we have a sdk wrote in typescript and im intrested to see how it looks
Awesome thank you. I am an old man trying to get into software engineering and think in graphs. This is perfect.
For me, Pascal is a pretty good 2d map as software experience. Begin/End pairs along with indenting 2 spaces each time make it easy to understand and provide landmarks that are easy to spot. I imagine this is true for most languages.

The only thing better would be if I could compile it to an abstract syntax tree I could manipulate, change the name of a routine, etc... then reverse back to updated code.

I think it's madness that we don't work like this. We would greatly increase productivity. Unfortunately, like most new ideas, few people see the potential.
Creating good software visualization tools is damned difficult, that's why most platform developers don't even try to do it. Most programming tools limit themselves to text parsing and tree-building, because tree structures are the simplest to build and layout programmatically.()

There is also a certain scorn for visual languages, because there are hardly any good general purpose languages and there are few developers specializing in the areas where specific ones are most useful. So visualization tools are often confused with them and derided for it.

However, when a good visual tool for programming it is universally adopted, and like what happens with the AI paradox, no longer considered a visual tool (see syntax highlighting, "intellisense" autocomplete, inspect expressions at debugging, file minimaps and function trees...)

() There are some excellent visual tools for software inspection, but they tend to be proprietary and/or tied to a single language or having their own IDE (e.g. see Sourcetrail), so they can't be easily generalized or integrated with other standard development tools, so they get limited usage.

https://www.sourcetrail.com/

As a fractal mental miasma of equations. Doesn't everyone?

https://www.youtube.com/watch?v=GIKfEAF2Yhw&t=30s

(comment deleted)
That's the same way I count cards. https://youtu.be/DeazgPwP3D0?t=41
In all seriousness, I do have a gripe with folks not allowing for artistic license in representing a specialized, trained thought process as a 2D visual artifact.

If the actual process couldn't be understood by & isn't relevant to 90% of the viewers, why is accuracy the goal? Instead of summarization and communication?

I look at representations of underlying systems all day, that aren't accurate to the underlying mechanics. But they're useful!

The representation is semi-based on reality as some people with extremely good visual imaginations do use them as scratch space for equations in a way that looks kind of like the "numbers in the air" metaphor, except that the numbers are in their imaginations, not hallucinated in front of them.

It is not very common among scientists, but I am willing to bet that a lot of people who end up in the visual arts (i.e. who put these scenes in movies) experienced math in a way that matches the visual metaphor when they were in school.

This visual imaginations comment reminded me of Dr. Temple Grandin, who who written books about her own visual imagination https://en.wikipedia.org/wiki/Thinking_in_Pictures

I think my own mind is visual. I can prototype physical inventions in my head. Ex: Once, given a need for a tool that I didn't have, I considered the parts I had on hand, and recreated the tool using spare parts. The time from realizing the need for the tool, to having a working replacement was a few minutes.

When I code, before I start planing on paper, I can see the various functions that I need to write or algorithms that I'll have to use.

There's also all kinds of probabilistic visualizations, which is maybe a third axis in that diagram. (I.e. call coverage, sampling profilers, various o11y approaches)

Research example: http://www.ijstr.org/final-print/apr2020/A-Hybrid-Weighted-P...

I think that will be an important field especially for software running at a large scale - because it allows to get a better understanding of large systems. It's also a loss of fidelity that has strong implications for individual interactions.

(And yes, I know o11y is already a large tool there. I'm just thinking we've merely scratched the surface of probabilistic views)

I don't really visualize 'code' so much as I visualize data structures as arrangements of rectangular blocks of memory and arrows pointing to them. I find that once I understand how the data is supposed to move and transform, the code almost seems to write itself.
I still support a full stack web app that I wrote for a client 10 years ago.

Whenever I revisit a section of code that I haven't looked at since then, I always have to re-learn the code's logical structure and function. I'm sure most developers have experienced this.

I wonder if, 10 years ago, I were to have routinely viewed my code in a visual manner like in the article, would today's relearning process take less time and frustration.

Sort of like when you revisit an old beloved vacation spot. Even though those memories have aged, the layout of the spot is relatively the same. You quickly remember where things are located.

I also wonder what value a code visualization like this would have for a new developer working with the code.

Oh, UML. That thing I learned formally in college and then never once used in professional practice. :)
you might not love, but not to mention it's weird to say the least, after all UML was a way to visualize code and its abstractions.

it could be said that it is another symptom of our field of study: things are forgotten very quickly.

Plenty of love for UML :)

That's a good point that I omitted it. I was more thinking about things as the individual diagrams/views into the system (e.g. class diagrams, structure diagrams, sequence diagrams), and to me, UML seems more of a general superset collection of those individual views (and, importantly, agreement on what they are). While it contains many of the visualizations I mention, the visualizations themselves are more interesting to me than the general modeling language.

My list is definitely incomplete!

For my purposes (embedded), UML statecharts are as good as any other way to do statecharts, and sequence diagrams are occasionally useful. The 10,000 foot view you started off with of big program blocks, also, especially to just draw out the processes in a system.

The complementary question, though, is how do you visualize data when coding? Some debuggers have features for visualizing data structures, time-series data, etc but there is plenty of room for improvement.

Slightly tangential: This is how I visualise how the behaviour of the QR algorithm varies over all possible PSD matrices: https://en.wikipedia.org/wiki/QR_algorithm#Visualization

In this case, it's less important to understand the convoluted structure of some code, than to understand how a simple but opaque algorithm behaves in general.

In 'Why we talk' (https://www.amazon.com/Why-We-Talk-Evolutionary-Evolution/dp...) Dessalles arguments that we have two modes of talking - the first one is visual and probabilistic, the second one is topological - that is concerned about zero one questions - like if something is inside or outside of something. The first one is about imagining situations and judging their salience (or improbability). The second is about argumenting - simplifying the information so that you can 'proove' stuff. The point is that visuals are too rich and there can be too many ways to imagine things - so it is hard to convince someone that a particular scene is wrong or right. When you simplify things to the topological level of question if something is inside something or outside - then you can use inference to arrive at some logical conclusions, with steps so obvious that it is hard to argument against them.

Programming is mostly about logic - that is why it is hard to visualise. I think this is the problem with 'visual programming languages' (like https://enso.org/ - which, disclosure, is in my investmet porfolio) - and also here. This is kind of surprising - because we naturally expect the visuals to be as rich as the logic. But we need to carefully think about what is complementary here.

"Programming is mostly about logic - that is why it is hard to visualise"

Maybe I understood it wrong, but I do not see that logic ...

Rather the opposite, since programming is about very strict defined logic - it is possible to visualize it very clearly. The various UML diagramms for example can do a good job with that.

The hard part, is to make tools, that generate the diagrams for you in a meaningful way automatically. Because generating them by hand, by dragging and clicking around somewhat works, but is apparently way less efficient than just writing the code. (and doing both is just double work)

The UML diagrams are a good example of the problem I am talking about: they carry too much (unessential) information - you can draw the boxes in too many ways.
Hm, I am still not sure I understand your point:

I mean the UML spec as its whole is quite a mess, sure, which is why it is not so relevant anymore. But very specific defined UML diagramms, like UML class diagramms - carry just the essential information for me. Like class name, member names with types and connections showing me where this class interfaces or inherits from. I really liked that and preferred it much over the same information in code representation.

But doing it by hand was just not worth it for me.

Diagrams are visual and need many more bites than the code they are created from. Just compare a gif of a diagram and its description. The additional information is how the boxes look - are they big or small, colors, what font is used, what margins are there, and many more. Describing it I use text and divide the differences into categories - but maybe I should just write that for the visuals you need information for each pixel.

When you interpret the diagrams you map them into a much smaller space of meanings. In that process you throw out a lot of that visual information.

> Diagrams are visual and need many more bites than the code they are created from.

Only if you store them inefficiently.

> Just compare a gif of a diagram and its description.

A bitmap image (GIF or otherwise) is an inefficient way to store a diagram. For a purely semantic diagram, the source it represents minus anything not actually represented in the diagram is sufficient; if you have additional presentational information you need that, too. For a diagram-specific format, something like graphviz or mermaid source is a possible representation.

What you are saying is that UML is not really visual but rather a kind of text. This got me thinking. The text I am writing here is also on one level just text - but I see it as a visual representation of black dots on a white background. But I think the point of diagrams is to be really visual and of text to be text.
Ah, now I understand what you mean. It is certainly true, that there is additional information in a diagram.

But - most of that information is just visual help to transport the raw information - to enable you to decode the information (which is what this is all about, as decoding code is mental work).

The x y position of a uml class diagram for example, is irrelevant in terms of raw data, but it makes a difference to the brain, of whether one diagram is centered or in some corner. Likewise all the other information, like color etc.

They are simply there to help you understand the main information. So I do not think they carry unessential information. If the color of a diagram helps get the information across - meaning it makes it easier for the reader to understand the main information - than that information might be not essential, but still important. Whether that works, depends of course on the diagrams and tools and how they get used. Again, this is the hard part.

In my experience, generating documentation from code is a fools errand (unless it's API documentation). The key (and hard part) to documenting existing code is to understand which details emphasize and which ones can be left out. I read documentation in order to more quickly understand a software component than I would by just reading it's code.
(comment deleted)
> This made me think about how I tend to visualize code, and it’s a little hard to describe.

This tells me someone is good at imagining castles in the air and that they have difficulty describing their vision. I can't even tell if the castle is stable, shimmering, changing color or shape.

There is an analogy to at least some forms of meditation here: the vision is a distraction to suffer through (however pleasant the suffering) to return to the practice.

I recommend working on the problem and being able to articulate and understand the problem. Two people could see and enumerate a castle and a bridge (and little else) and agree on this vision. Then one could propose burning it down, while the other would propose a trebuchet or breaching mine. A breaching mine would be overkill for a castle made of wood, but stone don't burn. We don't even know if the bridge goes over the walls or even touches them.

I love interesting and entertaining mythologies and applaud them, but they're not to be conflated with The Problem. Listen carefully to the mythologies of the people you work with, and watch carefully if they're more interested in spinning a tale or working on the problem.

I have been intrigued by the idea of visual coding tools for many years, but these kind of tools have always disappointed me. They remind me of the system used to teach small children to program in the programming language Scratch, see [Scratch].

I prefer to "visualize" my code as manipulating a set of logical assertions that characterize the state of the computation, ultimately reaching the point where the state of the computation's properties satisfy the requirements. Somewhat like that explained in [Gries1987] and [Dijkstra1976]. Visual tools are just too coarse to capture the details necessary to ensure correctness or real-life requirements.

While UML diagrams sometimes help to make sense of a complex set of OO Class relationships, this is far from how I normally work with the meaning of code in my head while programming.

[Scratch] https://en.wikipedia.org/wiki/Scratch_(programming_language)

[Gries1987] https://www.amazon.com/Science-Programming-Monographs-Comput...

[Dijkstra1976] https://www.amazon.com/Discipline-Programming-Edsger-W-Dijks...

>I prefer to "visualize" my code as manipulating a set of logical assertions that characterize the state of the computation, ultimately reaching the point where the state of the computation's properties satisfy the requirements

OTOH, functional code should be more like a pipeline (graph), and thus better suited for visualisation.

I think of code as a series of nerve cells. Nerve cells have internal logic (the nucleus) and a connection to others (the axon). Nerve cells should all generally be about the same size; one being bloated is a sign of a code smell - an area that could be refactored into smaller chunks. Real nerve cells only have one axon but, in programming, a single connection to the rest of the code base just isn't always realistic. However, a spaghetti mess of interconnection within a codebase is a code smell too.
Interesting metaphor. I was going to say a mindmap, but nerve cells also make sense. I also have the same code smell litmus test, if two different paths call the same thing twice (aka they both link to the same place), but like you said sometimes it's unavoidable.

With microservices things get a little bit more complex though. Anyway, very apt metaphor.

Ever since I saw the cover of Elements of ML Programming [1], which shows the book as charting a course across "Logos Island", I've wondered what a programming language might look like as a navigable space. Perhaps something like walking through a syntax diagram, but that hardly captures it, especially when so much of the semantics of a language is in its standard libraries. Would a program be a path through the language world? Would we think of the world as containing all possible user-defined functions, and we'd edit our way across this space?

For a historical metaphorical discussion of visualizing programming, I enjoy this bit from Johan Georg Raeder's 1984 thesis "Programming in Pictures" pp79-80 [2]:

"What real-world metaphors can fit programming? To get a feeling for how immense our initial search space is, let us amuse ourselves with a few possibilities. Is a program like a road with intersections and forks where we have to make decisions depending on our current errand, and with roadside inns where we can spend computation time or, if we are careless, completely overflow our stack? Or shall we abolish the 'meta-view' and, instead of seeing the program from the sky, put the programmer inside the program by presenting a view of a tunnel he/she can drive through? At each intersection one might have to throw dice or make guesses to introduce some of the challenge, fantasy and curiosity found in computer games. Perhaps we should rather present programs as physical, three-dimensional objects that we can turn around and view from different angles and in different light so as to reveal the various facets of their structure. Can we present a program as a play with actors and objects on a stage?"

See also Raeder's "Survey of Current Graphical Programming Techniques" (1985)

[1] https://archive.org/details/elementsofmlprog0000ullm

[2] https://archive.org/details/RaederProgrammingInPictures/page...

I just don't visualize it much.

I do visualize dataflow, and tend to encapsulate responsibility boundaries, so as to be able to assert properties of a bunch of code and not have to think about the internals. But other than big block analysis I just don't break it down that much.

I've been coding for 37 years, 23 of those professionally (it's not bragging, just to establish that I've read and written a lot of code), at this point I just kind of read the code a bit like prose, or more like a "Choose your own adventure" book.

I do like to have the ability to navigate symbols and do typed searches of a code base, I also appreciate typing and mutability properties of things (everything is assumed mutable unless proven otherwise, which complicates concurrency analysis).

It's my experience that most coders think similarly, and you can usually assume quite a bit about how something is structured once you grasp the style of the programmers that built it, this also means that sometimes you can even predict the kinds of bugs they will tend to have. We're not all so unique after all.

The challenge of becoming a programmer is that of learning to flip between all these different mental visualizations and more, unconsciously and without effort, just as the challenge of becoming a musician is that of seeing melody, harmony, intonation, progression, rhythm, phrasing, dynamics, and so on, without effort, as each moment demands.
his example is literally just data flow programming: https://www.youtube.com/watch?v=WjJdaDXN5Vs&t=924s

I've had a project related to this on the back burner for a little bit - data flow programming is really cool and helps with understanding code logic (and can be inherently reactive, which is IMO the future of programming) but it's hard to scale up.

Calling code on the left, function-being-called (or rather, its stack frame) on the right. Unless it's asynchronous message-passing stuff in which case the parts are in disconnected spaces.

At my previous job there was a lot of code that abused a pub-sub system to effectively do buggy temporally-coupled RPC. This didn't fit any paradigm I knew how to visualize (it went straight into the "fucking mess, don't try to understand it unless you're going to fix it" section of my mental library) and therefore I had a very hard time understanding what was going on, or getting much done at all, for that matter. I opened some tickets with suggestions for ways we could make it make sense but management deemed that type of work lower priority than chair-warming (this was last fall during the 'employees should be in the office X hours per week' period; meanwhile I was living 300 miles away) so I gtfo.

Here is my dumb army guy approach to programming anything. It doesn't work for everybody.

1. Think about the problem.

2. Form a tentative plan (the visual part).

3. Write a rough draft of code (the code doesn't have to work yet).

4. Test it and make it work (minimum viable effort).

5. Refactor. Polish the code and eliminate tech debt.

Think about the problem. Get a solid vision for what you want done. Once you have solid emotional confidence about that end state balance it against what you have. With that you know what you are missing. That stuff that is missing is the work you must perform.

When you think functionally everything is an input and an output depending upon context. This allows thinking about the flow control directly without worry for the composition. If you have been programming for more than a couple of days the leet code of loops and conditions are completely ignored from planning as implied tasks much like you don't spend your time actively thinking about breathing when planning your day. Now you have a plan. Plans often fail as soon they become necessary, so the plan itself is irrelevant. What's important is the planning, the thought exercise not the product, the thinking about what needs to be done so you know what to do.

Programming then becomes a conceptually visual experience. Simply the write the code you see in your mind. The most important thing here is that you have a visualized a plan and know what you need to write. The code doesn't even have to work at this point.

Then write the code. Test what you have written. Fix the code so that it solves the desired problem. Only then should you actively toil with composition. When composition is saved for last it becomes an exercise in refactoring.

Refactoring is a form of code polish. It allows cleaning away the rough spots from the rough draft in order to achieve conformance to code style, build rules, and validation criteria. Refactoring also allows the combining of similar mechanisms which increases simplicity and reduces tech debt.

does anyone here write code, align with having aphantasia, and have some form of an alternative answer to thread? alt.answer might end up being the same answers, idk what i'm saying, barely know what i'm asking
Yes.

I don't visualize code because I can't visualize on demand, period.

I think of it in terms of words and logical abstractions. Textual memory, reading comprehension, code intelligence tools, and search are how I understand and navigate projects.

I say things like "You're looking for the immutable DEFAULT_HEADERS property. I think that's in the HTTPResponse class?" fairly often.

I like documenting a project's high-level organization (top-level folders and what they do) in the readme or a similar place.

I'm strongly opposed to manually-created diagrams about a codebase because they require insane discipline to keep up-to-date.

I like having tooling to generate diagrams from the current state of the code. Ditto interactive tools with useful visual components (popups that show the doc comments for the abstraction under your cursor, auto-completion hints, SQL query editors that show you the visual schema of the tables in your query and the foreign keys to related tables [hypothetical, yet to find one that does this like I wish they did], etc).

I sometimes use git-heatmap to get an idea of what files in a project see the most change. Such files are usually worth getting to know better.

I frequently use ag / rg to search for fragments of text that I recall being near the code I'm looking for.

I found it odd that the drawing were confusing until I added my own personal imaginary time component.

Spacial memory include how I "feel" about something as much as the logic of what it is. When I misplace something I "feel" like I put that object (keys, book, etc...) in some place, despite it not being there.

So, like the idea of "I remember putting my keys here", there is a timeline.

The images of the boxes "main" and "counter" with all the lines was confusing, but if I had drawn them myself, I would have tiny timeline/memory of each line movement from one to another. Just the same as I recall (vaguely sometimes) why I wrote a piece of code or structured my files some way.

So, to change the thought from "what a mess of lines between the boxes" to "these lines really mean something to me", I would either have to have drawn them myself, or have some time component (ie, lines drawn during actual demo of code being run) to represent "how I visualize" the actual logic/code/system.