 Thank you for the introduction. Eric's talk was great because he was introducing his whole idea of using React in WordPress. The fact that we're switching over to Gutenberg means that we're going to have more and more React like code going on into the future. We're going to have more JavaScript generated code in the browser. And this really big shift into communicating over remote API calls is huge. And I'm glad that we got to see some of those with getting the ratings from the WPAPI registering a new endpoint from PHP, calling it, updating it. I'd like to talk today about API design. Without being ready for it, we start to enter a realm of complexity and chaos that we may not anticipate as soon as we start building out these APIs. Because it's not like when we're generating the HTML and the PHP and we have immediate access to all the data in WordPress and so on. So, it's almost impossible not to start with REST API. Who has heard of REST API? Who has built REST API? Who has been guilty to the point where you feel like you should be building REST API? You don't know what that means. A room full of experts. I'm going to address some of the things about like why is REST a thing? Why is it important? Why do we feel that we need to do it? And what do we need to do? So, I've got three slides here specifically framing this talk because I feel like in WordPress as a whole, we have already done a reasonable job of building out things like posts and comments and users and sites in the REST API or the WP API. And with these series of slides and images, I'm wondering if anybody can notice what's the pattern? What, as we compare in the top to the bottom, there's a fundamental difference between each of these pairs, the size, sure. Each pair is related. And the object is what is useful. That's where we're going here. On the top we have things and on the bottom we have processes or actions. It's relatively simple to build an API that provides information about a post. It's much more difficult to build an API that deals with submitting posts. Specifically today, I'm going to talk about processes. Not just posting an update to a post, but talk about processes that can take some time, processes that can be canceled, processes that might fail, processes that are like importing a site into your WordPress installation. For our talk, we're going to be discussing the hypothetical post content analyzer. This is going to be a Gutenberg plugin and what it's going to provide is a new type of block that you can write in and it's going to submit that content to a service that will analyze your own and provide feedback about it and it may even provide additional enhancements. The business model is the free version requires an account to be logged into and there's a premium version that will suggest context-sensitive images. So if you're writing about cars, you don't toss in a picture of a car that you can insert into the post. This is kind of like a rough idea of what we'd like to build. Where you can see on the left, we highlight some problems with the writing in the block and on the block tools on the right, it gives us more detailed information. What kind of backend services are going to be required for this and where are we going to have to build in our plugin to make this happen? We want to provide an additional dashboard in the WP admin that people can go to and we can kind of see trends of our writing over time and see any current operations. It's the dashboard where they're going to provide the login information for their account and where they're going to deal with things if their account's not going to be the standard. Turns out we're going to need a lot of data and a lot of different conditions to check for because, for example, while someone's writing one of our writing in this block, their account may go out. They may aspire their account. They had a monthly subscription and the month is up. And it's up to us to make sure that we don't continue trying to provide that service to them or if their account expires and we're not going to provide it that they don't have their editor crash as a result of it. So this is the kind of code that is like a naive first implementation of this. This is something that you'll see quite common with building these React interfaces. Just then through here, there's a lot of context that I'm not going through so I apologize if it's a lot. We've got some function that gets called that renders are blocking the editor. And we've got all these conditions. Well, first of all, we have to go out and grab the user information from our service. Is this user a real user? Is their account active? Do they have the premium? Is there currently some content that our server is analyzing for them? And if it is, draw something else and if it isn't, if it's got the premium thing, go ahead and grab the extra information. It's very common code. I see a lot of code that looks like this because it's kind of like the most straightforward way of doing it. I just want to highlight here the API calls that are being made in order to get this data. A very simple idea and we already have four different endpoints that we have to write four different kind of return responses that we need to provide and a lot of questions like what happens if I call the endpoint to get the status and user account is expired? What happens if I go to grab the premium things and they switched to a free plan? What happens if between this line and this line something changes or the server on the other end goes down from 8 minutes? I'd like to introduce a new concept, which is what we're going to call a state machine based API. Is anybody here returning a state machine? Good, at least a few people were paying attention because somebody mentioned it in the previous talk. We're going to look at a couple slides and then we're going to build out the concept. This is kind of the same function redone with a state machine based API for modeling that process. This is the API call, the only API call we need to do the same stuff that we did before. We have this new API endpoint that we're going to talk about in a minute. We call it once and as a response to that we have, it doesn't have to be switched to an endpoint, but we have switched it with discrete points in this process that we're going to look at and use as a mental model to simplify what's going on. It's a single endpoint. A single endpoint to maintain, a single endpoint to handle errors for, and it provides a single type of data. So if you look before we're moving things like if the user.is active or if the account.is premium and we have all these different things. I want to step through a couple of example responses that we might see for this Gutenberg post analyzer. This might be the response from that endpoint if somebody is, if our servers are currently analyzing a post that somebody has submitted. It's got a state field, it says processing. It's got a version which is based off of the words in the post so that every time they make a change you can submit a version. It's got a started at field which has some date and time and it's got a canceled property with a URL path to go to which looks like it might cancel that task in some process. This is the API response for an account that expired. It's got a state property that says inactive and it has an expired at property that tells us when the last time the account was active. This is the API response for somebody who never signed up for our service. They have no login credentials. We've never heard of that. And this is the API response after our servers have analyzed the post and responded. It's got a state property called complete. It has a list of string alerts and it has, you finish that property that tells us when the process can be. And then this one is for the account. We'll notice that it now has it. So that's a lot of looking at data. What am I getting at? This is the machine. Everybody's got one. The machine is already running. Everybody already has a running process in their play. This is a tool that engineers and people in business use all the time to model processes, to provide a mental map that's easy to reason about and which separates processes into discrete units of, discrete semantic units. Each state is just a label, but it has its own meaning. It has intrinsic properties that only exist in that form. For example, here in this waiting state which I have said, this is what it means when somebody is logged into an account that they've never submitted a post analysis. It doesn't make sense to try and cancel the analysis here because none has ever been started. It's a meaning of the state. It doesn't make sense to try and get a list of alerts about the post content because none has been submitted. The processing state means that my server is currently analyzing the content that somebody wrote. It also has its own meaning. A complete state we already talked about. It has its own well-defined meaning. You can't cancel a job if it's completed because it's no longer doing anything. And we have the inactive state, which is kind of like a catch pocket for anything that means the service or the account isn't valid. You'll notice there's arrows between these states. We can jump from one to another, and jump from any of them to any of the others. There's certain rules that we can define in English language, business rules that can say, well, once an account is established, we can start processing something. But we can't have an account on our servers that nobody has ever submitted something to and immediately jump into the bottom state where we are finished analyzing something. Unfortunately, a lot of times when we build out API-based components on things like this, we end up assuming that we go from illegal states to one to another. We'll see that later. When I'm talking to somebody on the phone about my plug-in, I can describe to them. I can send them this picture and say, look, here's the four different places somebody can be with our service and I can talk about each one in isolation. It's simple, relatively simple. I mean, the work that we're doing is complicated all around, but this diagram is easy. So why do we have to go and make things so complicated? This is the code we had at the very beginning. Honestly, this is much better than most of the code that we typically find in these circumstances. We tend to build things piecemeal, and we make a change, we add to it, we tap on the code. So this is actually better. When we already discussed, we have four API calls. We have race conditions where we can get into weird states. And the person who developed the alerts endpoint was different than the person who created the users endpoint. So you actually only get an error about account exploration when you call the users endpoint and not the other. Look at all the logic that's occurring inside of the web browser in order to understand what's happening. We're looking at all these different fields that come from different places. And any time, you know, let's take a look at that dashboard. The Gutenberg editor itself and the WPM dashboard both have to know if a user is active and if they're a premium account. So we end up duplicating all these checks in JavaScript in both places. And there's a lot of opportunity to get those out of sync with each other. We end up in big applications with like 30 different functions that are all intending to do that, but they do it in like seven different ways. And then you get a weird bug that says, hey, in my dashboard, it says my account is active, but in the editor, I cannot do anything and it's telling me I have to log in. And probably it's out of date. This is an example of a JavaScript callback from when we click Analyze, how we might typically see this being done. Eric mentioned in his previous talk that, hey, look, I wrote this code. This is not how I'm going to do it in production, but this is easy to see conceptually. And there was something that was kind of like this with the ratings. They submitted the ratings and then we have this like promise callback however we do it. We wait for the API response to return and then we update the reaction state in the render. There's a big problem here in that if we refresh the page during that process, it's gone. If we have, you know, let's say it takes 30 seconds to submit the review that Eric wrote and there's like a little spinner in the meantime. If we reload the page during that 30-second window, it looks like we haven't submitted it at all because it loses traffic. Additionally, this means it's hard to test our interfaces because how are we going to try and fake the browser into this state where we're submitting it? We can't do it. We actually have to make a network call in order to try and test out that loading state. So let's talk about how this changes. What we did is we looked at everything that we were doing and said what does it mean to submit a post-content to analyze and to receive these calls? We classified that process into different steps. We created four steps and we built a single API endpoint that returns one data object that encompasses all of the information about that process, which step it's in, intrinsic properties of that step. And in here, we just rewrote. So here's what we had before, four API calls. Here's our new one. Again, I'm sorry, this is how we changed with the state machine that same callback. So make it wait for the response and update state or the state machine said I'd forget. What we're going to see is that the user interface is no longer a result of a sequence of logical checks and verifications in our code, but instead it's a direct mapping, a one-to-one mapping between this data object and the display. When we submit a post, we're transitioning from one state to the next. When that happens, our UI updates, not because of the transition, but because of the raw data that the server tells us is the current status of what we're doing. Generally, we're going to pull this stuff, you know, we update it every so often, or in the case of submitting a request for something, when that request comes back, it has a new copy of that data object. Since it's all coming from one endpoint, too, all of the error handling information, all of the error bits of information about why it failed is in that standard shape. So all of our UI instantly responds when things change, and we don't have to update that. We don't have to make sure that the dashboard is subtracting what's happening in there. So this is like our dashboard code. One of the things this kind of gives us is since the actual truth of our UI, if you will, the actual design is not code, since code is a liability, we can reason about the code that we write, and we can say, like, is this code fully implementing our design? We have a case statement for each process and then everything else. So we can say, oh, look, if we had forgotten the labeling state, somebody confronted the diagram and said, what does the dashboard do when we're in an active account but we haven't yet submitted it? Well, because it's in the diagram, and we can just, again, one-to-one map it, now we have that case statement there. That's what it does. It doesn't depend on a sequence of checks. Further, at the top where we make the API call, we can end up pulling this out of our code and be hitting this endpoint in the background with some pull, whether it's a second, one second, five seconds in response to events. Our UI rendering code ends up being completely independent of any API calls. What that means is if we want to test the UI in the middle of the process, if we want to see what it looks like when that loading spinner is, all we have to do is manually inject that response object into the app and it will reflect that. We can fake it. So the state machine is a discussion about language. When we are developing software, the entirety, except for a tiny little sliver of what we do is communicating language and intent. Our entire trade is the trade of specification, of trying to understand what it is that we want to build. When we write that in the language of code, it's very noisy, it's very confusing. When we can step back and provide vocabulary and specification to define the processes that we're working with, then we have a much easier model to communicate with other people, people who aren't coders, people who aren't designers. And we get something that's easy to maintain and easy to gauge with. Is this app complete? What percentage of this project is done only? If we go back to the state machine itself, it's like a language bridge. It is the way that we go between domains of knowledge. If we look here, we can see how a designer can take each of these states and provide rough mockups of the UI during those steps of the process. They don't have to know any code, they don't have to say when the user is active, but they're not premium account. We just say, here are the steps for the intrinsic properties that we described in paragraphs and sentences, and this is the way that those translate into visuals. The coders can then take this and say in code, the switch signal is a really close match to this kind of description. We can say for each of these states this is the realization of the UI that the designer gives. Again, it's easy to fake all that. It's easy to test it. It's easy to change it because the change doesn't require scouring 20 different API endpoints and 100 different places in JavaScript. What about the server site? When we started this project, this is the list of endpoints that we had to interact. The client had to know, by saying the client, I mean the JavaScript code in the browser, had to know all these URLs, had to know how to form them, had to know how to interpret the response coming from each of those, and they were all different. Settled on a way to describe this process, we ended up with these three endpoints. The logic is all controlled on the server. It's all controlled in one spawn. There's no duplication. It has enabled us to, it has kind of like encouraged us to be able to write our code in a more modular way than a lot of APIs are written. Our API is actually just going to call the state machine code itself, which lives in our solution. And finally, we actually don't even need the client to know the other URLs. We can pass it all in through that data object itself. If you look at the diagram, the inactive state is kind of off by its own. In many cases, in many processes, we have these kind of global states that live on the site. These are typically error states, authorization permission type issues, waiting states, and this way of writing code really helps us to be consistent in how we provide that data back to the browser. Error handling is notoriously bad in software, and it's really frustrating as a customer to be using something and have it break and have no information. In this case, we can take a look and cone up the rules that we talk about and provide a function that goes through and looks for any condition that invalidates this request. I said the machine is always running, or it's already running. Those users that we've never seen, we don't have to go and check if the user exists. If the user doesn't exist, then in the PHP side, in the server side, we just send back the responses as this account is not inactive. It's inactive. There's no permission to do that. And no matter which action we're doing, whether we're trying to cancel a job in progress, start a new analysis, if anything happens, if anything gets unauthorized during the process, the server is just like checking this stuff and it'll keep that back instead of continuing the process. This is a real pain to manage for like 10 different APIs. I'm going to jump through some of these as we run out of time, and I'm going to give you a basic model of how we write the click on the server and move in through the steps of our process. Each step gets its own domain where we can kind of like forget about everything else. We can immediately toss out API requests that are invalid because they're trying to like start a job on an account that's not active. We don't have to replicate those checks of 30 different processes. And I mentioned our APIs end up becoming very hollow shells. This is the end result of our actual WPAPI code. It does one thing. It checks if the requesting user is authorized to make the API code. And if it does, it returns that data object and if another whichever is in there. What this looks like in reality this single data object governs the entirety of WPAPI. We can communicate different things about abilities without having to update our browser. Without having to update the code or the plugin that they're using. So in this case, we're looking at the state of a process that our servers are currently analyzing the post and we have provided this cancel property that indicates where they can go to to cancel the job. Maybe it gets stuck, I don't know. In this API response that property is gone. Now, why is it gone? Like in our client, if we want to provide the cancel button we just say like does the cancel property exist? And if it does, display it and use this URL path with a post request if somebody wants to cancel it. It's gone here. Why is it gone? Browser doesn't care. Maybe they're not authorized to cancel the job. Maybe they're allowed to see the jobs that are running but they're not allowed to cancel it. Maybe we're running an AB test and five percent of our users are able to cancel and none of the others are. Or maybe the servers on our side that interact with these things is just down, it's broken. The fact that that's gone means clients instantly don't show that UI on it. Don't show that button. That's the end anyway. Again, it's an advanced topic so I apologize if it was dry but when we are programming these things and again which we're going to do more and more with Uber and API based apps and WordPress the proclivity to expand our complexity grows so fast and it's super valuable to keep things simple if we can sit down, model our flows as a process and identify several states and build a single point in the server that produces all that information. We know that these are good candidates for this work if it's long running, if it's cancelable and if different points in the process kind of share similar value conditions permissions and volatility might expire. Do you think there's going to be something like that? Some of those things will intercept a request or will do something to request or modify a request before it runs a method in the API. Is there some kind of plan for doing a formalized way in WordPress or are there lots on that or what's a good way to do those kinds of things? To my knowledge there's a method like that and that has more to do with PHP and WordPress operates through hooks and filters. It's perfectly legitimate when writing your own APIs to do this. It's more of a code structure than anything else. Again, the reason we do a lot of stuff is because these concerns tend to be broken and tend to apply to a wide range of requests. No, I don't expect to see decorators but you're fully at liberty to do this. It's not very workable on WordPress PHP, especially since it still supports PHP 5.24, which does not allow a human and functional programming. But you can see we kind of did that in a dramatic way here. That's what it reminded me of. That's what it was.