I believe this is a problem with my code, as I cannot recall the last time some else's code has taken an hour of explanation to understand.
I'm happy to see this conclusion. Most commonly, people blame others for not understanding. It shows you can see things from other people's perspective, which is going to help you solve this issue.
Specifically, when posed with the question "I don't understand your code", what are some strategies I can use to explain my code?
Clean coding means writing readable code, preferably code that is readable enough that it requires no documentation. Your explanation, even if not written down, counts as "documentation".
Rather than trying to explain your code, rewrite your code to explain itself. The better response here isn't to tell your coworker what the code does (I'll humorously refer to that as "devsplaining"), but instead ask your coworker what is unclear about it. Take that feedback and revisit your code to see if you can rewrite it so that the unclear parts become clear.
I can't tell you that all code ever written should be crystal clear without any documentation or comments - that's overreaching. But crystal clear code is the goal, even if you never perfectly attain it.
Sometimes this works, but often the answer is "the whole thing". I have been in meetings with 5 other programmers, where all of the programmers agreed they didn't understand my code, but none of them could give any specifics parts which were confusing.
Assuming these developers are all of equal or greater skill to you, and they have the expected contextual knowledge of the application, this signals to me that you need to rework your code from the ground up.
"Are you familiar with concept X?"
I can't make any final conclusions here, but I do want to point two things out:
- Watch out with your tone when you ask if someone is familiar with something. It can come across as passive aggressive or suggesting that the other person lacks the required skill to understand your code. Even if that is objectively correct (e.g. a junior dev), it's still not the best way to express yourself.
- If you are genuinely dealing with developers who don't know a design pattern you've used, that seems to suggest that maybe your coworkers are lower skilled than you. However, even if you used a design pattern correctly, it's still possible (and I would guess likely, based on some indirect inferences from your question) that your low code readability is obfuscating an otherwise correct implementation of a design pattern.
Sometimes I try to get them to actively engage with solving the general problem, hoping that if they explain how they would solve it, I can show them the parallels between their solution and mine. This works, however often times the problem is a bit too complicated to just solve in your head
If that is the case, then the code you wrote has not been reasonably abstracted. Using clean coding and good practice, your code should already be subdivided into easily digestible chunks of logic, and you should be able to discuss one of these chunks by themselves. If you can't to that with your code, then your code is not separating its responsibilities correctly.
You haven't really shown concrete examples so I cannot judge your code. By extension, I cannot conclude whether you're making things too difficult or your coworker's skill it too low. However, based on what I read in your question, my educated guess is that your code works but is unreadable, and you're currently not in an environment where clean coding is actively enforced, so you're only relying on wondering if the code works or not, not whether it passes the smell test.
You said your colleagues communicate among themselves without much confusion, so what I would do is inspect their code. Do you understand their code better than they understand yours? How is their code different?
Secondly, putting your code itself aside for a minute, you also seem to struggle with explaining your intentions to others. That's also a problem. Me and my coworkers are generally able to explain implementation to each other without even looking at the code itself. We of course don't delve into specifics, but explaining the general design (i.e. "mental diagram") is not something you need to see concrete code for.
I think both your code quality issues and problems with explaining your design stem from the same problem. I'm paraphrasing here, but there's a well known quote that strikes at the heart of this:
Software development is breaking a problem down into a series of smaller and smaller problems until each individual problem is trivial to solve.
My personal addition to that adage is that programming (as opposed to development) is implementing those individually trivial problems.
If your code and explanation are too convoluted, then you haven't broken the problem down enough for things to become trivial.
Never forget that any solution to a problem, no matter how difficult that problem is, is really just a sequence of steps, each of which is trivially simple by itself.