در حال بارگذاری ...

Refactor Plan and Tests0:00

Alright, here's how this is going to work. I'm going to run any tests to do with steps, it should be those 8 tests that we created in the previous episode. And I can execute this as many times as I'd like. So, as I go through our step builder and refactor, if I want to check if I've broken anything, I head to the terminal, I rerun those tests, and ensure everything still passes. If it doesn't, I've done something wrong. So, with that in mind, let's make a start. The first thing I notice is that we're still using this array triplet. I think it would make more sense at this point to have an object for steps. So, how about we create that class.

Create Step Class0:38

I think it would make more sense at this point to have an object for steps. So, how about we create that class. Source, we'll add a class called Step, introduce a constructor, and we need to pass in the correct variables. So, for now we'll make it public, a public closure called Step. Let's actually import that closure to clean things up. We also have the closure or faults, which is for reverting the step. And then finally, we have a nullable string for the key that we want to use for referencing it in the array of results. We could also add some helper methods on this.

for referencing it in the array of results. We could also add some helper methods on this. So, why don't we have a public function called run. run returns mixed, and essentially it's going to return this step, and it will execute that step. And, of course, we'll want to receive an array of currentResponses. So, we'll receive that there and pass it in. And we could have very much the same thing for revert. Public function revert takes an array of responses. It doesn't need to return anything this time.

Update Builder to Step1:35

public function revert takes an array of responses. It doesn't need to return anything this time. The first thing we'll check is if revert actually is a closure. So, if this revert is an instance of a closure, then we want to execute it. This revert passing in the responses like so. Those helper functions should come in pretty handy. Okay, let's jump back into the step builder and make use of our new class. So, here we'll say new Step. And I imagine now if I rerun the tests, they're going to fail. Yes, they do.

And I imagine now if I rerun the tests, they're going to fail. Yes, they do. Cannot use object of type Step as array. So, basically, where we're destructuring, say in this foreach loop, we cannot do that and expect it to work. We'll have to change this to be step. And then here we're building up a new array of steps. We're going to need to use step again. So, new step, get rid of the brackets. And we can still pass in the key,

So, new step, get rid of the brackets. And we can still pass in the key, although we have to reference the key through the step. Step key like so. We have the previous revert, which is absolutely fine. And then previous revert will have to be set to step revert. All right, let's rerun our tests. We're still going to have failures, which I would expect. Argument one step must be of type closure, step given. Ah, of course.

Argument one step must be of type Closure, step given. Ah, of course. So, here we call step. We actually need to call step step. Now, I'm not saying this is going to be the final result. We're just trying to get it back to a working state before we refine further. Rerun the tests. Now, we have a different error. Cannot use object of type step as array. So, if we come to the while loop, we're destructuring here as well,

Cannot use object of type step as array. So, if we come to the while loop, we're destructuring here as well, which is why this is causing a problem. Let's reset this to a variable called step. For revert here, we'll check for step revert. Make sure that it actually exists before we use this closure. In responses, we don't want to access key. We want to access step key. We want to run the step passing in the responses. And, of course, if we reverted, we need to revert the step.

We want to run the step passing in the responses. And, of course, if we reverted, we need to revert the step. So, we can say step revert passing in the responses using that helper method we created. Let's rerun our tests. And now, we're back to a passing state. So, our first refactor moving away from that array triplet into a dedicated Step class is complete. Let's carry on. We can simplify this if branch here by switching around the condition.

Simplify Revert Control Flow3:59

Let's carry on. We can simplify this if branch here by switching around the condition. So, if we didn't revert, then we can increase the index. And then, I'm going to continue the loop, which will allow us to get rid of this else statement and simply have step revert and index minus minus at the bottom there. Rerun our tests. Still passing. Another successful refactor. I'm not happy with this here,

Another successful refactor. I'm not happy with this here, our little bit of code for creating the previous revert. First thing I might do is extract this to its own method just so we can see how much cleaner it would look. So, let's create a protected function. We'll call it normalizedSteps for now. And normalizedSteps is going to obviously return an array of its own steps. Let's drop the code in here. And then, at the bottom, we will return steps like so.

Let's drop the code in here. And then, at the bottom, we will return steps like so. So, if we come back up here now, we should be able to say $steps equals this normalized steps. Let's rerun the tests. And everything still passes. So, that is a lot cleaner, and it makes this run method less convoluted. But I still think that this is perhaps a little unnecessary, particularly now that we have a dedicated class for the step.

Link Steps to Previous5:11

But I still think that this is perhaps a little unnecessary, particularly now that we have a dedicated class for the step. What if instead we grab the previous step here? So, that would be equal to $steps, and then we'd want to grab the count of $steps, minus one, or null, because we could already be on the first step, and there's no step before it. And then we pass the previous step into the stepBuilder. Previous step like so.

And then we pass the previous step into the step builder. Previous step like so. And then in the step builder, we'll obviously need to update the constructor. Let's say public self, and that could be null, previous. Okay, so now each step has knowledge of the step that came before it, and we could simply execute the previous revert from inside the step itself. We could say if this previous, and it could be null, so we'll use a question mark.

We could say if this previous, and it could be null, so we'll use a question mark. If previous revert, then we actually want to fire the previous revert, not the current revert. This previous revert passing in the responses. Okay, now we can get rid of that if statement, and with that in place, we could come back to the stepBuilder, instead of normalizing the steps,

we could come back to the step builder, instead of normalizing the steps, we'll just run through the actual steps. This steps, this steps. All right, let's rerun the code. Ah, we seem to have hit an endless loop, and we've run out of memory, so something's not quite right. Of course, on line 34, we're still checking the current revert.

Of course, on line 34, we're still checking the current revert rather than the previous revert. Tell you what, what if we make revert protected instead of public? And in fact, we could do the same with previous, and we'll just access things through helper methods on the step itself. And then why don't we have another public method on here called canRevert,

And then why don't we have another public method on here called canRevert, and canRevert is essentially going to run this check. So this will return a boolean. We'll say return $this->previousRevert is not equal to false, and then we'll update this if statement to say if $this->canRevert, and we can update revert here to instead check for canRevert.

and we can update revert here to instead check for canRevert. Let's rerun the tests, and they're all passing again. Another successful refactor, which actually means we're no longer using normalizedSteps. We can remove that code entirely, rerun the tests, and everything's passing. Another cleanup I think is important

Refactor Prompt Revert API7:42

and everything's passing. Another cleanup I think is important is how we access revert using on the Prompt class. Currently, I have a public static closure, revert using as you can see, and we're setting it directly both here and here at the bottom to reset it to null, but that's very much out of line with how it's done elsewhere inside prompts. So you can see how they do it.

with how it's done elsewhere inside prompts. So you can see how they do it is they have a protected static closure for validation, and then they have a validate and validateUsing callback that you can actually execute on the class itself. So let's follow. We'll say protected static closure revert using. Let's add a little comment. We'll say the revert handler from the step builder, and that makes it clear

We'll say the revert handler from the stepBuilder, and that makes it clear that this is actually coming from an internal class rather than something that the end user should worry about setting themselves. Okay, why don't we take a look at validate using, and underneath we could create a public static function. Let's name this revert using, passing in a closure, callback.

passing in a closure, revert. In fact, let's call it callback. Again, we're playing with their rules. We keep the naming consistent with what already exists. Then we'll have void, and we can say static revert using equals callback. Underneath, why don't we introduce another static function. We could call this one preventReverting. It doesn't return anything, and essentially all it's going to do

It doesn't return anything, and essentially all it's going to do is reset static revert using null again. Let's go back into the stepBuilder and update to make use of those closures. So if we can revert, what we actually want to do is say, well, promptRevert using, and then we'll pass our closure in like so. Otherwise, we want to say promptPreventReverting.

and then we'll pass our closure in like so. Otherwise, we want to say prompt prevent reverting. Then here at the end, we obviously want to update this to do the same thing. prompt prevent reverting. Run our tests and ensure nothing is broken, and everything still passes. Great news. Now, I'm happy with my code as is at the moment. I don't want to go back.

Add Docs and Commit9:54

Now, I'm happy with my code as is at the moment. I don't want to go back. I only want to move forward with it, so I'm going to use my little work in progress alias to quickly commit this so that I can roll back at any point to this stage as needed. One thing I noticed is that in their classes, all of their methods and properties have descriptions. I need to add those for mine. So I added this constant, for example, control U.

I need to add those for mine. So I added this constant, for example, control U. Why don't we add a little description there? I'm pretty sure this is a negative affirmation. That's the official term in the terminal, negative affirmation, like so. Let's go back to our step builder and let's add descriptions for all of these as well. I'm not going to worry about the return type for now, although I'm pretty sure that this uses php stan,

I'm not going to worry about the return type for now, although I'm pretty sure that this uses php stan, so we'll probably have to come back and update that down the line. Run all of the given steps. Let's come up to add. We can get rid of all of these parameters, at least for now, and we'll keep this nice and simple. Add a new step. We'll also add descriptions for our properties here.

Add a new step. We'll also add descriptions for our properties here. So here's responses. The responses provided by each step, and for steps itself, each step that should be executed. I'm pretty sure I'm happy with everything else, so why don't we go ahead and commit what we've done so far, and I'm going to push this up. I want to set the upstream to origin.

and I'm going to push this up. I want to set the upstream to origin and I want to set the branch to steps. With everything pushed, I actually think we might be ready to create our pull request.

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟