 think it's time to get started. Welcome, everyone. This is Commerce to the Tech's lessons learned and that echo is really distracting. My name is Bojan Givanovich and I'm a Drupal contributor from Serbia and together with my colleague Matt Glamon I developed Commerce to the Techs which has been the inspiration behind some of the topics we'll discuss today. I work for a company called Commerce Guys where our mission is to engineer simpler solutions to the hardest parts of selling online and we primarily do that by developing Drupal Commerce which is our e-commerce solution for Drupal 7 and Drupal 8. In 2011 we released Drupal Commerce 1.0 which was built from scratch on Drupal 7 and by doing that we created a system that was immediately familiar to people who already knew Drupal. If you knew Drupal you knew Commerce and this had a lot of success. We got up to 60,000 live installations and then when it came time to write the Drupal 8 version we once again decided to start from scratch to repeat the same success and create a system that makes sense to Drupal 8 developers. Now what makes Commerce special is that it's a business application like an ERP or a CRM. This means that even though we provide a lot of functionality it is an application that's made to be customized and extended and made to represent your client's business logic and not only that but at the same time Commerce has a large scope and there are very few Drupal modules the size of Commerce and this has historically put us on the forefront of Drupal development. In Drupal 7 that meant us being early adopters of the entity API. It meant developing modules such as views bulk operations and inline entity form and others. In Drupal 8 that meant being early adopters of composer once again trying to improve the entity API in core and through all of these efforts we've had a front row seat to how Drupal has evolved and we've had a chance to observe new trends as well as create some best practices of our own and in the past year we've had a lot of Twitter conversations about how Drupal 8 has changed the way we write code and develop projects and I just wanted to turn all of these conversations into a talk and then here we are. When starting from scratch there are infinite possibilities but the question remains which functionality should we develop first and which groups of users should we prioritize and the answer to that is not easy and it develops it depends on the target audience. Historically our target audience has always been the more technical part of Drupal's audience and the reason why it's the more technical part is simply because of that customization and extension angle where it's simply expected that you will need to do that with commerce. However historically Drupal has struggled with defining who its audience is and that audience has shifted because even if we don't know who our audience is by making decisions we influence it and shift it but let's look at trends. In the past five years the bottom level of the market has disappeared. People have left for WordPress for static site generators and for software as a service solution such as Wix or in case of e-commerce Shopify and it's hard to compete with this kind of convenience where simply all of the maintenance is done for you and you just get to enjoy the results. As a result of this the average Drupal project has become larger more complex more ambitious and this is not really controversial anymore this is the same thing Dries said in his keynote yesterday. So we defined our audience as an agency that has let's say up to 10 people and the average commerce user is a person who uses command line tools such as Git and Composer and Drupal console and Drush and knows how to create an empty module perhaps override the template they're okay with Twig they know how to copy a hook implementation. So we're not targeting hardcore developers but we are targeting technical users and from there on we need us to pick which features we should include. Now with commerce 1.x and Drupal 7 these projects were developed by creating a small core and then making sure that they are extended by a large contrib space and after the initial core was released so Drupal 7.0 commerce 1.0 that core was frozen and it was not changed again and that approach has changed you've seen that Drupal 8 has many more features that deprecate a large number of contrib modules and there has been a discussion about which features deserve to enter core first and this is a question we struggled with for commerce as well. Furthermore we've decided that we no longer freeze software and then never add new features until the next branch instead we are continuously innovating adding new features and shipping them to our users simply to prevent this long development period that Drupal 8 and commerce 2.x have had and for us we've tried to look at the most popular commerce contribs and we created a list of all commerce modules that had more than a thousand site installs and there was about 60 of them and then we analyzed each one and the first group that we identified was a group of modules that could have easily been patches to commerce core so they provided extensions to APIs that we simply did not anticipate and add features in that direction and a good example of that is the credit card tokenization API that we had in the commerce card and file module which simply extended the payment API in commerce 1.x so we said for sure this is something that needs to live in commerce itself and we brought that functionality in. Then we looked at the second group which is modules that add small extensions to not APIs but actual commerce functionality in UIs so we shipped a fairly basic checkout experience because we wanted to give agencies the full power to customize it and create something special but we realized that most sites needed to add modules to add expected elements such as a checkout progress bar and once again these were the kind of features that we wanted to bring into the new commerce and finally we looked at pure usage if a module is present on 70 or more percent of commerce installs it deserves to live in commerce itself and the result of these analysis and this kind of thinking is that out of the top 60 commerce 1.x contribs half of them are no longer needed for the Drupal 8 version we've added the functionality of over 30 contribe modules but we didn't actually increase the size of our core that much because a contribe module needs to work around limitations in core it needs to add extra codes to accomplish its purpose but here we simply expanded our scope from the start and made sure that all of our APIs were flexible enough to support these use cases and it has been a big win for us with modules such as promotions and coupons and address book and card and file now actually shipping with commerce from day one which means that people can build great websites with just commerce and not commerce plus 30 contribe. Another dilemma that projects often have is whether to rely on tooling and how much and when I say tooling I mean a command line application that can be used to assemble or update your code base or generate codes and perform maintenance tasks usually tooling will save you time in the long run but it increases the time needed to get started with an application it presents an additional learning block in the front-end community the idea of tooling has won NPM is required for installing anything that's JavaScript related in the Drupal world we've always had trash and many people have always used the trash make to assemble their websites they use trash to clear cache to update their configuration but the trash was never required on the other hand in the wider PHP community composer became required for installing packages and an average commerce installation an average truly commerce site depends on a lot of external libraries each payment gateway needs its own SDK if you're using an external shipping method such as UPS or DHL they too needs there as the case then geo IP the geolocation module needs its own library search API solar needs the solarium library to interface with solar and the list goes on and on so it's not unusual to see a site that has at least six libraries that needs to be kept up-to-date and maintained with the rest of the website which made us early proponents of composer we counted on the fact that our target audience is already familiar with the command line and we started pushing for composer as a way to make sure all these libraries are always maintained and up-to-date as a part of our installations and of course that this created an additional roadblock roadblock for many users over years we've improved composer integration in core so it's now possible to install commerce all of its modules all of its libraries with only one command update all of that with only one command and yesterday we actually had a bit big meeting around composer where we talked about rewriting updates manager in core and including a UI that would allow us to keep core and commerce updated through update manager while the libraries are automatically handled for us simply for the users that do not want to learn the command line and composer just to get started with commerce so that will be something that will help the users that are currently feeling left behind by such a decision users who might not be our target audience right now but who we would definitely like to include as our module expands another result of our audience choices is a focus on slightly less UIs if you've ever used magento for example you've seen that they have a thousand settings so the views UI has nothing on them you have hundreds upon hundreds of check boxes of radio buttons of select boxes and when you have 500 settings is the same as having none because the average user is usually too scared to change anything and what's actually possible even for a developer like me is to simply have conflicting configuration I configure things in a way that makes the site not function properly and that that's definitely something that I do not want to have and wants to avoid in commerce if something is not a majority use case for customization then it doesn't get the UI a good example of that is our address module where we have address formats for every country and these are rules for which fields are required and how they're labeled in most cases most users will use the rules as we assemble them since they are results of a lot of research those who are not happy with that can implement a hook and change that or implement an event by removing the address format UI we managed to make the application more maintainable and we removed a UI that we needed to design and explain and so on it's the same with any kind of UI text that could be reached with a form alter but it's not something that most users need to change frequently when there is a user facing form people want to customize every piece of text that's shown but that's not always the majority use case and this is not something that's unique to commerce I've seen Gizra's blog post about designing organic groups for Drupal 8 and it has many of the same thoughts that I'm having both around the UIs and other parts of this presentation and then I've seen a comment by Wim Lear's who was rewriting his CDN module he said the same thing that he managed to cut the size of his module in half by actually removing UIs for features that were used by 5% of the users simply that the focus is on the majority use cases and then we make the rest possible through code-based extension points and one of the results of that is using more twig and twig is something that we're very happy with it has completely changed the way we write modules create Drupal website simply because it's so powerful and so convenient in Drupal 7 we had this UI where you could customize emails that commerce sends so someone goes through checkout at the end of checkout an email is sent to the customer and we used tokens to add required information such as the order number the address that was provided and so on and we realized this was not flexible first emails are long they include a lot of information a lot of really bad HTML because email clients are stuck in the 90s and editing that as a part of a really small text area doesn't make a lot of sense we also realize that tokens were not super flexible sometimes you would miss the right token or would not be able to output it in the right format and finally people realize that just using tokens meant that you have no conditional way of rendering a part of the template for example I want to output the heading shipping information if there's an actual shipping address on the order but if I just sold an e-book there's no shipping address which means I should not be outputting the shipping heading as a part of my email and we solved all of these problems by simply making the email template a twig template and we're now using twig for all of our emails which means that all of our emails are customized the same way as our pages are by overriding a twig template which gives you all of the power of twig it gives you access to every single piece of data we have in the system and it gives you the usual ways of formatting and altering that much more powerful and if there is a need to customize the page that's shown when your shopping cart is empty that is a twig template the page that's shown when completing checkout that is a twig template the order summary that shows what's in your cart as you're going through checkout that can be a view but also by default that is a twig template which means that designers themers but also ordinary site builders always have full control over the text over the markup over what's output is and at the same time of course this is still fully translatable so the only downside is that we expect users to know how to actually override a twig template how to make a copy of the template they want to modify and where to move it and that's something that we're planning to attack with even more documentation we've also become fans of YAML we realize that for example our entities have different workflows our Nord order can have a payment for workflow that indicates whether it was paid in full or not it has the main workflow that says this order has been placed this order has been returned and fully refunded or maybe it was canceled there's a shipping workflow all of these workflows are usually tied to relevant code that's executed at specific points when the order is placed you want to communicate with an ERP you want to send emails and because it's tied to code it doesn't make a lot of sense to make workflow definition live in config instead all of our workflows are actually defined in YAML which and these are files at the root of our modules and by using YAML we were able to put in place additional validation to make sure that the developers never actually write conflicting transitions or miss a state or anything else basically what were info hooks in Drupal 7 became YAML plug-ins in Drupal 8 and that's what we're leaning on in many places and you can see a combination of these two things with the way we do logs we have activity logs throughout commerce so when someone creates a payment or cancels an order that's displayed somewhere so that there can be an overview of all things that have happened to an order to a payment or to something else and the way we define these templates that gets that display the logged information is through a YAML file and then each template is an inline tweak template so if you focus on the last line of every entry here it says template purchased entity label was that is to the cart or the order was assigned to user by using inline tweak templates we were able to completely forget about tokens which means there is never a danger of a token not being available or not being formidable in a specific way you get everything that we know about the order about the entity that changed and then you can display the information that you want we've also developed a concept called bundle plugins usually entity bundles are configuration think node types or product types and that makes sense for many use cases you create a product type you create fields you can deploy that to another site add it to get but in certain cases the bundle and the fields attached to the bundle are actually tied to the code base they're tied to code that expects that to always be present in the product type case code does not care which product types you you have and how you're using them but let's look at payment methods types a payment method is something that you can pay with something that we can use to create a payment and it usually represents a tokenized credit card or PayPal account so that it's safe to store something that's tripe or brain trick gives us once you enter the credit card number we needed two different kinds of payment methods types and if it's a credit card then we need to show the credit card type and the last four numbers when representing that payment method so that we can say we are using your visa that ends with 1234 this means that the label is dependent on the field and the functionality is dependent on the field so we developed the bundle plugin approach which is a part of the entity API in contrib that allows you to define bundles by defining plugins and then that's plug-ins such as the credit card plug-in that you can see on the screen can define its own field that are attached just to that bundle and it can implement additional methods logic that's specific to that bundle specifically so we can say for this payment method give me the label and then that asks the actual bundle plug-in to make sure that different types can provide different logic it's a tool we're using more and more also for license types and it goes from there another lesson that we learned is that one is a special case of many and that means that previously we would design our module to support one shop for your site one cart one checkout process and that's enough for most people that is the majority use case but turns out if someone actually needs two different checkout experiences or different stores on one site for example one per country or one per subdomain that becomes really hard to do in contrib there is a lot of extra work that needs to happen additional entity types additional references additional logic just to make something like that possible but we design for multiple of these at the same time if we say by default we support multiple checkouts and multiple shopping carts and multiple stores but we understand if you're only going to use one then there is usually not a lot of added complexity it's as simple as it was before but at the same time people who have a larger need can accomplish that without spending all of that effort and entering buggy territory and this has had a huge payoff for us because for example the concept of stores that we added to commerce is now being used in ways that I did not even imagine I thought multiple stores would be something that only a few sites relied on but recently I've been hearing about stores used on every other commerce to the tech site where people have a store per subdomain per country per language there's even a booking site being developed where every property is its own store which means that every property has its own coupons its own promotions its own taxes its own payment methods which are used just for that place and that works really well when there are rentals from different countries belonging to different people so it's definitely a good rule to keep in mind when developing code we also realized that our code needs to be a lot more opinionated in the Drupal seven times we tried to make it generic we tried not to do too much to not interfere with what you need to do this meant that we shipped with a really bear checkout experience because we know that designers like to go crazy and implement these completely custom checkout flows but at the same time we later realized that many people just want a sane default experience they want us to make a good decision and have them use it simply because we are the ones who have the most time to research this we are the experts in this area we can pay our designers we can look at feedback and then we can create something that works for most people so the middle ground here is to create something that's really opinionated but allow people to provide their own alternative implementations our checkout flows are pluggable forms their plugins the default plugin has very strong opinions on how checkout should look they're my strong opinions but if your designer does not agree if your developers do not agree then it's very easy to write a custom plug in extend that and change every piece at the same time we design both for a pleasant experience and for the ease of customizing because it's something that we usually have to end up doing and the problem that we have then is that a lot of the UI code needs to be reused we could have a content and a config entity that use an address field for example but content entities use widgets while config entities don't or in case of checkout flow plugins we might want a coupon redemption form on all of our checkout flows but when creating a custom checkout flow we do not want to copy that code over and over again and we realize that the solution to that is to write form elements and you can see how the address form element looks on the screen form elements are something that Drupal has always supported though they've become slightly nicer in Drupal 8 because it's now a single class that has all of the callbacks that you need to use and it simply allows you to create your custom element that takes any kind of parameter that you need and then in the end output of the value that gets into form state so in this case we have a default value that takes the given name organization address postal code and allows that to be edited and then returns that when it's done and then it has additional settings for restricting which countries are available and on and on and we are using this pattern more and more to allow to provide simply a set of elements that can be remixed and used in different ways we also enforce coding standards strictly previously I was the one who reviews this and tries to catch every error but sometimes I'm just tired and there is no reason for me to create an impression that I'm giving someone a hard time just for a few stupid spaces or brace positions the solution to that has been to automate it are built on Travis CI and Drupal CI supports this now as well runs the PHP CS checker that uses Drupal's coder module and which checks the complete Drupal coding standards and style guide so if your code has a style problem that causes is to not respect coding standards the build will fail and we will not be able to merge your patch and this way there are no hard feelings there is no me being too obsessive about this and we ensure that our code base always looks consistent we also pay a lot of attention to tests previously I was one of those developers who hated tests and left that as the last thing to do before the end of a project in the Drupal seven times but with Drupal eight testing has so much improved in Drupal core that I've caught myself writing tests before writing actual bug fixes or new functionality we have great functional tests that use mink and can support Ajax and we use them to test UIs and to test integration between components to see whether things fit as they should on the other hand we have unit tests which are really fast but at the same time many pieces of Drupal are not easily unit testable anything that touches entities for example but there is a great middle ground which called the kernel tests and the kernel tests work like unit tests but they bootstrap a minimal Drupal install and that allows us to test our services that interact with entities and to make sure everything works well one thing to keep in mind is that tests need to be run against both the current Drupal branch and the next one core tries really hard to not break backwards compatibility but regressions happen and sometimes we've had a situation where unpatched would land to the next core branch for example 8.3.x at the time and it broke commerce our build fails and then we can say this commit has a problem and it should be reverted it simply protects us from any breakage that could occur when an actual release of that core branch happens. Drupal CI actually does this by default so it always tests against the future branch but some people change that and I just wanted to emphasize that it's an important thing to keep in mind. Previously Drupal had this motto that said we don't babysit broken code and this meant that there was no checking of input data if given an array that was slightly wrong an entity that was not saved correctly we would fail in very subtle ways notices warnings and it would be really hard to figure out what went wrong frequently functions would have a few sanity checks and then just return false or no and leading you to wonder what actually went wrong in Drupal 8 what we are doing and what many other modules are doing is checking for these this should never happen states and then throwing an exception so for example here is a payment gateway and it has a method for creating a payment but what happens if it's given completely invalid payment entity a payment entity that does not have the required data something that should never ever possibly happen but there might have been a bug in our form or maybe a wrong migration and something went wrong in this case we do not want to fail suddenly we want to fail as loud as we can show a message and allow the developer to fix the problem that they're having and if this is in production we want to say we cannot display your page something really bad has happened and we want to log that which is what Drupal does by default with exceptions and then allow that to be fixed so all of our methods now look like this check for the impossible things just in case and then proceed and we document the exceptions that we throw and we usually have at least five or six checks like this in the most crucial places and here's another logical thought we developers spend most of our time reading code sure we'll write some code from time to time but most of the time we're chasing a bug we're trying to figure out where to insert that new feature and we're trying to understand how this was built maybe it's our own code but we've started forgetting it already or maybe it was someone else's code and keeping this in mind has led me to write cleaner code simply because I'm less prone to cute solutions to nested function calls ternary operators because I know this needs to be really clear to me the next time I open this file but there is a really really stupid idea out there in the wider PHP and programming community and many of you have seen it on Reddit you've seen it on hacker news and it goes like this prepare for it good code should be self-documenting the problem with this idea is that it misunderstands what comments are for it says if you write down in a comment what the code is doing then in time code will change and the document the documentation will no longer be in sync thus it's pointless let's just make sure we have good method names a lot of small methods good variable names and that should be enough but that was never the point of documentation the point of documentation is to document the why and not the what what were the constraints when we were writing this feature what did we try which failed the more obvious way to solve this which problem are we working around this is the crucial information that I want to get from a comment so that the next time I return to a piece of code I I remember all of these problems and I remember what I'm doing and especially in Drupal we can frequently run into these complex situations where we solve it in a creative way and then too much later we just don't remember it we were also unsure where to put the general flow documentation to say so if you look at object-oriented code it's usually clean it has a lot of nice smaller classes but you're unsure how they actually fit together and there is usually no great place that will illustrate what gets called and when and in our case commerce has code documentation on interfaces the interface describes how the implementations will be used for payment gateways we support on-site and off-site gateways and a few other categories where the on-site gateways one that gives you a credit card form performs tokenization and then only once you've confirmed checkout and finished it it uses that token to create a payment and when you open the on-site payment gateway interface it actually tells you what an on-site payment gateway is it tells you it allows the customer to enter credit card details directly on the site and then that's safely tokenized and used later it also gives you the exact flow it says the customer enters checkout and then the checkout flow shows a checkout pane which shows a credit card form and then javascript happens tokenization happens we send that token to the server on the next page there is another checkout pane which takes the token and creates the payment the point is that I have a description here of how these methods are getting called without needing to fire up my debugger and this is something that can save a lot of time when writing code this is not just an interface but it's also a tutorial for anyone who needs to implement payment gateways we also realize that dependency injection can sometimes be a code smell and what I mean by this is that a class can sometimes have too many dependencies if you look at some code bases that were converted from let's say less clean code and this is not not often found in Drupal but it is found in other systems you'll see these classes that have like 20 dependencies injected in the constructor and what this tells you is that the class is doing too much it has too many methods which are doing unrelated things and are using unrelated dependencies to accomplish that and the solution might be to simply split the class into multiple or the solution could be to simply add a layer of abstraction some helpers that will be used to remove a layer of dependencies because the code is simply operating at a level that's too low there is no good recommendation on how many dependencies a class should have but if there's more than five usually something is going on you also need to beware the idea of solid which is frequently thought when talking about object-oriented programming the problem with solid is in the yes the single responsibility principle and more bad code has been written by those trying to follow these rules than anyone who has never heard of them because it's hard to define what single responsibility means the rule says your class should always do one thing and it sounds perfectly logical right but when misapplied it means that people create classes that always have a single function inside and then to accomplish a single process a single thing they need to actually string together 10 different classes and this creates an additional additional mental efforts needed to understand the code base modify it and it just results in bad code so always keep thinking about just how much code you have on in one place and for me I always are on the side of larger classes and then splitting them up as needed instead of ending up with this approach of fine line five line functions in single classes and this didn't go well this slide but another thing I wanted to mention is the idea of not repeating yourself it's another nice topic we like to discuss and it basically says do not have the same code in two places which also makes perfect sense right but that rule was never about duplicating code it was about duplicating knowledge if you have code that's only superficially similar and you abstract it out to a single place when the business requirements change that codes will probably need to be separated again because it does not represent the same knowledge and we've seen that when developing commerce multiple times we have a promotion module and that discounts an entire order or a set of order items your t-shirt is 10% off and then we realize we also need to charge fees we want to charge you two euros if you're using American Express and then we say but wait we have this discount module it brings the price down so maybe we can use it to increase the price it's the code looks kind of similar but then we realize that it's only superficial similarity because there are features that promotions have that fees never have you should you do not limit a fee based on the number of users fees are not activated by coupons nobody wants to enter a coupon that will increase the price by five euros people don't do that so that means that it's generally much safer to simply create a separate fee module and write these 600 lines of code again instead of risking this problem where we constantly have to think about two actually not identical use cases we've become less afraid of static classes as well now the regular rule is that you should always inject your dependencies to allow them to be swapped out and tested more easily but there is some code that is simply never replaced and it doesn't have many reasons to change think of a function that validates a date or a credit card number in that case it can be really beneficial to be able to access this code from anywhere including our forms and whatever without having to inject it and I'm not saying use static classes all the time but I'm saying they do have a use from time to time and it's not unusual we're also often using value objects as a replacement for the arrays of doom that triple seven used to have in triple seven a function could return an array that has multiple other arrays inside and then it has a bunch of keys and then we document those keys we all remember that I mean that's how forms technically still work the problem with this is that it's really not obvious what you're getting let's say that you're calculating the cost of shipping for an order you just received a big array and now you need to dump it to see which data you have inside but let's replace that instead of that let's use an object that simply takes that array in a constructor and then provides a getter for each piece of the array we've wrapped the array in a class and now when we receive a class our IDE will immediately tell us which data is available because it can see the getters it can see the methods also if something changes that requires us to rename a key these methods can preserve backwards compatibility because the the class inside can modify the data and transform it from an old format to a newer one for example and this also gives us safety for the future because we've done that multiple times we need to fix the API but we might be getting data that is not following the new format yet and we're using that a lot for actual field values for example we have a price field and the price field is a number in a currency code if you change a number or you change a currency code it's no longer the same price of course we thus have a price value object that has these two values and it ensures that they're always changed at the same time it provides convenience methods to be able to actually use value objects as field values we override the set value method of each field type where we say if I receive the value object take the data that's actually inside and make sure to save that and then we have a different method that says give me this field type as a value object and then we can use that in our entity getters and setters so by doing that we hide the implementation details of how entity API works how field types work and we simply provide a pleasant class for the end users we've also realized that to have a better product of course we constantly need to improve the code that we depend on fish swim upstream to reproduce and it's the same with code a good example of that are entity permissions we we would start developing commerce entities a product on order something else a payment and then each time we would create the permissions from scratch we would write each one update permission delete permission the create permission and then we realized that they were getting out of sync which was not ideal so we created a class that generated them for any entity we moved that class to entity API where it got integrated into other contribs such as media and then finally that code is being moved to core when where it's once again being improved so every time it gets a little more general or it moves into a more popular module it gets additional users and it's it ends up with less bugs so what I'm saying is that from time to time it's great to simply analyze our code and to see what the good candidates are for abstraction we tried to listen to support requests because usually repeating support requests mean that there is something that we need to fix and something that we need to document even if they sometimes take too much time the feedback is very valuable the last two thoughts that I want to share are about how we actually handle releases as a community and I'm the last person who should be giving advice on this topic but still previously in Drupal 7 and Drupal 6 we would tag a point or release when everything is done but when I say done I mean there is literally nothing else to do on this code base ever and that resulted in many Drupal 7 modules never actually reaching that point or release we are always in dev always in alpha always in beta but if our code is used in production if we are not allowed to break it without providing an upgrade path then it's already stable regardless of the features because that's how we must treat it so what I'm saying is it scares people to see constantly alpha and beta modules and it's if we take the efforts to always not just tag the initial releases but tag frequent releases we take away some of this fear while actually not making any underlying compromises and that's my final thought we sometimes try and release once a year and that forces people to use dev releases and it's not ideal so what I'm saying is tag a release once a month whatever commits landed whatever is there let's just ship it to the users it's a philosophy I'm trying to do more and more instead of focusing on features and then delaying it for months that way people only use the dev release when they have to and we decrease the chances of someone using outdated code and then reporting issues about it the ecosystem also looks more vibrant and better developed and we're at the end so let's see what you think who wants to tell me first how horribly wrong I am one small question you talk about the difference between the discounts and the taxes and how you should not use the same code base for both of them so have you used an abstract class to and then have to try classes with the difference between them or or maybe you can elaborate on why you want to completely different without the same parent right I'm not a big fan of base classes because they're basically language assisted copy paste and while they work for that just like traits do they do not solve the underlying problem and the underlying problem is that 50 percent of the logic feels the same right now but as these two different use cases grow this similarity might drop to 30 percent and I might find myself creating duplicate base class methods simply because the logic is not the same anymore it does not represent the same knowledge and there is no guarantee it's going to grow in the same direction and we can always have a piece of our shared logic in a separate service or somewhere just to make sure we're not coding it over and over the main part where this advice applies for example is entity types use your custom entity types and your data structures in a way that's unique to the current problem do not try to reuse them even where it doesn't make sense and when fields are constantly empty and of course any code that's built around it such in our is such as in our case with promotions where a promotion is basically an entity that embeds a few plugins and plugs into the pricing api that we have other questions coding commerce through plates we can do it all sure you'll need to go to the mic do you have a demo project like in triple seven for what a demo project like you had in triple seven yeah try out all the things yeah you need to talk to shan the man in the blue and white uh there's a commerce demo dot acro media dot com that's populated from a github repository and it has a kickstartish website with a demo store uh so so that that's a great resource to look at and i'm sure that's uh others will happen over time as more contributes develop and more teams show up uh oh there's clausie trying not to be nervous just just a very innocent question um did you look to magenta in any way to the magenta code base when developing commerce two dot x like did you get inspiration there did you look at their ui's did you copy stuff from there generally we tried to look at the competition but magenta was not the best of our competition uh so we analyzed many great solutions for example i was personally always a fan of spree which was a ruby on rails solution that recently went under but it's still being maintained as an open source project i love many things they've done uh software as a service solutions like shop if i have spent unlimited money testing check out conversions and designing specific ui so there are great details uh worth copying there uh usually uh i look at one spot for ui inspiration and another uh for potential feature or code inspiration i personally am not a huge fan of magenta too i've seen it i've played with it but it's it doesn't i'm not sure it had many things worth copying and i'm not sure i should be saying this with a mic on but that that's my personal opinion of course uh they struggle just like we did with the they went from magenta one to magenta two and we went from drupal seven to drupal eight and it was a similar process in the sense that it was late it was bumpy the initial release was not ideal and the code wasn't always clean and i'm sure it has improved since then just like drupal eight eight has improved this may be too obvious but um drupal seven uh drupal commerce in seven was heavily reliant on rules for just about everything um and now uh drupal commerce two is not can you talk about uh what you rely on and how you do it yeah the idea with rules in drupal seven was that there was a separate ui where logic could be configured uh in a config driven way uh logic that would decide when a payment gateway is selected when a shipping method is selected when an email is sent uh and when the the rules project for drupal eight started their team decided uh to look at embeddable uis which is a concept i really liked uh and over time since the the rules project wasn't ready for our initial beta we decided to create our own implementation of this concept where commerce has commerce condition plugins which are available directly attached to the relevant entities when creating a promotion there are conditions that say uh to what does this promotion apply based on the order data included products customer information when creating a payment gateway it's the very same conditions when creating a shipping method and it it goes on and on and we realize that this is a great user friendly way to do that because uh the conditions for selecting a us thing are right next to that thing they're not in a separate ui three tabs away uh so this is the main way that we've replaced the rules usage uh some other use cases are handled by our own event subscribers such as sending emails and that means that it requires people to write codes to send their own emails but i think that will improve over time as rules for d8 becomes stable and once we expand our user base we have two more minutes so time for one more question if anyone's in the mood there we go first of all uh Greg asked me to get you to sing a song do a little number because you got the mic and everything um actually it was uh are you going to adopt any release cadence for commerce uh core does every six months is commerce going to do anything like that have you thought about that and something you would actually like put down and agree to yeah ideally i mean at this point commerce is still at an early stage and there's a lot of activity people are people send in 10 to 20 patches each week with small improvements large improvements bug fixes uh which means that we want to make frequent releases to make sure that people who start commerce websites always have the most bug free experience and get all of the latest features so ideally i would like to do something uh like a release every month which might not always be realistic since at the same time we're also writing documentation developing contribute modules uh even working on new themes uh in which case it might be more realistic to do something like a month and a half but i definitely think it needs to be very very frequent uh and if we can do once a month that would probably be perfect well we're out of time so if if you have any other questions i will be at the commerce guys boost today and every other day find me and let's chat thank you everyone