Good naming. Or, if it's someone else's code, trying to attribute good names / responsibilities based on even bad names on that system's classes / functions so it makes sense in my head. Once it does, the low-level implementations become way easier to remember.
That's all I have. There are a lot of purists on this site who will swear-by god-knows what patterns or objects of whatever types, but good naming will get you far. I've done more than well by myself by creating minimally documented / well-named / well decoupled code and it never came back to bite me, even if my code was used in a lot of places, by a lot of people, but the one thing I did right was waste a lot of time on good naming, good comments and schematics that explained the flow of my code. Low-level implementation is necessary to understand if you desire to expand on my code in a deep way. Well written code can be expanded in reasonable ways, so, it's ok that someone or you don't understand / remember the low-level implementations.
If you're interested in a bit of controversy that people in my original field as well as me know to be the truth, but, if you listen to what is written down here, you'll learn to both agree and disagree to this answer, read on ahead:
But there's another issue at hand here - purists. You'll hear well-worded answers and ideologies that are reasonable and completely logical, in fact, there's nothing wrong with them. But you don't have to follow them, in fact, they might be playing into your disadvantage.
My friends worked with big systems and they just laugh off people who care a tad bit too much about conventions and patterns and for good reason, I'd do it too - I can find my reasoning for this from my main field of data analysis, since I'm not such an experienced developer: Most of the things you think matter, don't matter and there's a strong correlation to your ego in this sense. Often times an individual, due to his ego, will have obtained knowledge that he most likely misunderstood due to his biases that are now re-inforced by the an authority that he thinks just said "the same thing I did". This is a very well known trap which you should never fall into. This doesn't mean he's not using it rightly or for the greater good, but often times, what these people will do is promise that whatever they're saying is the golden prize.
So what can you do?
Explain your code to a co-worker and ask them if it makes sense from a high-level point of view.
That's all that matters. Of course anyone that's reading someone else's code will always have an alt-tab fiesta to see certain things' implementation, but that doesn't matter, if whoever's reading your code has the high-level understanding of your system and understands "why things happen" (again, without necessarily knowing, fully "how they happen"), then you're golden.
This is not me saying go ahead and write crap code that's not performant or doesn't respect anything, but what I'm saying is:
1) It's okay to forget. In time, you'll get better at reading code you're working with. If the code you're reading demands you know the low-level implementations at a good level, then it's code badly written and it plays into what I said before: does a co-worker understand you?
2) The world is filled with a lot of very intelligent people who are not very smart. They're also often times very emotional and they're prone to bias-reinforcing from outside forces. They are very good at what they do, but what they, as actors of spreading information forget is: ideas / information, even if backed by "logic" have the context of the one sending them, which is crucial in understanding whether or not that information is useful to you too. What makes sense for you could make sense for others and they'd love it but information shouldn't be taken as absolute and one, again, should consider, or at least try to figure out the context where it came from and check against his own context to see if it matches. It's really the same as billionaires giving us these "bits of knowledge to get ahead" - it surely is easy to say the things they say, but harder to implement, of course, this is a dumb example but you get the idea.
In short: write code that's understandable and realize that it's still debatable where we need as many patterns / classes and refinery as some say. There's very smart people on both sides of the argument and it should only reinforce the idea of doing whatever works for your team in a reasonable manner -- don't be stuck on small details that don't matter, you'll figure them out later, remember, you live in an extremely competitive world where timing is the most important thing:
Timing in startups success.
Allocate your time and resources in a meaningful, greedy way.