Software Design For Flexibility: How To Avoid Programming Yourself Into A Corner