Hacker News new | past | comments | ask | show | jobs | submit login
Ask HN: How to learn to create/draw mental models for programming?
86 points by neogenix on June 22, 2020 | hide | past | favorite | 36 comments
I've been programming all my life and creating drawings/diagrams of anything comes very natural to me. While this happens all the time in my head, I still grab a pen and paper sometimes when the mental overhead becomes too much. Currently, I'm struggling with a junior colleague. He comes from a different background (sales). Adjusting existing code, fixing and improving features is not a problem for him, but as soon as something becomes more complex he struggles a lot - even simply drawing it on a paper completely blocks him. I'm looking for advice or resources that can help him improve this skill.

First, I'd stop trying to make him draw - not everyone draws out their systems to think them through. I'd ask him to think about the most complex process he had in his prior role, and teach it to you - pay attention to how he is teaching it. Is he drawing it? Talking about it? Writing it down in a flowchart? With bullet points?

Next, ask him to add a new piece of work into that process, and see how he approaches it.

Finally, whatever he does, use the techniques he used to describe his old work to help him envision your code.

It is far easier to adapt pre-existing ways of thinking and working to a new topic than to ask someone to tear down years of habits and rebuild from scratch.

You're not wrong, but learning how to draw out a system is a critical communication skill in almost every Engineering discipline. It's so important in Software that there's even an entire set of industry standard diagramming grammars for this under the umbrella "UML".

I feel like UML was way bigger in the 90s. I haven't been on a team that used UML since 1998. To be fair, it seems like the Java community still uses it more. But I've seen a big backlash against tools that are so formalized.

UML is usually a bad smell rather than a best practice.

I've seen good sequence diagrams and good high level architecture diagrams, but nobody decent uses UML. It's far too cumbersome and at the wrong level for an explanatory diagram.

What is being used instead?

Common sense

In a bit more detail, and perhaps with less snark:

UML has some decent diagrams. What they communicate, they communicate well. But don't diagram everything - that's a waste. When you need a diagram for something, a UML-ish diagram is fine. When you don't need it, don't draw it "just because". We're actually not in the business of producing UML diagrams.

Wonderful suggestion. Find the right medium first.

I think programming is an iterative approach. If he's experienced with existing codebases, adding features and bugfixing, the existing structure and design might still seem like "magic" - because someone else figured all that out. That historical process become "lost art" to those not involved. While most people can learn to follow a map, very few create the opportunity to sweat out the ability to be able to create the maps themselves.

In design, there's both a bottom-up and a top-down approach. Both are required for a software developer:

1) Have the person build a small meaningful project from scratch using the very smallest building blocks (ie. stdlib). Have them build on top of that again. Make them iterate on design and codebase. Refactoring becomes a natural learning experience in its own why and how.

2) Have the person design the simplest overall system architecture from memory as free-form drawings (or other preferred method). The fewer boxes and lines initially, the better. Have them iterate on adding details for components and subsystems. The idea should form how free-form drawing is natural and the results be usable in understanding, improving, optimizing, discussing and communicating.

3) Combine #2 and #1, preferably as free-form personal projects. Just this time you start with #2. Knowing #1 is solvable by iteration; iterate on #2 and try out designs in #1. Inventions should be prototypes that are thrown into garbage bin until satisfactory design and code structure, or a better idea, has arrived.

This is by no means easy for most or not time-consuming. So a person must learn to love the processes and intricacies of discovery and invention, in order to put enough effort to improve. If there's resistance to go forward with one approach, one need to invent other approaches that works individually, so that some progress can be maintained. Developers are problem-solvers after all.

Alternatively, there might be other type of work needed to be done that suits the personality better, and where results flow easier.

That's a good point, I usually try to teach others to understand my reasoning, so I'll definitely try this approach and see how it goes.

I like your advice. I'm often asked myself if people understand me when I explain something to them. I will try your advice!

Your junior colleague is trying to solve a few problems at once. This is overwhelming them, and likely frustrating them. They're trying to simultaneously solve, "Why do I need to represent data visually?", "What data am I trying to present?", "How can I represent this visually?", "How do I map these things in code to this thing on paper?" without understanding any pre-existing solutions to these questions.

In comparison, you have a mapping from "I have a problem" to "this type of diagram will help me solve it."

At my first job out of college, my boss was obsessed with diagrams. He made sure that every person on the project could reproduce the system diagram. This means that I was personally given multiple years of instruction on how to visually represent data by someone who was very patiently correcting me. Are you willing to give someone that type of attention?

If you want them to learn the skill in a useful time horizon, and they're willing to improve, you're going to have to practice with them. Pick a thing they know well. Walk through an explanation of the system with them as you diagram it. Then have them draw the system while explaining it and having access to your diagram. Then have them reproduce the diagram without looking at it. This is the beginning - you'll need to do this a lot before they start to internalize a thing you've practiced for years. Over time, you'll realize that you can leave out some of these steps, and over time, they'll have enough bootstrapping that they can produce novel types of diagrams themselves.

Many of my former students had wildly inaccurate mental models so I built a platform that focuses on addressing that particular issue: https://wakata.io

It teaches JavaScript, but most mainstream programming languages have the same semantics. It's particularly challenging because building a good mental model of programming takes a lot of time and effort.

Hi, this is great. A few bits of feedback - let people skip lessons (those variable declarations are very tedious if you know what you're doing). It would also be good to automatically highlight the value field after creating a new frame variable. It takes about 4 keyboard actions to enter the value which is a bit frustrating. I get the forced restart is helpful for newbies to learn but I also found it a bit frustrating coupled with the interface.

Thanks for the feedback! You mentioned things I never thought of before, like selecting the value instead of typing it out

I came across @mappletons[1] profile, she is behind the illustrations of egghead.io and has a blog and newsletter about visual metaphors for explaining tech concepts, highly recommended.

[1] https://twitter.com/Mappletons

When I was a junior, I had similar problems. I can think of ideas, even solve problems and fix bug but when it comes to building something bigger, I was afraid. My problem the entire time was if soemthing goes horribly wrong. What if the data we are collecting is not stored? What if the code I am pushing is not properly documented? For me it was the fear of making mistake.

In case of simple bug fixes and minor feature addition, my supervisor would be checking everything so I didn't have to worry. For builidng something bigger, no one would be checking everything line by line. I was own my own and afraid to push my code. My team helped me overcome that fear by showing it's okat to make mistakes and nothing happens if you do that. Make mistake, test code, fix bug... it is an iterative process and nothing to worry.

Diagrams of system architecture usually mystify me. A common issue is that it’s unclear what the various boxes and lines and arrows represent.

Consider that it might be that your way of drawing diagrams only make sense to you; unless you are able to state clearly what a diagram illustrates, you might just be confusing your colleague by using drawings.

Different diagrams are useful for representing different systems. Some folks also use symbols differently. Determining the flow of the diagram can be hard when some folks use arrows to show "what is next" when others show "data came from here" or "data goes there" (in this way, the arrows mean nearly the opposite thing). Usually adding simple "1", "2", "3" identifiers to the arrow paths help.

A flowchart sometimes is best, a sequence diagram is sometimes more clear, a step by step list sometimes conveys the work in an approachable way.

The act of writing (and drawing!) acts as a forcing feature for disambiguation and makes us organize our own understanding. I think a diagram that only makes sense to the author is a good first step. Next is going over the diagram with others to see how they interpret it and making changes to make it more universally understandable.

I have experience teaching complex software to uninterested field personnel, so allow me.

Draw a state machine, send it a few events, let him follow it with his finger. For a state machine, all he needs to do is to keep the last state in his head.

There is a rare case that this doesn't work. But that is not your fault.

I've been surprised there isn't more of "Call graph" automatic generation for code. I would have thought having a visual representation of which functions call which functions can in some cases help tremendously.

I started working on TypeScript Call Graph to see if it's useful -- an experiment of sorts [1]

Could anyone chime in about call graphs and whether they are useful?

[1] https://github.com/whyboris/TypeScript-Call-Graph/pull/1

My experience is that such diagrams are only useful if they are hand-designed, not auto-generated. To make a diagram with explanatory power in practice you have to make a lot of decisions about what's relevant, which requires a sortof mental model and some common sense. Jetbrains IDEs can generate call graphs, but they look like absolute spaghetti because they're totally dominated by omnipresent but irrelevant details, like exactly how the logger is threaded through the call chain, or that hundreds of functions call User.id(). Same thing goes for class diagrams. You wouldn't start explaining AbstractEvent by enumerating all 70 child classes, but a program will totally warp the whole diagram to fit them all. They also have the problem that some links are much stronger conceptually than others. A should have an arrow to B because it's semantically a container for Bs, but B having a member of type A because it knows its owner shouldn't even be displayed.

Are you sure it is just because he is junior (I mean that may very well be the thing but maybe not?) in my case I am not a visual thinker, in high school they tested my understanding of visual relations and I was in the lowest 3% of the population, understanding of written text I was in the highest percentile of the population (since then I believe visual has improved and textual degraded by all the stupid things I've done)

At any rate I have always struggled to draw or diagram a solution to a problem. I like to write out a paragraph describing it.

Out of curiosity, are you an "inner monologue" type of person?

What reasoning is behind the question?


Unless you're following a regimented and formalized diagram paradigm, drawing is no different than writing. You have to be comfortable with failure and starting over.

I love drawing, but also struggle to make my diagrams relevant and useful in tech applications (software).

On the other hand, diagrams in software have a long and rich tradition. One of the topics I discovered which was fascinating and highly informative was a course on Business Process Management from TU Delft on Edx (though I can't seem to find it now).

I was amazed to discover business concepts diagramed and executable! How's that for formalized.

Besides that, it might just be a case of visual literacy. Katy Borner of Indiana University [3] had a great MOOC, Information Visualization at Edx (though, again, it's not available now).

[1]: https://en.wikipedia.org/wiki/Business_process_management

[2]: http://ebooks.iospress.nl/book/challenging-the-chain-governi...

[3]: https://info.sice.indiana.edu/~katy/

I've personally found that sometimes using a tool like PlantUML[1] or others (lot DOT graphs) to sometimes be easier to create visualizations with. It seems to allow me to focus more on various pieces as the big picture is built. It also seems to provide a great way of ensuring various parties thinking is similar. There are many more diagram types than many realize.

[1]: https://plantuml.com

Think of your experience and context as “ground floor.” You have a lot of it, which makes your starting point much higher than your colleague’s. Some things you are likely naturally taking for granted, he may have no context for. You can’t fake “taking for granted.”

Your goal should not be to help him do something that is hard. It should be to understand how to make it easy.

So, perhaps guide him towards the path of least resistance. He is likely not wanting to draw the wrong thing either; tell him to treat the first version as a draft and make him promise he will throw this one away.

Maybe draw something out for him and be willing to make mistakes in front of him, so he doesn’t feel self conscious about getting it perfect on the first shot.

Lower the stakes, focus on smaller problems, and find a shared vulnerability.

When I've taught friends to code I start with a program flow chart to describe the logic of the program.

Then when things get bigger than a single file/class I introduce the dependency diagram, which helps figure out which components depend on what... This helps you separate concerns logically

Some good tools which help:

- https://code2flow.com/

- https://draw.io/

I used to always make pictures and I still do make a fair amount but it tends to be higher-level system or data/process flows.

When it comes to getting a handle on complexity, I find it better to list all the dimensions of variability and decide how they relate. Any before-and-after (but not necessarily during) invariants are gold. Then I can choose where/when to deal with which dimension(s) while other parts are agnostic to those.

For myself, a quick debriefing after something doesn’t turn out the way I’d liked seems to speed the process of learning from experience. It’s basically just taking a moment to answer a few questions:

- What did you set out to do?

- What actually happened?

- Knowing what you do now, what would you have done differently?

- How does that generalize to a wider class of situations?

Is it still actual and worth time, or paid trainings is already sold? Because slack link is broken =\

Thank you, this looks interesting.

When starting to program so much abstractions take place. So explaining code paths step by step really helps. Plus writing it out, makes it easier to tackle it step by step. Then taking this flow and explaining it to my senior give me great points to ask questions.

generally a person that does not do programming have less friction with the topic if you approach him with a functional style. for example, try to get a proof of concept or a big picture of the problem in excel and build up from there. it does not have to be something complex, replace services and databases with simple rows.

As a programmer also I recommend to learn category theory, which is known for its diagrams (drawing!), its hard for a while, but when you get to adjunctions I found it makes easy to navigate any problem and as a consequence, you can explain/reason about it better.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact