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

Tracing Field Source0:00

Let's say you have created this extensible structure allowing you to add multiple payment options in the future, even though you're dealing with a single one right now. And you have done this several months ago, time has passed, now you get a new request asking you to change a field in the wire implementation. Let's say you need to add an address field that will connect to the Google API and enable users to search their address while repopulating everything else. Since my application is using Blade for displaying the front-end, the natural first step for doing the change that I have been requested to do is opening the views and trying to find a place where I can add this new field. Now, when I open my PaymentDetails.blade.php, I can see that the whole data is pooled dynamically, so instead of trying to do the adjustment here, I would be better off

where I can add this new field. Now, when I open my PaymentDetails blade, I can see that the whole data is pooled dynamically, so instead of trying to do the adjustment here, I would be better off going to the controller and see where these fields are coming from. I open the controller, I see the fields, and the PaymentOptions service is used to pool the fields. Now, if I see the dependency here, the PaymentOptions is an abstraction. So, what I need to do next is open the service provider and see what this abstraction binds to, so that I can find the proper place to handle the fields. In the service provider, the instance of my class is set to wire if the payment type is wire. In any other case, it's set to throw an exception. And this is that scalability part, so I get it, I need to look for the wire service class to dig further in the code. Opening my class, I now see that it is depending on a WireRepositoryInterface, so using dependency inversion to depend on

I need to look for the wire service class to dig further in the code. Opening my class, I now see that it is depending on a wire repository interface, so using dependency inversion to depend on abstractions, that's good. I need to find what is the appropriate class that is binding to this interface. Checking the service provider again, wire repository, let's open it. And here are the fields I'm looking for. So, the GetFields method within the repository, I need to find a place where I can add my address. Looking at what we had to do to add the new input field on the front-end, it kind of feels like we have over-complicated things, and we need to go through all of these unnecessary steps to just edit a simple functionality on the front-end. It does make sense if our code needs to scale and if we need to work through multiple different options, so this dynamic loading really is necessary. But in our case, it's kind of like an extra complexity instead of something that

Refactoring to Simplicity2:45

scale and if we need to work through multiple different options, so this dynamic loading really is necessary. But in our case, it's kind of like an extra complexity instead of something that would make our lives simpler. Now, let's explore an alternative approach here, because from what we've seen, our app is much less complex than we are making it. It's a simple application that is dealing with Users, it's handling payments through wire transfer, so we don't need any complexity around dynamically choosing the type of payment. So, how can we, let's say, refactor this in a simpler way to make it work with our use case? Payment type is not really necessary because I don't need to choose between different types, I only have wire as an option. I'll remove it from here as well. Then, fields. Dynamically pulling the fields from a service doesn't really make sense because, again, it's not supposed to be dynamic, it's only a single option, so I can just remove these fields and

Then, fields. Dynamically pulling the fields from a service doesn't really make sense because, again, it's not supposed to be dynamic, it's only a single option, so I can just remove these fields and handle them manually in the view. So, just adding all of the fields over there, we'll get to it shortly. The data, the data I can pull from my authenticated user, and then get wire details, for example. The fields will also not be necessary here, so I'm just sending the user data to the view, and then our view would be changed to something like this. I don't need this for each here, let's just do this, removing this part. I'll have a div saying an account name, I'll have an input, this one, closing the div, and then I'll do the same with the select. I don't need to dynamically pull any values, just copying this html as many times as I need to manage all the fields that are necessary. And now, what happens when I want to add a single field to the implementation?

Simpler Change Workflow4:49

just copying this html as many times as I need to manage all the fields that are necessary. And now, what happens when I want to add a single field to the implementation? It's been a while, as we said, so going to the controller, okay, I see that I'm pulling the wire details from the authenticated user, simple enough. I know that the details are stored in the database and they will be displayed, and then I'm dealing with the payment details view, so I just need to open that view, see all the fields that we need for the form, add my new field in the appropriate location, add the implementation with the Google API, and close the deal. Much faster and much easier to navigate through than dealing with the whole complexity that we've introduced earlier. Now, don't get me wrong, I'm not trying to diminish the value of the solid design principles, I just want to share a point of view where you are aware of the context of your project and what

Context-Driven SOLID Usage5:38

Now, don't get me wrong, I'm not trying to diminish the value of the SOLID design principles, I just want to share a point of view where you are aware of the context of your project and what you're dealing with and you're not relying on some specific design principles or best practices just for the sake of complying to those. SOLID and any design principles or patterns that you choose to use should be a tool that helps you achieve code that's easy to maintain and extend. It's not an end goal on its own. So whenever you decide on the design structure for your code, think about how you expect that piece of code to change in the long run. If you anticipate a lot of change functionality, by all means invest the time needed to structure your code in a way that will allow you to easily scale it in the long run. But if not, then investing that time up front just to make the code much more complex for you to navigate through it doesn't justify the whole investment.

Avoiding SRP Over-Fragmentation6:24

you to easily scale it in the long run. But if not, then investing that time up front just to make the code much more complex for you to navigate through it doesn't justify the whole investment. Another thing that I'd like to caution you about is overdoing it with SOLID, particularly the Single Responsibility Principle. It's hard to comment for people to look for ways to refactor away from Single Responsibility Principle. If your code makes it harder for you to navigate through it rather than easier, you want to reconsider the structure you opted for. Let's look at our WireService class for example. A common issue is fragmenting the responsibilities too much. You could argue that getFields is one responsibility to manage the display of the payment option. Then storePaymentOption would be another. deletePaymentOption would be another. And you could create them in separate classes: WireFieldService, WireDetailStoringService,

Then storePaymentOption would be another. DeletePaymentOption would be another. And you could create them in separate classes. WireFieldService, WireDetailStoringService, WireDeletionService. You get my point. And when you think about isolating responsibilities, this might make total sense. But it fragments the code too much and then it will make it much more difficult to navigate through it. So when you think about single responsibility, think of payment management as one like we did here. Then payment processing is another. So you'd have a completely separate service that handles the whole processing regardless of the small pieces it includes. Just a rule of thumb, any design principle you choose should make it simpler for you to read, understand, manage, and extend your code. If you find it too complex to do that, you should revisit your code structure and see how you can improve it.

understand, manage, and extend your code. If you find it too complex to do that, you should revisit your code structure and see how you can improve it.

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