This Old Pony: Working with Legacy Django Projects

This Old Pony: Working with Legacy Django Projects

DjangoCon 2016: "Legacy" is a word that produces fear in many software developers. However it means nothing more than software that already exists, and you're probably working with it already, admit it or not. We'll take a tour through what legacy Django projects look like, how to approach them, and how to work on them while keeping your wits.

A3b1bb5e498495de407c0a2547982139?s=128

Ben Lopatin

July 20, 2016
Tweet

Transcript

  1. This Old Pony DjangoCon US 2016- Ben Lopatin Working with

    legacy Django projects
  2. Partner and developer // Wellfire Interactive @bennylope ben@wellfire.co

  3. Legacy software?

  4. None
  5. None
  6. None
  7. What is “legacy”?

  8. Code someone else wrote

  9. None
  10. Code that has no tests

  11. None
  12. Software that’s in production

  13. None
  14. Written software is an investment

  15. Ugly, old systems deliver value

  16. The world runs on legacy software

  17. What is legacy Django?

  18. None
  19. 0 tests run in 0 seconds

  20. Not radically unique

  21. Some assumptions

  22. Goal: improve code in discrete steps

  23. None
  24. This is the right way.

  25. This is the right way. This is some good ideas.

  26. None
  27. Code Review

  28. Why?

  29. Step 0: Ask questions

  30. Talk to people

  31. What’s it supposed to do? What does it do? Known

    bugs? Planned features?
  32. Reading the code

  33. Confusing areas Architecture Code smell Style &c.

  34. Tools

  35. flake8 PyCharm pylint

  36. Logging

  37. Understand production errors

  38. try: do_some_stuff() make_some_calls() except: pass # TODO: handle this! (Chris)

  39. try: do_some_stuff() make_some_calls() except: logger.exception("Chris's error")

  40. Testing

  41. Why?

  42. None
  43. Fix bugs Guide development Deployment confidence

  44. Tests provide information about code quality.

  45. Test suite scenarios

  46. Great tests! No tests! Bad tests Slow tests!

  47. Great tests!

  48. No tests!

  49. Bad tests!

  50. Slow tests!

  51. Prioritizing new tests

  52. Bugs

  53. Smoke tests View-centric integration tests

  54. New features

  55. Refactoring

  56. Upgrading

  57. Backwards incompatibilities

  58. Superpower: tox

  59. tox tox tox tox tox tox tox tox tox tox

    tox tox tox
  60. [tox] envlist = flake8, deployed, py27-django{19,18,17} [testenv] setenv = PYTHONPATH

    = {toxinidir} commands = python manage.py test deps = django17: Django>=1.7,<1.8 django18: Django>=1.8,<1.9 django19: Django>=1.9,<1.10 -r{toxinidir}/requirements/base.txt
  61. Goal: LTS

  62. Dependencies

  63. Tight integration with obsolete libraries

  64. Unnecessary version [over]-specification

  65. Version support mismatches

  66. None
  67. {

  68. { Version Compatibility

  69. None
  70. Upgrade!

  71. None
  72. Solutions

  73. Patch and pray (upstream)

  74. Fork

  75. Extract what you used

  76. Remove/replace

  77. pur pip-tools

  78. $ pur -r requirements.txt Updated flask: 0.9 -> 0.10.1 Updated

    sqlalchemy: 0.9.10 -> 1.0.12 Updated alembic: 0.8.4 -> 0.8.6 All requirements up-to-date.
  79. Issues

  80. Formatting

  81. None
  82. autopep8 PyCharm

  83. Settings

  84. Secrets!

  85. bandit

  86. One big app

  87. None
  88. Solution: Break up apps

  89. Big views (lots o’ logic)

  90. “Fat models”

  91. Humongous managers

  92. Expansive forms

  93. Not just views

  94. Seek to minimize scope of changes, continually.

  95. Refactor as you go

  96. New feature? New app!

  97. Feature uses old code? Refactor old code.

  98. What didn’t we talk about?

  99. Continuous integration Automated deployment Configuration management Documentation Security

  100. The End

  101. I am ready for your questions