Formal training or not - there are a few simple guidelines to making good code. Good in this context meaning easy to read, follow and debug.
- Don't repeat yourself. Got something you do again and again with only minor deviations? Pack it up in a function!
- Avoid multilayered nesting. Got If statements packed inside a select-case statement in a for loop triggered by yet another if statement? If you got three or more layers of nesting, abstract away into functions.
- Avoid globals. In AppGameKit some things do well to have access to all over, like image IDs, sprite IDs and such. But control-variables should be restricted and local - and if need be, passed by reference.
- Avoid discrete variables, pack them up into datatypes instead. Only temporary throwaway variables should be discrete. This makes it easy to pass data around, and add new fields and functionality into existing structures and code without doing a lot of editing of old code.
- Group functions by, well, function in separate files. If a function do input like say reading a key, have it in a file called 'input.agc' and import into main using #include "input.agc". Same with output, views, fileIO, httpIO etc. Makes it easy to find what you are looking for in a big project.
- Functions should do as little as possible to get *one* job done, but no less! So shorter functions is better than longer functions. Though, that said, don't be afraid of long functions. As long as it is focused on doing one job, all is well.
- Plan ahead. Not in any detail, but by main functionality. This helps with setting up initial structure and datatypes, which saves you a ton of work later on.
...and finally and most important:
- Make sure you're fully stocked up with coffee and caffeinated soft-drinks.