What criteria would you suggest for ranking such tasks in order to create something like "Maintenance Pain" or "Developer Pain", so that one can then just pick the ticket with the highest pain score?
I believe you are looking at this from the wrong direction. You basically have N tasks labeled maintenance or technical debt and you want to compare them together to figure out which one is the biggest issue, fix that first, then continue down the list until all things are fixed.
But you are forgetting something.
Technical debt and messy code affect not just the maintenance but your current work and new features. Technical debt means you decide to make a mess now to gain some benefit or profit form an opportunity and fix it later once things are "more chill", so to speak. If you don't repay the debt, your code gets messier and messier and adding new things or changing existing things becomes harder and harder. That's when you need to think about repaying technical debt or do some long overdue modification that's sitting in the backlog.
To provide an example, say you decide to take on technical debt in some part of the application to chase an opportunity. The code is such a mess that you can't look yourself in the mirror anymore. So you create a backlog task of "Clear up the mess and write a proper implementation" to clear up your conscious later. But with the mess you take advantage of the opportunity. And then you discover that you don't need to touch that part of the application anymore and it doesn't affect adding new features or changing existing ones. What do you do? This is really a huge mess compared with other technical debt tasks in the backlog. So do you work on this or on something else? Put another way, do you clear up the mess or leave it like that?
And most of the times the answer is, you leave it like that. It's isolated in one part of the application you won't work on. It's not something that slows you down on the things you are doing next.
To give an analogy, unpayed technical dept is like walking out into the sea. The first feet are OK, the ground is solid, water is up to your knees. But go further along and your feet are no longer on solid ground, water is up to your head, you struggle to take a breath. You can walk in the sea with water up to your knees indefinitely, but when you are in over your head that's the point you need to turn back. It's the same with technical debt. At that point you need to repay it. Look at what's preventing you from making progress and you will then know what to fix now, and what can wait for later.
It's usually a combination of three things:
- frustrated developers who notice the difficulties in doing their job;
- conflict between developers and managers (i.e. managers want something done within a timeline, developers complain they can't because of <insert specific technical debt here >)
- an increase in defects because of a reoccurring cause or the need for extra trials to make something work instead of getting it right the first time.
Being mindful of your technical practices and business decisions, and keeping track of those three points will give you the information you need to prioritize your technical debt tasks.
In ending, I want to make a distinction between technical debt and plain mess of the code. Taking on technical debt is a (mostly business) decision, to sacrifice something now for a gain, and fix it later when you have nothing else to loose. Technical debt is not a mess caused by bad practices, incompetent developer, lack of skills, etc. That's just a mess. And it's not solved by prioritizing tasks and fixing them, it's prevented by using good practices, working on improving everyone's skills, doing code reviews, refactoring, etc.