tl;dr On the contrary, you should start to ask yourself if to be a Software Engineer is the right career path when you stop caring about quality.
There are good books about dealing with legacy software (for example the evergreen Working Effectively With Legacy Code); the point is that you do not have to ASK to write good software as you do not have to ask to test the code you write. Refactoring and improving quality of existing code is almost always part of the maintenance process, as writing tests is also part of delivering a new feature. Related and interesting: As a developer; Not getting time to test, receiving extreme deadlines and not being listened to by the manager.
You can run away every single time, pursuing the perfect company chimera with the perfect code base (or always new projects without any legacy). Alternatively you can embrace this challenge and add your own professional value to the company you're working for.
Working on older projects will also teach you extremely important lessons about scalability, reliability and maintenability that you won't ever learn if you keep switching to new projects every year or so.
What you may improve is your approach to the problem. First of all you have to understand that technical debt is intrinsic in almost every software project, this is a fundamental point and you can't change it.
As you already know a technical debt may be high because of many reasons:
- The project started as a prototype (if not just a proof of concept) and then evolved over time. It might be because a poor SE choice or because of a business choice (no time to rewrite something that more or less works).
- The project started as a simple tool and evolved to something too big to fit the original architecture/design. This usually happens in small steps where code goes progressively out-of-control.
- Source code has been originally written or maintained by someone with a less than optimal skillset.
- Source code has been well written but it's old, technology and best practice evolved enough to make it "outdated" but still functional.
- Regardless original source code quality the applied business pressure (for example in a Startup environment) forced more and more technical debt.
After you embraced this revelation you have to understand how to deal with it. Sometimes a complete rewrite is a possible choice but you, usually, need to explain your managers what is the value that this big investment will bring to the company. This has been widely discussed and I won't repeat it here, the correct strategy is slightly different for each the above mentioned cases. This is the main point: a non-technical (but also a technical one because from her position she will see things from a different point of view) manager is not against quality but they need to justify the investment, consider:
- Rewriting is expensive and provides no visible short-term output, and they may not even have a budget for this.
- It's a risk because you will (for sure) introduce new bugs.
- You may fail, any non-trivial project may fail (someone even says that most software projects fail) and then they'll have the original code base and X months of wasted time (or a new code base with the same, if not more, problems than the original one.)
What to do? Start with communication: first of all explain the situtation but don't simply go ranting about code quality or you will be unheard:
- Be prepared: provide examples of when poor existing code quality was the source of some major production issue.
- Be prepared: provide few different estimations of simple tasks that required much more time than it should be (again because of existing code quality).
- Be prepared to discuss a potential architecture for the new implementation.
- Be prepared: provide a wild (at this stage) but educated estimation.
- Be prepared: provide a road map of how this transition may be conducted and which resources you will need. As Stefan noted in a comment this does not need to be made in one big jump.
If they do not agree with such rewrite (it might well be) then you have to take a step-by-step approach as part of your daily duties.
What you can do is to understand that it's YOUR DUTY to write good code with all the constraints given by your management (time, budget, resources). It means that you MUST:
- Write tests every single time you change something.
- Apply basic local refactoring techniques every time you're adding a feature or fixing a bug.
- When big changes are required then you may extend refactoring to other modules/packages keeping them as small as required to complete the immediate task.
- Schedule, if possible, some intra-module refactoring time when - after local refactoring has been completed - you see an opportunity to clean-up one step above.
- Apply all of the above to collateral elements (like documentation, for example.)
Iterate enough times and your code base will now be good enough. Sometimes some big architectural changes may need approval because they're too long or complex but when you're at that point you probably have an already solid base.
This is an invisible process, quality is constantly evolving but it's not necessarily visible from outside. I think this is what Tom (the firt boss' boss) tried to tell you: "do your job (step by step!) without bothering your boss, it's your duty and I trust you know how to do it (send him to me if, by case, he doesn't understand this)." Should he had to speak about it with your boss? I can't say but if you do your job in a non desruptive way then the process is invisible and effective.
Sometimes they [management/boss] are to blame but it's often a communication problem, you may like to read Representation and Misrepresentation: Tufte and the Morton Thiokol Engineers on the Challenger and original Tufte's text in Visual Explanations: Images and Quantities, Evidence and Narrative.