Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Silent Running: Dark Launches, Feature Toggles ...

Silent Running: Dark Launches, Feature Toggles & Avoiding Technical Debt

- Shipping frequent, low-risk, regularly scheduled releases as part of a continuous deployment strategy is widely regarded as a valuable agile practice.
- Achieving continuous deployment nirvana can be a big ask for mobile apps, particularly for iOS where the vagaries of the App Store approval process can lead to unwelcome & unpredictable delays.
- This talk will consider the merits of feature toggles and dark launches and the beneficial impact they can have on your development workflow
- We'll also take a look at a Swift approach to minimising the technical debt inherent in these approaches.

Avatar for Tim Antrobus

Tim Antrobus

October 15, 2015

More Decks by Tim Antrobus

Other Decks in Technology

Transcript

  1. KEY THEMES ▸ Continuous delivery - quicker feedback, better quality

    ▸ Continuous delivery for native mobile apps - LOLWUT ? ▸ DevOps secret sauce: Dark launches & feature toggles ▸ Reshaping your delivery process to reshape your code ▸ How to avoid getting up to your ears in technical debt
  2. CONTINUOUS DELIVERY (CD) ▸ Quick feedback is key to Agile.

    Shapes next steps ▸ Reduced risk via smaller, more frequent releases ▸ Minimises codebase complexity & stale branches ▸ Focus on optimising process for quality/learning ▸ ScrumBan + GitHub + CI + Cloud Platform = ❤
  3. CD FOR NATIVE MOBILE APPS - THE GOOD NEWS ▸

    Mobile apps often a superset of server backend and client frontend ▸ Continuous delivery dovetails well with server tech stacks & tooling ▸ Apple CloudKit is a notable exception - keep control & roll your own ▸ Implement a server for greater flexibility & separation of concerns
  4. CD FOR NATIVE MOBILE APPS - I'M SORRY DAVE... ▸

    Apple & Google own the OS, platform and means of distribution ▸ They make the rules & often change them + annual OS updates ▸ App Store review delay breaks the CD model & negates benefits ▸ Unpredictable feedback cycle, opaque platforms, loss of control ▸ Amplifies the complexity & thus the cost of production bug fixes
  5. DARK LAUNCHES - FEATURES IN THE AIRLOCK ▸ Release server

    side & native app logic early prior to surfacing in UI ▸ Exercise new logic/components to gather metrics & de-risk rollout ▸ Leverage MVVM app architecture ViewModels to play new features
  6. FEATURE TOGGLES TO THE RESCUE ▸ Conditional activation of app

    features via static or dynamic config ▸ Not just binary on/off switches - can be complex A/B testing logic ▸ Staggered release, deploy to specific user segments/geographies ▸ Push unfinished feature code to avoid long-lived feature branches ▸ Ensure all deployable features present in App Store release binary
  7. FEATURIZE ALL THE THINGS ! ▸ You've got a feature

    toggle hammer so every feature looks like a nail ▸ Decompose your app structure into loosely coupled atomic features ▸ Play nice with App Store constraints but regain autonomy & control ▸ Quickly address production bugs with fine-grained feature rollbacks ▸ Beneficial impact of featurization on backlog grooming & estimation
  8. CASE STUDY : IOS @ SPOTIFY ▸ 500 KLOC, 40

    iOS devs, 100's of daily commits, millions of users ▸ Only 70% of branches were successfully merged back to master ▸ Sophisticated backend to manage features for users or markets ▸ Small feature teams merging code into master many times a day ▸ Feature driven workflow sees 90% of branches merged to master ▸ Master branch stable no need for release branch - deploy 2x week
  9. RUNNER ! YOU ARE TERMINATED ▸ Implement clear lifecycle management

    process for feature toggles ▸ Apply RESTful CRUD semantics for toggle management interactions ▸ Some features may be long-lived. Automate removal of old features ▸ Collect features in meaningful groupings & use to manage lifecycle
  10. SWIFT PROTOCOL ORIENTED SOLUTION TO TACKLE TECH DEBT ▸ Provides

    flexibility & extensibility without bloating codebase ▸ Minimise boilerplate & tight coupling via protocol extensions ▸ Supports feature switching & more complex conditional logic ▸ Uses value types, generics, closures & higher order functions ▸ Implement in a Swift module delivered as dynamic framework
  11. PROTOCOLS DEFINE CONTRACTS FOR BEHAVIOURS ▸ 'Togglable' Features - unique

    identity, status & actions ▸ Feature Contexts - meaningful scope to group features ▸ Feature Predicates - encapsulation of conditional logic ▸ Feature Source - abstraction of toggle status provider
  12. PROTOCOL EXTENSIONS IMPLEMENT DEFAULT BEHAVIOURS ▸ Avoids boilerplate, enforces 'DRY',

    implements 'traits' ▸ More flexible, powerful code sharing than inheritance ▸ Useful hook for extensibility for framework consumer
  13. TOGGLABLE PROTOCOL & EXTENSION public protocol Togglable { var context:

    FeatureContext {get} var signature: FeatureSignature {get} var featureSource: FeatureSource {get} func featurePredicates() -> [FeaturePredicate]? mutating func bindFeaturePredicates(predicates: [FeaturePredicate]) -> () } public extension Togglable { func shouldExecuteFeature() -> Bool { guard let activeFeature = featureSource.activeFeature(context, signature: signature) else { return false } let activeFeaturePredicates = featurePredicates() return activeFeature.shouldExecute(activeFeaturePredicates) } }
  14. GENERIC TOGGLE CONDITION TYPE TO ENCAPSULATE PREDICATES public struct ToggleCondition<T>

    : FeaturePredicate { public typealias Evaluator = T -> Bool private let subject: T private let evaluator: Evaluator public init(subject: T, evaluator: Evaluator){ self.subject = subject self.evaluator = evaluator } public func evaluate() -> Bool { return evaluator(subject) } }
  15. PREDICATE EVALUATION LOGIC SUPPORTS ON/OFF OR CONDITIONAL FEATURES public protocol

    ConditionalFeature : Feature { func shouldExecute(conditions: [FeaturePredicate]?) -> Bool } public extension ConditionalFeature { public func isActive() -> Bool { return status == FeatureStatus.Active } public func shouldExecute(conditions: [FeaturePredicate]?) -> Bool { guard let predicates = conditions else { return isActive() } return predicates.reduce(isActive()) { (aggregate: Bool, predicate: FeaturePredicate) in return aggregate && predicate.evaluate() } } }
  16. SILENT RUNNING : DOUGLAS TRUMBULL, 1972 PLANET OF THE APES

    : FRANKLIN J SHAFFNER, 1968 BLADE RUNNER : RIDLEY SCOTT, 1982 2001 A SPACE ODYSSEY : STANLEY KUBRICK, 1968 STAR WARS : GEORGE LUCAS, 1977 ALIEN : RIDLEY SCOTT, 1979 THUNDERBIRDS ARE GO : DAVID LANE, 1966 THEY LIVE : JOHN CARPENTER, 1988 THE MAN WHO FELL TO EARTH : NICOLAS ROEG, 1976 LOGAN'S RUN : MICHAEL ANDERSON, 1976