You can try to work with your team/coworkers to build up a checklist of good questions to ask yourself while reviewing each other's code, ideally tailoring it to the languages you code in, the projects you work on, the domains in which your code runs, etc. In practice, I don't think it's reasonable to expect developers to pull out a spreadsheet and check it off every time they review code, but I think it's a good exercise to periodically do nonetheless. Additionally, if all code review "results"/responses are sent to the entire team, you can learn from the sorts of things that more experienced developers look for and spot during code reviews. (It also tends to lead to pretty good discussion.) At a few points, my team actually all got together to go through a sample code review, comparing each of the comments we had privately made...
As for specific questions to ask yourself, here is a non-exhaustive list of some of my usual ones (in no particular order):
- Is the code correct, according to the design of the change?
- Is the change approaching the problem in the right way--from a design perspective?
- What is the context in which this code runs?
- Are there any possible corner cases / boundary conditions that are being missed? Are all failure points / failure modes appropriately and correctly handled?
- How hard will it be to test and maintain the code introduced by this change?
- Will any behavioral changes introduced be surfaced to end-users? If so, will the end-users' experience be negatively impacted?
- Is there a simpler fix possible that accomplishes the same work with negligible disadvantages?
- How will this change impact the performance of the application/library/driver in question? Might any leaks be introduced?
- Does any new code duplicate existing functionality present elsewhere in the software project, or perhaps in an external library that could be used instead?
- How easy is it to understand the code? (Is it commented "enough"?)
- etc.
The most important question for me is one of the first in my list--regardless of how good the code is, is the code change trying to do the right thing. Many times I've seen well-coded changes that don't leak memory, are performant, handle errors robustly, etc. but still aren't the right changes to make for the overall library/product/project.