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

مرور همکاری بین اشیای مقداری0:00

On the last lesson, we had a grid introduction to value objects, and on this lesson we're going to continue to bid. On top of that, we're also going to take a look at a new value object, see how we can have different value objects talk to one another, and also refactor some of our code to take those value objects into account. So let's jump into the code. Okay, so the first thing you might notice is

Introducing InterestRate Object0:18

So let's jump into the code. Okay, so the first thing you might notice is that I've added a new value object. It's called InterestRate, and we just have a few tasks here. The first one is that we can create an InterestRate from a percentage and that we have a dsmO representation and a percentage representation. We also task, we can add interest to an existing InterestRate.

We also task, we can add interest to an existing interest rate. So for example, if we instant sheet an interest rate of 20%, we can add an extra 30% on top of it and we should end up with 50% of interest. If we take a look at the ValueObject, pretty straightforward, we have an InterestRate class, we have some static structures, and then we just have some formatting methods for us. In this example, I also chose

and then we just have some formatting methods for us. In this example, I also chose to make our internal representation private and have methods to give us those values instead. That gives us a little bit more freedom if we want to change how things are handled internally. Finally, we have an ad method that also returns a new instance of InterestRate because they are immutable. So if we go back to our invoice interest simulation

Refactoring Simulation to Value Objects1:26

because they are immutable. So if we go back to our InvoiceInterestSimulationController and to our tasks, let's see if we can refactor this a little bit to use those value objects instead of just holding plain primitives. First, let's start with the InvoiceInterestSimulation. And of course we want to make sure that the tasks are passing and stay passing. So let's go into InvoiceInterestSimulation

are passing and stay passing. So let's go into Invoice interest simulation and let's update the structure to take an interestRate instead of a float. Since we have a static structure, we don't have to update any other places but the structure. So we can say that we have an interestRate and we'll have to add it from decimal method as we can only create it from a percentage. Right? Now, let's add this method

as we can only create it from a percentage. Right? Now, let's add this method and we can say monthlyInterestRate. This is going to return south, and then we can refactor this to return fromDecimal percentage divided by a hundred. Let's update this to rate. There we go. So if we go to our invoiceInterestSimulation, we're now calling fromDecimal. We are expecting an interestRate here.

we're now calling from decimal. We are expecting an interestRate here. Let's try running your tasks and see what happens on unsupported operating types. So we're trying to sum an interestRate with a float. Let's see what we have here. Okay, we're trying to add some interest. So now this, this is a rich object we can simply call add, and now we can make this a value object instead. So let's do interestRate from decimal interest.

and now we can make this a value object instead. So let's do interestRate from decimalInterest. There we go. Now we're trying to divide it. Let's see what we have here. dailyInterestRate. Well, we know we can get the decimal representation, so let's do that. Let's rerun our tests and we have something funky here. Let's see what we have on the data. Hmm, we're regarding an MTRA. Remember what we talked about regarding

Handling Serialization and Equality3:10

Hmm, we're regarding an MTRA. Remember what we talked about regarding object serialization. So let's go into our Invoice interest simulation, and this is where we serialize it. We could do a couple of things here. Let's say give me the decimal representation, let's rerun our tests. Now we're getting a different failure and this failure is because we're comparing an object with a float, so we have

Now we're getting a different failure and this failure is because we're comparing an object with a float, so we have to do something different. Remember that I said that when it comes to value objects, we do equality by value. That's what we're gonna do here. So we have to somehow make sure that this object is equal to an interest rate of 0.32, even though they're different objects. So here's what we can do.

even though they're different objects. So here's what we can do. We can sense that we are gonna call this equals method, which does not exist, and we're gonna say interestRateFromDecimal like this. Same thing here, we're gonna say equals interestRateFromDecimal like this, let's rerun our tests, call it to defined method equals. So let's add this. And when it comes to ensuring that two different value optics are the same, we just have

So let's add this. And when it comes to ensuring that two different value optics are the same, we just have to compare its internal values. So you can simply say that the decimal representation is going to be equal to the other objects decimal representation, and we're gonna call this otherInterestRate. Let's rerun our tests and we are back to green. So now that we have those objects, we can actually refactor this a little bit.

So now that we have those objects, we can actually refactor this a little bit and instead of using decimals, let's say from percentage, and this would be 2% and this one would be 3%. Let's rerun our tests. They're passing. Now going back to the serialization issue, if we run a test, they're passing grade, but if I remove this, they start to fail and that's because B three does not know how to serialize that object. So one thing we could do is we could go into our interest.

because B three does not know how to serialize that object. So one thing we could do is we could go into our InterestRate object and we could implement the JsonSerializable interface. Let's add the method here. So we have a method called jsonSerialize, and with this we can instruct php on how this should be serialized and now we can just return the decimal representation if we rerun a test they're passing.

and now we can just return the decimal representation if we rerun a test they're passing. Now there's a reason why I did not enjoy this and this is because it's too magical for me. When I look at this, I wanna know exactly what is being passed here and if I have something explicit like the decimal representation, I know that I'll be looking at a decimal representation in the same manner.

that I'll be looking at a daal representation in the same manner. If I were to say percentage, I would know that I'll be looking at a percentage that is 70 would be something like 70%, right? Whereas with a decimal representation, there'd be 0.7%. Either way, I know exactly what I'm looking at right now. So I personally prefer to be explicit and just call a method, for example, like we're doing here. But if you wish to just pass the

and just call a method, for example, like we're doing here. But if you wish to just pass the object, that's not a problem. You just have to instruct php on how to serialize it. Okay, so we have converted interest into a Reacher object, but what if we could do the same to the monetary values and ideally we would have that on the moderate self. You're gonna take a look into that, but for now, let's go to totalInterest and see if we can refactor this.

Adding Money ApplyInterest Feature6:18

but for now, let's go to TotalInterest and see if we can refactor this to use objects instead of those primitives. I'm looking at the schedule and thinking, you know what would be really cool if we could pass an interestRate to a Money instance and get back the amount with interest added. So let's not edit on this specific object right now, but what if we just add some tasks for it and maybe just implement it real quick.

but what if we just add some tasks for it and maybe just implement it real quick. So let me close everything. I'm gonna go to moneyTest and I'm gonna see it applies. Well task, it applies interest. So first we're going to create a Money object and we're gonna say let's go with $50. And then we're gonna say, moneyWithInterestApplied, it's going to be money->applyInterest(), and this is where we're going to pass an Interest instance.

it's going to be money, apply interest, and this is where we're going to pass an Interest instance. So interestRate from percentage, let's think 10%, I think 10% is okay. And then we can simply say that we expect this to be 55 like this. Let's run the sta. It is obviously going to fail. So let's implement this. So let's say something like this. We're going to return a new instance of itself and we expect this to be in the inte, right?

We're going to return a new instance of itself and we expect this to be in the inte, right? So we're gonna say, actually, you know what we could do south for a major and this is going to be major plus major times the decimal representation of the interest rate. Now let's rename this to interest rate and see what happens. Hmm, okay, something didn't work. Oh, of course I'm testing on the wrong object. So let's go with money, with interest applied. There we go.

Oh, of course I'm testing on the wrong object. So let's go with money, with interest applied. There we go. So now we can apply interest to a money object. Now we could also do this a little bit differently. We could do, we're gonna return a new instance of itself and this is going to be the amount plus the amount times the interestRate decimal representation. So you can get rid of this and we'll have to cast all of that to an integer.

So you can get rid of this and we'll have to cast all of that to an integer because this class expects an integer. So something like this, let's run a test and there's surpassing and now we can just type hint this by saying it returns an instance of itself. With that said, I think the other one read a little bit better. So let's refactor to front major.

Recap and Next Steps8:37

read a little bit better. So let's refactor to front major and there we go back to green. So now we have a very expressive API and we're combining those two value objects. Awesome. Now we have everything set up so that in the next lesson we can replace the primitives in our Invoice interest simulation object with those richer objects and also have our Invoice model return a richer Money object.

and also have our Invoice model return a richer Money object. As usual, I hope you enjoyed this lesson and I'll see you on the next one. Bye.

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