Evite codificação sofisticada. Quanto mais complicado o código, maior a probabilidade de haver erros. Geralmente em sistemas modernos, o código claramente escrito será rápido e pequeno o suficiente.
Use bibliotecas disponíveis. A maneira mais fácil de não ter erros ao escrever uma rotina de utilidade é não escrevê-la.
Aprenda algumas técnicas formais para as coisas mais complicadas. Se houver condições complicadas, pregue-as com caneta e papel. Idealmente, conheça algumas técnicas de prova. Se eu puder provar que o código está correto, é quase sempre bom, exceto por erros grandes, burros e óbvios, fáceis de corrigir. Obviamente, isso só vai tão longe, mas às vezes você pode argumentar formalmente sobre coisas pequenas, mas complicadas.
Para o código existente, aprenda a refatorar: como fazer pequenas alterações no código, geralmente usando uma ferramenta automatizada, que torna o código mais legível sem alterar o comportamento.
Não faça nada muito rapidamente. Levar um pouco de tempo para fazer as coisas direito, verificar o que você fez e pensar no que está fazendo pode render muito tempo depois.
Depois de escrever o código, use o que for necessário para torná-lo bom. Os testes de unidade são ótimos. Geralmente, você pode escrever testes com antecedência, o que pode ser um ótimo feedback (se feito de forma consistente, esse é um desenvolvimento orientado a testes). Compile com as opções de aviso e preste atenção aos avisos.
Peça a alguém para olhar o código. Revisões de código formais são boas, mas podem não ser em um momento conveniente. Solicitações pull, ou similares, se o seu scm não suportá-las, permitir revisões assíncronas. A verificação de amigos pode ser uma revisão menos formal. A programação em pares garante que dois pares de olhos olhem para tudo.