Pro Yearly is on sale from $80 to $50! »

Evergreen Legacy Applications

F863e9eb811851834773398e72614dc1?s=47 Harry Wolff
September 27, 2019

Evergreen Legacy Applications

Let’s make what’s old, new!

F863e9eb811851834773398e72614dc1?s=128

Harry Wolff

September 27, 2019
Tweet

Transcript

  1. None
  2. None
  3. None
  4. None
  5. None
  6. None
  7. Evergreen Legacy Application

  8. hswolff.com @hswolff

  9. None
  10. youtube.com/hswolff

  11. None
  12. None
  13. None
  14. None
  15. None
  16. None
  17. None
  18. None
  19. #thoughtleadership

  20. Rule 1 Have a good reason to do it

  21. Rule 1: Have a good reason to do it •

    Why are you even bothering? What are you trying to solve? • Does the state of your current application make it difficult to add more features? • Is it hard for you to recruit because the job market for the tech you use is shrinking? • Make sure you have a good reason for tackling this large tech debt problem before you begin.
  22. Rule 2 Don't stop and rewrite everything

  23. Rule 2: Don't stop and rewrite everything • This is

    a stop the world solution and one that is rarely a good idea. • It takes a lot of time to get to parity with your existing application. • Hard to rediscover all the edge case bugs that were fixed over years. • Stops work on new functionality. Which can be hugely damaging to a young company. • There are times when it's the right call… • …but those are the exceptions, not the rule.
  24. Rule 3 Prepare to be in a state of constant

    migration
  25. Rule 3: Prepare to be in a state of constant

    migration • Having an Evergreen Legacy Application means your old code and new code will exist alongside each. Possibly forever. • You have to be ok with living in this hybrid world. • Prepared to take a small cost when switching context between the old and the new. • It's ok to not have an end path to removing legacy code, but you have to be ok with living in a world of flux
  26. Rule 4 What is new today is legacy tomorrow

  27. Rule 4: What is new today is legacy tomorrow •

    Be careful with how many new things you adopt. • Each new thing increases your overall maintenance burden. • Eventually everything becomes legacy.
  28. Harry’s 4 Rules • Rule 1: Have a good reason

    to do it • Rule 2: Don't stop and rewrite everything • Rule 3: Prepare to be in a state of constant migration • Rule 4: What is new today is legacy tomorrow
  29. Harry’s 4 Rules • Rule 1: Have a good reason

    to do it • Rule 2: Don't stop and rewrite everything • Rule 3: Prepare to be in a state of constant migration • Rule 4: What is new today is legacy tomorrow
  30. 2009

  31. 2009

  32. V1: 2009 Server with jQuery

  33. 2014

  34. V1: 2009 Server with jQuery V2: 2014 SPA w/ Backbone.js

  35. React

  36. V1: 2009 Server with jQuery V2: 2014 SPA w/ Backbone.js

    V3: 2017 SPA w/ React
  37. None
  38. Rule 2 Don't stop and rewrite everything Don't stop and

    rewrite everything
  39. None
  40. None
  41. React + = ♥

  42. UI Data Styles

  43. None
  44. Rule 3 Prepare to be in a state of constant

    migration
  45. None
  46. const FooterView = mixInto(Marionette.View)( onInitialRenderPromise, removeViewOnDestroyMixin ).extend({ className: 'app-footer', template,

    initialize() { this.onInitialRender.then(() => this.render()); }, });
  47. const FooterView = mixInto(Marionette.View)( onInitialRenderPromise, removeViewOnDestroyMixin, viewWithReact ).extend({ className: 'app-footer',

    template, initialize() { this.onInitialRender.then(() => this.render()); this.registerReactComponent( <BackboneProvider models={{ settings: this.model }}> <SiteFooterBackbone /> </BackboneProvider>, '.js-react-site-footer' ); },
  48. registerReactComponent(reactElement, selector) { this._registeredReactMetadata[selector] = { mounted: false, reactElement, selector,

    }; }, onRender() { Object.keys(this._registeredReactMetadata).forEach(selector => { const reactComponent = this._registeredReactMetadata[selector]; const domElement = this._getElForSelector(reactComponent.selector); ReactDOM.render(reactComponent.reactElement, domElement); }); },
  49. UI Migration 1.Add viewWithReact mixin 2.Register React Component 3.Profit!

  50. None
  51. const person = { name: 'harry', location: 'spain', }; const

    model = new Backbone.Model(person); model.get('name'); // 'harry' model.set('name');
  52. None
  53. class BackboneWrapper extends React.Component { componentDidMount() { this.props.model.on('change', this.handleChange); }

    componentWillUnmount() { this.props.model.off('change', this.handleChange); } render() { return <li>{this.props.model.get('text')}</li>; } } <BackboneWrapper model={model} />
  54. None
  55. import { connectBackboneToReact } from 'connect-backbone-to-react';

  56. const userBackboneModel = new Backbone.Model({ name: 'harry', location: 'spain', });

    const mapModelsToProps = (models) => { const { user } = models; return { name: user.get('name'), location: user.get('location), }; }; const MyComponentConnected = connectBackboneToReact(mapModelsToProps)(MyComponent); function MyComponent({ name, location }) { // All it has to worry about is plain javascript values. } <MyComponentConnected model={{user: userBackboneModel }} />
  57. None
  58. Rule 4 What is new today is legacy tomorrow

  59. None
  60. None
  61. this.registerReactComponent( <ReduxProvider store={reduxStore}> <BackboneProvider models={{ settings: settingsModel }}> <SiteHeader />

    </BackboneProvider> </ReduxProvider>, '.js-react-site-header' );
  62. None
  63. None
  64. None
  65. None
  66. None
  67. Evergreen Legacy Application @hswolff youtube.com/hswolff