 Welcome everybody. It's a quarter past the hour, so I think we're gonna get started. So this is a core conversation. So it's meant to be a conversation first and foremost. So I'm going to do a short presentation, kind of short presentation about my perspective on backwards compatibility in Drupal Core, specifically about Drupal Core. Kind of a general observation for projects. So software projects like Drupal and dealing with backwards compatibility and how we can get better. So it's meant to be a conversation. When you do speak up, please go and talk to the mic, via the mic, so that the recording contains the entire discussion. So that people at home who cannot be here can also follow along. So backwards compatibility. I'm going to talk just about a few things that I learned. So I kind of know better the things that I didn't know before. So there's still a lot to know, a lot of things to learn. I don't have a complete answer and I'm not going to have a complete answer. And I see that I forgot to disable my notes. I think it was this. Maybe not. I'm really sorry. There is something in here with no notes and it doesn't work. Yeah, okay. Was that? I know what's going on. Before the fragments. There we go. So I don't know how URLs work apparently. So yeah. So yeah, things I learned, I have learned a few things. I'm sure that lots of you have different perspectives and so on. So let's let's get a discussion going. The things I will mention, I'm responsible for both the good and the bad. And I'm going to rush through these so that we can have as much discussion time as possible. So I'm going to look at this from a core perspective particularly. So Hans up who worked on Drupal core. Okay, a third or so. It will be helpful for you as well if you're working on maintaining contract modules probably it will probably be or maybe be less useful if you're working only on custom modules because then you're not really facing the burden of backwards compatibility necessarily because you control the entire experience. So with that out of the gate, my analysis in a nutshell, if I had only one slide, I would be putting up this Drupal can be used for anything. So what we do in Drupal is that every bit of code must have an API to be generic because we want to support all the things. It must be over idable for the edge cases, but we don't necessarily have enough time to carefully design every such API. So what we end up with is something that is over engineered because we have APIs for everything yet under engineered because the APIs that we have are not necessarily always well designed, well thought through and therefore if we're not careful BC backwards compatibility can be a nightmare. So let's get better. This I think is a summary and this is what the core conversation is about. So looking forward to the conversation. Backwards compatibility in a nutshell is basically just promising that you can update without problems. That's the benefit. The burden is the rest of the talk basically because that's the thing we face as developers, the maintainers of Drupal core. And of course Theresa announced recently that the point is that Drupal would have easy upgrades forever, which means that backwards compatibility is ever more important because we must be backwards compatible for a far longer period of time. So over engineered, why? The question basically is why does Drupal have so many APIs? Well, I think the answer is, this is my perspective, is that we optimize for targeted overrides. So you want to be able to override that one small thing. The consequence of being able to do that or wanting to be able to do that is that you need granular APIs very to be able to touch those very small things, very specific things. And as a consequence of that, because there are many things that can be granularly overridden, we have many, many APIs. And so if we use an analogy, then I think this is something that kind of works if Drupal is a specific Drupal site is like a forest and a module is then or a component is like a tree, a feature within such a module is a branch, and then a super tiny thing within such a module is a leaf. Then the thing is that Drupal always optimizes to allow you to override any leaf in the entire forest to be able to override that one particular tiny thing. And other projects like WordPress or Django, maybe Ember, they all require you to replace an entire branch or maybe an entire tree. So they don't allow you to do the super granular overrides and that makes their lives a whole lot easier and it's less overwhelming as well. I think Drupal has roughly three types of APIs. Explicit APIs, so hooks, plugins, tech services, the things that we advertise as being the ways to provide APIs. We also have implicit APIs, which are our markup structure, renderer-based structure, the order in which things are called. So for example, the execution order of hook implementations, and those depend on weights and priorities. So those are kind of the implicit APIs, which aren't officially APIs, but if you do change them, that could break backwards compatibility, so we kind of cannot change them. And then there is the sad bucket, which is accidental APIs, because many of our interfaces, if not most, if we're very honest, and even some classes are actually also APIs, and we didn't really design them as being APIs, but we have to support them anyway. The official Drupal 8 backwards compatibility policy basically says this, so there is three different ways that you can have an API, or there's three distinctions in our APIs. There's add API, which is specifically marked as being, hey, this is an API, this is supported, we guarantee backwards compatibility, feel free to use this. Add internal that we explicitly used to say, this is not an API, you could override it, you could extend it, but it's up to you, you're on your own. And then there's a third category, which is the sad bucket, undocumented, and it says literally, if an API carries neither of these distinctions, nor add API, nor add internal, we treat it as we'll try very hard, not to break it, but we may, which is, of course, a lot of things, and then it's going to be very hard to try very hard to not break the API, but then accidentally still do it. And as you can see, this document is still in our discussion, so we have a backwards compatibility policy, but it's not fully fleshed out yet, and that's a problem as well. And so the add API and add internal, we have that, but in Drupal core, we sadly use add API zero times and add internal 53 times, which is not a whole lot. So that means that 99% falls in the undocumented bucket, so this one, which means that 99% is effectively considered kind of API. So we have a way to be explicit about things, and ideally we would be using it, but in practice, we're not yet using it, and that's a problem. So elsewhere, how do they do things? WordPress, the last time I gave this talk was a Drupal Dev Day Seville. There was the very well-known Drupal, or former Drupal contributor, Son, he was there as well. He's moved on since kind of to WordPress, to a large extent, and he confirms that this is indeed the set of APIs that you work with in WordPress. And so a much smaller set of APIs for Drupal, this page, or this screenshot would have to be maybe reaching the moon, maybe not as much, but it would be very, very long. Django, very similar, a very, you can easily get a good sense of what APIs are that are available. So the difference is that in Drupal, we assume that something, some piece of functionality is an API, it must be an API. Others don't have that default assumption, and that's a very important difference. They are more conscious, more explicit about making something an API. And so for the under engineered parts, so I mentioned before that I think some are under engineered because we provide it as an API, but are necessarily very conscious about it. So the accidental API, I think the key reason that we have many of these is that in Drupal 8 we went with the Adagio or the Adagio, the motto, or make everything object oriented. And so we had a rule basically every time we added a class in Drupal 8 core, it had to have an interface because somebody might want to override it at some point. Of course, that means that because we just extracted an interface out of the sole implementation, our interfaces are tightly coupled to that single implementation, which means that as soon as we find bug fixes that we need to do and need to change the signature of some of the methods on the interface, we break the C. New implementations that we add in contrib or in core that surface certain needs, we break the C. An example for me, for example, is in a quick edit module, we have an access checker, turns out we weren't actually using the dollar, well, the current user card, or we weren't explicit about the user that we were checking access for, we were always using the current user service. So we need to actually fix the interface by injecting that as well to the interface method, but we can, because doing this is breaking the API, because the interface is being modified. This is a super simple example, and I am the one who introduced this, so blame me, but this is something we didn't really, like it didn't bother us, but now, four years later, when we want to make things right and make things better for the future, we're suffering the consequences. So poorly designed APIs, because honestly, I didn't design this API, it was just, oh, I have this method, let's make an interface for it, so anybody can override it. This is now the consequence, we have a very hard time maintaining BC. And so I think, in general, what we need to think about when we add APIs is the support cost, and what we very often do is we want to have an abstraction for everything, so that you can cleanly, elegantly, with minimal code, do things differently. Well, many other projects prefer duplication instead, because that removes the cost of maintaining and supporting a new abstraction, a new API. I think it would be better if we would only add an API when we have the data to prove to scientists, and when there is sufficient demand, like you can add APIs for everything under the sun, it doesn't always make sense for the 0.1% that needs it to support that API, to provide that API. So I think maybe we need to be more strict about it, and then say, okay, you've got a super, super edge casey thing, you'll have to duplicate and change things that way. Another consequence of having so granular APIs and so many APIs is that we have problems with discoverability, because we have granular APIs, and that means that you have to do very little work, like how many of you have written a hook that has a one or two line implementation? Show of hands? Yeah, see, let's have to have the room. But how much time did it take you to find the exact proper name for that hook? Like how many of you have spent sometimes at least 20 minutes raise of hands easily? Yeah, it's the same amount of people basically. So that's a cost, like we have we have granular APIs, we have many APIs, and so it's very hard to find just the right incantation of this magical thing, basically, if I'm being a bit facetious. So that's the way we went so far, but what we could also do is go with the other route, which is simpler, but require more work, which is just duplicate things slightly, and it would be so much simpler to support. The second, so the first one was a under-engineered, sorry, the accidental API. Now, orthogonality, which is a fancy word, but it really just means small number of components and you can build complex advanced things. So how do we have a small number of components to build anything that we want? I think in the case of Drupal, the answer is no. And a few examples to make this maybe a bit more clear. The automated CRON module in Drupal 8, it has, it depends on five APIs in Drupal. It depends on the form API to provide you with a form where you can configure things, the configuration that you can set up there is stored in the config API and that configuration is then used by an event subscriber that runs on every request, that runs the CRON service and tracks in the state API when the last time was that it ran. See, I can explain this in one sentence basically. That sounds like it's a pretty reasonably, well, it's pretty simply built in a simple way. It's understandable. Big pipe is a similar story, but then entity API itself, so just using entity API means that you're using more than 10 APIs. And it's, it's, it's necessary. Like it makes sense that entity API, which is a bread and butter of Drupal, that it uses many of the underlying APIs. But maybe we can make that a little bit simpler. I think we have to be more, we have to try harder maybe to do so. But so the consequence is that whenever you're using entity API, you don't have to know just entity API. You have to know about more than 10 APIs and maybe understand or debug in very different sets of APIs. Another related thing is cascades. And this is something that's particularly true for the entity API. And again, for, for good reason, we wanted to make sure that you could jump in at the right level of abstraction for your use case. And so we have a very steep hierarchy of things that are extending each other to ever layer on more meaning. And it makes sense, but the end result is that you have these very, very complex sets of interfaces that are being implemented, then you need to know about all of them. And then once you have an entity and you retrieve a field and for a field itself, it's again the same story. This is very difficult to understand and it can take you a long time to layer or to step through the different layers in order to figure out what exactly is happening. So we did this for the right reasons, but at the same time it has consequences for DX for debug ability and so on. Maybe we need to reconsider that. So using some of these APIs can actually take you down the rabbit hole, kind of like this. And it can be kind of scary, even though it kind of looks cool. In any case, massive composition is what we do. We have long inheritance chains that we do as well. And the consequence is that for both you need massive amounts of knowledge, like you need to learn the inn and outs of the system. Then the last kind of under engineered assumptions, so this cute little baby is trying to fit the block in and it's really not fitting in any of the holes. So she just goes the other way. If you can't find the right, the exact right hook you might just go with a nuclear option and do in Drupal 7 the equivalent of hook page alter and replace all the things, that sort of thing. So when is this necessary? Well, Drupal Core does a certain thing and then the module and the API all have been built with the assumption that the same thing is always what happens. That's how it happens and it will never change. But then once you install a contract module, whoops, all of a sudden it's no longer true and then sadness. So for me, for example, I suffered from this as well. So I published a super simple module, no configuration, no UI. I thought, what can go wrong? Well, turn something goes wrong when you install the advanced segregation module because in my code I assumed that everything in the HTML head elements would always be something of this form that would have a parent tag, render array kind of, and then we could work with that. But turns out that once you install advanced segregation, there can be something else in there still. So my assumptions were wrong and I didn't test them. It worked fine as long as you were using just Drupal Core and dozens and dozens of modules, but as soon as you install this one extra contract module then there's something new appears and my thing breaks completely. So assumptions, we have many of them, but we are not always explicit about them and we're very often forgetting to test them. So making those assumptions explicit by using asserts or adding test coverage, that would be better. And then finally, the extreme one-ends for the consequences of these things, rest and serialization. It's a beautiful thing unless it breaks down. In Drupal 80, we shipped rest as stable, but unfortunately we had only very thin test coverage and only for the happy path. So as soon as you made a mistake like something that would trigger a validation error or what not, you would be getting very, very, very difficult to understand errors and you would be able to solve them basically only if you were stepping through it with a PHP debugger, which is not ideal for a REST API. Things like serialization gaps, so we need to provide everything, like everything that is in Drupal Core in terms of entities and fields needs to be accessible for your rest. But unfortunately when we fix those things, the things that are currently not entirely supported or even broken, the problem is that we will break BC. So this is something we didn't anticipate when the REST module was made stable, when it was built, and we're suffering the consequences now. So we're fixing these things, but it's very hard to find just the right line between fixing it and breaking BC. So when the entire response is an API, you have to apply extreme care. So in this case, I think, or overall the lesson is when the API surface is great, the test coverage must be even greater. And for REST, for example, that is the case. It's an enormous surface that we are exposing to the world and that we're supposedly supporting and so on, but it's very difficult to actually do that. And the problem is, again, that we're not clearly clear about what is the API, what is not. The extreme other end is something that has no interface. This thing is moving and has no interaction at all. It's moving by itself. For example, the dynamic page cache module. This is the entire list of issues. This is any status, any priority, any category, any version for the dynamic page cache module. It's five issues in total because we had, like it was very scary to add this to Drupal Core. It was even scarier to enable it by default. And so we had a lot of time spent on test coverage. So we tested every possible assumption, every possible edge case. And the result is that it's far more maintainable. Big pipe, we were very explicit about this because of the experience I had with REST. I was very explicit and I marked every single thing as internal because what big pipe provides is not something that is configurable, it's not about APIs, it's about functionality. So we were very explicit about not providing APIs so that we don't have something that is kind of undocumented and therefore we need to maintain VC, otherwise we break it. And so I think something that we very often forget about is that we can actually also choose to not provide an API. I think very often we can provide a very sane set of defaults or sane default behavior and you can customize it by swapping out an entire service or swapping out an entire class. That can be the only way for you to override something that makes it far more easy to configure, easier to support and so on because the default behavior for the 99.9% will always be the same. And that's something that's not possible for everything but for example for a big pipe it is. But we could have provided several configuration options for it as well but we chose not to. And so this is what I have and now we switch to discussion basically. I think these are the three things that for me jump out. Functionality first and then later at the API and not start with also shipping an API. That's something we did. So in other words everything should be marked as add internal first and you can add API later. Once you have sufficient confidence and you see the proof that there is a need for it preferring duplication over the wrong abstraction and finally I think we're pretty good about testing the critical path. We're decent about testing edge cases but I think we're not good enough yet about testing assumptions and so assumptions that this thing will always have this this data will always have this sort of shape that's something we've I think kind of often forgotten about. So I want to make Drupal Core more supportable more backwards compatibility maintainable because I see in REST that it's very difficult to do so. So with that let's discuss if anybody wants to. I have a question so use right on this Daniel winner. On this slide you say API later internal first but that means for new things. Even reset today we don't want to put too many new things into core. So I'm wondering can we make existing things internal? Oh, that's a really good question. Or on which levels like I mean there are layers in our system which is like yeah, I mean like bootstrap stuff. You could overwrite some of the bootstrap stuff but is that our API? Can we say this is actually not our API? We still kind of support you but if things break, man. There are lots of things that I think that's also what you're getting at. There are lots of things that are like you could theoretically overwrite them but we should actually mark them as internal because there will be maybe one in 10,000 people who override it. Can we then mark it as internal now so that we avoid pain in the future? I think that's what you're getting at, right? So there's a very long, I'm catch, by the way, not catch, well, there's a very long documentation page on dupal.org about the BC policy that which I'm sure well hasn't been as a cycle yet and that has a list of things that are internal, that aren't marked and it's a long list and a lot of those things in core don't have the internal and that's actually whatsoever. So this is the small part that you missed the beginning, so that's fine. So at API, that's what we use to mark something as an explicit API at internal to say, this is not something we support, you can do this but you're on your own and then there is this one and that's the problem, the undocumented one because that says we'll try hard to not break it but we may, these will receive a release note to mention. So we'll try very hard not to break it, it's very much what we do but that means that we're getting ourselves stuck in a corner. Yeah, but then underneath that we have these other things that we're gonna break and those things we should go back retrospectively and mark them as an internal. And if we did that then I think people's expectations would be met a lot earlier rather than what normally happens is we break something in minor release and feel like you broke my module and we're like, yes we did that's why it was in a minor release. Here's the long page that explains the reason that we broke it for you. So you're saying rather than pointing people to this long page and expecting them to look it up for every single thing let's move the ad internal explicitly into every single thing that this page says. Yeah, I mean we've had an issue open to do that three years ago and it's never been done. I would be happy to do that. I mean but I mean it's but part of the problem that we've had is that getting to that list has taken two or three years of iterative work like some issues go in and the only way that they go in is that we've had to edit this page to kind of retrospectively define a policy about whether certain changes could be made because it was completely open and that's, I mean it kind of says look it still says these technical review because it's in process and there's a big disclaimer at the top because we didn't do this work three or four years ago. Yeah and I think this is now even more important with Theresa Nouncing that we want to be able to move gradually to triple nine with our pain so it's even more important that this is moved out of this in discussion phase and into a phase where it's more explicit. Yeah I mean the things that are explicit in there can be documented in core. Okay. Why can't people go? Hi I'm Ed, I wanted to I'm hearing a lot of similarities to other things I've experienced where I'm more involved in the Ember community because we cared a lot about background compatibility for over a series of years and one idea to throw out there is we started out with kind of two categories which are mapped very much to API and internal, public and private and we realized there's always a third category and it's not necessarily whether it's undocumented or not but we tend to call them intimate APIs and they get discovered by use case, right? So mostly and I think this is true in Drupal as well most of the people who are diving into internal APIs are probably writing modules they're probably writing plugins, right? They're like usually you don't go hopefully you don't go directly from your app to diving deep into internals you need some functionality you write a contrib module, right? Or custom module at least. If you can get visibility into which modules are using which APIs that getting that data is extremely valuable to making these decisions because it's like you said a lot of these things might actually be tiny minorities of apps that get broken and then that's much easier problem. On the other hand you might have some piece of internals you don't realize that a huge number of sites rely on because of some very popular module it does it. So data is critical there. The other thing I wanted to say about retconning which things were private I think from Jesus keynote when he talked about the strategy of making minor releases additive and then major release with deprecation warnings and then major releases dropping deprecated features that's the same pattern we've been using very successfully and it's a way out to doing this thing with private APIs as well. Basically you can take something and move it and make the old one deprecated, right? And it might still be there it might even still have the same API but you've decided it needs to be private now you know people are using it you make it you essentially make sure anybody accessing it through the old path gets a deprecation warning now when they go to Drupal 8.5 or whatever some minor release if they try to actually clear all their deprecations they're gonna have to get off that API that private API and now and then when you hit Drupal 9 you can now it's like completely private and the publicly accessible one is gone it's a great strategy so it's just some insight. Yep, thanks for letting us know that it's working really well for them. Yeah, it definitely does. So at the beginning of the conversation you mentioned about the burden and just being on core but it actually you know when you're talking about rest it's just it's everywhere. Yeah, for rest it's everywhere. And it's not just Drupal so when you make an API and you provide a restful interface for vendors or whatever to consume out in the world they're gonna be making apps and then when you update a contrib module or you update core and it breaks some sort of like content negotiation just somehow changes and then that app or several apps that you have no control over written by someone else in a different language now breaks, they're coming to you and you feel this intense like it's become very hard to defend those changes. So I feel really strongly about just like having a good API like standard and not breaking BC as much as possible because it gets really hard to defend Drupal when you're running into these changes in front of like people outside of the Drupal community. Yeah, so you're specifically referring to rest APIs and it sounds like, or... It could be other things as well. Yeah, for rest it's extra difficult especially for Drupal because we allow data model changes to be made by anybody so that will also cause backwards compatibility breaks for those APIs. So I know the rest community which is a different program language and what they have is like packages they have a poster of all their like libraries and what they do is for changes in their APIs or even for any change they run a test against each library with a new compiler. So we could like, I mean, what we do at the moment is we run all tests of conflict modules against them but we could get the data into the core issue. So we always run them, we just need to facilitate them. So, I don't know how easy that is. Another thing is... Of course it doesn't work if the test coverage for that module is not complete enough but it will already help because many do have at least minimal test coverage. You can make a test for something, I don't know. And the other thing, so I was wondering again about this internal API thing. So I'm wondering whether we can deprecate things before we actually change things and then wait a release. I was thinking about your public function of your example of quick edit. Yeah. So let's assume that would have been an API. We could probably in that example somehow throw an application or some other warning in 8.3 and then change it in 8.4, like one half year later. Oh, so you mean require modules to update within one minor release cycle instead of waiting until major because that's something that Adam mentioned in specific that Amber at least is... So we do... Can you go to the mic? Do that somewhat similar and we make a distinction between things that are explicitly private and we're already private, we can break on a minor. That's okay. Yeah, of course. Things that are explicitly public, you can't drop until a major and that's obvious to the intimate APIs which is the ones that we know they were either not marked, they might have been explicitly marked private but we know that they're very popular because some popular add-on just needed it to get the job done and started using it. We consider those an intimate API and those we will not break until we have deprecated them for one LTS cycle which for us is about the same as your minors because it's about six months. Our minors are six weeks, our LTS cycle is six months. So you get to guarantee that as long as you hit the LTS releases in order you will see a deprecation before you get a break. Even though it was marked private we know a lot of people are using it so we do that way. So do we think that minor releases like from one minor release to the next we could in Drupal mark something as deprecated in A3 and then introduce the alternative in A4 and require that to be used? Can you go to the mic? It depends. We've done, there's been things with Migrate because Migrate's still experimental but people are using it and that's probably the closest to something where you're not supposed to use it but you have to. And we've introduced BC brakes with BC layers with the intention of removing the BC layer if it's a burden to maintain. So it's, but it really, it's gonna depend on what it is. I mean, but I mean, also- But something theoretically it's possible at least for some use cases which would alleviate the pain somewhat. Yeah, I mean the other thing is you can also introduce a complete replacement like a completely new interface and then switch on the new and the old interface. Yes, but that's still a BC break, right? Because modules have to follow in order or you're saying not remove the deprecated one in the next minor. You don't remove the old one but you don't have to change it if you just, you do something completely different. So, but it's a much more, you have, like you're not just adding an extra thing on an interface so you're adding a whole new interface just for that extra thing on a newly named method. So you have to do a lot more work in the background but it doesn't stop the change being made. It just makes the change a harder to do. So there's a whole spectrum of stuff but that's what we have to figure out patch by patch. I think what's important with this tool is that everyone needs to be thinking about this a lot more. And with Dupal 9 only dropping backwards compatibility all the things that people wanted to do in Dupal 9 they can now do, they can do now, right? That's always been the case since we introduced minor releases but people haven't been thinking in this way. So kind of how far can we stretch it so that we can actually get stuff done is where it's, and it's a lot of it's open. Like we don't want to break people's actual real life models and sites in minor releases and within these parameters but the parameters are still being defined and we have to figure out what the lines are. But it would be good to have it less issued by issue than it has been. I mean, it really is like an issue come up and you have to have a whole discussion about whether it's backwards compatibility break or not within the existing rules. Sometimes change rules, sometimes clarify rules or what do they, it's tricky. Hi, my name is Agostino. I would like to ask you if you can go a bit deeper in preferred duplication because this is recorded and maybe you can explain what is your approach to prefer duplication instead of using that dimension. Yeah, so for example, in this case let me open PHP storm. So in this case, we're providing an explicit API to implement a quick edit field access check thing and my PHP storm is disappearing. That's, no, wait what? So we provide an explicit API to implement such an access checker but what the alternative would be is things are being very slow. I don't know why. What the alternative would be is instead just overrides this entire service. So that would be something that you can do in very many cases just replace the service entirely and instead of this implementing a particular interface you just copy paste the default implementation which is this one and you modify it and point to that modified class in the access check service. So then this would point to my alternative class. That's basically the duplication that you could use for example for many, many services. So instead of providing an explicit interface duplicate and the burden is on the comfortable or custom module developer to keep up to date because we don't provide an explicit interface for it. So the risk is that you are going to have to update it with every release but that is exactly what we want. We want to hear whether it is something that is a common need, whether it is something we need to support whether there is demand, whether there is enough demand for it. So that's what I meant. Hope that's clear. So another thing that from my opinions is that like base classes should always be considered API because we made a base class and we want people to use the base class. So when a base class signature, math has a signature changes it's going to be very, it could be disruptive regardless because we say, hey, you use it and then, oh no, we're going to change it. So if you open up the API, a BBC documentation page it says for public interfaces I think if there is a base class, you are safe because like new methods will be added to those base class so you don't have to care when you extend the base class. But if you have a constructor, the construct method then that's not safe. Okay, so constructors for base classes should be considered API? Yes. Yeah, or we use magic. Yeah. We usually solve it with magic, right? If the constructor technically needs to be updated we don't update the constructor and we just go and retrieve it by talking to the service container directly. And I know there's ways of working around it but if we do have a base class that has a construct method already defined I think that it should be at API and not at internal because it is, you know, I've been bitten by that. I think that's why I'm so opinionated. I think that we're, that is something at least that we do think pretty decently. We don't break base classes I think. I've yet to know of one that we broke and had problems with. I think it's one of the account access base classes that I have to work. It might have been an interface as well. Okay. I overrided a service and just to pass in a different argument and my class is just an empty class extending, I think it might not be a base class because I have to work again. It was very useful. I was like, hey, I don't have to write any code. One thing I was wondering, so you mentioned that we have on the page where you mentioned how our APIs are designed as everything is just copied from the old implementation objectified and then put an interface on that. Yeah. So I'm actually wondering whether we should skip shipping with interfaces until we know that we wanna support this API. Because like, so I'm currently working on patch and this patch introduces a whole new subsystem but I don't need an interface. Like I have classes, I have inheritance but I don't need an interface. And it's an API which is designed to be used. Like I call something, get something back. It's not designed to be extended. And I think we don't necessarily have to design every piece of everything to be extendable. Yeah, exactly. I agree. And that is limiting the API surface, right? It's postponing the adding. This is basically what I said in the conclusion which is functionality first API later. It's like what you're saying. And I remembered that when we were working on the media entity patch in Drupal Dev Day Civil we explicitly removed several interfaces and marked a few methods on the base class I think as internal precisely for this reason so that we wouldn't be exposing ourselves to supporting that API forever. Whereas we weren't, because we weren't certain yet that it was the right shape and form. So I think we're getting better about it but we need to be very conscious about it when we add new things to Drupal Core I think. I think we should reiterate on the existing things because like we have a lot of APIs. So you're saying we should reiterate on the existing APIs to remove them? Yeah, and mark the interfaces that are deprecated for example but keep the implementations major. For the ones that haven't been very explicitly designed, yes. To limit the future backwards compatibility burden because then we discourage module authors from using those. Yeah, yeah exactly. And I mean we wanna be able to go to Drupal 9 at some point and like the problem is like if we have so many depth like if we have all those APIs in place we will have a hard time to go to Drupal 9. We need to remove it now because we don't wanna have this weird gap of 4.5 years again. Are we hearing an API removal initiative? Mateo. I was beaten by a change on a base class. It was a change on the content, entity content and base class. And literally it was less than 24 hours until someone submitted a bug report and it could be fixed because I was implementing the class directly. So this happened in contrary. So maybe it's good to know or I didn't know that I should be using the base class otherwise I didn't have BC guaranteed but that didn't turn to be like catastrophic. So. And that's something that Daniel proposed that we would have tests, the tests that run in Comtrip for the next version of Drupal 8, the next minor that would have detected the failure that you're describing and would be creative that will surface to the Drupal core developers. Yeah, exactly. So on that note this seems to be like in practical terms. Let's say that I'm maintaining a bunch of Contrips and I decide to go all in for marking everything at internal, right? But someone wants to kind of build on top of what I have done, right? And they just start doing stuff and they say, okay, I need to get this thing, which is this class but they get this strike through in PHP storm and they realize I cannot use this so I cannot get the job done. So what is it then? Because it feels to me like there is like an approach of the intimate APIs but we need to discover that. How can I know that someone wants to use something that I mark as internal but I may change it to API if I know that anyone uses it. Static analysis could help with this. So I think that PHP storm thing maybe we can work with the PHP storm people to ensure that deprecated versus internal are marked in a different way. Oh, sorry. Yeah, because both are just the strike through, right? It would be good I think if they had a different indication that it's not as if one thing is deprecated and it will be removed versus internal will not necessarily be removed. It's just something we don't support. So it should be marked differently in PHP storm. That though is something that would help I think but yes, otherwise great question. I don't have an answer. So if you're marking something deprecated for developers who use a different editor than PHP storm or site builders and they're just installing random modules and they've got no idea that a big chunk of something is calling something that's deprecated and it's going to disappear next month or next year or whenever. Like have you thought through that? Is there any idea of like some sort of weight with a message on a site status page? The same way as when the database needs to be updated. I think and that might have some ideas about that apparently. But I noted trees mentioned it this morning in the keynote kind of he mentioned that we will need tools in order for you to know whether this module is compatible with the future or still using deprecated APIs. That is something that will help. There's the developer toolbar that's like basically what develop module does in Drupal 8 now. And because we do trigger error at deprecated you don't get deprecation errors in the logs but you can customize the error handler to expose them. So if you install a toolbar it doesn't work because no one's actually done it yet but Symphony has implemented it for their version of it. So all we really have to do is port the logic over. So you have a customer error handler, it collects it, at the end of the page it's gonna stick in a thing, 20 deprecated usages on this page because it's actually seen the deprecation messages that we're firing. But it doesn't, it just like literally it just needs people to work on. Also there's PHP unit integration for the same thing so that you can run tests where deprecations are okay. You can run tests where they cause like warnings, fails, you can test the deprecations that the actual deprecation message is firing when the wrong input is put into it. All of that is done but the actual infrastructure is not there for call yet. Like conceptually we have most of that because Symphony has done it for their own system. But that would only work though for the code that is executed on the current page. So maybe if there's a module that is running in some far forgotten corner that is running by Chrome, triggered by Chrome, then the code wouldn't be triggered and then you wouldn't see the error messages that you're referring to, the ones in the toolbar. So I think you will still need the Drupal.org level indication or the status page level indication so that as a site builder you know, oh, this module, it's not going to be supported once I upgrade to the next. I mean, if we do it on the Drupal CI and then there's test coverage, then it would, but I mean static analysis, it's like an API module, drupal-contrib.org, I don't know what the status of that is now, but that used to be really good for is this hook being used. You could go and you could see, oh, at least 15 modules are using this hook versus no one implement. I mean with API breaks, it's like, if a tree falls in the woods, like if I break this API, if no one's using it, who cares? Because no one's ever going to know, versus some, you think it's okay and then suddenly it's like, someone's house is falling back. And that's kind of the demand thing that Ed has also been referring to, like you need the data and knowing how many people are using that hook or that event subscriber or that whatever it is, would be super valuable because then indeed it's safe to break, well, safe to the extent that custom code could still be broken, of course, but yes. Would you, like do you think it would be recent, just like on the status page to go back to that because that's what the site builders at this point are going to go. In the same way they can see if a module has an upgrade or a security upgrade, there's two different statuses there, do you think it would be possible to add a status to say this module doesn't have an upgrade, but it contains a deprecated API calls and it's probably going to have problems in the future. Yeah, it's an open question how we will solve that, I think, but I think it should be possible in theory, maybe something along the lines of static code analysis run by Drupal.org so that you don't, you have update status, but you also have deprecations status kind of so that you know for a given module, is this compatible with the next version of Drupal, the next core miner or the one that is already out maybe and so on. I think something like that is what we will need, but what we don't have yet. Yeah, I'm wondering whether we should just allow like module authors to have a flag in the info file. Oh, it's thinking the same thing. Like, I mean, it's so simple. I mean, and yes, it's like tricking the system and everything. Well, no, it's not tricking the system. The problem is just that you then need contract authors to do a new release at least every six months, even though there may be nothing, that nothing has changed and they need to be active in maintaining their modules to do a release every six months. So that's like, I was thinking the exact same thing just now, but I think that's where it breaks down. Hi, I'm Lauri and I was just wondering like how much does this drive us from being a, what Drupal is to be a just generic framework because of one of the powers that we have because of the APIs, like the very generic and complex APIs is that plenty of different contract modules can work out of the box together. Like you can install 15 different contributed modules using the same API and whoever is installing them don't have to really care about that at all. But instead, if we move towards the, you know, copying all of these things to application, then it's the responsibility of the application builder to build like proxies and things to make the multiple different contributor projects work together. I think that's a super, super good point to be honest. And I recently heard a podcast, I think by the Lullabot folks, I think Mike Herschel, I think I saw him in the back just earlier, but I think he's gone now. He was talking about WordPress and Drupal and how they have, our WordPress has a problem that, for example, they have many competing implementations of what we call CCK or Field API. And because of that, everybody has to duplicate all the things and the entire ecosystem is duplicated essentially, or they have enormous if else switches to detect different implementations of field API and CCK, and then they have different code to deal with each of them. That's the thing that would be the consequence. But I think we're so far removed from that, like I've never heard that be a problem in Drupal. I think it's kind of like we're 100 times bigger in API services, if we could go to 10 times bigger, we would still support all those things and walk a better balance, walk a finer line of choosing to support what you say would be a problem and avoid that problem. So still make it possible, but remove some of the things that are barely used as APIs. Yes, we need to be careful. I definitely agree with everything that you've presented and what's happening. It's more of just something that we have to consider when we do it, and I just wanted to hear if you have any thoughts about that. And yeah, I think we've done some pretty good decisions in the Drupal 8 lifecycle that we've marked a lot of markup internal, which has allowed us to make things like the status report page that trees presented on the keynote in Drupal 7 that wouldn't have been possible because of the markup was all marked internal and it's pretty, it makes my life as a maintainer easier because like now we actually can change things in like full teams, but the problem over there is still that even though those are marked internal, there is plenty of even large contributed projects that are using the internal API as their API. And it's like, I still feel scared for breaking sites even though it's marked internal. Yes, exactly. So basically this, it's an implicit API like markup technically is internal and we don't need support, but kind of we still do for some levels of the markup kind of like the overall structure cannot really change them. That's a difficult line to work. That makes sense. Especially for the render array structures, we've stated that they're internal but there is specific types of changes that you know would break everyone's sites, yeah. Hey, my name is Mike. I work mostly in the contrib space, so not much core but I feel like the really granular APIs have really helped for the unforeseen contribution so people taking things in a completely different direction but still tying them in with these APIs that exist and this conversation's made me think of kind of an analogy. There's a landscape architect who designing a quadrant planted all grass rather than planning out any sidewalks at the beginning, waited for people to actually just walk through the grass and carve out paths and then pay for those. I think we wouldn't want to go to that extreme where it'd just be chaos and to determining what's internal and what's an API but maybe there's some, the static code analysis. Think of seeing the use, seeing what people are doing with it and then taking that and basing some of the decisions around that. I think that's a great approach. Yeah, I agree. Thanks, that's a great analogy indeed. So Ember apparently documents or says says it explicitly paving the co-paths which is indeed the expression. So I really did the duplication concepts that we do. You really like it, you said? Yes, and for the reason that it prevents as many BC breaks and it's gonna be hard, right? We're at a point in Drupal 8 where we have all this complexity and then we're gonna have to start duplicating and it's gonna be, it's gonna hurt. But when we get to Drupal 9 and we start making decisions in Drupal 9, it's gonna be a lot easier because it makes some smart decisions of like, okay, this didn't work. One thing didn't work and the duplicate thing did work or we can maybe have three choices and then in Drupal 9, the code base will shrink, hopefully. And I think that once we make these decisions of and solidify the backwards compatibility or incompatibility policy, we will be in a good place. But I think it's gonna hurt at first. Yeah, no doubt, but it's already hurting, right? So the longer the more time passes, the more it will hurt because we fix more bugs and that fixing those bugs will sometimes require backwards compatibility breaks and so on. So yeah, it's unavoidable. We have to get through it anyway. So yeah, I think we should prefer duplication over the wrong abstraction. All right, I think we're... I thought of one thing that I wish I could go back and do differently and maybe you guys can do it from the beginning. When you mark something deprecated, the way you do that actually explicitly in your code, I would strongly suggest that it actually have kind of as of version information right there in that line that's programmatically accessible. Do you already do it that way? We do it, but it's not programmatically accessible, I think, per se. And even in fact, actually two ranges, like deprecated as of this point will be removed as of that point because you really want automated tooling to be able to let people focus on these in small bite-sized chunks and you wanna be able to keep rolling out new deprecations even though people are still chasing the old tail of them and you want people to be able to do things like in their test suite, forbid deprecations older than a certain point so they don't regress but let them slowly chip away and move forward in getting the newer ones. That's super valuable. So that you have a certain number of releases to fix your code. That would be the dream, I think, for now. Okay. Anything else that we wanna bring up? Nobody has any burning questions. So I think this was a useful discussion. Hopefully we'll get some useful direction out of it for Drupal Core as well. So thanks, hope this was fun.