Structured problem solving

When I built the first implementation of Text Annotations for PSPDFKit for Web, the goal was the rendered text should look the same on every browser. When I got the task, I chose contenteditble to let users edit the content and thought it would handle all problems for me. I started with a prototype, and the rendered Text Annotation actually looked similar in Chrome and Firefox.
I was young and naive and thought it would just take me “one day”.

Famous last words…

So I was happy until, well…, until IE 11 came along.

Encountering the problem

contenteditable didn’t produce the same output on IE11. After more investigation, neither did Chrome nor 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 had solved the issue, I found a new edge case.

A few days went by, and I realized that continuing this way didn’t make sense. The feature would not make it to the next release, and I’d get gray hair in my early twenties if I’d continue like this.

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.

So I asked them to help me and ffter 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. I tried many of their proposed solutions already but forgot why they didn’t work.

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

Learnings

1. Write a debugging journal

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

1. Using SHIFT+ENTER in IE11 produces a different amount of `<br>` tags
2. Firefox generates a `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 from other browsers.
5. Suspicion: ENTER and SHIFT+ENTER produces a different output on all browser

It is essential 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 the journal again.

2. Build a test case as quickly as possible

As soon as you have a reproducible 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, this could 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 a more manageable 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 a 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 so much time on the problem like you did. On the contrary, your colleagues 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 quickly.

For my contenteditable problem, this could have looked like this:

contenteditable does not produce the same HTML output in every browser. 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ß.