Hi, I am Nicolas 👋

Full Stack Software Engineer at GitLab who deeply cares about UX. Passionate to build magnificent products everyone loves to use.

← Back to see all posts

Learning to solve problems

Back then, when I built the first implementation of Text Annotations for PSPDFKit for Web. I chose to use contenteditble to let users edit the content.

The goal was: No matter the browser, the rendered text should look the same.
Easy! I thought. I was young and naive. I thought I’ll be done “in one day”. Famouse last words…

The output in my prototype looked kinda similar in Chrome and Firefox. Until, well…, until IE 11 came along. Since then, it’s been there for a long time, haunting me in my dreams for years.

Anyway, back to the story…

Encountering the problem

contenteditble didn’t produce the same output on IE11. After more investigation, neither did Chrome or Firefox. IE 11 was just the most incompatible one. So I tried fixing it with a few tricks here and there. Every time I thought that I solved the problem, I tested it just to find a new edge case.

A few days went by and every time I fixed something, something else broke. Continuing this way didn’t make sense. The feature would not make it to the release and I’d get gray hair in my early twenties.

Asking for help

My colleagues are great engineers, for sure they will be able to help me! And yes (spoiler!) they did. But I didn’t just learn how to solve this particular problem. I learned how I can tackle problems in a general and structural way.

After I explained the problem, they started to ask questions. Lots of them.

“Have you tried X or Y?”. “What happens if we do Z?”.

I was overwhelmed with all of the questions. I forgot why the proposed solutions didn’t work.

I tackled the problem unstructured. So what are my learnings from this story?

Learnings

1. Write a debugging journal

When exploring the problem, a lot of thoughts will come to your head. Write them down. Like a journal. For example, here is an actual bug that I debugged at GitLab where I shared my Debugging Journal. I can’t remember the details for the contenteditble problem I shared. But it could have looked like this:

  1. Using SHIFT+ENTER in IE11 produces different amount of <br> tags
  2. Firefox is sometimes using span instead of p - not sure when yet.
    • Found that it depends on using ENTER or SHIFT + ENTER
  3. Chrome produces a <br> tag after a p tag on new lines
  4. Rendering in IE 11 of a <br> after a <p> tag is different than in other browsers.
  5. Suspicion: ENTER and SHIFT+ENTER renders differently on all browser

It is important to write it down, so your brain can focus on new problems when they appear. And later, when your colleagues ask, you can go through it again.

2. Build a test case as quickly as possible

As soon as you have a case that causes an issue, document it and write it down. You can now use this to replicate the bug, or even better, write an automated test for it. For my contenteditble example in the beginning this would have looked like something like this:

  1. IE11 doesn’t produce a <br /> tag when using SHIFT + ENTER. Potential solution: Create a <br> tag for each <p> tag in IE 11.
  2. Firefox produces two <br /> tags on ENTER. Potential solution: Remove two <br /> tags in Firefox if they come after a <p> tag. …

Now we got some sort of rules figured out for the problem. You might even have potential solutions in your mind.

3. Solve small problems

Getting contenteditable to produce the same output on all browsers is hard.
Removing a <br /> tag on IE 11 was an easier problem.

Divide and Conquer: Make hard problems as small as possible, so they are easy to solve.

4. Document all your solutions

You probably have multiple solutions in your head. There are often tradeoffs. Document all of them with pros and cons. This is important because your colleagues will likely come up with similar solutions and you want to give them an answer why you have chosen one over the other.

If possible, you might even have a short, a mid-term, and a long-term solution that you can think of and propose to your colleagues. For example, If the bug is urgent, it will be ok to favor the quick fix over the proper long-term solution.

5. Explaining the problem is your job

There is a high chance that no one else has spent as much time on the problem like you had. Your colleagues though only get a limited time to think it through and you need to provide them with the right amount of context. It’s now your responsibility to share the information you know in a well-written form, so they can understand it.

For our contenteditable problem this could look like this:

contenteditable does not produce the same HTML output in every browser. Therefore, the rendered result, when changing text would be different every time. Please see my debugging journal where I documented all the edge cases I came up with.

Due to the sheer amount of edge cases, I’ve written a normalizer that takes the contenteditable HTML nodes from each browser and based on the browser, produces the same HTML structure.

If we ever find a new edge case, we can work it into the well-tested normalizer.


I am glad that I learned this early in my career. I got lucky to work with such great engineers. Thanks to Martin Schürrer and Philipp Spieß.