Ask HN: Why aren't code diagram generating tools more common?

132 points by lurker137 ↗ HN
When I'm trying to get familiar with a new codebase it often takes me a long time to build a proper mental model of the whole system. Even with my own projects, it's easy to lose track of all the components and their interactions since they're constantly changing, and making hand-drawn diagrams is time consuming.

So my questions are:

- Why isn't diagram generation automated as part of the build process (UML or otherwise)?

- Why aren't code visualization tools more popular? The options out there seem outdated

- Would you want to use these tools? What would be your ideal tool?

Edit: looks like this is a duplicate question https://news.ycombinator.com/item?id=31569646

I can't delete it so feel free to discuss more

111 comments

[ 0.74 ms ] story [ 173 ms ] thread
I find those diagrams a lot more confusing than just reading and having a mental model of the code.
It's a very valid criticism of diagram "systems" like UML. But, "read the code" doesn't scale. It makes it brutal when onboarding new team members who will not understand the "tao" of the system without a fireside chat with the original developers. And, usually, the OG devs are long gone...
The tao that can be sequence diagrammed is not the true tao, either.
I always had the same feeling, and I found out about aphantasia in the last few years: I do wonder if these are related?
Because most code diagrams would look like a solid black square.
It's more the layers of wrappers around the black box I have trouble with. Maybe it's just a Java problem
I think the main reason is that it is slower than having a mental model.

One reason it is slower is that it is is difficult to create a map like diagram where you zoom in to get greater detail.

A decade or so ago, I was tasked with auto-generating documentation, including diagrams (super- and subclasses, to begin with), of a fairly large system in a domain-specific language developed over the past couple of decades. The language had a kind of multiple inheritance (a traitlike system), and at the time around 1500 types/classes/traits/mixins/whatevers, with the entire system all queryable at runtime (and indeed that’s how I generated it—someone else provided Python bindings to the system, then I traversed it all in Python). Just to amuse myself, I generated one class diagram of the entire system. It was around 30 metres wide and I think 30cm high when I zeroed all the margins and padding I could in GraphViz. Flipping its orientation, I got it to be 15 metres tall and almost 1 metre wide. I figured it could be fun physical wallpaper for the office, but in the end settled for just a labelless rendering with random line colours as a desktop background. It was pretty.

But more seriously, it depends on how complex the system is and how it’s modelled. The case I was working with then transferred excellently to such diagrams (shallow and deep inheritance, and other forms of composition and linkage, with every box a link) and key-value property sheets about the types and the likes, but I don’t think I’ve encountered another system where anything even vaguely like that would work particularly well.

That's a great point, I doubt there can be one single modeling solution for all systems. I imagine a modern tool would be more like a suite with many options for common use cases. And it would be essential to be able to narrow down on specific subsystems maybe using something like a gitignore file
I have used visualization generation tools but have found them of limited utility to me. When the generator is built into an IDE, the artifact it generates is less useful than the IDE itself, which typically provides a structural (symbol tree) view of the code as well as symbolic navigation ("Go to definition/references").

A visualization can be helpful as an artifact for non-technical colleagues, but I always end up hand-rolling those diagrams to highlight a specific aspect of the system and hide irrelevant features.

I’ve felt the same problem. IntelliJ markdown files have support for mermaid is and plant uml diagrams. You have to Google/tick a box to enable it though.

I find creation of a sequence diagram with class instances as columns and method names as arrows can help visualise things.

The problem facing these tools is a catch-22 really - diagrams are useful when understanding big messy codebases but big messy codebases are hard to visualise.

For instance, I frequently build small paper diagrams of different code paths through a component and nearly always find leaky abstractions, mixed layers of abstractions, weird cyclical dependencies, etc. etc. and there really is no clear way to diagram this. Instead, you sort of have to make judgements and assumptions to make the diagram concise and understandable; the sort of decisions that machines just aren't that good at.

On the other side, when code is simple and easy to follow then the pay off of building a diagram just isn't there.

Paper and pencil is definitely the way to go. If i make something that turns out to be useful I’ll make a digital version after.
I'm starting to see all the problems with static diagram creation. I still think there can be more work in this area, maybe a full dynamic solution separate from the IDE that just helps you navigate the maze and make your own diagrams. With all the work that's been going into making developers' lives easier surely someone could focus on the exploring codebase part.
"... make the diagram concise and understandable; the sort of decisions that machines just aren't that good at. ..."

Exactly. I've found that there is no perfect tool and I'm closing in on 40 years of writing software. I use a blend of UML, IE (James Martin's Information Engineering), etc. Anything that makes it "easy-to-grok". Draw.io generally does what I want it to do; there is no feedback loop back to the codebase. It's really just to help onboard new helping hands.

Even a few very basic UML diagrams (Use Cases, Class, Sequence) can form a very effective introduction to a system.

I feel that people have just embraced Agile blindly and simply forgot about basic modelling.

Embraced or been forced into it? If you want to do long term planning and design, good luck. Everyone wants to continuously change their mind on what they want/need and have the software react yet they also somehow assume this approach creates well defined systems when it does quite the opposite. Adaptation can still create reliable and well defined systems but the rate of adaptation needs to be reasonable. In agile that simply isn't the case, it's just a way to pass consumer demand and responsibility for meeting that demand right down to developers while arbitrarily placing budgetary and time constraints around that process. Development teams are often acting as small businesses anymore with similar risks but less rewards with a middle men sitting between them and the consumer, unless you work at a large tech company where that's still a little bit insulated although not entirely when product lines are killed off.

Ultimately, you just create and endless amount of complex work that keeps developers continuously busy. On the bright side there's a never ending amount of tedious work wrestling systems back into some manageable form, on the downside that work is miserable, in my opinion because much of it can be removed whth proper planning. At some point, expectations eventually meet reality no matter how many developers management burns through, at some point it's clearly not an issue with technology, it's an issue with approach and project management. By that time the organization has had enough turnover in those above and below those pushing agile that those issues too can be hand waived away and the cycle repeats.

Absolutely this! Communication of design is an enormous gap that has emerged in the last could of decades.
>I feel that people have just embraced Agile blindly and simply forgot about basic modelling.

Very Good Point!

If you only look at things piecemeal and never holistically, the need for modeling and corresponding tools decreases.

CASE Tools with round-trip engineering need to make a comeback.

To answer your question, people do use various tools to extract Class Hierarchies, Call Graphs, Cross-Reference listing etc. The other HN thread that you have linked to contains some details. Lots of people do use them. You can easily add Doxygen/CFlow etc. to your make files to generate the diagrams during every build. The key thing for usage is that do not try to comprehend the entire system as a whole (all but impossible for large systems) but localize your study to a module at a time. Once you have the different pieces mapped out, you can combine them by hand.

Fully agree. A diagram is ok to describe a flow, but for complex code or systems, round tripping is a necessity, otherwise the diagram is or quickly becomes inaccurate and worse than useless. In the 90s I tried software called TogetherJ, it seemed to support round tripping really well, so well maintaining code was the same as maintaining diagrams, and led to better quality in both, along with documentation and other benefits such as relaying higher order concepts. I just did a search for togetherj and the only reference I could find was a 20 year old forum mention. Weird. I suppose there must be high end enterprise CASE software that still supports this approach, though I'm guessing most people abuse it so it's no longer respected. I think these things happen in cycles, as we can 'orchestrate' larger systems with meta descriptions of components, they become more valuable.
I remember both Rational Rose and TogetherJ CASE tools. Round-trip engineering was supposed to be practiced by both Domain Experts and Programmers each modifying their models and still having them all consistent with each other. But what happened in practice was that only Programmers used them who did not see the utility of updating a UML class hierarchy instead of directly updating the Class itself. That and the exorbitant pricing is why they fell out of favour. It is really a shame because with the explosion of distributed apps using a variety of languages/tools a single uniform interface modeling all aspects of the software is sorely needed.

PS: Came across the book Software Visualization - Visualizing the Structure, Behaviour and Evolution of Software by Stephan Diehl which seems to provide a good survey of the field.

One issue is that a general visualization tool might have have a lot of problems jumping from a codebase in language X to a codebase in language Y (let alone a mixed codebase). MS seems to have this Code Map tool but it looks like it's for C# / VB mainly, with some C++ support.

https://docs.microsoft.com/en-us/visualstudio/modeling/map-d...

In many cases it might really be faster and easier to just diagram things out with a pad of paper and a pencil compared to setting up a tool like this and getting all the parts working correctly without any bugs.

That said, a virtual reality 3D tool for visualizing code base dependencies, internal structure, what parts call what other parts, internal exception handling etc. would be pretty cool. Maybe it's an area where AI machine learning could do something.

That tool from Microsoft comes closest to what I think would be ideal, generated diagrams that aren't static and where you can include/exclude and move around components. It would definitely have to be language specific, but once things catch on IDEs implement language specific plugins soon after.
Maybe it'd be neat.. but, I think sometimes "the map is not the territory" goes both ways. - I probably want a diagram to be simpler than the actual system.

With a manually constructed diagram, I have leverage to handwave irrelevant details away.

Perhaps to compare with documentation: it's easy to automatically describe things like types, and maybe callgraphs, but there's value in having prose which explains details about the interface which the program's type doesn't reveal. - With diagrams to visualise a system, the significance (or incidental nature) of the relationships may be hard to pick automatically.

Yes exactly. There are no tools that can build proper mental models.

Most of a system is either uninteresting or trivial. You need someone to tell you where the interesting part is.

This isn't a tool for generating diagrams from actual code, but I have really enjoyed using PlantUML lately while putting together design or architecture proposals: https://plantuml.com

As someone who is not a very visual person at all, I found it really nice to use to make my design docs more comprehensible to visual learners. I've gotten good feedback about designs every time I've used the tool.

One of the problems is: what is the language to describe these diagrams? We do have UML and it's various variants: PlantUML, Mermaid but these are too low level to prescribe conventions over how to use these to describe complex architectures. A sequence diagram could describe anything through customer journeys, rest api call patterns to call stacks within a VM. Granularity/level of abstraction needs to be captured or else you end up with metres squared of boxes that cannot be parsed at a glance unless you're Rainman.

The closest I found that solves this problem is https://c4model.com/ but you still need the code to turn your code into these markups. Can this be well inferred from code alone without framework specific interpreters? I doubt it.

And then you still need a frontend to zoom and navigate the ridiculous amount of hierarchy found within any modern software architecture, e.g microservices.

It also doesn't help microservices patterns also prescribe that you don't share repositories or code. So now you also need to pattern match untyped references across these codebases.

This is a lot of convention and tooling that I'm not sure exists.

Edit: and this is before even getting into version control and reconciling the target->as-is iterative loop.

I really enjoy(ed) using c4. Still need to figure out how to protect against screenshots though!
Protect against screenshots? Could you elaborate please
I believe the parent commentator is referring to how screenshots of a diagram generated at build or runtime are almost always out of date.

It’s better to generate a diagram as needed than to archive an outdated artifact that could lead to confusion.

We just treat them as any other artifact, a plantuml job builds it and it gets published under a certain URL.
It would be funny if there was a single explanation, like, “The tool for creating simple visualizations that helps you understand codebases doesn’t exist yet.”
I've already mentioned this on the other thread (https://news.ycombinator.com/item?id=31569646), but my friend and I have been working on https://www.codeatlas.dev as a sideproject - it's a tool for creating pretty (2D!) visualisations of codebases, while providing additional insights via overlays (e.g. commit density, programming language or other results from static analysis like dead code/test coverage/etc.). For example here's the Kubernetes codebase visualised using codeatlas: https://www.codeatlas.dev/repo/kubernetes/kubernetes

At the moment, codeatlas is just the static gallery, but we're only a few weekends away from releasing a Github action that deploys this diagram on github pages for your own repos - if you're interested, feel free to watch this repo: https://github.com/codeatlasHQ/codebase-visualizer-action

OP, how close is this to what you had in mind in your question?

EDIT: fixed broken links :o

I've since been convinced that what I had in mind initially (generating a bunch of static diagrams with each build) is not very useful. Your site comes closer to what I think would be the better solution, an interactive diagram, but at the level of classes/functions and their interactions instead of files/folders. Your project looks great for exploring a Github repository though.
(comment deleted)
Just a heads up: Your links are broken. I think it's because you are using Reddit's syntax which HN doesn't support.
(comment deleted)
Speculating based on both writing large systems from scratch, and joining a group where a large confusing system was being used...

Diagrams are sometimes unnecessary overhead early in a project. Sometimes I’ve used them and seen other people use them for initial design planning, especially if management needs to be involved or approve the plans & schedule. But by a year later, the design has grown and changed, and everyone on board is so familiar with the code, but also so pressed for time and feature delivery, that making diagrams doesn’t make sense: nobody involved at this point needs them. Two years later, when the code is getting complicated and slowing down, and you’re onboarding some new people, that’s when it might help to sketch the flow of code.

FWIW, sometimes a good profiling tool will show you and let you explore call stacks, call graphs, execution charts, etc. I often reach for a profiler when I’m new to a codebase. Flame charts are a fave of mine. You can find flame charts in Chrome’s debug tools, or in compiled language profilers like vtune or valgrind. Here’s a decent article on how to use them https://www.brendangregg.com/FlameGraphs/cpuflamegraphs.html

Another issue is that well designed code bases diagram themselves by their module structure, while diagrams for poorly designed code bases may not help understand them at all. When code has too many side effects, or things are poorly or misleadingly named, when class boundaries aren’t well defined or the code has a lot of spaghetti, diagrams might not really help.

IMO two things worth doing are: get a mentor in any new codebase any time you can, and 2) start building your own arsenal of code diagramming tools, rather than wondering why or waiting for others to do it. Demonstrate the value of diagramming code to people around you and see if you can get it to catch on.

The thing with profiling tools is that they're more focused on the details than the big picture at the system level. I'll definitely be using flame graphs more though, thanks for the tip. Also you are absolutely right about waiting for others to make the tools, but sometimes the tools don't exist for a good reason that I wouldn't have realized otherwise.
Yep, that’s totally true. Profiling & debugging tools are designed for sampling the behavior and performance, and not primarily for understanding architecture. Still, they’re great for inspecting call stacks, which can be pretty damn helpful for certain parts of understanding the code.

IMO there’s no real substitute for getting the design explained by the people who designed it. (Of course this isn’t always possible, but when it is, take advantage.) Automated tools can never prioritize the explanation nor summarize what parts are critical or tricky vs what parts are incidental or trivial, and they can’t tell you which parts should be redesigned because they were slapdash vs which parts look ugly to a newbie but have a long list of hard to see requirements, and touching things should be done with extreme care. Good diagrams are very helpful, but best used as a supplement to in-person stories, in my opinion.

I’ve had this need a few times. Just a couple weeks ago I needed to quickly understand the set of package dependencies within a codebase and wrote some scripts that extracted a report as well as a graphviz file. I’ve done that a few times over the years. The biggest obstacle to a general purpose tool usually is the compiler front end that is needed to correctly parse the code to get the entities and relations you need to visualize. Without that it’s hard to write a reliable tool for extracting the information, and if you care about multiple languages you need multiple front ends.

People do want it (contrary to the common HN refrain of “well, I don’t want it so clearly nobody wants it”). We’ve had customers where I work specifically ask for these kinds of tools. They’re just harder than they seem to write, not only for the parsing reason I mention above. For many codebases you see a giant ball of spaghetti if you look at the full graph, or the layout algorithm gives you something gigantic and hard to browse. That’s a deficiency in graph visualization tools: again, a hard problem with little good tooling out there.

I’d love to see more work in this area since there do exist people who see value in it, contrary to the skeptics.

I agree that dependency graphs are the way to go - they show the structure of the code better than anything else. And yes, the problem is that the graphs show all of the details, whether they are important for gaining a good, overall picture of the system or not.

What you need is the ability to filter the graph. Narwhal and the nx mono-repo toolset has a pretty cool dependency graph feature built in. Here's a video of how they use it:

https://youtu.be/KTGKpoiLE0k?t=253

Where is the funding for this work? Customers want to solve end-to-end problems, now, so it's difficult to get support for deep work on a particular part of the visualization and analysis stack (for almost anything, not just code).
i think the hype is producing working solutions over documentation
the hype is producing working solutions over docs
because a code diagram is no different than reading the actual code, it'll be just as confusing. the learning occurs when you create the diagram yourself.
The diagram can also be a view into the thoughts and motivations behind the implementation. Which can help the next programmer know the design and why certain design decisions were made.

But not everyone thinks about designs as 2-D pictures. I'd argue there's selection pressure that favors programmers being good spellers and symbol-manipulators. Some people find it intuitive to think of concepts as boxes and the relationships between those concepts as lines. Or maybe to think of a 2-D grid of actions/dependencies with deliverables on the vertical axis and work-steps on the horizontal.

But not everyone likes these kinds of visualizations. Some prefer a text-based description. And some designs don't fit any obvious pictorial representation.

they are not useful at all.

I want to see the big picture, what they can generate are direct translations of the code down to the line level.

When UML was 'cool' I remember that at work some poor soul was tasked with producing UML diagrams using a $$$ tool, of course the tool failed and the poor guy had to manually produce most of the diagrams, which were obsolete quickly..

I was so happy not being the one doing this useless task..

> Why isn't diagram generation automated as part of the build process (UML or otherwise)?

I vaguely recall Visual Studio has this option where you can generate some sort of class diagram. It looked like shit the last time I used it (~2019) especially as your classes get more and more functions built into it. I also can't imagine how shitty it looks for codebases that have a significant coupling problem.

Furthermore, creating a UML diagram is a documentation process rather than something that should be automatically built in. I put it on the same level as writing a document in a word doc or something that's done as the project gets closer to being finished. Some places can live with it, a lot of places (actual software companies) probably do not as they move unreasonably fast (Agile) which does not even allow time for documentation or they just purposely neglect documentation.

> Why aren't code visualization tools more popular? The options out there seem outdated

Because they look like shit. I tried mermaid with markdown, I was not happy with the results, I tried plantUML back in 2019, I hated how it ended up looking, I hated how I have to install java for it, and I gave up on it pretty quickly.

The only code visualization tool I ever use is either draw.io or MS Visio. At lease there's a plugin for that for VS Code.

> Would you want to use these tools? What would be your ideal tool?

Markdown with vim option. It also must have an option to force a top-down flow approach and not freaking forcing it to be a left-right layout

>It looked like shit the last time I used it (~2019) especially as your classes get more and more functions built into it. I also can't imagine how shitty it looks for codebases that have a significant coupling problem.

That's the point, right? Visually representing the complexity of the system. I've used IntelliJ to do this before to show why modifying certain behavior was so slow and error-prone. In that case there were 3-4 classes with heavily overlapping functionality because, surprise, in the past there were multiple teams contributing to the same codebase that all did their own thing.