I have seen my share of this 'program gets output' but the programmer has no clue how she/he got there. It's funny how that happens so many times. 

This is what I have done to at least handle the issue.

Before assessments, I break down the evaluation to include the following. 

 - Simply getting the output gets them the bare passing grade. 
 - Those who can use meaningful names for their variables, function calls get extra.
 - Those that can back up their loops, method calls and variable declarations with expansive ( 2 to 3 lines at least) comments get extra points. 
 - In addition to that, those that can write psuedocode above the program code (perhaps in a big block of comments) get some more. 

Obviously, this makes me their least favourite faculty in terms of evaluation and gets me a lot of complaints but I stick with it.

Update : Please note that, during evaluation, I don't expect all of them to be done. Say, a student is already using meaningful names everywhere, I would not mark her/him down for not writing comments.