Too much junk in your Angular components? Try composition instead of inheritance!

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
one good way to simplify our components is to break them into smaller components we might compose one parent component together with multiple dumb or presentational components and you can see i've done that here by creating two presentational components a search bar and a data list and i am pulling both of those in from this shared ui folder so we've already optimized things a little bit here but we have more than just our template we have the logic in our class as well and we don't just have this one employee list page we also have a second product list page and we can see that the general idea for both of these pages is more or less the same we have a list of data i can filter that data and now if i go to the product list page we can see it's the exact same thing just a different title it has some different items in here because it has products instead but still we can filter it and it's just like the employee list page so if we look at the employee list page we can see we're creating a form control to pass into the search bar component we're setting up an observable stream so that when the search term changes we can pass the values into our data list component so it knows what value to filter on and then we're calling a service to get the appropriate data for that list as well and you can see that that is also being passed into our data list component now if we look at the product list page we can see that it's doing the same basic thing the only difference is that it's pulling in its data from a different service so generally we want to avoid repeating ourselves like this it's annoying to have to set up the same thing twice it's more error prone and harder to refactor so this particular example isn't too bad but it could easily be way bigger and more complex than this the most natural solution to reach for here especially if you are familiar with object oriented programming is inheritance so these two pages are doing the same basic thing so we could create a base page class that implements this common logic and then we just extend our product and employee pages from that so let's take a look at what that might look like so in this example we create a base list page and we put all of our common code in there so you can see we have the same basic code set up in this baselist page class however the list data is going to depend on the page we are on for the employee page we want to use the employee service and for the product page we want to use the product service so to deal with this what we're going to do is pass the service back up to the parent components constructor so we're expecting this page service here and we create an abstract class called abstract page list service and what this will do is ensure that the service we pass to it implements a get all method that returns an observable with an array of strings and that's important because it is relying on this to get that list data and if you aren't familiar with the concept of an abstract class it's basically just defines what is expected of that class it's like a an interface in typescript so we can say whatever methods or data we're expecting this class to have but we don't actually provide the implementations for that then if we look at our employee page we can see that it is quite a bit simpler now and all we do is use super to pass the employee service up to the parent components constructor and this service will satisfy that abstract service we have defined because if we take a look at it we can see that we implement a get all method and if we look at the product list page as well it's the same basic thing we're extending the base list page and we're passing that product service instead up to the parent so this works and it's fine the components inherit the shared logic and they can each define their own templates and extend with other data and methods as needed however if we want to get all best practices it is generally recommended to prefer composition over inheritance so i'm not going to get into the why in this video i'll link to some resources that will explain it better than i will but let's just focus on the what what would composition look like here and what does it even mean so in general inheritance defines an is a relationship so our subclass is an extension of our base class our employee list page is a base list page or to bust out the usual object-oriented programming examples a dog is an animal so we could have class dog extends animal so where inheritance defines an is a relationship composition defines a has a relationship so a dog has a tail legs eyes a head and so on rather than extending a bass class we can pull in all of the things we need to assemble what we want so let's take a look at how we might do that using services in our example here and we're going to do this in two steps okay so this is step one of our service composition attempt here and we can see if we look over in the the pages we can see that our base class is now gone and our product and employee list pages are backed to just being standard employee list and product list pages there's no extends here anymore but as you may notice all of that pesky logic is still gone what we are doing instead is providing this component with its own instance of the employee service and all of that logic is in the service so if i open that up we can see we have that get all method here still and we also have all of that setup code that we had in our base component class before and an important thing to note about this approach is we're not providing this in root like we normally would so this isn't globally available we are just providing this component with its own instance of this provider which is why we're using this provider's array here and we're going one step further here in making our code loosely coupled by providing an abstract list page service so again like we did before with the abstract class we're just defining what we expect this service to provide and in this case we are expecting it to provide the search control and observable stream for the list search and the list data and then we're providing an employee service that satisfies that abstract class and so what this allows us to do is we can provide this abstract list page service and we can use that in our component so where does using this generically defined implementation which looks like this and then we provide the specific concrete implementation of that that we want to use so in this case we're using the employee service but we could swap this out with anything that satisfies this abstract class and our component here doesn't need to rely on the specific implementation details of this employee service it will use the implementation details of whatever is defined in the abstract service so this is a nice way to go about doing this but perhaps you've noticed a fatal flaw here we can do one of those fun things where you pause the video and see if you can figure out what is wrong with this approach so what is wrong here is that if we go to our product list page and we can see that again it's using that abstract list page service and the specific concrete implementation it's using is the product service but if we take a look at the product service we can see that it also implements all of that same setup logic that we were trying to get rid of we're trying to get rid of this duplication and right now we've just moved it out of our page classes and into two separate services it's in our product service and it's in our employee service as well so we're just going to move the problem somewhere else so now we're going to take this one step further to deal with that issue as well okay so now if we look at this second step of the composition approach you can still see that the product list page and the employee list page look exactly the same we're just providing that abstract service and we're using our specific implementations of that service what we have done instead is now if we look at the services again you can still see that they're implementing that abstract list page service but we're also extending a base list page service class and that's where all of our common logic is going to go and anything specific to this one service is going to live in here so if we take a look at the base list page service you can see that is where all of that common code is now living and when we're creating our service that we want to satisfy this abstract list page service we're just going to be extending this base class now obviously we are still using inheritance here we are just using it with our service instead of our component but the goal isn't to never use inheritance it's just to prefer composition where possible and at least personally i like this approach of using composition in our components to pull in what we need rather than extending a base component and passing things back up to the parent with super so that's it for this video let me know what you think of this approach i'm by no means saying this is the one and true way we should approach this situation i just think it's a nice pattern but there are probably ways this could be improved and maybe i'm even making some glaring mistakes with this approach so if you have any thoughts please do let me know in the comments so i hope you liked this video if you did please feel free to leave a like and subscribe and i will see you in the next one [Music] you
Info
Channel: Joshua Morony
Views: 24,501
Rating: undefined out of 5
Keywords: ionic, tutorial, tutorials, ionic tutorials, ionic framework, coding, coding tutorials, angular, angular tutorials, cordova, cordova tutorials, capacitor tutorials, mobile, mobile apps, apps, html5, ios, android, native, hybrid, pwa, web apps, progressive web applications, programming, ionic 5, react, stenciljs, stencil, performance, ui, ux, animations, screencast
Id: rcDsRyVhcxY
Channel Id: undefined
Length: 10min 15sec (615 seconds)
Published: Wed Jan 19 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.