software problem solving techniques