Teaching programming to beginners is a complex task. In this paper, the effects of three factors -choice of programming language, problem-solving training and the use of formative assessment -on learning to program were investigated. The study adopted an iterative methodological approach carried out across four consecutive years. To evaluate the effects of each factor (implemented as a single change in each iteration) on students' learning performance, the study used quantitative, objective metrics. The findings revealed that using a syntactically-simple language (Python) instead of a more complex one (Java) facilitated students' learning of programming concepts. Moreover, teaching problem-solving before programming yielded significant improvements in students' performance. These two factors were found to have variable effects on the acquisition of basic programming concepts. Finally, it was observed that effective formative feedback in the context of introductory programming depends on multiple parameters. The paper discusses the implications of these findings, identifies avenues for further research and argues for the importance of studies in computer science education anchored on sound research methodologies to produce generalizable results.