 Okay, I guess we can start quickly. So this is the coupling Drupal modules into PHP libraries, a commerce to the text primer. My name is Bon Jovanovich, I'm Bon Zee on Drupal.org, and I'm the Commerce Development Lead at Commerce Guys, which basically means that I work full-time on commerce to the text, our rewrite targeting Drupal 8. Commerce Guys is the company behind Drupal Commerce and Platform.sh. We have offices in Paris and Arbor, Michigan, and London. We also have a booth in the exhibition area, so come by, have a chat, look at the platform demo, or let's just talk to Commerce if you want. So we built Drupal Commerce from scratch on the then-new Drupal 7, making use of its new technologies. We used Entity API for the data model, we used views for our listings, and rules for our business logic. And by doing that, we created a system that was immediately familiar to Drupal users and developers. If you knew Drupal, then you already knew Commerce. Commerce aims to be minimal, making minimum assumptions, so it allows you to take the parts that you need, change what you don't like, and simply build your project. And three and a half years later, we now have over 56,000 report installations, which is a current record for e-commerce and Drupal in general, powering many important sites from Olaj to Ryan's RealMilkCheese.com. And he's not here to appreciate that joke. So in the past three and a half years, the world around us changed completely. PHP 5.3 happened, Composer happened, Symphony 2 happened, and Drupal 8 is happening. And if we want to repeat our earlier success, that means starting from scratch and re-evaluating everything while still keeping our old values. And doing that actually gives us an opportunity to re-evaluate our problem space. You will notice that there's no such thing as the e-commerce problem, just like there's no such thing as the content management problem. Instead, it's a collection of connected problems each with its own complexities and its own tradeoffs. And when you look at it, taxes or addressing or payments, these things are not really tied to Drupal. And if they're not tied to Drupal, maybe they don't need to be done inside Drupal at all. Maybe we can do it outside of Drupal and by doing that, get additional people on board. So that's what we decided to do. We decided that instead of starting by writing Drupal code for commerce to the text, we would start by writing libraries. Then commerce to the text would depend on these libraries and pull them in via Composer. And that's it. By doing that, we gain additional exposure, we open ourselves to non-Drupal communities, and we validate our expertise. CommerceGuys.io.pl was the first library that we created. We needed a source of currency information that was kept out of up-to-date because we hard-coded the currency list in commerce1.exe, so it kept getting outdated every few months. We found an up-to-date source of that information in CLDR. So CLDR is this big project that provides locale data. So it has currencies, and it even has translated currency names and symbols in all languages. It has a list of countries, Drupal core uses it, languages, and a lot of other data. And it's maintained by big companies such as Apple and Microsoft and Google. So we decided to build a library that would take parts of the CLDR data set, and then it would provide these entity classes that would represent that data, and then we could use that from commerce. We also needed a way to format currencies according to locale, so a euro amount is not formatted the same way in France and in Germany. And the only previous way to do that was with the PHP IMTL extension, which is good, but it's not available by default on many servers, which meant we couldn't depend on it. Even Symphony couldn't depend on it, and their user base is much more technical. Luckily we found the formatting information in CLDR again, which allowed us to re-implement their number formatter in 300 lines of code. So when you add all of that together, you get commerceGuys IMTL. And we had great success with that first library even to the point of influencing Symphony IMTL. So Symphony IMTL started its life as a library that just provided the English fallback in case you didn't have the extension. But once they saw our library, we convinced them to follow the same steps. So they copied their approach and our generation scripts, and they started shipping CLDR data themselves. So right now if you're using Symphony 2.3 or even 2.6, you have the same functionality in the sense of currency lists and country lists and so on. They still don't have the number formatter, but we are working with them to merge that into a future release as well. So with our first library, we actually managed to influence Symphony and connect with them and start cooperating with them, which was a pretty nice win to start with. The second library we created is called Addressing, and it's the library version of Address Field, basically. It handles postal addresses, their storage, their validation, their formatting. And when you think about it, every country has its own postal requirements. So these requirements tell you which fields you need to show in which order, how they're labeled, how they're validated. So we needed to introduce this concept of an address format and then use the loaded address format to generate an address form or to validate an address or to format it for display. Of course, this also means that the library needs to have a data set to be truly useful. And luckily, we didn't need to create such a data set because we found it in Google. Google created a data set for 200 countries along with their lists of administrative areas because they needed it for Android. So we contacted them and got their permission to release it under DMIT license. And by doing that, we created a truly unique PHP library, which got over 300 stars in one week. So it made us the trending developers in all of PHP on GitHub, and it connected us with the Cilius project, which aims to create an e-commerce solution on Symphony 2. So Cilius decided that they want to use our addressing in zone and text libraries inside their own system, which is a pretty big win. Now I should mention that that hasn't happened yet because they don't really have full-time people working on it, and I'm afraid that we will have to be the ones to help them do it if we want to see it happen. Then we created the zone library, which introduces the concept of a zone as a geographical grouping. So a list of countries, a list of states, including or excluding postal codes, which is very useful if you're doing any kind of shipping or taxes. So for example, you might have one shipping price for California and Nevada, one for the European Union. And it's very useful for taxes because you might have tax rates that only target a specific zip code or a country plus some zip codes, which is common in Europe with German VAT, for example. And then there's our crown jewel, which is the tax library. The tax library holds over three and a half years of our tax knowledge. And we learned this the hard way. We actually had to spend more than a month listening to David Kitch and our tax expert explaining this over and over to get it right. No e-commerce solution gets this right. So we decided to do it right and to create the library that others can use. This tax library has a data set with predefined tax rates for all of the EU. And we hope that the community will help us by adding tax rates for their own countries. Then it has a really smart data model that takes into account that tax rates can change so they need a start and end date. And finally it has this system of resolvers that allows us to write pluggable classes for each country. So we have one class that handles EU specific logic, one class that handles Canadian logic, and so on. And these classes can be units tested and they handle the differences between B2B and B2C physical and digital products. And all of the other complexities that we can think of. And this library really attacks the whole issue of EU VAT changes that targets people who do digital commerce. So from 2015, you need to start charging the VAT of the customer. And this created huge ripples in the community. We addressed this with the library. And by doing so, we did not just get the attention of other e-commerce solutions that are open source, but we also got the attention of SAS solutions. So Foxycard, which is a host of e-commerce solutions, is now using our tax library. And Kong, a British SAS solution, is also using our tax library. And because they are using that library, they found bugs in our tax rate data, they found edge cases, and we fixed that, and together we made a lot of progress. I'm really, really happy about that. And more welcome. We are working on libraries that are on pricing, so the interaction between taxes and discounts, payments and shipping. But that's not important. The point of this is that we now have enough examples to look at the actual problem space of creating libraries and what can go wrong. Of course, before we do that, we need to ask ourselves, why should we go through all of this effort in the first place? Well, first, it's a good chance to re-examine your problem space. If I'm writing an addressing library, then I'm suddenly thinking about the addressing problem. Where does it start? Where does it end? How do I need to solve this properly for my library to be truly useful? So I don't really have a chance to do it in a half-baked way, like I might do if it was a part of a much bigger application. Of course, for us, one of the main reasons is that you get additional exposure. Suddenly, many other communities are using Commerce Guys libraries, which means that I can tell them, if you like this, there's more where that came from. And it also means, of course, additional developers and additional help, additional people coming to Drupal Commerce. It gives us a chance to validate our implementation. Commerce 2-point tax won't be ready for other six months, but people are already using our addressing and tax implementations in production, which means that I'm getting fixes for edge cases all the time. Someone will open up PR saying, your postal code validation is not precise enough in China for Taiwan. I say fine, we'll fix that. Or someone says your tax does not account for a U.S. company that's registered for UVAT, I say fine, we fix that as well. So that means that when I release Commerce 2.0, it will have many of these edge cases removed and it will be much more battle tested than it would have been if I had kept it under wraps. It's a big win. And you get more maintenance help. You will notice that these are hard problems, maintaining address formats for every country, maintaining tax rates for every country. It's a really big maintenance burden and no one really wants to help, because as I said, that's the most boring part of e-commerce. But if I gather maintainers from other communities, if I work with the silliest maintainer and other maintainers that may be together, we can solve all of these problems and just leave more time for solving the fun problems. And finally, it allows you to back forth this logic easily, because the library is isolated. It means that I can plug it into Drupal 7 or Drupal 8 into a symphony app. Wherever I am, whatever kind of a project I'm doing, I can count on my code, which is also a good thing to have. The not so hidden cost of this is time. Remember how much more time it takes to create a contrib module versus just doing something for your own site? Well, the same kind of a trade-off exists between creating a module and creating a module and a library. For us personally, it's been months of additional development. We would have had a beta of commerce two-point text if we hadn't gone to library routes. But as I said, for us, the additional exposure was worth it and it was something we really wanted to do all along. One cost that's a part of it, well, let's break down the time cost. The first problem, of course, is learning how to make the library in the first place. I can help with some of that. The other problem is the fact that you're looking at more edge cases and solving the problem in a more complete way. It's also fine. But the third problem is that your library needs to appear native to developers of all kinds of systems. So symphony developer, a larval developer, a triple developer, all of them should find your library easy to use and integrate. Code should not be weird just because it uses an external library. If it is weird, then you've already lost because the developer experience has suffered. So doing this is actually hard. So think about all of these systems and all of these developers and how they're going to proceed your code. And we'll look at some tips and tricks on how we can actually solve that. Let's look at how a library looks like. Let's say I want to represent currencies. So I start by creating a currency interface. The currency interface describes how a currency behaves. So a currency has a currency code, a name, a numeric code, a symbol, and the number of fraction digits. I can get all of this data and I can also change it. This is the contract for the currency. Now at the same time, I implement a default currency object. This is the default object that I can use, for example, if I'm loading data from JSON. So if I'm taking JSON data inside the library, I will load it into the currency object. The currency object is also used by symphony systems that use doctrine. When you're using doctrine, you can add an additional mapping file that describes how such an object is persisted and loaded. So you can reuse the provided object by just providing the mapping separately, which is really neat. However, systems like Trouple and Laravel cannot do that because they require entities to extend their own base class, which means that for Trouple, you create your Trouple entity types like usual, but you just implement the library interface, which means that the data that Trouple loads and creates can actually be used by the rest of the library. And we'll see how that looks. Of course, an entity might not just be a bag of getters and setters and empty properties. It might have some kind of logic. OO purists will say that an anemic data model is not a good thing, and at least it will have some kind of helper. So for an address format, there might be different ways to get the format information, which fields are used and in which layout. So what we do is we use traits to accomplish this. Who here knows how traits work? One, two, three, four, five, six, OK. So a smaller portion of the room. Traits are basically language assisted copy based. They are a new feature of PHP 5.4. And you write a trait the same way you would write a class. And then other classes reference that trait. They use the trait. And so that way, both the currency default class and the troop entity use this trait, or the address format one, doesn't matter. And they share the same methods. That way, I can share a code between different classes without needing to extend a base class. So that's good. It also means that we can unit test this trait in only one place, and we don't need to repeat our unit's tests for both the library and the triple integration. So traits are a really useful tool for writing libraries. And they're the main reason why I went with the PHP 5.4 minimum requirement in the first place, though since then it has become normal since PHP 5.3 became unsupported. Entities frequently have references, relationships. So a node has comments, for example. Now with the triple, you would get an array of comments. But doctrine would actually give you a collection. Now a collection is an object that behaves like an array. But since it's an object, it means that you can lazy load stuff. So the collection can load each comment only when you first access it, which is a really great performance optimization. Now, luckily, doctrine collections are a separate project, a separate repository that has only two classes with 200 lines of code, maybe less. So you can easily pull in collections inside your own library, which means that you can make your own code in the library more elegant. And since you're using doctrine collections here, it means that doctrine can still use your default data model without changes. So it can use your class with the separate mapping. So that's really a useful trick. And it doesn't really affect your triple implementation. It just means that you're more accessible to symphony people. Once we have entities, we need a way to load them. In Drupal 7 terms, that means having a controller class. In Drupal 8 terms, it means having a storage class. The outside world calls this a repository. So that's how we're calling it here. And if you look at this code, it's a repository interface that loads one or all address formats. And that's all that we need to know. And then we can provide a default repository implementation that loads data from the JSON that ships with the library. But then Drupal can have its own implementation that loads entities. And you can introduce a caching layer or anything that you want. And of course, finally, now that we've described our data model and our data set, we, our library actually needs to do something. It has some kind of business logic, something that it's doing. We call this logic in these kinds of objects services. And when you look at them, they're just dumb objects. There's nothing special about them. They specify the requirements in the constructor. They don't assume the presence of a dependency injection containers. It might be used or maybe the dependencies will be passed manually. So look at a zone matcher. It requires a zone repository, which will be used to load all available zones. It type hints the zone repository interface, which means it doesn't care which repository it's getting, the Drupal one or the library one from JSON or from the database as a source. It just wants some kind of a repository that can give it zones. And then it has a match method, which will load all of the zones and match them against the provided address. So simple. And all of our services work the same way. Simple small objects that do one thing and do it well. Validating an address, formatting a price amount, deciding on a text type, resolving a zone. As I mentioned, the library has the problem of having to appear native to different kinds of developers. And that's not always easy because no matter how much closer we are in architectural style, Symphony and Laravel and Drupal still do things differently. And you need to account for that. So let's look at some of the problems that might appear. The first problem we have is the problem of translatable strings. Now, don't get me wrong. You can have entities that have the concept of multilingual baked things. So you can assume that a currency might exist in multiple languages. That is not it. What I'm talking about is simply translating some strings that might appear through the library. So for example, if I'm outputting an address form, I need to translate the string state or province. So we basically cannot do this. Why? Because different frameworks do this in a different way. So the way Symphony and Laravel do string translation is to force you to create your strings in a separate file, keep them IDs. And then your PHP code just calls the string translator with DID. So they say, translate the string with DID, commerce guides addressing province. But Drupal, as you know, has the T function, which always requires the full source string. So that means that you cannot have a single unified way of dealing with translatable strings. And what our libraries do is actually not translate strings at all. Instead, we use constants. And we tell the implementing application to replace the constant with the translated label. So let's say that we have three different labels for the city field, the locality field. It can be a city. It can be a district. It can be a post town. We simply define three constants. And then the Drupal module is the one that maps the constants to a label that was passed through T. We have this neat streak where we don't add the constants to the interface. Instead, we create an enum class. So an enum class is a really dumb concept on enumeration. So it has the constants that you're using. And then it has a bit of sugar that allows you to say, this is the default one. And these are all of them, which is really useful if you're building a UI. So for example, a Drupal UI for creating an address form can now list all of the available options. We have a commerce guys enum library for that. So it's a good thing to keep in mind. No translating strings. It's not so bad if you know your strings in advance. Then there's the problem of pluggable implementations. So let's remember how resolving a text type works. We have multiple resolver classes and we call them one by one until one of them gives us an answer. Now, other libraries or modules might provide their own implementation. Someone might provide a Serbian text type resolver. The question is, how do we discover these implementations? Well, on the library level, you don't do that. So the text type resolver engine does not do any kind of discovery on its own. It just assumes that it is past all of the discovered resolvers. And how the discovery is done is not the library's concern. Different systems have different ways of doing this. So in Symphony, you would register all of the resolvers in the dependency injection container and give it tags. So you'd use tag services. And then the Symphony application gets all of the resolvers with the specific tag and passes them in. Drupal, Drupal 8, uses plugins for this. You declare a plugin type and then you have a bunch of plugin classes that have an annotation on top. And that's what Drupal uses to discover which classes are available. So you want to use plugins if you're using Drupal. And Drupal Core actually has certain places where tag services are used, but I would argue that's not really a native thing to do in Drupal. And I'm not sure how much you can see this, but in the bottom, there's an example of how Drupal Core integrates Symphony constraints. So Drupal uses the Symphony validator, but it makes the constraints discoverable as plugins. So what Drupal does is it declares the plugin type and then it creates plugins that extends the constraints that were provided by Symphony validator. So we would do the same thing here. I define a text type resolver plugin type and then I create a DOM plugin class for each of the resolvers that ship with the library and that's it. I extend the library class, I maybe replace the message with something that was already localized and I add the annotation on top that is used to do the actual discovery. The important thing to note here is knowing when to stop. This means that there are some problems that are simply not worth solving in the library. Why? Because the different parent systems simply vary too much. For example, forms. Each framework has a completely different way of doing forms, Symphony forms, Drupal forms, Laravel forms, whatever the way that's done. So it means that the library simply should not provide forms. It's easier if you don't do it. Now you might be tempted to say, okay, I will build my own form builder that will create some kind of generic form structure and then I will create class that will transform that structure into a Drupal form, a Symphony form, and so on. But don't do this because it's complexity and it means that your implementation won't appear native to Drupal people or Symphony people. Suddenly you have a form that you cannot alter or you cannot understand how it's built. It's weird. So that's also one thing to understand. Know that duplication is not always a bad thing. For example, the addressing library has a formatter class. So the formatter class takes an address and it outputs HTML with the rendered address and that works great. However, if you're writing a formatter inside a Drupal, then you would expect to have a render array. So to appear more native to Drupal people, we simply implement our own separate formatter duplicating about 150 lines of code. But it means that the developer experience is better. So let's talk about which problems we should actually tackle. We now know why we would want to do a library. We know what can go wrong. We know how we can fix some of those things, but which problems do we actually start tackling and what do we handle in our own libraries? Well, the first problem is the one that I like to call hard problems. So hard problems are the ones that require domain knowledge to get right. These are the things that require experience and you can often see other systems doing them completely wrong. So a good example of this is taxes. Many systems do taxes in a wrong way or the interaction between taxes and discounts. If you are solving a hard problem, then you're basically turning all of your experience into a library form so that it's available to all of the PHP community, which means that you're providing great value. Then we have boring problems. Boring problems are the ones that have a lot of edge cases. So think for example, addressing. Addressing is not hard, but every country has its own address format. So you need to gather all of this information. It's not easy to do this alone. So if you're doing a library, you can do this with more people and you can tackle a boring problem. Think also about logging. You really don't want to reimplement logging, but for example, monologue does that for you and that's why it's useful. So in this kind of cases, you usually start by thinking, oh please tell me, I want to spend a week doing that and then you find a library. But if you don't find a library, then you will save many other people the same efforts and that means that your library will be very valuable and if no one is using your library, then it's not very valuable. The main question to ask is, are you saving anyone time? When I talk to e-commerce maintainers and we talk about libraries, they say, yeah, sure, libraries are a great idea. Let's create a cart interface. Nobody cares about your cart interface. Why? Because a cart interface is something each of us can think of in 10 minutes and then we're done. If a library can be reinvented in an hour, then it will be reinvented in an hour because everyone has their own opinions. If you want your library to be widely used and if you want to go through all that effort, make sure that it's saving someone days and weeks and months of effort. That way, it's more bulletproof. So definitely don't just provide a data model. A data model is great, but you usually want to have some kind of business logic, some kind of data set, something that you're doing. And we'll look at Drupal examples in a second. That second has passed. So let's think about what we can decouple from Drupal and release to the outside world. It's a big conversation to have. I only have my own personal opinions, so I cannot really provide definite answers. But for example, there's Migrate. Migrate is an awesome tool that I haven't seen anywhere else. Many projects would benefit from having Migrate, having that kind of pluggable architecture that really allows you to load, extract, transform the data and do what you need. So I think there's great value in providing some kind of an ETL library like that. And then there's our Darling Views. I don't know if you've noticed, but many projects have started to imitate or duplicate views. So in the symphony world, Celios has started a bundle that's basically views. An Auro platform, which is this really great business framework that's used to build Acchia Neo and Auro CRM. They are also building their own views thing. And the way they do it is they create the view in YAML. And then they load that YAML and they build the HTML from that. But it's not as dynamic and it doesn't have the architecture of Drupal views because we've spent so many years perfecting that. So if we could actually spread that kind of architecture with pluggable fields and displays and extenders, that would have great value. There are many other examples we can talk about it. I mean, for example, we are talking a lot about how Drupal 8 has this insanely great rendering and caching with this kind of intelligence that other systems don't have, always knowing what is cacheable and what the cache contexts are. So maybe we can export some of that to other communities. The point is in spreading our own gathered knowledge outside of Drupal. Why? Because it simply makes sense. We've already spent the time figuring out these problem spaces. So if we are doing that, we might as well reap some more benefits from that. Just take into account the differences between systems. Drupal is this dynamic introspectable system that's configuration-driven. Symphony and Laravel are code-driven and static. So that means that you need to think about different expectations. Drupal people want UIs. Symphony people want to write YAML. You need to account for everyone. But if you're smart enough, then your library will hit the sweet spot and it will be truly useful. And I'm looking forward to having this discussion in the community and then figuring out together how we can do this in an easy way. Okay, so we have a good 15 minutes for questions. So let's start the discussion. What did you find confusing? And what are your thoughts on this matter? I know there's at least one question. You're just shy. Oh, there we go. Okay, sorry. My question is, was there a reason why you took the approach of making completely separate libraries rather than the symphony approach where they created subtree splits that were read only? What was the decision making behind that? Well, that's just a code organization thing. What symphony does is they're basically one huge library and then they split parts off as separate repositories. I mean, we could have a repository with all commerce guys libraries and then split them off, but it doesn't matter. It's just an organization thing. We certainly wouldn't be able to automate splitting off that if it was inside the main Drupal commerce repository. You need to make the separation between Drupal commerce, the module, the Drupal application, and the library, which is this small, powerful piece of code that doesn't have any dependencies. That's the trick. Our libraries only depend on each other. They don't have any other dependencies. I have two questions. The first one is, in Serbia, do you refrigerate your eggs? Yes, I refrigerate my eggs. I just needed to know that. And two, you talk about maybe views or, I don't know, maybe panels. Some of the really things that make Drupal great. So I guess there's two parts to this question. One, I get a little scared if we're gonna give views away to everybody because I think it makes Drupal awesome. But two, I think big parts of what makes views awesome is the C tools integration, being able to have the UI. That would be really hard to separate out from the Drupal implementation, no? Yes, sure, it's not easy. But the main point of my idea is that we take at least the knowledge that we've accumulated over the many years we've been doing this as a community and then allow others to benefit. We keep talking about how much Drupal it has benefited from using Symphony, but we actually have a lot to give ourselves. And even if we are not using a library directly, which we would, at least by creating a library, you allow others to make use of all the knowledge you've gathered. So I don't think we should be afraid of spreading knowledge. As I said, people will look at it and then we'll be able to tell them there's more where that came from. So what else is on the roadmap for commerce libraries going forward? What else do you plan to break out into these separate? Yes, so the main one we're currently working on is the pricing library. The point of the pricing library is to have calculators that can figure out how to apply a discount to a price that contains tax. So that means applying percentage and fixed rate discounts to one line item or the entire order or doing some proportional calculation. So all of this is common with discounts and shipping. Other systems get it wrong. So there's a lot of value in sharing that. We initially tried to also do this kind of a price value object, but turned out that cannot be integrated back into Truebolt, so we are focusing on the calculators now. And Nik Fahalik, my colleague, has a great architecture in place for a shipping library which also doesn't exist elsewhere. So I think that we can provide a lot of value by doing this. Thank you very much. Discounting is and couponing is a huge debacle. So we really appreciate that. Yeah. So this is a question, it's just a comment. So this approach of building libraries is actually really useful, even if you're not building those libraries to be shared outside of your company, right? So we're doing that now in Drupal 7 with complex Drupal sites. Building shared libraries is actually a lot more powerful. You can do unit testing on them. You get a lot more test coverage and those kinds of things. So it's definitely an approach that I think everyone will be doing in Drupal 8. Yeah, I agree. I've actually heard stories about certain French projects where they had to use Drupal 6 or 7, but they elected to build all the logic inside the decoupled libraries and then connecting that with Drupal so that they have the benefits of unit testing in clear code and the ability to more easily migrate to a different Drupal version or even a different framework. And Frederick Moran, FGM, has been doing a lot of that. He had a session about that at Dev Days. He's at Drupal.com. So if you see him, you should ask him about it. So you see, I knew you had questions. So in any case, if anything else pops into your mind, I will be at the Commerce Guys booths all week so we can continue this discussion. The point of this was just to make you curious and get you thinking and then we can go into more details. Thank you. Thank you.