Evolutionary Architecture - 9. Guidelines for Evolutionary Architecture ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.png]] things that change, but we don’t want to change remove snowflakes “custom hand-built things” -> remove these [[pattern-immutable-infrastructure-aka-phoenix-server.md|Pattern_ immutable infrastructure (aka phoenix server)]] immutable infrastructure: phoenix server - never change a running server, change the code and rebuild it case study ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.1.png]] ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.2.png]] google search: “bankrupt in 45 minutes” commodities trading firm - PowerPeg -> SMARS -> reused old “FeatureToggle” -> updated it on 7 of 8 servers -> turned on the FT -> 7 machines started doing SMARS, 1 PowerPeg -> SMARS was selling & PowerPeg was buying -> revert deploy but did not turn off FT -> 8 machines now doing PowerPeg problems: -didn’t cleanup old feature toggle -reused feature toggle -didn’t automate deployment Make Decisions Reversible ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.3.png]] blue green deployment canary release -> without over-engineering![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.4.png]] ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.5.png]] predicting changes would be nice, but we can’t unknown unknowns ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.6.png]] ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.7.png]] ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.8.png]] aka “branch by abstraction” ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.9.png]]![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.10.png]]![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.11.png]] -> you now have an “anti-corruption layer” ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.12.png]] ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.13.png]] choose: keep interface or remove? ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.14.png]] ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.15.png]] cf strangler pattern - external scope ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.16.png]] ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.17.png]] know you are building something you will throw away ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.18.png]] Article example: twitter orignally in ruby sometimes it is better to start from scratch 1. capture market 2. retrofit architecture afterwards control change: mitigate external change ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.19.png]] ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.20.png]] example: leftpad.io every platform has this issue Dijkstra: “goto is considered harmful” ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.21.png]] Book: Continuous Integration ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.22.png]] standard: static dependency also needed: - fluid dependency ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.23.png]] change in framework version should trigger a build and potential change in downstream ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.24.png]] ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.25.png]] failed update ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.26.png]] guarded: some developer needs to - fix me - wire me to a static dependency ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.27.png]] ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.28.png]] -> have your own dependency store PR from it eg. reject the PR “remove this leftpad.io dependency” that’s going to break everything eg. protect from malicious code ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.29.png]] ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.30.png]] dependencies work differently libraries: pull model (update only when you want the new functionality) frameworks: push model (aggressively push that update into your codebase, once there is a stable new update) ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.31.png]] (maven popularised snapshots for in flux code) ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.32.png]] versioning service - 2 options - make version number part of endpoint - version internally (don’t change the name of the endpoint ; make the endpoint intelligent -> which version do you want, I’ll send you back the version that you want ; instead of making your client understand all these different versions) ??? -– example company ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.33.png]] initial state: ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.34.png]] introduce toggle router: ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.35.png]] remove old way once nobody uses it anymore: ![[./resources/evolutionary-architecture-9.-guidelines-for-evolut.resources/screenshot.36.png]]