We have academic clinics once a week and in supporting a pupil who was struggling with Python, I realised there was an issue I hadn't noticed before. He was struggling to solve an exercise and I asked him to explain his code to me. It occurred to me that he was not looking ahead in his code, he was literally explaining one line at a time to me with no reference to any aim or purpose. I started to question him to check that and it became clear why he was stuck: he just wasn't forming an overall picture of his solution; he didn't really know what he had done!
This led to me to create a set of exercises where pupils had to improve coded solutions to problems. All the solutions worked but they were written poorly. They did not include a description of what they were supposed to do so pupils had to work that out as well. I used single-letter variable names, no input prompts and no output messages which, I have to say made writing the programs really hard! I ended up having to write the fixed versions and then 'break' them.
Pupils needed to be persistent and curious about what the code did. They needed to read it carefully and run it multiple times with different inputs.
Even my strongest programmers found this quite difficult. Part of this was because it is genuinely more difficult to follow someone else's code, even if it is written well as it just might not reflect your way of thinking about a solution. However, one of those pupils came to me outside a lesson and told me how much he loved these exercises. He said they were really showing him ways in which he was writing poor code and compelling him to reflect on his approach - I was very pleased about that!
I have to admit that I (not very) secretly enjoyed torturing them with single-letter variables and incomprehensible code - revenge at last!