 Can everyone hear me now? All right, so I'm going to be talking a little bit about how to move your logic out of Drupal. So a little bit about me first. My name's Eric. I'm a backend developer for Previousnext. Previousnext is an Australian-based firm, but I'm actually based in Indonesia. I've been working with Drupal for a little over four years now, and you can usually find me around on hash-contribute or hash-supports-fact tunnels as Eric115. So this talk is aimed at anyone who's got a little bit of an idea about object-oriented programming, best practices, and is looking for some logical ways to split their code base up. I'm going to go over some of the basics of decoupling your logic to improve testability, maintainability, and usability, and take a look at why you might want to move your logic completely out of Drupal into something like a separate composer package. So the first thing you might be wondering is why I would stand here today at a Drupal camp and encourage you to move your logic out of the very platform that you're using to build your project. Well, bear with me and hope it'll start making some more sense. When I say move your logic out of Drupal, I'm mostly referring to decoupling your business logic and treating Drupal as more of a presentation layer or wrapper around your library. So we'll look at some ways to do this shortly, but it doesn't necessarily have to be right out into a separate composer package to reap a lot of the benefits of cleaner architecture. However, sometimes holding this idea in your head while you code can help you to shape your code in a better way, similar to how you might consider something like test-driven development. This kind of architecture lends itself particularly well to integrations and data modeling, so they'll be the use cases I'll be focusing on today. Frequently when you're writing these kinds of integrations, there's no inherent reason for your code to be coupled to something like a block or tied in with Drupal at an architectural level. Even if you're relying on Drupal APIs to process your data or complete some of your functionality, you can often simplify your integration greatly by just focusing on the raw integration first and then figuring out how to send your data across to Drupal, which will often come out naturally as you implement things in smaller pieces. It does, of course, depend on what you're implementing, and this is definitely not applicable to everything that you do in Drupal. In real world projects, you're going to end up with some of your logic in Drupal. So you can define a domain as a field of study that defines a set of common requirements, terminology, and functionality for any software program constructed to solve a problem, or more simply put a sphere of knowledge. And domain is an important consideration when you're structuring your code. So if you hold the idea of Drupal as a presentation layer in your head while you code, it sometimes helps outline where domains are overlapping and where it makes sense to split your code. In the case of an integration, it can usually live in its own domain because it should be agnostic to how it's been presented in something like Drupal. So let's have a look at a bit of an example. So let's assume we were tasked with writing an integration with sportservice.com to show upcoming FIFA World Cup matches and display that information in a block in Drupal 8. We're going to assume that there's a nice JSON API for us to use. So let's say it looks something like this. We've got two endpoints that we're going to use, future matches and teams. The first one is going to show return a JSON array of upcoming matches with some team IDs, a location, and a start time timestamp. And the second one is going to show a JSON array of team information. Hope we can see them there. So the first thing I want to look at is how you might implement this if you didn't consider your domain and you just went straight in and implemented this within Drupal. So this is about the bare minimum required to implement this. It's a super compressed example for this implementation, but it is something that I frequently saw in Drupal 7 code bases, particularly in Drupal 7 blocks, although perhaps it may have been split across a few more functions. So it's not too important exactly what this code is doing in this example, but we're making a few HTTP requests to request some data. We're looking through that data to link things together, and then we're passing that new array to a custom theme function when rendering the block. Now implementing things like this probably would work, but at least do a couple of problems. The first one is testing becomes a lot harder. So when you couple your logic to the presentation layer like this, it makes it a lot harder to test your logic in isolation to the other code and how it's being presented. So in this example, it'd be pretty difficult to write a unit test for this, because what you're writing, your logic is tied to how it's rendered in Drupal in a block. Even if we could test this method, all the logic and data fetching is coupled together, so it would be hard to test what happens if one of the requests failed, or if you wanted to do some more complex mocking. I mean, I guess you could get around that with a lot of try, catch statements, or if statements, but it probably wouldn't be very nice to maintain. In the scenario that one of the requests did fail, the entire method would fail as well. So you're losing a bit of resilience there, too. And finally, this code isn't really maintainable or reusable. If another developer had to come in and make a change to this method, they're going to struggle to understand what this does, and it's not really clear what this method should return. And in another example, if we had to implement a new block to show a list of teams, we couldn't reuse any of this code, even though what we would be doing would be principally the same. So let's take a look at how we might restructure this within the Drupal module by considering your domain. If you consider Drupal as a presentation layer, a good approach to take in separating the integration is to make it mostly agnostic to how the data is being presented or used. This means that this integration just integrates with the service and makes this data available in a useful format. But it's not overly concerned with the presentation. So let's have a look at how we might break that down into some smaller pieces. So here's an example of how we might split things up. I've created a module called soccer block. I've created a match schedule, which I'm using as a folder and a namespace. I've created a match schedule client to make requests to the API and fetch data, two new value objects, match and team, and a schedule class to tie things in together. Now, the schedule class could be considered overlapping into the presentation layer, but I'm going to talk a little bit more about that shortly. Just a note here that a complex example, or a real world use case, might have a few more subfolders as well. So this is a little bit more code than the previous implementation, but in my eyes, that's not really a bad thing, because it breaks things down into much more logical pieces. So from a maintainability perspective, it's much easier to read and understand a single concept, small class, than a large chunk of complex code trying to process data like we had originally. Breaking things down like this also tends to lead to cleaner interaction between pieces. So definitely don't underestimate the usefulness of having a value object for your different concepts. If you work with Drupal 7 a lot, you might be used to constructing and passing your data around in render arrays. But having a value object opens up all kinds of doors to make your life a lot easier. So an obvious benefit of being that the models can have methods to make accessing properties easier and allow for abstracting things like normalizers or other nitty gritty things that you may need to do when dealing with data from an API. In this example, I've added some methods to get the team name and team ID. It's not very complex, but if we ever needed to do something like upended string to a team name, it would be a very simple and logical change to this code. And anywhere that's using this code wouldn't need to concern itself or change to make use of this. So value objects also allow for factories for creation, which are particularly useful when you're creating things from Paris JSON. You can see the create method there, hopefully, which follows the same ideas as the create method in Drupal, if you've used that before, which is defined in the container injection interface. Although this one in particular doesn't use any Drupal interfaces or base classes. So when we break things up into value objects like this, we're able to model the data in a way that makes sense to us, rather than how it's presented to us by the API. Now, in this case, even though the API doesn't pass us a match with a team name, just a team ID, we can abstract that fact in our data models and add some sugar to allow us to use a match object to nicely fetch the team names as a string, without actually worrying about the fact that that data comes from two separate API endpoints. In this example, I've added a property to the match class to hold an instance of team and a method to fetch the name of team one by accessing the getname property on the team instance. So to take things a step further, you might consider moving your logic out of Drupal completely. Now, whilst this was possible in Drupal 7, Drupal 7 wasn't really architected in a way that left itself to move the packages out. Although you could achieve it by leveraging the library's contract module or adding some order loading. Drupal 8, however, makes it really easy. Most of us are already managing our project dependencies with Composer in Drupal 8, and if you're not, you might want to look into it. So it makes sense for us to leverage this by moving our logic into separate Composer packages and leveraging Composer to require them. Creating a new package is quite easy. You just need to create a Composer.json file for your package, and you could submit it to something like packages.org, or create a customer repository for your project. And you can use something like GitHub if you're willing to modify your Composer.json file for your project route. So this is an example of what the Composer.json file might look like for our demo package. Requiring this would be as simple as running Composer.require, eric1.1.5, slash DrupalCamp.sg. Something else I want to point out in this is that you'll notice that our package has a dependency on guzzle. Now, this is so that it can make HTTP request itself without relying on the Drupal Core dependency. Now, in the real world, you might want to open up your package to accepting dependencies injected so that we can use the HTTP client created in Drupal. So after creating a new package and moving all your business logic out into a nicely contained and well tested domain, it's time to go back to the original task of displaying a list of upcoming matches in a block. Now, this is where the schedule class we created earlier comes back into play. Our integration with sportservice.com doesn't really have a concept of a schedule, but this is a concept that we're introducing to make presentation easier. So in this case, it makes sense for the schedule class to stay in Drupal as a presentation helper or perhaps the main wrapper for Drupal to interact with our integration. This class calls the integration to fetch the matches and then structures a return data correctly so that we can pass it back to our block for rendering. A presentation helper method like this means that we can remove the original method that we had in our block earlier and use the result of this method directly in a block render method instead. It also means that other things could use the same output if they wanted to. So all of this leads to the question of when is this useful? Now, I've personally found that this kind of architecture is particularly useful when dealing with complex data models. Something to remember when considering this is that unit tests are by nature a lot faster than integration tests. So in one project, we decoupled our domains and we moved our data models into separately maintained composer package with its own unit tests. We were able to significantly cut down the time required for our test suite to run while increasing our test coverage. And that, of course, pays for itself in saved development hours over the course of the project that can definitely be used for other features later. As a company, we've also been pushing to start moving integrations out into a separate package where possible for a while, as well as the reasons I've gone through today for us and why this would be useful for us to do internally. It also makes open sourcing the packages a lot easier later. In particular, integrations with commonly used services, once they're already written in a generic fashion like this, they're very simple to push out to an open source community. And I don't think we've got time for questions right now. Oh, yep, two minutes if there's any questions. All right, thank you.