تماشای این درس نیاز به اشتراک حرفه‌ای دارد.

Refactoring Test Setup0:00

Alright, I think we're almost ready to push this up to GitHub and tag our first release. But before we do that, why don't we take one more episode to review all of our code here and make any final refactors. I have a couple ideas in mind. First up, let's visit the tests. Now I'm noticing here that for every single test, I have a $final variable, and then we load a transcription. So we do it there, and then here, and then here again, but this time we inline the file, and then we do it again. Okay, so I'm not a big stickler for removing duplication in a test.

and then we do it again. Okay, so I'm not a big stickler for removing duplication in a test. Really your tests are supposed to be examples, so it's a little bit different in my mind. But nonetheless, why don't we go ahead and move this to a setUp method. And then, yeah, I'm just going to grab all of this, move it inline, inline that variable, and we get something like that. And then of course, we will assign this. So protected transcription. Okay, so now, I can do things like this, this, this. And does that work?

Chunking Lines Logic1:40

Okay, and then finally, get rid of that, and that. So yeah, we're just removing bits and pieces of duplication here. Next, I'm on PHP 8, so I should be able to indent all of this. And I think that still works, yeah. And now, let's have a look. Is everything okay? Yeah, I think this is good enough for this file. Okay, next, I'm going to switch over to transcription, because I have some ideas here. If we scroll down to the lines method, I'm not overly happy about this. We iterate over all of the lines, and then for each one, we build up a line object where

If we scroll down to the lines method, I'm not overly happy about this. We iterate over all of the lines, and then for each one, we build up a line object where we grab that line, and then the one that comes after it. So we grab this line, and then we move on to the one after that. Really though, I sort of just want to say, give me, just group all of these lines into little collections. Like maybe this is one collection, and this is one collection. And you know what? There is a php function for this called array_chunk. It does that exact thing.

There is a php function for this called array_chunk. It does that exact thing. So with that in mind, why don't we play around for a second? Why don't we test any of these, where we call the lines method, this one. Okay. So yeah, if I were to come back, I could start by var_dumping this lines. And here's what we're going to get. All of those lines. And like I said, we want to chunk them into sets of two right now. So what if I said array_chunk the lines into sets of two?

And like I said, we want to chunk them into sets of two right now. So what if I said array_chunk the lines into sets of two? Now if I run it, you'll see I have an array where the first item contains only the relevant lines to build up the object. Okay. So if we took that approach, we now have this. And let's clean that up. Next, I can simply map over those lines. So for each line, then build up your object. So new line, where we have the first item and the second item.

Does the whole suite pass? Yeah. Okay. So that was a successful refactor. Now I can clean anything else up. For example, I think we can just chunk it directly here. Get rid of that. And then, of course, I don't see any reason to define the variable and then return it immediately. So I will return at the top, and we get this.

Handling Three-Line Chunks4:58

So I'm going to come back, and we will chunk them into sets of three. But before we do that, of course, we need to update how we prepare this file. You'll remember originally, we got rid of this line, we got rid of blank lines, and then we got rid of the numbers. But now, we're not going to get rid of the numbers anymore. So right down here, let's get rid of that check. Okay. I have no idea how we're doing here. So is this passing? That is.

So is this passing? That is. Let's run the full suite. Yeah, I didn't think everything would pass. It renders the lines as HTML on line 21. Okay. Hmm. Let's come on down, and I'm going to begin by var_dump. Let's just inspect this real quick. What are we working with?

Let's just inspect this real quick. What are we working with? Okay. So I do have an object where we... Oh! Okay. So here's the problem. Now that we've chunked into sets of three, the way we pass the parameters to the line object is no longer correct. The body is actually the timestamp, and the timestamp is the position.

object is no longer correct. The body is actually the timestamp, and the timestamp is the position. Okay. Let's fix that. I'm going to go back to the line, and now we're going to instantiate this to include the position. And then, when we instantiate it, yeah, we could say line zero, line one, line two. Run that. And yet, now that passes. Get rid of this.

and then you tweak it. So I'm going to do that now. And this is okay. This kind of jumps out at me. It feels long. The method itself, yeah, even if I scroll down here, this feels a little off. Sometimes I pinpoint methods with many words in them. And that's okay. But sometimes it's maybe an indication that, I don't know, you're missing an object or you're doing too much.

So think about it. Get rid of the heading. And by the way, you might be wondering, well, why don't you just manually delete it? We're assuming that we are working with VTT files that we have not manually processed. So maybe this is coming from somebody else's server, and I just need to process it and make it work. But anyways, I need to remove that, and then line breaks, and then everything else is good. And that's actually pretty easy. So now I'm starting to wonder if I even need this valid method on the line object. Because it's pretty simple.

Simplifying File Cleanup8:12

So now I'm starting to wonder if I even need this valid method on the line object. Because it's pretty simple. So let's play around here. I'm going to get rid of this real quick. We have our lines, dd lines. So let's have a look at this real quick and ignore this error for now. But if I scroll down, yeah, here's each line. So notice these blank lines are empty strings. We have one there. We have one there.

We have one there. We have one there. And I guess that's it. Well, we could just run that through array_filter. array_filter. And if we don't pass anything to it, any callback, it's just going to filter out falsy values. So if I run that again, now notice it takes care of those blank lines. Now the only thing I need to do is just remove that first item from the file. And we can do that in a couple of ways. First I could say lines equals array_filter.

And we can do that in a couple of ways. First I could say lines equals array_filter. You could then use things like array_shift. Is it shift or unshift? After all these years, I still can't remember it. Yeah, it's shift. Okay, so if I did that, now notice if you've already dumped the lines, this may already be what we need. Yeah, the number, the timestamp, the body. The number, the timestamp, the body.

Can I just do this? Run my test, and yeah, how cool is that? It still passes. The full suite is passing, which means now this valid method is not even being used, as you see there. So I can get rid of that, and it becomes a little cleaner. Okay, so once again, we do the squint test. Maybe we're still making this call, but I'm starting to wonder. Well, first, let's just move ArrayMap back into discard. So that would be a lot of array functions here, but that's okay.

Well, first, let's just move ArrayMap back into discard. So that would be a lot of array functions here, but that's okay. Maybe in future versions of php, this will be even easier. Or, of course, you could pull in something like Laravel's collection component to make it a bit more object-oriented. But is that still okay? Yeah. So you know what? Maybe it's fine as a method. Maybe it could just go up here directly.

I'm ambivalent. It might be nice to assign a name to what this is doing here. I don't think it's a huge deal either way. I could make an argument for both. But why don't we keep it like this for now? Okay, load method is fine. lines method is fine. HTML lines. So again, I'm noticing two words here. And plenty of times, there's no problem at all.

So again, I'm noticing two words here. And plenty of times, there's no problem at all. But I think on a very light level, it's a code smell. And remember, code smells aren't immediately bad. They are not synonymous with bad code. They're just smells. Maybe have a look there and then decide if it's okay or not. It doesn't mean you got to fix this. It just means take a look at it. So with that in mind, it seems like once we have our lines,

Introducing Lines Collection11:48

It just means take a look at it. So with that in mind, it seems like once we have our lines, you may want to render those lines differently. So in this case, we are rendering the lines as HTML or anchor tags. You could also imagine at some point rendering the lines as a PDF or rendering the lines as some other format. But right now, every time you would need that, you'd have to create another method. And you do something like pdfLines. And then you'd have that code there.

And you do something like PDF lines. And then you'd have that code there. And that can get sort of messy. So what we have right now, I don't think is a big deal because it's so basic. But just to give you an idea for larger projects, how you might go about this. What if you had a LinesCollection class? And then you could add additional behavior and rendering options on that collection. Maybe that would be cool. I'm not sure.

Maybe that would be cool. I'm not sure. So let's make sure everything's passing and then we'll tinker around with it. Okay. So if we were to add a Lines class, this represents a collection of Line objects. So we'll have our constructor here. And that would be an array of our lines. Okay. So now I'm thinking here's where we would instantiate our Lines class like that. And then things like this would move here.

So now I'm thinking here's where we would instantiate our Lines class like that. And then things like this would move here. But now notice the lines is a little bit redundant, isn't it? Because we already have a lines object. So we can remove it entirely or even a connecting word like that might be okay. Lines as HTML or another one as PDF or things like that. And that logic can maybe live here. Let's try that. Okay. So now we're not calling lines anymore.

Okay. So now we're not calling lines anymore. We're going to work with the lines array that we have in memory. And then we might even add a toString. Actually, you know what? Let's go back to transcript. Yeah, you know what? Let's try this. Let's put a toString on lines. And then notice we have a little duplication here.

Let's put a toString on lines. And then notice we have a little duplication here. So maybe get rid of all of this. And that would be our formatted lines. Sometimes I create these temporary variables temporarily while I'm still kind of figuring out what I'm doing here. And then we want to call toString on that. But I don't want to mutate the line. So what if we just build up a new lines object with these formatted lines? And then I could explicitly call toString on that.

So what if we just build up a new lines object with these formatted lines? And then I could explicitly call toString on that. All right. I might tinker with that just a little bit more. But let's get our test to green. So now when I call this lines method on transcription, it's going to return a lines collection. And we're getting there. But yeah, I think we're still going to have a bunch of failures. So let's run anything like this. And actually, we don't even have to run the test.

So let's run anything like this. And actually, we don't even have to run the test. Immediately, we get, well, this was supposed to be countable. But we gave it this NewLines class, which is not countable. So if we want to make that work, what we could do is on our collection, we implement the Countable interface that PHP provides. And that Countable interface just expects that you include a count method. OK. So we could do that right down here. Method count.

So we could do that right down here. Method count. And that's going to give us... We're basically teaching it how to determine the number of lines we have. So that would be the count of this specific property. OK. So we come on back. And now that warning goes away. But we still have one here. Expected parameter of type iterable.

But we still have one here. Expected parameter of type iterable. OK. Exact same thing here. So when we introduce these custom collections, it does require a little bit more work. But you may also know, if you're leveraging Laravel in one of Laravel's collection classes, you get all of this stuff out of the box for free. So you don't have to implement the interfaces yourself. And it ends up being much more appealing. In this particular case, it's almost a little more work than it might be worth.

And it ends up being much more appealing. In this particular case, it's almost a little more work than it might be worth. But yeah, if I were pulling in that package, it would be a no-brainer. OK. But I'm still going to show you how to do this. So now we're going to implement another php interface, IteratorAggregate. And we'll add the method stubs here. All it is is one method that needs to return an iterator that you want to use. And we can use a standard ArrayIterator for the lines. OK.

And we can use a standard array iterator for the lines. OK. So again, bring that down. And if I come back to our test, now that error goes away. OK. So let's give this a run. And now it passes. Cool. What else? Give this a run.

What else? Give this a run. That passes. What about renders as HTML? That doesn't pass because we've gotten rid of that line. So we do need to fix that. Now we're going to say transcription lines as HTML. And that passes. Cool. So I'm feeling a little better.

And now, look, it's only 30 lines. This is pretty basic at this point. There's transcription. Here's our lines collection. And we can now render it as HTML or potentially a PDF in the future. We can iterate over it. We can fetch the count. And then here is our line object, which is basically a value object. And in fact, why don't we put these on their own line? If you're using PHP 8.1, we could even make those read only.

Final Review and Release17:25

And in fact, why don't we put these on their own line? If you're using php 8.1, we could even make those read only. But I think it's OK now. OK. So our tests are returning green. I think we're ready to tag a 0.1.0 release and push it up to Composer and Packagist.

The Squint TestExtract CollectionsCountable and IteratorAggregate

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