 The session has a very poetic, first title, the Eternal Struggle. I wanted to talk a bit about two opposing forces that we're constantly trying to get under control, not only in WordPress, but in computer science in general. And I want to delve a bit deeper into how they interrelate and what that does mean for WordPress. So first of all, what is technical debt? Technical debt is a metaphor that Ward Cunningham had first created. It basically relates the problems you can encounter in regards to code quality to financial debt. So basically, if you cut corners, it's like taking on financial debt. But as long as the debt stays in, you pay interest. So it comes with an added cost. And you will need to pay interest into the future for as long as you didn't repay the principle of that debt. And repaying that principle is basically refactoring the code and getting rid of the technical debt. For as long as you don't do that, you're paying interest. So the interest tends to grow bigger with more and more technical debt. It's like an added cost to any change you need to do, to any maintenance work you need to do. And you need to constantly repay some of the principle to make sure that the interest does not grow too big. Because when the interest grows too big, it becomes almost impossible to build new features, to fix bugs, to just keep the software running. So the software, by itself, when it accumulates technical debt, it's not ever cost free. It comes always with the cost. And the more technical debt you have in the project, the more interest you pay on that cost. So there's four types of technical debt that Martin Fowler had identified. You can basically division them into two different axes. You have the reckless versus prudent debt, and you have the deliberate versus inadvertent debt. I've put some examples here of what that would mean. So if you have reckless deliberate debt, it just means that you don't care about anything at all. You just go the quickest route to have something workable which would usually be called a hack, and you don't care about any of the consequences. That's reckless deliberate technical debt. Reckless inadvertent debt is just when you don't know it any better. When you try your best, but still what you're doing is not according to best practices, and it creates problems without you even knowing that these problems are there. And on the other side, you have prudent deliberate debt that's very common as soon as deadlines are in play. So you need to ship it at a certain date, so you can opt to take on a bit of technical debt to cut corners to make your deadline. But you will always need to keep in mind that you will have to repay that later on. Then we have prudent inadvertent debt, which basically means that once you've finished whatever development work you did, you probably learned a lot during that time. And once you're finished, you probably already know how you could still do it much better than what you've just finished. So that's usually the prudent inadvertent debt, which is also very hard to completely avoid. I want to say that the reckless side of technical debt is something that is very common, unfortunately, in WordPress, but it's completely avoidable. So we will concentrate mostly on the right side of this axis for now. When you take shortcuts, just like with financial debt, it's usually that the debt gives you an advantage that outweighs the disadvantages that it comes with. So if you take on technical debt to move quicker with your development, usually you plan on being able to be first to market because of it, just being able to iterate faster, to get more feedback from actual users, or just start the cash flow. The difference between taking on this technical debt or doing it properly is something that crosses at a certain point and it's called the design payoff line. At that line, that's where the advantage or the disadvantage of technical debt switches around. So if you design your code properly, as you can see in the axis, you will start out slower with your project, as if you just do no design and just get quickly to getting the first iteration. But at one point, the good design becomes faster and faster while the other approach with the technical debt gets slowed down because of the technical debt. And that means that we have a clear design payoff line somewhere that tells you if what we're trying to do right now is above that line, there's no point in taking on technical debt because we are worse off because of it. So there's no point in cutting corners, we're just slowing us down with a first perception of being faster only. Where this design payoff line is exactly that's difficult to say, it differs very much from project to project, but most computer science agree that it's probably much lower than most people expect. It's probably in terms of a project work, it's rather weeks than months where you cross that line. So what is backward compatibility? Backward compatibility means the interoperability to legacy piece of code, and usually you refer to an older version of the same code. So the code just means that it can still interoperate with older versions of itself. There's a working continuum that the software just keeps on going. And breaking changes, this is the effect that you call when you make a change that interrupts this backward compatibility. So a breaking change basically means whatever we produce now, it's not compatible anymore with the previous version we had. That's a breaking change. Backward compatibility is about the interface, about the public facing interface of the code. So usually your code has interfaces that are meant to be used by other code and your code has implementation details that can be considered a black box. If you do changes inside of this black box, it does not have any negative impact on the backward compatibility, but as soon as you change the interface, it means we have indeed a breaking change. So that's an important concept because usually you want to be as explicit as possible about what constitutes this interface. This interface is the contract you create with the users of your software, with the developers that couple their code to your software. So this interface, this contract, you should be precisely aware of what it entails so that you can make proper decisions of what changes you can do without breaching your contract with your users. So why is that important? Why is backward compatibility important? First of all, it's much easier to develop against something that is not constantly changing. It can pretty much feel like a moving target if you try to develop against code that isn't flux all the time. A good example right now is unfortunately the Gutenberg code, which is constantly changing so they need to do fast iterations, but it's very difficult for developers then that need to make use of these interfaces to code against it because the interfaces constantly change, the documentation is not up to date, et cetera, et cetera. It's a moving target, it is very difficult to hit, and when you think you hit it, with the next version it's gone again. So that's very, very tough to develop against. It increases trust, a software platform like WordPress that is known to be very reliable in terms of backward compatibility creates a lot of trust and usually this trust is one of the main arguments of why bigger companies would want to use that platform instead of another platform because they cannot have any guarantees of what the future will bring. They can only trust more or trust less whether the platform will be a good fit for the next 10 years or next five years. Also, it's ideal for end users because all the problems that the developers face usually result in bugs and end users, they are the ones who are faced with these bugs and don't know how to go on from there. They cannot fix them themselves so they are usually the ones stuck with the most devastating side effect of all the difficulties that developing against something brings. So if it's so important, why is not everything completely backward compatible? But first of all, backward compatibility is often opposed to innovation. Usually if you want to innovate, you move fast and you break things. That's just part of the deal because you cannot plan for the next 10 years and then be very conservative to radically innovate. It just doesn't work that way. So disruptive change is almost impossible if you completely focus on backward compatibility. Also, backward compatibility is hot. WordPress being well-known for always being backwards compatible has a lot of breaking bugs all the time where people need to introduce issues on track because the general platform keeps backward compatible but there's hundreds and thousands of little small details that break all the time. Someone's theme has one color all of the sudden or the users are not displayed correctly, et cetera. And it's very hard to really completely enforce proper backward compatibility. Also finally, backward compatibility usually is unsexy. So nowadays people try to opt for the shiniest JavaScript frameworks and make everything as fancy as they can and that goes very straightly against backward compatibility because one thing is, as I said before, that backward compatibility does not allow for this innovation but it's also that this goes against the notion of trust that you build. So if your potential user base just notices that you're always only chasing after the newest things that is very bad for the trust they put in your platform. So how do they interrelate? This is the interesting question now. Our goal should be for our users to maximize backward compatibility and for developers to minimize technical debt. I think that should be pretty clear on its own given what these terms mean. However, there comes the first caveat. Backward compatibility causes technical debt. It's one of the main reasons of why you accumulate heavy technical debt in the first place. So with a backward compatible philosophy, your changes turn into additions instead. So you cannot just radically change a function. You add a new function, keep the old one around. Your deletions turn into changes so you cannot remove anything because you need to stay compatible with the older versions. So instead, you change or you add to what you normally would delete. The things that get deleted usually then throw a deprecation notice but they're still around. They're still able to mess up the rest of your code. And bugs turn into features. The thing is that an old legacy platform like WordPress, for example, it is full of bugs. That's not necessarily a well hidden secret. And the bugs are just part of the experience and all the ecosystem works around these bugs and the bugs are part of the characterization of WordPress. So some of these bugs, if you would fix them, it would break the plugins and the themes that rely on the expected behavior of that code even though it would be technically a bug. So this actually then turns bugs into features. You need to keep them around. You cannot get rid of them. Sometimes you can fix them but sometimes it's just that it's part of how the platform works and you need to deal with the consequences of it. My pointer doesn't work anymore. There you go, sorry. Another important concept that comes into play is forward compatibility. So as we talked a lot about backward compatibility, keeping compatible with older versions of oneself, forward compatibility means that in strange words, it basically means stay compatible with your future self or better translated, it means that keep in mind what the future might bring, what the probable outcomes of future requirement changes will be and then build the code from the start so that it can easily adapt to these future requirements without forcing you to include a lot of technical depth again to make this work. So forward compatibility basically means that you set yourself up to minimize overall technical depth in time. This concept of time is a very important one. It's very important to always be aware of the additional dimension of time when it comes to computer science and basically your goal should never be to do something now, to solve one problem now, to build one plugin now. Your goal should always be to decide what time frame you want to practically support, what is your goal, how long should this be around and then solve the problem so that it is solved for this amount of time. Which will probably lead to different solutions because if you take into account what the maintenance cost will be, what future requirement changes might be ahead, then you start immediately with a different solution and this also allows you to avoid a lot of technical depth. Another important concept that I want to explain here briefly is semantic versioning. So basically as backward compatibility causes technical depth. You could deduce that 100% backward compatibility produces unlimited technical depth. So there needs to be some way to introduce breaking changes again to make up for that and somehow interrupt this endless cycle. That's where semantic versioning comes in. So basically the premise is we cannot keep compatible all the time because it just means we constantly accumulate technical depth until nothing else works anymore. So semantic versioning says yes we will break but we will do it in a very controlled way and a way that is well communicated and that you can properly control in your third party reliant code. So semantic versioning basically means that every version number has three components. A major version, a minor version and a patch version. If you bump the major version it means that you included breaking changes in the public interface. And that's what allows you to again reduce technical depth. A minor version bump means that you had additions or changes that still stay compatible and the patch version bump means you just did backfixes. So basically the major version bump gives you a get out of jail free card. So at that moment when you do a major version bump you can say okay I will have a breaking change. The old version is still available for people that need it. People can properly decide whether they want to also support a new version or not because there's a clean cut and from that new version on as I can do breaking changes I get rid of all the technical depth that I can avoid by now. The effect of semantic versioning is basically this. So as you can see here with the versions usually technical depth just continually grows, continually gets accumulated but a breaking change means that you can reduce it again. And this means that there's always an interruption between backwards compatibility whenever there's a breaking change. That means that you cannot have it all. You cannot have no technical depth and perfect backwards compatibility but semantic versioning is one way of optimizing against both in a reasonable way. Just accepting that it's not possible to have both in a perfect way so make the most out of it in a controlled way. So what does this mean for WordPress now? First of all WordPress accumulates technical depth. This is an interesting screenshot I took from CodeClimate which is a static analysis tool for PHP code. And basically what CodeClimate tells us is that it would take us 15 years to get rid of the technical depth that we have accumulated in WordPress. So given the recent anniversary that WordPress had, I think most of you know that WordPress recently turned 15 years old. So that would basically mean we just constantly collected technical depth and not much more. But it's not as bleak as that sounds because this statistic is calculated on one single developer working pretty reasonable hours. But I found the coincidence to have these 15 years pretty funny. So WordPress interfaces are not explicit. That's another issue we have with WordPress. Oftentimes coaches appears in WordPress, it just happens to be there. People just happen to use it. And when there's no explicit interfaces that were defined then all of a sudden the entire code becomes the implicit interface. So basically whenever someone codes against whatever hidden function, we need to keep this function around and keep it working in the exact same way. We just grew or implicit interface by another function. So that's why having explicit interfaces is so valuable because it gives you control over what you want to guarantee and what you want to be able to easily change. If you have this implicit interface, it basically means that as your entire code becomes the public interface, then any change to any part of that code is a breaking change. So saying that WordPress is backward compatible in this perspective is actually technically wrong because WordPress pretty much has breaking changes with almost every single commit that it does. This of course, there's a difference between the technical logical reality and what the practical effects are. So in general, all of these changes are technically breaking changes. They are close enough and never change anything important so that it still works the same. But technically speaking, almost every single commit would be a breaking change. WordPress requirements are constantly growing. So the backwards compatibility needs, they need to be considered as additional requirements to the project. So if you need to solve problem X, that's one requirement. If you need to solve problem X and keep compatible with your old version Y, then you all of a sudden have two requirements to solve the same problem. So the more details your backward compatibility needs to take into account, the more requirements you need to solve against at the same time. WordPress has a huge scale. It's a 15 year old code base. It currently supports 12 years worth of PHP versions from five two to seven two. And all the security patches are back ported across 13 major versions. So any change you make needs to take all of this legacy mumbo jumbo into account as well. Which makes it pretty difficult to actually make a change. Which causes a lot of developers to be very afraid of changes and be very wary of progressing too quickly. Which might explain why it's so arduous and so slow to get something fixed when you introduce an issue on track. It's just that it's very difficult to make sure that you don't inadvertently break something else in the process. There's more and more requirements conflicts. So recently, for example, when PHP 7.2 slowly became a reality, the compatibility code of WordPress to stay compatible with another version of PHP became incompatible with a newer version of PHP. So all of a sudden, we're spending such a big rage, that the code becomes incompatible to itself in some way. So we're hitting more and more issues where we're slowly finding out that we might need to do something. It cannot go on for all eternity like it's going on now. So the clock is really ticking. It's becoming worse and worse to work on WordPress Core. Every single change is becoming more and more costly. And then uncontrolled technical debt will eventually lead to technical bankruptcy. Technical bankruptcy basically means that the project is not able to accommodate requirements in a way that satisfies them properly. It might be because of cost. It might be because of time. It might be because of the required expertise not being available. But we're slowly approaching this closer and closer and it's very important to realize that with such a legacy platform, just keeping everything around all the time will eventually be actually the demise of the project. So there needs to be a compromise we need to find there. How can we improve this? So first of all, let's revisit the technical debt diagrams, diagram, the cred runs. So as I said, for the left side of our technical debt, the reckless one, this is not something that should happen. It does happen in WordPress space but it actually shouldn't. To solve these, you can plan more, design more and you can educate people. So just creating technical debt because you don't know it any better can be solved by educating people, by explaining what the best practices are or by looking outside of the WordPress bubble and seeing how other people have solved this problem years before. So that's actually pretty easy to solve when you're dealing with an individual person that you can directly interact with. At the WordPress scale, it's actually also quite an interesting problem in and of itself. Then for the other side, basically whenever we deliberately take on technical debt, we should already plan for the needed refactor in the next iteration. It basically meant we took on a loan to move quicker but we cannot just ignore the fact that in some next iteration we need to repay that loan. So that needs to be taken into account from the start as soon as such a decision is being made. And then for the prudent inadvertent technical debt, where I just noticed that while we finished it now, but yeah, actually we could have done it better, that's why semantic versioning is so important. However, with WordPress, we have a bit of a problem. Semantic versioning is not only actively being used, it really goes against the principles of the project. As WordPress tries to stay backward compatible, no matter what, it's just not as simple to just say now we use semantic versioning and we can break whenever we want, we just need to bump the major version. It's not that easy. So usually with semantic versioning, you would drop support of something. So here as an example, I have the PHP versions that WordPress currently supports and the PHP versions that are used by site owners, which of course right now properly fit. So semantic versioning would tell us that we need to drop support for a version. However, that is a breaking change and that leaves some site owners out in cold. They're completely lost, they have no way to get updates, they cannot properly keep the site secure, et cetera. So we basically abandoned these users. What WordPress should do instead is do it the opposite way, reduce usage first. So basically what we're trying to do right now with several smaller projects that have a common goal is to reduce the usage of the thing that we want to get rid of. And once the actual usage is so low that it is negligible, we can just adapt our support without actually having a breaking change. Because as I said, there's a difference between the technical breaking change and what is the practical effect of it. And if no one is using it, then yes, it's still technically a breaking change, but in practice it's not. So that's what the recommended approach is in the WordPress space. Yeah, key takeaways. First of all, technical debt should be avoided. So what's the best way of not completely drowning in debt? In the financial world, everyone pretty much knows that, just not taking it on. Technical debt needs to be repaid. If you do need to take it on, then make sure that you repay it as soon as possible, because otherwise you will face bigger and bigger interest rates. Backward compatibility should be maintained. It's a very important feature, especially for the WordPress platform. But backward compatibility creates technical debt and only breaking changes can substantially reduce technical debt. So that's why it's important to keep this in mind and only incur the technical debt that you have because with that it's already very difficult to keep it in check. And then finally, forward compatibility can reduce technical debt upfront and as a side effect or as an indirect result, it reduces the breaking changes that we need to make. So it's in the best interest of WordPress to get deeper into forward compatibility, better plan ahead and make sure that we don't end up with lots of code that is from the start just meant to be the future technical debt. Basically, think before you code because every mistake you make makes your future job more difficult. Yeah, that's it from my side. Are there any questions? Yes. The code climate, which had 15 years of man-hours that what does it work, what does it base the number on? It makes a static analysis of the PHP code in the GitHub repository, the develop repository and that static analysis creates a huge list of issues where documentation might be wrong, where variables are not strict enough, et cetera, et cetera, et cetera. And for each issue, it has a severity. So from A to F of how maintainable, of what the impact is on maintainability, and these letters, they also relate to a given duration in time to fix these issues. So if you have a code of quality A and it has an A level issue, it means, yeah, it's an hour to fix it and you get to go. But for some of the code in WordPress, there's, for example, individual files that have a very bad maintainability rating and where code climate estimates that that file alone requires one year of work just to fix that single file. So, yeah, it basically, it's just a guesstimate. It collects issues in the code that go against best practices and then attaches solid guesses as to how much time it would need to fix it. Yeah. So you were talking about the explicit and implicit interfaces provided by WordPress. Yes. WordPress 7 makes it easier to provide explicit interface by typing that kind of thing. I've heard this is not supported by JavaScript, for example, it's explicitly in place. And with WordPress moving more towards a JavaScript ecosystem with the introduction, how do you see preventing another implicit interface appearing in the JavaScript part of WordPress? That's a good question. So first of all, having an explicit interface does not necessarily mean that it can be enforced at the language level. So these are two different concepts. So with PHP 7, you can enforce type declarations at language level, yes, which is already a nice improvement. But some of the parts that make up the interface, for example, cannot be enforced at language level. And you can just as well have explicit interfaces that are explicitly documented, but are never enforced in any way. It's just there are conventions and everybody needs to adhere to them and you can use tools to detect people that are not adhering to the rules, et cetera. So while there's not as much language support in JavaScript per se to enforce such an interface, there are tools like TypeScript, or for example, the way you can do that, but regular JavaScript does not allow for that. But that doesn't mean that you cannot specify very explicit interfaces and state, this is the code that you're meant to use, this is our black box. Don't look at it, don't touch it, don't care about it. Use this one. And that works without enforcing it through language. However, JavaScript also, in terms of its entire ecosystem, it's much more lacks regarding interfaces and it's probably very difficult to avoid these same issues because the entire JavaScript ecosystem has not yet figured out how to do this properly in JavaScript. Because most of the systems, you have some libraries or some frameworks, for example, that have pretty clear interfaces, but then at the same time, you have code that just extends at the prototypical object level and basically changes the interface for all the code that is running in your browser. So it's very difficult to get right in JavaScript. I think the only way to properly manage this is to decide that we want to have explicit interfaces and then properly design them and have them documented as best as we can and let everyone know when they're doing it wrong. Thanks. Yeah. And how will support for newer PHP versions help with the structural issues that WordPress had? It doesn't change the way WordPress works. No, so newer versions introduce newer language constructs. But first of all, we can only ever look at the minimum PHP requirements we use. So right now we have PHP 5.2, anything that PHP offers beyond that, we cannot use it. And it's also, when we now, when we, for example, would now bump 5.2 to 5.3, it does not mean that we would then re-architect WordPress to make use of 5.3. That will just not happen, it's just not an option. But what we can do is, for example, use language features that are introduced with 5.3 to have better options of making important changes while still in some way keeping everything working with older versions. So the more the language can offer, the more creative you can get to get around backwards compatibility issues. And that's mainly what will help us in the coming future. Of course, something like PHP 7 with strict declarations would be awesome. But as long as it's not the minimum requirement for WordPress and we want to completely rewrite WordPress, it's just meaningless. Okay, time's up, thank you everyone.