Engineering software that is subject to uncertainties that are difficult to anticipate before deployment is challenging. Self-adaptation extends a software system with an external feedback loop system that monitors the system and adapts its configuration or architecture to ensure that its qualities are met under uncertain operating conditions. In this tutorial, we provide a particular perspective on the evolution of the field of selfadaptation in six waves. These waves put complementary aspects of engineering self-adaptive systems in focus that synergetically have contributed to the current body of knowledge in the field.