Utilizing Information Technology and Hands-on Learning Practices to Improve Student Learning Outcomes in a High Failure Rate Introductory Programming Course