Managing technical debt is difficult in rich text editors
Published November 26th, 2022
One of the biggest dangers when starting a new development project, is not understanding the trade-offs you may need to make during development, and the technical debt those decisions could incur. Developing a rich text editor, in particular, is a minefield of potential technical debt. So, before you start, you need a plan.
Product Manager at Halo Connect
After all, technical debt isn’t something you can just leave until later. Technical debt lurks in your codebase, accruing interest in the form of lost developer time and complicated workarounds. It can also snowball. A small problem, that carried a small cost, could become a much larger problem if left too long.
You need to be actively managing technical debt. Every. Day.
Typically, technical debt has a habit of rearing its head at the most unfortunate times – complicating codebases, delaying releases, and blocking the development of new features.
So, managing technical debt becomes especially important in a project as complicated as a rich text editor. There are a few ways you could approach it, such as trying to pay it down each sprint. However, that could affect your developer velocity and clash with project prioritization.
Instead, the best plan is a proactive plan. And that requires an understanding of why rich text editors are so prone to technical debt.
Why rich text editors accrue technical debt
Three key factors make rich text editors especially problematic when it comes to technical debt:
- Rich text editors usually have big, complex codebases – especially if you want a full-featured editor.
- Rich text editors are at the mercy of an ever-changing environment – that you often don’t control.
- Developing rich text editors requires extensive domain knowledge that rarely overlaps with other kinds of application – without which, it can be difficult to find the right solution to many development problems.
Understanding these three factors is crucial to understanding how tech debt accrues in a rich text editor, and how proactively managing technical debt can make or break your development schedule.
Where does RTE technical debt accrue?
Rich text editors tend to be multi-layered applications, with an editing model wrapped in a configuration layer to make a core engine, on top of which other features can be built. This complexity often leads to rather large codebases – which means plenty of places for technical debt to appear (and hide).
Insights on the complexities of RTEs
Buy vs Build: The Great Debate White Paper
Opportunity Cost of Technical Debt White Paper
Tiny puts a price tag on building your own core rich text editor
Multiple editing models are used in rich text editors
For example, from the outset – on that very first layer of a rich text editor – you have a rather important decision to make.
There isn’t just one editing model. Do you choose:
- The browser's ContentEditable API
- Or a model-based library like Slate
- Or develop your own library.
Each model has inherent strengths and weaknesses, but crucially, often what’s not factored in up front, is that your choice directly affects the features your editor is able to support.
For example, TinyMCE is a ContentEditable editor, but it switches to using Slate when in real-time collaboration (RTC) mode. This was done because RTC was easier to implement on a model-based editor.
Likewise, the whole editor could have been switched over to Slate. However, some features are easier to implement on a ContentEditable model, so instead Tiny develops and maintains the two models.
ContentEditable vs Slate for RTC
From January 2023, TinyMCE no longer offers Real-Time Collaboration (RTC) for new customers. For Existing customers, we'll be in contact to discuss options. Please reach out to your Account Manager if you are a customer using RTC, and you have any questions about the plugin.
Basic editor vs fully-featured editor impacts tech debt
Choosing a model and building a wrapper only gets you a very basic editor though. Next, you want to start adding features, like support for tables and advanced formatting.
However, with every feature you add to a rich text editor, other aspects of the product need to be kept in mind. These include, but aren’t limited to:
- Key handling
- Undo management
- Content filtering, and
- Mobile support.
This matrix of considerations multiplies the risk of technical debt for every feature you add, and needs to be planned (not just when the feature is being developed) on an ongoing basis.
The other problem with rich text editor codebases, is that some pieces of your code may live for a long time, so cruft and code rot can become commonplace, if it’s not kept in check. Again, that's where your efforts to proactively manage technical debt comes into play.
Over time, rich text editors build up cruft
“Cruft” is a term for code that was badly designed or unnecessarily complicated – often from a developer implementing a feature they don’t fully understand. Similarly, “code rot” refers to code that has deteriorated over time – possibly becoming cruft in the process. And both are prolific sources of technical debt.
Unfortunately, this is where forces beyond your control start taking over.
All software projects have dependencies – libraries or tools they rely on to function. Usually, you can control which dependencies you use and when they update. However, a rich text editor running in a web application is dependent on the whims of the browser and operating system (OS) of the user.
This creates a matrix of environments, each carrying its own unique quirks and challenges. And you can’t control that, but still have to account for it in your development work.
What is cruft, code rot, and code half-life?
As an example, TinyMCE 6.2 supports 8 combinations of browser and OS
Because of this, rich text editors can accumulate cruft and code rot – not just because of internal factors like code becoming outdated, but also because of external factors (like a browser deprecating an API). This technical debt can multiply if fixes for those external issues are rushed, or problems are bandaged over again, and again, and again…
Managing technical debt in rich text editors
Regularly scheduling developer time to pay down technical debt might help you stay on top of it, but that depends on how much (and how fast) you're accruing technical debt and how much time you can afford to dedicate to remediation.
So, how do you plan for and manage technical debt in a product as complex as a rich text editor? Or, even better, how can you prevent technical debt from accruing in the first place?
The answer is domain knowledge.
Deep RTE domain experience minimizes technical debt
When it comes to managing technical debt in a rich text editor, the biggest danger comes from the things you don’t know.
|KNOWNS||Known knowns: things you are aware of and do know.||Known unknowns: things you are aware of but don’t know.|
|UNKNOWNS||Unknown knowns: things you have forgotten you know.||Unknown unknowns: things you don’t know and aren’t aware of.|
The four degrees of knowledge, represented using the Johari Window technique. The different colors represent the risk of technical debt in a rich text editor, based on the level of understanding of domain knowledge.
Developing a rich text editor requires very specific knowledge, such as DOM walking, selection models, keyboard key codes, and input events. There are very few companies in the world that develop rich text editors, and therefore the domain isn’t widely known or documented. The learning curve is steep. And without the right knowledge, your risk of adding technical debt (intentional and unintentional) rises.
Why is that?
Informed choices help to limit technical debt
Very basically, technical debt is the cost of choosing a simpler solution over a more robust one. However, if you’re unaware there’s a choice to be made, you can needlessly take on technical debt.
Worse still, even if you’re aware of all the factors but you don’t really understand them, you can’t make an informed decision about whether taking on technical debt is wise. You also can’t manage technical debt you aren’t aware of, and you can’t easily prioritize technical debt you don’t understand.
Extensive rich text editor domain knowledge, helps you manage technical debt in five ways:
By avoiding technical debt in the first place:
Implementing features correctly the first time, choosing solutions that are less prone to technical debt, and engineering your rich text editor in future-proof ways.
Estimating and prioritizing technical debt:
This is especially relevant for complex debt that might require refactoring in your rich text editor and advanced features.
Managing the impact of existing technical debt on velocity:
This positively affects the quality of your rich text editor, by avoiding hacky workarounds and “fixes” that only make the problem worse.
Identifying when existing technical debt will interfere:
Whether that's on an upcoming project or feature, avoiding surprises, complications, and delays.
Remediating technical debt faster:
By having a better understanding of the potential solutions and how to implement them, you can manage technical debt more effectively.
Let’s explore a few more concrete examples.
Intentional vs unintentional technical debt
Paraphrasing Splunk, intentional technical debt is created deliberately so a product can be released quickly. Taking on the technical debt is a known and accepted risk.
However, unintentional technical debt comes from sloppiness, unexpected complexity, or a lack of expertise or knowledge.
This creates unknown risks which can’t be tracked or managed.
1. Code architecture in rich text editors
Good architecture can save you from accumulating technical debt, but good architecture requires good domain knowledge.
TinyMCE’s core engine is tens of thousands of lines of code. It isn’t just a wrapper around the ContentEditable API – it also contains code that abstracts out many of the aspects of rich text editing. That includes everything from basic formatting like bold, to DOM walking and selection handling.
These abstractions mean that TinyMCE’s developers don’t need to think about them every time they’re working on a feature. They just call a TinyMCE API, and the core engine handles it for them. When an abstracted concept needs to be improved or fixed, it also means there’s only one place in the code to update – not several spread across every feature that uses that concept.
However, architecture can also hinder more than it helps, if done incorrectly. This is where domain knowledge becomes important, so you can find the right balance between ad-hoc and over-architected.
2. Intentional and unintentional technical debt
Ideally, you would only accrue technical debt you have chosen to take on. Sometimes, though, technical debt creeps in unintentionally. Often, that’s due to a lack of knowledge.
Developers can't always know and account for everything. Maybe the developers didn't have enough time to brainstorm, or they didn't have the knowledge required to find the optimal solution. Or maybe the implemented solution was a good solution at the time, but it wasn't future-proofed against a problem that popped up later.
This is where cruft and code rot can start to pile up, creating an ever-growing backlog of technical debt you might not even realize exists. The risk of stumbling on severe technical debt at an inopportune time also increases – potentially delaying or blocking future features after you start development.
3. Continual refactoring in rich text editors
Without the domain knowledge required to see the bigger picture, it can be all too easy to continually patch the same piece of code over and over, potentially adding technical debt each time.
If you find yourself patching and improving and replacing the same piece of code again and again, it’s a good idea to stop and ask yourself “Why?”
Sometimes it’s necessary, due to that feature requiring constant updates. However, there’s also a chance it’s a sign of a deeper problem – such as the code having been based on incorrect or incomplete assumptions, due to a lack of understanding.
The danger of this kind of code is that it’s costing time and effort each time it's updated.
Constant changes also increase the chance of cruft and code rot due to something being forgotten or missed. For example, an API that isn’t used anymore, but hasn’t been cleaned up yet. Such code sits around in your codebase, unnecessarily bloating and complicating it, and making all future work in that area of the codebase more complicated than it needs to be.
Avoiding, finding, and remediating these kinds of situations are all easier with the right domain knowledge.
Planning for and managing technical debt in rich text editors isn’t only about features and day-to-day development work. There are other things done at a higher level that can help too.
Programming principles affect code quality and technical debt accrual
Quality code is the antithesis of technical debt.
In addition to domain knowledge, sound software engineering knowledge (particularly in programming principles and their applications) is also essential to developing a quality rich text editor.
Although to be clear, choosing the right programming principles isn’t completely divorced from domain knowledge. There are many principles to choose from, such as KISS, DRY, separation of concerns, and incremental development. And no one principle suits every software project.
Choosing the wrong principles may, in fact, have a detrimental effect on your project. It may even increase your technical debt accrual, by promoting ideas that negatively affect your decisions around technical debt.
Over the years, TinyMCE has learned by trial and error which principles are useful for rich text editing, particularly when it comes to reducing technical debt. Some of these principles tie back to our use of functional programming, but most can also be used standalone.
Examples of some programming principles Tiny uses are:
Modularity, or modular programming, is the practice of separating code into independent building blocks, each with a specific purpose. Applications are then formed from many modules. Modularity is a great tool for managing a complex codebase, like a rich text editor, especially if you start abstracting concepts.
One of the easiest ways to add clarity to your codebase is through types. The quick feedback of a type checker, and the ability to know at a glance exactly what types you’re dealing with, can be great for avoiding technical debt. In a rich text editor, types can be essential for ensuring the layers of your application work together correctly.
What is functional programming?
Functional programming is a programming paradigm that aims to produce cleaner, clearer, more robust, and more maintainable code.
Trade-offs rule when managing technical debt
It’s also worth noting that some principles may be overkill, when you’re just starting to develop a rich text editor. However, others might be painful to introduce later, and are better adopted right from the beginning.
Just like technical debt, understanding the rich text editor domain and the trade-offs involved allows you to plan long-term, thus ensuring you’re using the right principles, at the right time, for the maximum benefits.
All that said, there’s always another option.
Choosing the right RTE minimizes technical debt accrual
The learning curve for developing a rich text editor is steep, and the risks associated with not properly understanding the domain are high. It can take a significant amount of time to build the required domain knowledge in your team. It can take just as long to find the right ways to track and manage your technical debt.
If your application needs a rich text editor, there’s another choice.
You could take on the overhead of developing and maintaining a rich text editor yourself, or you could buy-and-assemble, relying on the expertise of specialists to carry the weight of the technical debt for you.
This allows your developers to focus on domains they’re already familiar with, driving your innovation, scaling rapidly, and delivering value quickly.
You still need a plan for choosing the right rich text editor for your use case, and absorbing updates (especially security critical ones) throughout your application’s lifecycle. However, that’s a significantly simpler plan than developing your own rich text editor.
It’s up to you.
Download the white paper
Opportunity Cost of Technical Debt: Minimize Your Rich Text Editor Development
Product Manager at Halo Connect
Millie is a Product Manager at Halo Connect who dabbles in writing. Previously, she worked at Tiny as a Product Owner, dev, and QA engineer. She loves learning above all else, whether it's about people, tech, or leadership.