Ask HN: Visualizing software designs, especially of large systems (if at all)?

156 points by lovehatesoft ↗ HN
I learned about UML in a course, but have never used it or seen it in practice as a junior developer. Sometimes I'll see a flowchart, but that's not too common. Is this the same in other companies?

With some of our code, the designers are either gone or sometimes unavailable, and it can be tricky to see how all the pieces fit together. A good IDE makes the job a little easier (finding references, ctrl+click to go to declarations, etc.), but it'd be nice to have a diagram or something for visualization.

So, is it a good idea to try documenting the code design through some sort of visualization? If so, using UML or something else? I suppose there might be tools for doing this automatically in some languages? Otherwise I think if it was valuable enough, it could be something we make sure to review and update along with code changes.

Any thoughts would be appreciated!

128 comments

[ 9.5 ms ] story [ 270 ms ] thread
This tool is good for making simple UML diagrams and even lets you do it with simplified syntax

https://plantuml.com/

I'd say the big problem in visualizing big systems is that you can't usefully do it in one graph. For instance I worked on a system that had 2000+ database tables if you were going to make a diagram of that which shows everything it is going to take up a long wall. (This can be useful, but it is a big commitment)

A useful tool is going to let you make meaningful diagrams that show the subset of entities that are part of a story. I went to an art show of Mark Lombardi's works

https://en.wikipedia.org/wiki/Mark_Lombardi

who (before he was murdered) drew elaborate diagrams of conspiracies. One thing they showed was drafts that he made in the progress of creating his visualizations and he would sometimes make 40 or more of them. He would start out with a "hairball" that was disorganized and gradually figure out how to lay the diagram out in a way that made the meaning obvious.

Good stuff. I am doing similar things but have not been murdered yet!
wikipedia page says suicide
We will probably never know if it was a suicide or he was "suicided". Given his works one has to wonder... Did one of them hit too close to the truth?
alternatively, given his obsession with conspiracy - maybe he was unable to establish deep connections with anyone in his life
PlantUML with C4 and the additional cloud icons, is what I use
I had to do a double take, there was a similar question couple of weeks ago [0].

I was blown away by the idea behind C4 when I first saw the presentation. I think what's missing is the tooling. I use C4 PlantUML do document my architecture designs.. what I'd really love though is a google maps style interface where I can zoom in or out of the current level I'm at. That'd be a game changer. Then you can really describe and understand the system.

The original presentation, in fact, used the google maps interface to illustrate the idea where you're first looking at a continent, then you zoom in to the city and finally the street level.

If you are using C4 right now, how do you compose the various level of architecture and navigate around them?

[0] https://news.ycombinator.com/item?id=31370268

> I'd say the big problem in visualizing big systems is that you can't usefully do it in one graph.

That’s because it’s flat

Imo this changes the game

https://noda.io/

Imagine being able to make a fully 3D graph inside a space the size of a large building

I have been working on a natural design system for visually thinking about technology. Maybe it will help you.

Its called MTREES and its a free epub on Apple or Google.

https://mtrees.io

Depends on what you want to understand about the system.

If you're looking to understand it's properties and how it behaves I would look into something more robust like Alloy 6 [0] which has a great visualization system for inspecting models. However if you're looking for a class diagram tool then it's outside your wheelhouse.

There's also something I've played around with a bit but haven't used seriously: Moose [1]. It's basically an IDE for doing analysis of code. The trick is writing good parsers.

[0] https://alloytools.org/alloy6.html

[1] https://moosetechnology.org/

Moose looks really impressive, visually! I think it's one of the flagship Pharo applications.
Why are all these comments suggesting new tools instead of answering your question? From what I've seen, high documentation only comes into higher level abstractions such as individual services or architecture design.

In school, I was taught to draw UML for classes within a program. I have never seen that IRL. I think the difference is the time required to comprehend the application.

I gave this a bit of thought earlier this year (https://alexanderell.is/posts/visualizing-code/) and, with the help of HN commenters, collected a small list of ways people are working to help with code visualization. I don't think most of them are production ready (some are just research papers), but you may find them interesting all the same.

SoftVis3D (https://softvis3d.com/): where a "‘code city’ view provides a visualization for the hierarchical structure of the project".

Code Park: A New 3D Code Visualization Tool (2017) (https://arxiv.org/pdf/1708.02174.pdf), a “novel tool for visualizing codebases in a 3D game-like environment” with code represented as “code rooms” with code on the walls.

Code Structure Visualization Using 3D-Flythrough (2016) (https://opus-htw-aalen.bsz-bw.de/frontdoor/deliver/index/doc...), with spatial metaphors and first-person exploration of code.

Primitive (https://primitive.io/), a VR collaboration startup with a Matrix-looking “Immersive Development Environment” with “new tools for visually analyzing software in 3D”.

AppMap (https://appland.com/docs/how-to-use-appmap-diagrams.html), an automated code analysis tool that includes dependency maps and trace views.

plurid (https://github.com/plurid/plurid), a framework for visualizing and debugging code in a 3D explorable structure.

fsn (file manager) (https://en.wikipedia.org/wiki/Fsn_(file_manager)), an experimental application to view a file system in 3D (featured in Jurassic Park).

If I may be so bold as include something I’m working on myself, I’d love to chime in! I’m not functionally complete, but feel like I’m writing an amalgamation of all of the above tools.

https://github.com/tikimcfee/LookAtThat : A macOS and iOS app to load, analyze, and walk around your Swift code, version 0.0.0-prealpha!

These look great, I think the general idea of using space is pretty solid. Anyone who's ever tried to draw a tree structure finds it gets busy really quickly with more than a dozen or so leaves, but an actual tree in 3D space can have thousands of leaves yet fits into a reasonable chunk of space. Graphs are similar, if they are connected in 3D rather than 2D (ant nests and termite mounds are decent models).
Just wondering, did any of these give you a Minority Report kind of vibe ?
No automated tool will come close to having a 5 minute conversation with the main designer and having him draw you a diagram freehand on the back of a napkin. This is a social and organizational and communication problem, not technical.

If that can't be done, there are some interesting things you can try. A lot of the suggestions in the thread are "top down" methods; you can get a lot of value out of "bottom up" visualizations too. Things like:

- Histograms of which lines / functions get called the most, or spent the most time in

- Which lines / functions / files get changed the most in the git history

- CPU flamegraphs

- Plain old print-debugging

In over-architected systems it can be difficult to figure out where the real "meat" of the code is, as opposed to the endless layers of configuration and wrappers and interfaces and indirection. UML diagrams may not help, or even be deceiving, but a stack trace never is.

The way to capture the content of a conversation like that, so that more than one person at a time can easily benefit from it, is in a theory of operation document with appropriate illustrations. Simple block diagrams will take you far before you need to specify something in the level of detail that the UML supports.

I like the range of approaches in the Architecture of Open Source Applications books: http://aosabook.org/en/index.html

Different types of diagrams highlight different aspects of a system.

If you can, try to put together 2 different diagrams presenting different views. For example, sequence diagrams, model diagrams, etc. each tell you something different. Having a few different perspectives on the same system will give you a richer understanding.

Not specifically related to visualization, but, also, if you spend a lot of time trying to understand a piece of code, once you understand it, document it (e.g. in a function or method comment). Over time, this makes a huge difference and will help you and others out when you revisit the code later.

I'm a big fan of Terrastruct (https://terrastruct.com/). They focus on building great software for visualizing complex software architecture. Their secret sauce is this idea of attention where they allow you to zoom in and out so you can get the 10 foot view or 10,000 foot view, whatever you find most useful.
The challenge is that there are different ways of "mapping" software.

You could map the way programs fit into machines, and the networks between them. This would be the topology.

You can map the way services call upon one another with requests. This is the service graph.

You can map how systems interact over events or shared resources. You could say this is the logical graph.

The problem happens when you try and graph them all at once. It's the same as trying to draw a real map, with all the services, bus routes, railways, shops and administrative regions superimposed on one image. It's very busy.

So I use separate maps.

Tools are another matter. Personally I use Mermaid for graphs. I also have my own tools that create SVG visualisations using DAGre. This can be helpful for interactive visualisations where you can click into different nodes and explore more detail.

My system uses CloudFormation templates and our in house deployment DSLs to figure out the "topology", then let the users see the different superimposed "graphs" as they see fit

I'm a visual learner. I wanted a way to see how documentation of complex systems looked too. I'm working on a https://gainknowhow.com/software-companies.html . It is basically like a mind map for documentation. The high level documentation like core values is on top connected through learning paths to learn the complete context of low-level skills.
We like using PlantUML and it embeds in Asciidoc nicely.

Also the C4 Model seems cool but I don't currently use it

https://c4model.com/

Plus one for C4 Models. Most important aspect of it: When you do lines and boxes in a diagram, put descriptions on the lines, not just the boxes. Sounds simple, but is often forgotten. The result is people seeing UML, making all sorts of assumptions.
An alternative to PlantUML is MermaidJS, which GitHub recently added support for in Markdown documents.
I'm a fan of https://www.ilograph.com/. I've only used it for a few small things, but the author has good samples, including a diagram of ilograph itself - https://app.ilograph.com/demo.ilograph.Ilograph/Request.
This looks interesting :) Not sure about YAML, been burnt with OpenAPI, but it looks good.
This looks very cool. It looks similar to the C4 model, where you can have nested components of arbitrary depth ("containers" in C4 parlance).
I use Ilograph pretty heavily both for documenting existing systems and designing new systems. The paradigm of “everything has context” makes diagrams much easier to understand.

I have even used it to render infrastructure diagrams of actual production systems (clusters, load balancers, etc)

UML is not a documentation tool, it´s a communication tool. It is a standardized way to communicate. It removes ambiguity. UML is the best way to manage, communicate and handle a large amounts of complexity. Most of the free UML tools are very basic and does not have traceability features (we can see many in the comments), and this is really a no-go if you want to understand large systems.
I agree with your view on UML, but now I'm curious what you consider documents to be for.
I can assure that documentation is not UML. Documentation can contain exported diagrams that were created using UML.
Documentation is communication, albeit asynchronous.
Documentation is a tool for communication, not the same thing. The dictionary is our best friend =]
No, documentation is communication, not just a tool for it.

Please don’t be condescending and incorrect.

The most important rule is that you can’t include everything in a single doc as it quickly gets too big and complicated.

So you need to break it down into multiple documents that cover different use cases and include only the components for a small set of use cases.

Then use the C4 model to break up the docs.

I like using https://c4model.com/ - the Level 2 diagram is particularly useful.

I use https://mermaid-js.github.io/mermaid/#/ for the diagram itself because Github natively supports it in markdown files, so you can revision control the diagram. I managed to get reasonably close to the C4 diagrams minus a few features that mermaid does not support.

A nice talk at kubecon last year spoke about visualizing protocols and more complex multi-party exchanges.

The suggestion it made was to look across module boundaries or microservice boundaries, while making a particular request. So I go to update a Project with a new Pipeline, and I find out that the project service talks to the pipeline service which then has to create resources for which it talks to various resource services, all of that.

Since there aren't great digital tools for doing this, for visualizing these things, it was suggested in that talk that one of the more outside the box things you could do is to just take cardboard and modeling clay and strings and cut out some shapes to represent the different services, let each string be an RPC, and the actual diagram you would imagine being alive in time, like little beads flying across these strings, to indicate requests going out and then responses coming back... But the key was less to witness the time but more to get a timeless sense of connection, “oh, it turns out ResourceService is very hairy in these diagrams, it is kind of the central hub for this microservice cluster.” and for that it was helpful that the visualization had a certain physicality to it, it had weight and structure and engaged more senses than just the visual...

I've actually thought about just digitizing these ideas, even though it misses half the point LOL. I think that could be some wonderful documentation and diagrams in our onboarding for new folks.

There are tools that help with visualising requests between services, provided the information is augmented with some extra observability data.

Most APM/distributed tracing products have ways of visualising distributed traces so we can see starting from a specific call which services were involved and how much time is spent in important operations (e.g. db, etc). Here's an example: https://www.datadoghq.com/product/apm/#end-to-end-tracing

Datadog builds this service map automatically for you from APM and RUM data: https://docs.datadoghq.com/tracing/visualization/services_ma...

AFAIK you can consume the data via API so you can build other visualisations on top of it if you don't want to stick with the flame chart or service map.

Since this is runtime information it won't be as comprehensive as static code analysis but it does show what's actually happening in the system.

disclaimer: I work for Datadog edit: add link to service map

I want to make a computer runtime which doesn't execute the program but instead allows for a programmer to understand what's going on.

a metacomputer of sorts; maybe epicomputer would be a better name?

For a small but complicated project I got thrown into a while ago, the only way for me to understand it was to print out all the source directly, vertically tape together the pages for a single file, and then lay them all out on a huge table. Then I took multicolored markers and started physically drawing out the call chains. I then I sers-toi the system, and also found an enraging bug: the system widely used the variables "blah_name" and "blah_id", including in many functions' parameters. Except, in one case, blah_id was passed in as blah_name and thenceforth became known as blah_name.

I don't know if an automated visualization system is possible, but you'll have to understand the whole thing before doing so. Pen and paper was the most expedient solution for me at the time.

Sounds like something the type system should have caught!
Lucky you if you work with people who see the value in a language with good type checking or that doesn’t just use strings for everything.
Is it really worth staying in a team that doesn't? Sounds like you'll spend more time fixing bugs than creating features.
I also used to do this when working on a big convoluted system. I had a conference room near my desk with all the walls completely covered in code. A big pack of multicolored highlighters is key.

I remember a whole bunch of light bulb moments when I showed other developers the "big picture". It's an awesome technique when you're forced to work on spaghetti!

I use pen and paper as well, but rather than print out all the source code, I write down the call stack. A calls B calls C, etc. along with the line numbers of the call. Much easier than printing out the source and you still have the IDE niceties like go to definition, find in source, etc.
This reminded when I had to maintain dozens of old 10,000 lines COBOL programs as a junior programmer. I felt so lost I made a program that would print only the names of data structures and functions. Seeing the source resumed in a handful of pages, and being able to highlight and draw on it, helped me a lot. Digital has flexibility, but sometimes paper works best.
Paper is one of those Perfected technologies. It's been there for a long time but boooy. It's powerful
Hah! I did the exact same thing for ages on paper and eventually evolved the system to manage my workload and context switching… I still use it a lot for going deep while debugging/understanding code. I ended up making it into an app when I broke my wrist and could still type but couldn’t hold a pen. I can’t remember if there’s rules about self promotion in comments here but it’s up at journalist mode dot com
I've done this too, taped a bunch of impenetrable code to the wall and scribbled on it with pen to figure out wtf was happening. I propose that this be called the "Pepe Silvia" debugging method since it looks like a crazy conspiracy chart. Eventually you'll figure out why nobody is getting their mail ...

https://www.youtube.com/watch?v=_nTpsv9PNqo

First principles! I've totally done this. Especially in a large pub/sub oriented frontend codebase where it's really hard to map out where any given data could have come from
Language support varies but if it’s possible, why not generate an AST and count references, bubble up most common, etc?

Could do similar with bash text mangling tools, but language native would probably be best.

I dunno, just a thought in an EOD fog. I don’t own a printer these days, so I guess I’d need an alternative.

Tell computer to observe self and report back.

I use what I call "UML Lite" (UML, without all the frou-frou). It's handy for illustrating points[0].

What I generally do, is start with what I call a "napkin sketch" (which can be UML-ish)[1], and try to avoid writing down too much stuff, in order to reduce "concrete galoshes"[2].

I try to use tools like Doxygen and Jazzy, to document the code, in an inline fashion[3]. Doxygen will generate a UML "Lite" diagram[4].

[0] https://littlegreenviper.com/miscellany/swiftwater/the-curio...

[1] https://littlegreenviper.com/miscellany/forensic-design-docu...

[2] https://littlegreenviper.com/miscellany/concrete-galoshes/

[3] https://littlegreenviper.com/miscellany/leaving-a-legacy/

[4] https://doxygen.nl/manual/diagrams.html

In my experience it tends not to be done because there's an inevitable drift between the system as it actually operates and the relevant visualizations and diagrams. I have seen them used as a starting off point at times, although that's also been infrequent.

There is however a growing movement of being able to visualize how a system is functioning at various levels. XState/Statecharts are a good example (https://xstate.js.org/viz/). Another example in the Ops space would be https://github.com/spekt8/spekt8 for K8S. I work at Grafana and we're more or less trying to expose these things in ways that make sense. Our bread and butter is timeseries data but we're adding more in that regard (it's possible to build node graphs from running systems).