loading...

Prioritization for Perfectionists, or: How I Learned to Stop Worrying and Love the Non-Perfection

ice_lenor profile image Elena ・6 min read

Are you a perfectionist? That kind of a person that can never say "I'm done", "it's ready" or "let's ship it"? The one who can't release the new feature unless it's polished and perfect?

Me too. I just don't seem to be able to stop. When I work on my personal projects, the backlog seems to grow every minute.

"Refactor this!"

"Improve that!"

"Make that button align with other buttons on another screen!"

"Improve drawing speed by refactoring X!"

"Write more comments to that algorithm!"

"Write tests for Y and Z cases!"

"Optimize this algorithm!"

And even:

"Redraw this icon", "change the color of this button", and "move this one pixel to the left".

I can't even publish an article in my blog without re-reading it many times and rewriting a couple.

I can't even tweet without deleting the tweet and reposting it.

Guess how many times I changed the following header, just swapping the words in it there and back? :)

Ice and Fire

Yes, this header.

Pretty chill

My career started at a company where we paid much attention to code quality. This played along very well with my perfectionist nature. I could polish a four hour task for a couple of hours more than needed, before giving it out to code review. I was always in the mood of adding just a couple more tests to a complex business logic module.

The company didn't have plenty of developers nor lots of money to hire more, but our users were demanding, had a lot of complex business requirements, and their work depended on our product and its quality very much. So the code quality was very important. Because of that, the bugs were fixed on time and completely, and the developers didn't spend lots of time adding new features, as the system grew.

And it worked: by investing some more time in the beginning, by being slower, we managed to save more time later. How many times have I looked at a new ticket and thought: now nice we've refactored that place a month ago! Now it's much easier to implement this new task.

Some time has passed, and I found myself in a completely opposite company.

Hot lava

In this company the speed of delivery was valued more than anything. It was okay to ship completely messed-up code, but you should've done it on time. And no one is allowed to refactor. There's no time for that. Ship features, and ship fast!

This approach has its points. If you are not on time, you've failed, and never mind how good your code was. Also never mind how bad your code was, if it was on time and (at least partially) worked. The business was above all, the time was money, the product was important, the code was secondary and disposable.

No one cared too much about bugs too. Well, sometimes it fails, sometimes it displays invalid data, but there's no time to fix small things. No tests too. New features are more important.

But how many times have I looked at a finished task and thought: it took me just half of the time it'd take if I was doing it as comprehensively as before. Sometimes it felt like slacking, I must admit, but it was much faster and more business-effective than in the previous company.

This approach was very new for me, and it took me some time to digest it, but I've found the middle ground at last.

My middle ground

In the winter, soon after I started at the second company, I also started a pet project - a small Android app called Word Cloud, which makes nice and colorful word clouds.

I can visibly compare how different my approach was back then, when I just started. I took time to refactor the code just because I didn't like it. I spent time fretting over perfect button sizes and best icons for them. I wanted to apply all the best coding practices there were.

The active work took a month, maybe two, of fairly relaxed coding in evenings and weekends. By the beginning of spring I had a finished project in my hands, ready to be used.

And still, it took me another half a year to ship it.

And I wasn't actively adding new features in that half-year.

I had an internal block in my head, and I just couldn't publish it. I was very afraid that the users will see how my buttons and their icons are not perfect. I felt uncomfortable that I had a circular dependency in my code. I was embarrassed that there's a class in my code that's quite big, and I should have split it in smaller pieces. I was ashamed of another singleton class. I was disgusted by the fact I'm reading the settings file more often than absolutely necessary. I was depressed that I had that five-line piece of code copied and pasted with just one small change. I had a class that was named badly.

Can you imagine? I couldn't publish the finished product until I fixed the bloody singleton and the blasted circular dependency and the abominable naming.

So for half a year I was basically procrastinating. I was refactoring small things, adding comments, renaming things, but wasn't making any big changes or adding features. I was purely making my code better before publishing the app.

Then, one nice evening last October, I pulled myself together and pushed the button. (Pulled and pushed. What a pun!)
The app was live.
And nothing bad happened. Users were downloading the app, they were saying lots of nice things about it, they were asking for more features, and overall it went well.

This blew my mind. The users didn't notice my singleton and my massive badly named class! They genuinely didn't care about me having an if instead of a switch. They paid no attention to the lack of comments in a file. Users didn't care about my code.

The second release took much less time. The third one, even less. I deliberately decided NOT to refactor some things that were bothering me. I firmly limited myself when I'm too involved with petty fixing and improving. I learned when to say to myself: "Stop, it's done, let's ship it" and "It's good already, don't worry too much".

It was like teaching myself to walk, but instead I was teaching myself to stop. The first step (or stop, in my case) is hard, the second is easier, and so forth.

Since then, my releases pretty much don't depend on my perfectionism, but on readiness of features. By "ready" I don't mean "perfect", I mean "good enough, maybe better than average, but not perfect, if it takes too much time".

I still can dive deep into a refactoring, but now it must be justified by a feature coming up, or by a bug I'm trying to fix. No more "just because I don't like it". No more preventive refactoring.

What about the code quality?

My code didn't become worse because of it.

Years of working in the company that values the code quality taught me how to write readable code from the very beginning, how to separate it in blocks with clearly defined responsibility, and where to put comments to make it even more clear.

But years of working in the company that values speed and the product taught me to value the product too.

I learned to make right trade-offs.

My code is not spotlessly perfect. But it is good enough to become a product.

Instead of the morale

Your users don't know about all your struggles. The product isn't going to stop being interesting for them because there's a method in your code that accepts eleven arguments. Yes, it would be nice to make them into a configurable object, but you don't have time right now, and it shouldn't stop you from shipping.

The users are not going to laugh at you because you have that dreaded singleton helper and don't have the courage yet to make an object and pass it through everywhere you need it. Yes, you'll do it one day, but you shouldn't wait until you finally make it.

You shouldn't wait until you finally fix everything in the world, and your code is shining like a diamond. You should ship. The users care about the product, not the little imperfections.

Posted on by:

Discussion

markdown guide
 

Fantastic Post Elena!!

I am working towards finding the middle ground. In my current job, delivering the product takes priority over quality of the code some times. It's not too crazy, however being a perfectionist, I tend to feel uneasy submitting a PR that doesn't satisfy the code quality I set for. Over a period, I'm learning to see the trade-offs and makes appropriate decision.

I would like to ask you two questions.

  1. How do you handle the technical debts? There are situations where you want to ship the code however bad the quality of the code is, as long as it's working. I find it very difficult to convince the management team to get time to improve these "Just Enough" working solutions.

  2. Have you been in a situation where you needed to handle a co-worker who's always trades off code quality to finding "Just enough" working solutions (No matter there's deadline or not).

 

Hi Subbu,
Thank you for the compliments! :)
Regarding your questions.
1) I completely understand how you feel. The trick for me is to think from the business perspective. Is it beneficial for the company to refactor now or later? Can I justify investing time in it? There can be different answers depending on a situation. If I need to convince someone on a high-level position, numbers help as well. How do you estimate the workload in, say, 6 months without refactoring? Sometimes I find out it really doesn't matter that much - in this case I need to silence my inner perfectionist.

2) Yes, I have. This also depends on the company's priority. If it is a non-critical piece of code, is needed only once, and has to be finished very soon - maybe speed is indeed more important.

Please note: I am not trying to convince everyone to produce bad code quickly :). This is about how a perfectionist learns to prioritize better.

 

For me it's the opposite. I've recently worked at a company where we focused on end-user value. A feature that was badly needed by lots of people got priority, and bugs that could easily be reproduced but wouldn't bother so many people got down prioritized. Which is as it should be if you ask me. Well, it all depends on what kind of software you're talking about and how critical it is for the business. And now I work at a company where the focus is more on code quality and we try to make sure no bugs slip in.

To me there is a point of diminishing returns. To fix all and every bug is going to require an infinite amount of time because as soon as you touch the code you risk introducing new bugs. For me I can't stop imagining how many actual end users will be affected by a certain bug. If one or two people is going to be bothered by this bug once or twice, it may not be worth spending even a 1/30th of my salery to try to fix it with the additional risk of introducing new bugs, which always happens. And for me to spend a week on something, it's got to be a bug that causes real problems for people. End user value is what it is all about and whether it is financially worthwhile to spend time on it.

 

Great article! I'm in the company that needs to deliver high quality code (it's typically safety critical), and there we've done a good job of knowing where to draw the line (i.e. it's ok to ship with bug X, we'll fix that in the next release but it's not ok to ship with bug Y, it's dangerous and needs to be addressed now). There are always code reviews, and lots of testing to try and make sure nothing slips through.

My problem is with my side projects. Because I can't come up with the perfect idea, I'm paralyzed by indecision and can't seem to get started. I'll keep trying and see if I ever decide to actually do something; but reading this was helpful. It's always nice to know that others have struggled with the same problems, and found a way to overcome them.

 

Thank you, James, nice to know you liked the article!

I know exactly how you feel. Your approach works perfectly well in your current company, but for some "less important" projects it's really hard to switch this mindset.

Yes, you need to be brave and decide to release, even if it's not perfect. You'll feel very good about that, I promise! You'll get a lot of endorphins :).
Also, the earlier you release, the more user feedback you'll get, and the better you can move forward with your project. The user feedback is both reassuring (people actually like your thing!) and helpful (they tell you what features they'd like, and you can focus on them first).

 

Lol, when I read this post I was like: How could she so accurately describes Me!!? 😂

💯 agree