logo

drewdevault.com

[mirror] blog and personal website of Drew DeVault git clone https://hacktivis.me/git/mirror/drewdevault.com.git

Avoid-traumatic-changes.md (4551B)


  1. ---
  2. date: 2019-11-26
  3. layout: post
  4. title: Software developers should avoid traumatic changes
  5. ---
  6. A lot of software has gone through changes which, in retrospect, I would
  7. describe as "traumatic" to their communities. I recognize these sorts of changes
  8. by their effect: we might have pulled through in the end, but only after a lot
  9. of heartbreak, struggle, and hours of wasted hacking; but the change left a scar
  10. on the community.
  11. There are two common cases in which a change risks introducing this kind of
  12. trauma:
  13. 1. It requires everyone in the community, or nearly everyone, to overhaul their
  14. code to get it **working** again
  15. 2. It requires everyone in the community, or nearly everyone, to overhaul their
  16. code to get it **idiomatic** again
  17. Let's call these cases, respectively, strong and weak trauma. While these are
  18. both traumatic changes, the kind of trauma they inflict on the community is
  19. different. The first kind is more severe, but the latter is a bad idea, too. We
  20. can examine these through two case-studies in Python: the (in)famous transition
  21. to Python 3, and the less notorious introduction of asyncio.
  22. In less than one month, Python 2 will reach its end of life, and even as a
  23. staunch advocate of Python 3, I too have some software which is not going to
  24. make it to the finish line in time[^1]. There's no doubt that Python 3 is much,
  25. much better than Python 2. However, the transition was poorly handled, and
  26. upgrading can be no small task for some projects. The result has been hugely
  27. divisive and intimately familiar to anyone who works with Python, creating
  28. massive rifts in the community and wasting millions of hours of engineer time
  29. addressing. This kind of "strong" trauma is fairly easy to spot in advance.
  30. [^1]: Eh, kind of. I'm theoretically behind the effort to drop Python 2 from Alpine Linux, but the overhaul is tons of work and the time I can put into the effort isn't going to be enough to finish before 2020.
  31. The weaker kind of traumatic change is more subtle, and less talked about. It's
  32. a slow burn, and it takes a long time for its issues to manifest. Consider the
  33. case of asyncio: clearly it's an improvement for Python, whose previous attempts
  34. at concurrency have fallen completely flat. The introduction of async/await and
  35. coroutines throughout the software ecosystem is something I'm generally very
  36. pleased about. You'll see me reach for threads to solve a problem when hell
  37. freezes over, and no earlier, so I'm quite fond of first-class coroutines.
  38. Unfortunately, this has a chilling effect on existing Python code. The
  39. introduction of asyncio has made large amounts of code idiomatically obsolete.
  40. Requests, the darling of the Python world, is effectively useless in a
  41. theoretical idiomatic post-asyncio world. The same is true of Flask, SQLAlchemy,
  42. and many, many other projects. Just about anything that does I/O is unidiomatic
  43. now.
  44. Since nothing has actually *broken* with this change, the effects are more
  45. subtle than with strong traumatic changes. The effect of asyncio has been to
  46. hasten the onset of code rot. Almost all of SourceHut's code pre-dates asyncio,
  47. for example, and I'm starting to feel the limitations of the pre-asyncio model.
  48. The opportunity to solve this problem by rewriting with asyncio in mind,
  49. however, also presents me a chance to rewrite in anything else, and reevaluate
  50. my choice of Python for the project entirely. It's a tough decision to think
  51. about — the mature and diverse ecosystem of libraries that help to make a
  52. case for Python is dramatically reduced when asyncio support is a consideration.
  53. It may take years for the trauma to fully manifest, but the rift is still there
  54. and can only grow. Large amounts of code is rotting and will have to be thrown
  55. away for the brave new asyncio world. The introduction of asyncio has made
  56. another clear "before" and "after" in the Python ecosystem. The years in between
  57. will be rough, because all new Python code will either leverage the rotting
  58. pre-asyncio ecosystem or suffer through an immature post-asyncio ecosystem.
  59. It'll likely turn out for the better — years from now.
  60. And sometimes these changes *are* for the better, but they should be carefully
  61. thought out, and designed to minimize the potential impact. In practical terms,
  62. it's for this reason that I urge caution with ideas like adding generics to
  63. Go. In a post-generics world, a large amount of the Go ecosystem will suddenly
  64. become unidiomatic, and breaking changes will required to bring it up to spec.
  65. Let's think carefully about it, eh?