Self-adaptive software systems are capable of adjusting their behavior at runtime to achieve certain functional or quality-of-service goals. Often a representation that reflects the internal structure of the managed system is used to reason about its characteristics and make the appropriate adaptation decisions. However, runtime conditions can radically change the internal structure in ways that were not accounted for during their design. As a result, unanticipated changes at runtime that violate the assumptions made about the internal structure of the system could degrade the accuracy of the adaptation decisions. We present an approach for engineering self-adaptive software systems that brings about two innovations: 1) a feature-oriented approach for representing engineers' knowledge of adaptation choices that are deemed practical, and 2) an online learning-based approach for assessing and reasoning about adaptation decisions that does not require an explicit representation of the internal structure of the managed software system. Engineers' knowledge, represented in feature-models, adds structure to learning, which in turn makes online learning feasible. We present an empirical evaluation of the framework using a real-world self-adaptive software system. Results demonstrate the framework's ability to accurately learn the changing dynamics of the system while achieving efficient analysis and adaptation.