> I love fixing things. I actually enjoy working on a crappy codebase that has made the company money but is now too hard to maintain/extend and needs cleaning. Adding tests, refactoring, extracting functionality to discrete functions, figuring out what the black box actually does, etc. This is what I’ve specialized in.
I am thankful that people like you exist, but after having taken on that role out of necessity myself, I've mostly been left disliking the experience.
Working withing under-documented and under-tested "legacy" codebases, especially the kind where the developers got clever with design patterns, both putting them in when they make sense as well as when they didn't. Those codebases are hard to navigate and hard to refactor (outside of fully automatic renaming/extracting interfaces etc.) and even harder to change - in many cases because you're not even aware of the design assumptions or aspects of the architecture that were made by someone who is now long gone.
For example, I worked on a system where users could submit corrections to data and those could either be accepted or removed. There was a CorrectionFormService, that also was related to CorrectionEntryService, but both of those were abstract and had corresponding CorrectionFooFormService and CorrectionFooEntryService instances, as well as an additional CorrectionFooService. In the database, there also were foos and foos_corrections tables, the latter of which was related to correction_forms, sometimes with additional related tables. The problem was that the logic didn't actually fit such neat structure, so depending on whether you're working with Foo, Bar or Baz, more and more of the methods had to be overriden, as well as new ones added, none of which was actually documented. In most cases you were supposed to have the original_id column point at the foos (or whatever) table id that had the actual data, except when for some reason original_id was the same as id and instead you had something like object_id store that information. And on top of that, there were database views which were used for querying the data, where there were additional rules for the id, original_id and object_id column values, with about 10 prior Jira/Redmine issues related to how this data should work. Not only that, but there were also requirements for accepting some of the data recursively (since parent_id was needed for some of the data structures), but not in all of the cases, only when some other enum column had a particular value in a related table.
Long story short, the more you looked into it, the more details spilled out, to the point where you could not keep a full mental picture of it in mind. Some of the implementation was okay, some of it was ridden with iteration overhead and accidental complexity. Contrast getting to write new code and getting things done in hours, versus spending days if not weeks (across multiple developers, actually) working to get things done within this pre-existing setup. Maintenance work will typically take longer than developing new features and, in my personal experience, will be more mentally draining.