How To Reduce Coupling With Facade | Design Pattern Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
if you want to provide a simple interface that controls a complex system the facade design pattern is a great choice if you do it right but how does it work and what are the limitations one limitation is that if you suggest using the pattern to someone that doesn't know it you sound like a snob facade facade other than that it's great if you really want to come off as a snob you should watch my free workshop on code diagnosis ion.com diagnosis to get access if you follow the three Factor framework that I show you in a workshop you'll be able to completely demolish any piece of code can you please increase the font size in your IDE it's too small to read from the high horse that I'm sitting on anyway iron dot gold slash diagnosis to get access for free other developers are going to love you really I'm going to be using an Internet of Things example here so this is a simple application that allows me to create Internet of Things smart devices when I run this it opens an application it has two buttons I have a speaker off button and when I click that then it switches to speaker on so I can use this to power on or off a speaker you see it logs some messages like what speaker I'm toggling connecting to the IP address sending some data etc etc and there's a status update button when I click this it's going to retrieve status information from each of the devices that are connected to this application now this is not a real application all of this stuff I just made up so there's no real smart devices here but it's just to show you as an example so it uses TK enter to create this user interface and you see that I rely on an iot package that contains things like devices Services sending messages connecting to network etc etc so this is the file structure you see we have these three folders here and there are things that contain devices like the smart speaker that I used in the example but there's a couple of other ones as well and then there is a service that manages all these different devices we have a message type that has a sender receiver some content messages are sent over this network in a base 64 format all this stuff is not really important it's just the idea that we have some complexity in the example and then there's also a network connection object which has connecting disconnecting that's a host and if you look at the main file though which contains the GUI specification as well as all this interaction with the Internet of Things devices fake devices then you see we have in the initializer we create a service then we create the smart speaker then we create the user interface which is pretty simple it's just a couple of buttons and the status label that contains status information then we have a toggle method that logs some info so this toggles the speaker power and then what it does is well it changes the text of the button but then it also creates a connection to the smart speaker by getting the device first retrieving the connection info creating the connection object then constructing a message and then sending the message over the connection as v64 string and then it logs against something that we're done similarly we have display status that also goes through the devices in the service and then adds status information and then prints that in the interface and then it logs some extra info as well and then there's a main function that simply creates a smart app instance and starts the main Loop and there's some logging initialization there's several problems with how this is being implemented one is that the GUI needs to know lots of implementation details about the Internet of Things service you know needs to know that there's a service that it needs to create a smart speaker device it needs to know all kinds of low level connection information and that's not great another issue is that currently everything is in one big class that's responsible for both GUI things and for business logic things and that's also not really nice the class has low cohesion it tries to do too many things at the same time so it's helpful to split this up a bit which I'm also going to do in this video but most importantly if you want to decouple the low level things like Internet of Things services and connection objects from your actual application then the facile pattern is a really nice way to do that the facade design pattern helps by introducing an object that sits between your low level system and your application code the object defines a simplified interface to that lower level system so that your code is no longer coupled to low level things facade often hides some Concepts and simplifies others here's a class diagram that illustrates the pattern the facade hides the various classes to the clients and the client uses the much simplified interface of the facade in The Internet of Things example we can use facade to decouple the GUI from the low-level Internet of Things system however there's a problem at the moment the GUI class basically contains everything which means it has low cohesion it has way too many different responsibilities it's better to let the GUI focus on user interface things and move the logic somewhere else so let's start with improving that but before I do if you enjoyed the video so far give it a like it's going to help other people find my content which brings me closer to becoming an evil software development Overlord on YouTube you didn't hear that last part the first thing that I'm going to do is split the GUI code from the business logic code and the way to do that is by introducing something called a controller and what I'm actually implementing then is the architectural design pattern called model view controller model stands for data view stands for the GUI and controller stands for the business logic now in this example we don't really need a model because we don't really have any data so technically speaking you could consider the whole internet of things connection layer the data because that does store some status information about those objects but I'm going to concentrate on splitting the view and the controller here you can decide to use a purely object-oriented approach here and have to control B an object of a particular class but what I'm going to do in this case is simply Define two functions one to handle powering the speaker and one to handle retrieving status information so the first thing that I'm going to do is instead of putting everything in one main file I'm going to create a main file and a GUI file so I'm going to rename this to gui.pi because it contains already most of the GUI stuff but then I'm going to add another file called main.pi and then what I'm going to do is I'm going to take this part told main part and I'm going to put it in the main file like so and now of course I also need some imports like logging so also need to put that here and of course I'm going to need to import the smart app so that's automatically imported like so and then we have our basic main file and now I can remove this from this file like so and I still need all of the Imports that I have here so that's already something we have GUI and we have a main file now the next thing that I want to do is split out the business logic and the business logic that's basically the initialization code here it's the toggle behavior all this low level stuff that we have here and finally it's the displaying status information here especially the part where we retrieve that information from the internet of things servers basically what I want to achieve is that I remove these low level imports from my GUI object so that the GUI is not concerned with that anymore so let's create a new file here called iot controller dot Pi like so and that's why we're going to put the controller functions so what I'll do to get started is take these two methods and I'm going to copy them and then I'm going to refactor them so that they do something slightly different so let me de-indent this code like so and now of course I'm going to need some imports like logging now let's think about how we want to structure these controller functions so one thing is that they're going to need access to the internet of things servers and of course it's no longer part of an object so what we can do is instead pass it as an argument to each of these functions so instead of calling this toggle let's call this power speaker and we're going to provide it with a surface which is an Internet of Things surface object I need to type that correctly of course and then let's also import that there we go now instead of using self.service I'm simply going to use surface what you also need is the connection object and apparently there are lots of different connection objects but I want the one from Network dot connection like so I'm going to need a couple of other things as well like the ID of the speaker so let's also add that as an argument and that's a string and now instead of self.speaker ID I'm simply referring to the argument and then I can remove those parts here like so we also need the message class so from message dot helper import message and I'm using MSG it's a bit shorter as non-liers here so then this is what we get there's also still some GUI stuff here in power speaker like this for example so this we need to remove here because that still belongs in the GUI so I'm simply going to remove that also we don't have speaker on because that's an instance variable of the GUI so what we can do is pass another argument here which is whether we want to power the speaker on or off then this we can delete and what we can do then is construct the message before so that we can also log it so here I'm going to define the message which is switch on if on else switch off and then I can create a login message here for example Sending message to speaker and then I'm getting the speaker ID and the status is going to be message like so let's have a point at the end so on this stays the same we still have a speaker IP and a speaker port and we use the service to get the device we create a connection and then we construct the message and for that we need the server speaker ID and then we need the actual message but we already defined that at the top like so then finally we connect and send the message and login info here we can also change that a bit to message sense speaker and then we're going to print the message once more like so stats are power speaker function let's also refactor this function and let's call that get status because we're not displaying here that's what we're doing in the GUI but we're simply getting the status and this is going to return a string so we still have the logging info and then we're going to construct the status string for each of the devices so again here we also need access to the surface so instead of self we're going to pass here the surface which is an Internet of Things service instance and then I'm going to remove the self here so we'll log in the status and then this part updating the label that's part of what the GUI is supposed to do but then in the end we're going to return the status like so so this is our business logic we've put that now in this single file which is really nice so how do we connect this to the GUI well one thing you can do is that the GUI actually gets references to these functions that attempt calls whenever you press a button almost like callback functions actually so let's go back to our Google class and then we have the smart app class so the initializer we're going to now add a couple of arguments here and the first thing that we'll add is a power speaker function so this is going to power the speaker and that's going to be a callable and we want that to be very simple it just should get a Boolean value whether we want to power the speaker on or off and then it's not going to return anything now that's not what our current power speaker function looks like because it expects extra information I'll just show you how to deal with this in a minute so another thing we're going to need is the get status function and that's also callable that can get anything and that's going to return a string also here doesn't match the Control Function that we have but we're going to fix that in a minute so then what we'll do is store these things so self dot power speaker function equals the value of the argument and self dot get status function as well so now we have access to this in the rest of the code this part that's initialization code shouldn't be in the GUI so I'm going to remove this and I'm going to put this in the main file so this is where we'll now create the Internet of Things service and that's not self we're going to turn that into a local variable and same here so we have a speaker ID that we register and then here of course we need access to these things so we're going to import them like so let me save this I'll continue working in the main file in a minute let's first fix the GUI so we have stored these functions create UI we don't have to change anything but now in the toggle method we need to change things because of course this we're not going to do here anymore so first let me remove the logging information because already that we're not going to do this we still need to do because we still want to switch the speaker status here and keep track of it in the GUI because we need to display the right text on the bottom so that's what we're doing here you can probably avoid using this variable by the way if you just read the text from the bottom but I think that's really clean I think this works a bit better so these things we still need to do here but what we can do now is call the power speaker function and simply pass it the Boolean variable which is self.speaker oh and then the rest we can simply delete because our controller is going to handle that which we still need to connect to the GUI display status very similar so we're not going to do logging anymore but what we're going to do is status we're going to use self dot get status function so now we have the status and then we can simply display the status on the label and logging we also no longer do here so that turns display status into A2 line method so this is good our GUI is now a lot more Compact and there's also a couple of imports that we can now remove as you can see logging no longer needed and we're also no longer dependent on any of these low-level things that we depended on before so let me just remove all of that and that considerably simplifies the GUI class now the only thing we need to do still is make the connection here so smart app is going to expect two functions from us but the controller functions are not exactly what we want them to be because they expect the service and the speaker ID and the GUI can't deal with that because it doesn't know about those things a nice thing that we can do is use partial function applications to create functions that match what the GUI expects for example the power speaker function foreign tools to create a new version of our original controller function so that's power speaker which we import from the controller file but then and this is what parcel does it allows you to supply arguments to function that creates some new functions where those arguments are already applied we can apply the arguments surface which is going to be our surface that we defined in the main function right here and we're going to supply the speaker ID and this is nice now because now power speaker function is a new function that only expects a Boolean because the other two arguments have already been applied so this is exactly what the GUI needs we can do the same thing for the get status function so that's also a partial application of get status and here we simply Supply the surface like so so those are the two functions that we're going to need and now we can simply pass them to the application so we have power speaker function and we have get status function like so let's run this code and see what's happening so again it has exactly the same behavior but now we've split up the code a bit more status update also still works as expected so this already helps a lot instead of one file we now have three files the main file which is relatively short that creates the things we have the GUI which is now pretty separate from the rest of the code it only knows about controller functions that it's going to call like power speaker and get status and we have the controller that defines what actually needs to happen so it does help but it still doesn't solve all of the problems because the main function still needs to know implementation details of the internet or think system it needs to know that there's a smart speaker device that it needs to register that there's a service etc etc and the controller that's of course still the same problem we simply moved our low level things to another layer so if let's say we want to extend this application later in the future by adding more facilities like maybe we want to add extra devices that want to control from the interface well then we need to copy a lot of this low level code and we have to deal with that ourselves in the controller functions which is not ideal and you can create helper functions but it's still going to be coupled to the low level Internet of Things system with the facade pattern you create a layer that hides a lot of these things to the rest of the application which is why the pattern is so useful it really provides a strong way of decoupling your code so let's use the facade pattern to provide a layer so that's the GUI and the controller functions don't need to know anything about low level internet of things things internet or things things that's weird okay so what I'm going to do is create a new file Internet of Things facade and this is going to provide the layer between the GUI and the low level Internet of Things surface so I am going to use class for this let's call that iot facade that's going to provide the separation and what that has is an initializer and here in the initializer we're going to do the things that we did in the main file now if we want to keep this kind of clean we should probably still create the surface in the main file so that if we want to test the facade we don't have to patch the surface if you want to completely separate this you could still create a separate function that creates a service and then a facade object and then passes the surface to it but for Simplicity I'm not going to do this here this is simply going to get a Internet of Things surface that of course we need to import here and then I'm going to store that as an instance variable like so and now what we do is we take the initialization code here like creating the smart speaker and registering it as a device on the surface and do that in the facade so that we don't need to do it in the main function anymore so that's this part so I'm copying this over so here I'm creating a smart speaker device that I'm also going to import here and then I have the speaker ID that I'm going to need to store as an instance variable like so then the second thing that I'm going to do is to move a lot of The Internet of Things low level stuff from the controller to the facade so the controller doesn't have to deal with that anymore so again let me just copy these two functions because they contain a lot of that detail and then move it here and then I'm going to refactor it so I'm assuming that the logging part is not something we want to do here but that's still something we will do in the controller because this is just the interface to The Internet of Things layer so I'm going to remove the logging information here so now we have a power speaker and that's going to get that's what the method so in itself obviously and these things are not needed because they're part of the class and then this again becomes self-taught service self dot speaker ID and we're going to create a connection which again I need to import from Network dot connection there we go and also the message helper obviously like so and then this all Remains the Same get status doesn't get a service but uses self-taught service and that's all it does so this is basically the interface to the whole internet of things system and as you can see the facade now provides a simplified interface to this whole layer by having a power speaker method and having a get status method it's not the most generic way of setting up a facade maybe you want to have something that supports generic message sending if you want to support lots of different devices it's not really the goal of the video today just want to keep it simple now the controller becomes also a lot simpler of course because it's only responsible now for logging things and then I can simply call the facade methods so what we can change now is that power speaker doesn't get service and speaker IDs anymore because it is not concerned with that but it gets a facade object there we go and then let's also change the logging info powering speaker and then it prints the on off status like so and then what it's going to do it's very simple it's simply going to call iot.power speaker and it's going to pass the on value and then this we can delete and the only thing we do is we keep the logging messages and here we simply write message sent to speaker because we're logging here on a higher level so the f is also no longer needed so that's power speaker then get status is very similar we don't get an internet or thing service we get the facade and then we're going to use dot get status from the facade we log the info and we return the result so that's get status now you could decide to move all of this actually directly to the GUI but I'm keeping it separate here in the controller function because then maybe you want to add other things like other types of logging emailing whatever and then that part is separate from the lower level Internet of Things surface so how do we change the main Farm now well we still need to create the internet of things servers because the facade expects that but then as Next Step we're going to create the facade like so and we need to pass it the surface there we go and now we don't need to create a smart speaker anymore we don't need to register the device because the facade takes care of that and it also means that coupling the GUI with controller function now becomes much simpler because the power speaker function that expects Now The Internet of Things facade like so and get status very similar so then this is what we get so we have to facade that hides lower level Concepts from our application like smart speaker device and network connections and things like that we have the controller that separates the behavior which is logging and controlling The Internet of Things device from the GUI and the GUI simply gets controller functions so now things are nice and cleanly separated and you'll see in main function if we scroll up that well not these low-level things we're not going to need them anymore because we simply rely on the controller and facade again the service is still here because we are patching everything up in the main function but you can also decide to split that out if you want to really keep it separate so let's run this one more time and you see we get exactly the same effect the same results as we had before so as you can see facade works well with an architectural pattern like model view controller if you want to learn more about software architecture in general and the model fuel controller pattern check about this video where I show you an example of how to set that up so there's a few interesting things to note first since I'm already using a controller I didn't need to update the GUI class at all since that relies on the controller only that shows us one of the advantages of splitting the view from the model and the controller if something changes it'll probably be less work to update your code second the only place where I'm still referring to low level internal things code is in facade class and in the main file to patch things up the rest of the application is decoupled the main function creates the facile object and uses partial function application to create the controller functions an alternative thing you can do is create a controller object that gets a facade in its initializer and then the controller functions will be methods of that class it achieves the same thing I slightly prefer to do it with partial since you don't need an additional object and you have a bit more flexibility and that you can decide to move some of the controller functions to different files which you can easily do with class if you want to completely decouple your application code from lower level internal things code you could decide to let the facade create the Internet of Things service objects you can then also remove the dependency from the main main file however this would make testing the facade a bit harder because you would have to patch the server's object one thing you could do is create a separate helper function that creates The Internet of Things surface object for you and then also creates the facade then at least you've still separated creation from use but you don't have to worry about that in the main file when you want to extend the code in the future to have more functionalities you might have to extend the facade as well to support it this is one of the disadvantages of facade since it's a simplified interface to the lower level system it may need to be modified so that new features can be supported it's always a balance however the interaction with low level system is centralized in facade making this a much easier job than when everything is coupled like in the original version of the code I hope you enjoyed this video as you've seen the facade is really helpful in reducing coupling and this helps your code become a lot easier to manage if you'd like to see more ways to reduce coupling in your code check out this video next for watching and take care
Info
Channel: ArjanCodes
Views: 29,067
Rating: undefined out of 5
Keywords: facade pattern tutorial, facade design pattern, facade design pattern example, facade design pattern tutorial, facade pattern, python facade, python pattern, design pattern, design patterns, design pattern tutorial, facade pattern explained, design patterns in software engineering, python pattern programs, python facade design pattern example, python facade design pattern, design patterns tutorial python, internet of things, iot internet of things, iot projects
Id: jjoLejA4iAE
Channel Id: undefined
Length: 28min 29sec (1709 seconds)
Published: Fri Nov 18 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.