Design Patterns and Modern C++

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
all right hi everyone I hope you can hear me and see my screen my name is Dmitry and today I want to talk a bit about design patterns which is a very kind of 90s topic something that we've kind of stopped discussing along the way and I think if you take 10 or 15 years back and you if you went to a job interview back then people would definitely ask you questions on design matters but now it's kind of somewhat forgotten so what I wanted to do is to give a few examples of why design patterns show up in our daily C++ programming life and how you can actually implement them and I wanted to start with something that I hear quite a lot from many different developer teams and that is the idea that a lot of companies have their own string classes and you might be wondering well why on earth would anyone won their own string class instead of std string well let me give you a very simple example of why you'd want something like that let's suppose I have a string with hello world something like this I'll put a few spaces in between just for the front of it now let's suppose for example that I want to have let's say I want to make the string lowercase and then I want to split it by word and then print the length of each word it's a very simple operation but unfortunately if you if we're talking about the standard library you don't really get this functionality at all the standard library doesn't provide you a way of making the string lowercase or splitting it by word or well it does give you the length in a kind of confusing way so typically if I wanted to do this just using the standard library stuff I couldn't I would have to use at least the boost string algorithms to get the lowercase and the split so it to do that to do what I want I would type something like the following I'll make the string lowercase oh I would use to lower copy of the string and then I would prepare a vector of where I would have these separate words and then I would call boost split which is another function from the blue string algorithms I would specify the parts to put the data into I would specify my lowercase string and then I would specify the delimiter that I want to split on and maybe some additional arguments as well so typically this is what it would look like if I wanted to do just using V standard forum and I would have each of the parts in my parts and I would maybe see out the length of the appropriate part like so so this is fine I mean it works we're going to see it run in a moment it's absolutely no problem the only problem with what I've just written is discoverability well there there is another problem here that I have three zeros in between so the length of hello is five the length of world is five and then I have a bunch of zeros because there is another argument here which happens to be optional and as a consequence if I want to get rid of a zeros I would have something like boost token compress on just to get rid of those extra zeros but it anyway the problem with all of this even though it does work and it works just fine is that ultimately it's non discoverable meaning that unless you know that there is a function call to lower copy unless you know that there is a function and these are global functions by the way called bizarre split you're not going to be able to even find out that these operations exist and certainly if you are coming from the Java world or net world you would expect the string class to have a split function you would absolutely require it and this is why we build adapters so an adapter is essentially just a way of getting the interface that you want instead of the interface that you're given so let's build a string adapter I'll have a class called string with a capital S and here I'm just going to essentially encapsulate an ordinary string so I'll have it in here and then I'll generate a constructor maybe to initialize the string like so and then of course what I can do is those api's that I've been using as global functions what I can do is I can take them into the adapter class so instead of having all of this which is okay to some extent I guess I could have them in here so if I want for example to lower copy I would have a capital string notice I am Capital strain my own string and I would have a function called to lower copy which would be constants here I would simply return a string constructed from boost to lower copy taking taking the string that we're encapsulating here and similarly for the split function if I want to split something and get a vector all these capital strings I would have something like the following I would have a vector of a string called split and I will have a con string delimiter maybe with a default value so I might have the empty space as the default value kind of makes sense and I think that's default in other programming languages here I would have a vector of lowercase string called parts I would call boost split split like so providing the parts providing the string to split on I would use boost is any of - actually it is any of like so with the delimiter and I would maybe also get rid of those empty token so I would use boost token compress on like so and then I would return a vector off capital string constructed from the vector of these parts so I would simply see parts that begin and parts dot and like so so essentially what I've done is I've taken these global functions these global api's and I've moved them into my adapter and now I can change it I can make it capital string here and then the operations can essentially be done one after another what is it saying here oh there is a typo apparently I don't think there's a type of delimiter is it is there really a type of rename - no I think I'm alright in here okay so essentially I now have this capital string and actually limit yeah limiter so let's let's do it this part way delimiter money okay no more complaints from the system obviously so now if I want to split the the appropriate part what I want to do is I can I can just write this as a single for loop so I can say for auto W let's say if it's a word in and then I can do the following I can do s dot and you'll notice that after the dot I get code completion so I get some information about the kind of student things that my particular string is capable of doing like turning the string lowercase and then splitting it on a wood and I can all do this in line and here I can see out W dot and now I want the length now one of the things you if you take like a developer from the street and you tell them that STD string has both a length and a size the weird thing about all of this is that it's it's confusing so the the STD string has a size and a length and if somebody if you take somebody who's not very familiar with C++ and you ask them what do you think these actually mean they would probably tell you something like the following they will tell you that length is the number of characters and size is the number of bytes that the string occupies which we know is not the case we know that these things are identical so in the process of constructing my adapter I can actually determine my own API for how I want to get length and certainly length is not a behavior yeah and having the name length I don't like this because I think that length like this implies that the string has some sort of behavior called length instead I prefer get length and this is a very simple implementation so I would do as dot length here for example and so I can actually help with this at this location get length and line okay so what have we done I mean we haven't really changed you know the structure of the universe we haven't delved into SDL to actually modify these things in actual fact the implementation of boosts global functions like split for example is a good example of kind of a non-intrusive design in the sense that you you don't break the open close principle which we'll talk about in a moment but essentially instead of jumping into the steal and get getting it this way what you end up doing is you end up kind of having these global add-ons the problem with the Global's is discoverability and we've solved that problem by building the adapter and as a result we can uh we can certainly run this and get the I get the same output as before but the key thing here is that it's usable meaning that somebody who is working with a string with a capital S would actually get the api's that they might expect like to lower copy for example right inside code completion that having that list after the dot is kind of crucial because it basically tells you everything that you need to know and it is impossible to provide I mean one of the ideas is to provide the code completion list for every global function which takes the string as a first argument so you might say well this this might work but in actual fact if you look at split in split the string isn't even the first argument it's the second argument not to mention the fact that there is a temporary being introduced here that you have to make a separate statement for and it's all a bit confusing and and so so the the approach here is you build an adapter which just just the things that you want and and certainly it's and there is some overhead to having all of these calls and not much there isn't much overhead but there's only a certain amount of overhead but the end result is that you get just the api's that you're looking for and this is why people actually build these sort of things so even despite the overhead we end up building lots of these adapters because the default API I'm set to say but the default API of SD string is somewhat lacking and this is why you end up using boost and that sort of stuff ok so so this this has been a very small example of how you know a design pattern occurs in the wild let's take a look at something else let's take a look at the Builder design pattern which is something that's used to essentially construct objects so if you think of a scenario where let's say you were building some sort of web server for example so you want to output HTML you can certainly go ahead and start out ting HTML just using an O string string for example so let's suppose I want a list of two words let's say hello and world so let's have these words and I'll have I'll have hello and I have world as well so I have these two words and I want to have them as part of an HTML list the the kind of simple approach is you just make an L string stream let's call it OSS you add the fact that it's you know an unordered list let's do a line break here and then for each of each of the words that you're given so Auto W in words you add something else to this list you might add a couple of spaces you might have the actual list item than the word itself then close the list item maybe two line break at the end and at some point you close out the whole thing and then you sort of see how to assess dot STR like so something to that effect I mean it works just fine until you actually want to build something more complicated and until you want to actually have this situation kind of manageable we're only getting the output that we want but it's it's kind of not very pretty shall we say so at some point you may end up actually building object-oriented structures for storing this entire thing so that it's it's kind of easy to build so you may end up with a some sort of structure like an HTML element for example so you would have an element which would have a name and you would have the text and you would have maybe a vector of children HTML element let's call them elements and you might also have some formatting information so you might have let's say the indentation size we'll use that in a moment so the HTML element you can certainly have a HTML element where the constructor does absolutely nothing but you can also have an HTML element where the constructor actually initializes let's say the name and the text so I'll use sealions functionality to Gen rate those and then of course at some point once you've built up this tree because it's essentially a tree because an element can have other elements to infinity what you need to do is you need to have some sort of out but you want to output this stuff as text and I will spare you the actual code for pretty printing this stuff because I'll just paste it here from the from the github repo so now we end up with an object-oriented structure and what this means is we can already start kind of building building it up in the sense that we might have a root element called an unordered list and in this case we can give it the name ul like so and absolutely no text and then for once again each would in the collection of words we can say you will dot and in this case its elements dot pushback and we can make an element which contains the while it's HTML element isn't it so you might have an HTML element of type Li list item which contains the word W and at some point you can certainly take ul and once again STR it so we haven't made a dedicated builder here but the what we have done is we've made everything object oriented so it's now more logical in a sense to actually construct this HTML but we can we can sort of take and here is the output by the way so you can see we're getting pretty much the same thing however we can make it even better by essentially having a dedicated dedicated component for building up building up these structures so if we want to build up a list we might as well put a an HTML builder now what this HTML builder is going to do is it might take the name of the root for example so I might have HTML builder which takes the root name and we might say assign the root name we're going to have an HTML element that we're actually building up so here it is element ah let's call it root so you make this builder and then we can have a function for actually adding the children and the function might be something like this so first of all I'll make it void so we'll have a function called add child and this function takes let's say the child name and the child text and all we have to do here is we we make a new HTML element and we added to the children of this element so essentially we make a HTML element E with child name and child text and then what we do is we say root dot elements dot and place back and sort of move the element over and that's pretty much it now a consequence of this as soon as I learn how to spell because I see that I've made a couple of errors here they're going to go away in just a moment but the consequence of all of this is that we can further improve this example so now we have a dedicated component for actually building stuff we have an HTML builder called builder and this builder might be building an unordered list and then when we want to actually add a couple of children I'm going to just instead of going over the list I'll just add the elements manually so you would have builder don't add child with the child name being Li list item and the text being hello and you do the same thing with the text for world and then of course once you're done building up the entire thing you want to once again print it out and in this case it would be a builder dot root something I got builded rooted STR and and it works in a similar fashion to what we've just had a couple of times already the difference is that we now have a dedicated component we can make an improvement and here is the output by the way same as before we can make a small improvement by making the builder fluid now a fluent interface fluent interface is when you can chain the calls which make up something when you can change the calls which make up an object so here instead of turning void I can return an HTML builder reference and I can simply return star this and the consequence of this is I can now delete this part and you can see that I can call builder dot add child and a child once again and again and if we had other functions in addition to a child different kind of build up functions they can all be strung together because each of these functions would return a reference to self a reference to the Builder itself now let's suppose that we want to have the Builder as the only way in which you can construct an object in this case what you would do is you typically take the Constructors and you just make them private first of all so you would make maybe a private section here just hire the Constructors and this way nobody can really make an HTML builder anymore you can see that there is a there are complaints here because HTML element is now private so obviously you need you need some sort of improvements to that in the sense that you you now need to have the you need to have a friend class HTML builder and by the way we need to forward declare HTML builder seeing how we are doing everything in a single file so I'll put HTML builder in here you'll see why in a moment because essentially what the situation we have right now is that you you cannot really construct the you can construct the HTML element any more app so the only way you can go is through the Builder and suddenly yes you can you can work through the Builder but there is another way you can sort of hint to the user that they're actually meant to call some sort of static build functions so here in the public section we can make the following we can make a static function which will return a unique PTR called HTML builder we'll make the function build build like so and it would take a root name and it would simply call the constructor of HTML builder so you return make unique of HTML builder root underscore name by the way to to get make unique I think you need something like C++ one why if you have 0x here it's not going to work on all systems so we return essentially an instance of the builder class right from the class that's being built up so the consequence of this is that we can now do the following so instead of making a builder like this what would happen typically is the following you would have the HTML elements itself so HTML element colon colon and then you would call build with the the argument of an unordered list and then you will do dash greater then and then uh to all those add child calls remember the add child calls return references so that's why there is a dot here you can have them return pointers instead and it would be a dash greater then now the question is well how do you output stuff because we certainly we still have this this builder route but there is another way of doing this kind of the icing on the cake and that is to simply return the route as an operator to HTML elements so essentially what I can say on the Builder itself is I can say whenever somebody asks you for an HTML element why don't you return one why don't you return route like so and the end result is that you can write the following you can write HTML element e.e equals and then do this entire call and this will actually be valid because after all these invocations remember this is a fluent interface it returns a reference to an HTML builder after all these invitations you would end up essentially constructing an HTML element and here what we can do is we can say he dot STR and hopefully this runs right fingers crossed so we should really be getting the same the same kind of stuff as before and here it is ok so this is an example of a fluent builder but many programming languages nowadays they go one step further they say oh by the way if you want to build HTML we'll give you a nice-looking dsl dsl like structure right inside the programming language now amazingly enough you can also get this kind of construct in c++ and i'll show you how in a moment this is something that is present in languages such as groovy so let's get rid of this and we're going to once again make some HTML but we're going to make HTML using initializer list of all things so once again I'm not going to bore you with the details of the implementation of the tag class that we're going to be using it's similar to what we had in the HTML element in the sense that we have the name the text we have a bunch of children I also have a bunch of attributes as a vector of pair of strings we have some pretty printing here and that's pretty much it let me close this out however the the key thing that we're going to construct here is a bunch of protected constructors protected there we go so essentially I'm not going to allow anybody to actually manufacture this tag because it's a top-level construct that we're going to specialize to inheritance but it is going to have a bunch of rather useful constructors so let's actually see if we can generate some of them I'll just jump in here generate a constructor so we'll have the name and the text as one of the constructors but the other constructor is going to be a bit tricky and no I don't want it public I want it protected specifically so the other constructor is going to take the name and the bunch of children so may as well write it myself construing name and Const vector a vector of tagged children and also initialize the name and initialize the children okay so we have these protected constructors the question is why do we why do we bother with all of this and the answer is that we're going to inherit from this tag so essentially if you're talking about HTML you have very well defined tags like a paragraph or an image so why not specify those explicitly and that's exactly what we're going to do so if I want a paragraph I can say that a paragraph inherits from a tag and then I will have an explicit constructor called P which takes just the text and by the way I should probably be using just the you know cogeneration stuff for it as you can see if I use cogeneration it actually asks me which constructor which base constructor I want to call and the answer is well at the moment I'll call the first one the only thing is that we don't really want to take name as an argument because we know that the name of a paragraph is P so I might as well remove this part and I just replace this with P because that's a predetermined kind of tag and similarly for the other constructor let's go and generate the constructor once again now you'll notice that in the base we have a vector of stuff however I can do a small trick here and we already know the name and but we do want to pass the children the only thing is we want to pass the children as an initializer list because well that's the beauty of modern c++ initialize it lists are going to give us that magic that you'll see in just a moment so what I'm going to have here instead is I'll make an initialize a list of tags called children and then for the initialization for calling the base class I know that the name is paragraph so that's P and we leave the children as is so there's a bit of magic happening here because you're taking and initialize a list and you passing it into something which is expecting a vector and this is absolutely fine so we have a paragraph let me just build up another construct let's build an image so IMG is going to be a tag as well and in this case we'll have a constructor which takes just a URL so I'll use the I'll use the code generation even though in this particular case it's it's not so useful I'm afraid but we'll we'll still call the the base as before I'm going to replace the actual constructor arguments here because all I want for an image is the URL of that image so here is the URL now the tag we know the tag is IMG and the image contains absolutely no text whatsoever it does have an attribute though so here in the constructor I can say that attributes attributes dot and place back and I'm going to add an attribute let's do make pair so the SRC of the image is equal to the URL that we provide okay so what just happened what is the what is the why did we build all of this essentially we build all of this to construct a strongly typed DSL specifically for HTML and to actually use this we can use this as follows so I can for example see out and I can see out a paragraph and notice the the curly braces here so I can make a paragraph which contains an image which has the URL of some site a PNG for example so this what I've written just now and line is completely valid C++ amazingly enough so this may look like a DSL but it's it's really not it's just using initializer lists to essentially construct these these kinds of notations out of the fact that we've taken the base class and we specialize it so that you can either take a text or you can take and initialize a list of attack so a paragraph can contain an image and that image becomes the one and only element of this argument so a very small trick which once again if you are building some sort of structured data this kind of groovy style builder can actually help you define these nice little dsl x' so just a just a small syntactic trick that you can do in c++ sticking with this idea of builder as though i do want to show something a bit more complicated and that is the idea of multiple builders working to build a single object that's going to be a bit more complicated and we're going to have more more classes and more constructs here so bear with me as I go through this and try to construct this one so essentially the idea is that let's let's actually make a new class so I'll make a C++ class let's call it person for example so let's have a person in here now the person class let's suppose that there are two distinct aspects of person that we want to build up so we're going to build up some address information that a person has so you you might have let's say street address postcode and city but we also have some information regarding employment so a person might have a company name they might have a position they might have annual income let's put a handy fault value in here as well so uh you might say well why don't we just make a single Builder which kind of builds everything but an actual fact we can be even smarter about this whole thing in a sense that we can build multiple builders in actual fact and and to do this once again what I'm going to do is I'm going to hide the constructor so how to construct to make it private but I will have some public stuff now in terms of the public stuff which I'm going to expose I'm going to expose a builder so let's have a static static function called create which will return a person builder person builder create sorry there should be no no round brackets here so uh the question is well what is this person builder what given that we're going to have several builders what does person builder actually look like so for this we're going to add yet another class and this time around I'm not sure we actually need to have the well let show we need the the CPP for let's have let's have both the header and the CPP so we'll have person builder now person builder is not just an ordinary builder for passing instead it's a it's a is something that exposes different builder facets and different builder facets are essentially aspects of the overall builder by the way I see that some of the files here are grayed out let me just briefly add those to the to the C make list so that's person builder uh person builder dot HPP as well okay so that's gonna is going to take a while to actually spool but in meanwhile let's let's jump into person builder so person builder is this wonderful class which instead of building a person what it does is it gives us different sub builders which can build up the different person information like for example the the address information or the employment information separately there are two different aspects to this person builder thing so essentially it's it is going to be rather complicated so we're going to have the person that we're actually building up that's that's that's you know that's that's alright that's what we're building that's what we're doing but in addition to that it's going to have some protected members and this is where things might turn a bit weird by the way if you're wondering why some of the kind of code assistance that's supposed to be showing up as though showing up it's because we're in the process of reloading the see make lists and getting all those extra extra files in here so essentially the faceted builder is a bit sophisticated because in addition to the object bill being built up in the protected section it also has a reference to this person being built up and it also has an explicit constructor in specific constructor person builder which actually takes a reference to a person and initializes that preference and you might think that this is somehow redundant but in actual fact it is necessary for our little demonstration and it has some public members finally well we're going to have some public elements and specifically we're going to have a default constructor so have a person builder which initializes the person reference to the person that's being built up again a bit unusual that and it will also expose those builder facets so remember I'll go and by the way yes we we do need the we do need percentage here but I'll go in all of these in all of these cases is to provide functionality for building up the address information and provide functionality for building up the information regarding a person's employment so we'll have two builders here we'll have a person best builder and the function is going to be called lives and will have a person job builder and the function will be called works like so right I do need to have a couple of fixes here you can see that there are there's a certain number of complaints because essentially we're trying to get into person whereas person is kind of private and wouldn't really allow itself to to kind of doesn't allow other classes to get into it so we need to fix that first of all and this is done using friend classes so here down below I'll have friend class person a person builder person builder friend class person address builder and friend class person job builder that's what we're going to call the the Builder which builds up the job part so in terms of the forward declarations I think we need to forward declare the person builder here and that's that's pretty much it I think certainly yes we do need the string and I'll just get using namespace STD in here as well so that solves all the problem in this case obviously we haven't got an implementation for create so that is something that I'm going to generate right now and we'll see what's going on in terms of the the actual creation of the person builder so bear with me a person builder right so the the person builder create is rather boring we just make a new class and we return that there is absolutely nothing of interest that's going on here however the interesting part happens in the person builder dot cpp because essentially if we look at lives and works you'll see that we're referring some to some classes which do not exist that kind of explains the error and by the way let me generate those because i'm getting really tired of all these red all this red code so we'll have a person address builder you may as well have it header only so let's have person address builder and let's also have once again header only person oops person job builder right so so these two classes are going to be building up the address information and the e job information as well and the question is well what do they look like because it's all getting it's not getting reasonably complicated so let's start with the person job builder and now person job well there actually happens to inherit from person builder and this is the piece of magic so the sub builder happens to inherit from the Builder which exposes it which means it has access to the object that's actually being built up and it also explains why we made all those crazy constructors so let me type deaf person job builder alt are deaf the passenger builder itself because I want to have a fluent interface so we'll have a constructor I think we actually we actually need to add it to see make lists of course so let me do that so that's person job builder and person address builder so let's have that now we need a constructor which actually takes a person reference and initializes exactly that so for that I'll just write this myself for now given that the see make lists is file is reloading so we have a person job builder which takes a person reference called person and then it calls the base class with this reference and that's why we have that protector constructor so that whenever you make a sub builder you actually referring to that one and same object that you're building up throughout the entire thing so the constructor is here and now we can make a fluent interface and yes this does require and include off I think person builder don't HTTP that's that's pretty much all that we need we are going to include this later on but yet the errors are gone so essentially if you want to say that a person works at a particular company you make a fluent interface so that's where the self and percent comes from and you say at and then you you take the company name so you take the company name you say person dot company name equals company name and then you return star this then star this so you make this a fluid interface and same goes for the other parts of your employment information that you're trying to build up so if you want to say that the person works at a particular position you say as a you specify a position here and you say person dot the dot position equals position and return stylists again and if you want to specify the earning you say earning in annual income maybe income and you once again you say person dot annual income income equals annual income and you return start this okay so that's the job builder done and we also have the address builder that's for building the address information so it's also fairly obvious I will spare you the actual details and simply paste the the code from the from the repository I think we also need a string for this one do we need string for the other one as well we might I think we might but then again I'm not so sure okay anyways we have we do need a reference here I think or maybe not it doesn't really matter so so anyways we now have two builders which build up a person and they are exposed through these they're exposed through the person builder which essentially gives out whichever sub builder you are actually interested in so that might be a sub builder for the the address or for the job so I I'm going to forward declare those as well so I'll have person address builder and also person job builder like so so essentially when you kind of interact with this you interact with these function functions called lifts and works and yes these are some redundant round brackets here so help us an address builder and person job builder they they'll turn they'll turn green at some point now let's talk about how this this entire thing is actually used because we want to help we want to construct a person at some point so how do we do it let's go into our main so essentially the idea is that we want to write something I can follow first of all I want to say person P equals and yes that requires a header person colon colon create so the create call here is what I want for the the creation of the Builder so as you go create you get your builder and you can start calling things on the Builder meaning that if I want to specify the information about where a person lives I can say don't lives lives like so and and then I can say dot at and specify where the individual actually is because you remember at the end of create what you get is you get a reference to a person builder let me open that up and person builder has functions called lives and works so we get those and if I kind of complete the picture so this big so that you get the the feel for what we've been trying to achieve it would look something like the following so essentially you would have the call to create and then you would have the sub builders I suppose I can make them a bit prettier but by kind of moving moving things around and having them kind of aligned like this but the end result I'm going to try compiling it I hope I get older I got all the headers in in the right order so this beep the let's see what we get here so a person builders and all of them oh yes the one thing we didn't do is we didn't do the operator remember this this function for for making the the converting operator so that's that's kind of the icing on the cake so to speak for for our person builder implementation in the sense that somewhere here you can say operator person and you you may as well move out the the person that that we've been working on Oh like so so this should be okay I think and even if it's not the demo that's up on Han github is perfectly fine I won't dwell on this let's see what form what are we getting here person builder is not a member of person okay so this is something that should probably go into a person builder dot CPP so somewhere in here and let me see if I if I need anything else in in this because I think I think I need plenty of includes I think I need the actually the one thing that that you might want is a hold on did we all we hold on yeah this guy at work yet because we need to implement lives and works and this is where certainly some of the magic happens because these implementations what they do let me just paste them in here what they do is they expose the different builder facets so they expose the person addressed builder and they expose the person job builder initialized with the person that we're kind of referring to in here so uh the the consequence let me just jump into main and I'll explain what's what what's kind of happening here the consequences that lives and works essentially they let you jump from one build it to another and therefore thereby you can you can initialize the address for example and at any point in time during this flew into invocation you can jump to the the job builder and then continue working with the job builder so that's the point of the kind of multi faceted multi faceted builders right now the final thing I want to show seeing how time is short and we probably want one half time to cover the specification pattern is the maybe mode which is another interesting kind of construct so I'll get rid of I'll get rid of some of the things that we've built here and you can you can download the you can download the actual sources from github if you want to see how the entire thing works and I'll just sort of jump ahead and chill show you the the maybe implementation so essentially C++ is not a it's not a functional programming language however the cool thing about it is that you do have functional plurals you do have things like STD function and as a consequence of that you do have some of the capabilities for building monads which are design patterns in functional programming so let me give you a very small and very contrived example of the maybe monad I'm not going to use the classic notation the classic terminology but I am going to kind of show you how some of the things are solved in the functional world so let's imagine that we have a struct for a plus and then that person may or may not have an address so address pointer address equals now PTR I'm deliberately using pointers here yeah you might be using something else like smart pointers or references or something to that effect now let's suppose that this address that I'm defining also has a house name so if you're living in an ordinary house you might have just a street name and number but if you're a rock star and you bought yourself a castle that castle probably has a name but it might not you might not have one so that's an L PTR once again now the problem is what if I want to write a function which actually prints the house name so given a person I want to print their house name I would write something like print house name which takes a person pointer P and then if I want to do this correctly I have to make all these null checks so I have to say if B is not equal to null PTR and P address is not equal to null PTR and P address house name is not equal to null PTR then and only then can I actually print out the address so then I can do P house name can do it like this and light so the maybe monad essentially tries to encapsulate the very idea of checking for the presence or absence of something in this case the presence or absence of a value because you might don't have a value might just have an L PTR instead so the question is how can we encapsulate this so that we don't do these checks ourselves and the maybe monad is one of the ways that you can actually do this so let me show you how you can construct one essentially what we do is we'll make a template class so let's make a template type name T struct ha maybe and this is something that we're going to build up so let me put this in here now that maybe monad itself is just something which keeps a context of where we are in the process of drilling down into person because what's happening as we get into person then into addressed and into house name is the process of drilling down into an object-oriented structure and the consequence of that is that we have a context we have a location where we are at the moment so here I can specify T star as the context that we're in T is a template argument so it can be virtually anything now what I want to do is I want to be able to construct this object so I want to be able to construct an instance of maybe using the context just initializing the context to the variable context context like so nothing particularly magical happening here now if I want to make a maybe out of P I cannot simply write something like maybe M of P because type inferencing unfortunately doesn't work yet on the maybe I'm not going to be able to compile it so what happens typically what we do quite often is we make these functions which actually help us get that type inference so I'm going to copy the actual declaration here and just forward declare it like so and then I'll have a template phone which template type mt so I'll have a function which returns a maybe of T and is called maybe with a small M which takes the context and simply returns a maybe of T with the context now why did I just do this why did I waste so much of your time and the reason I did this is that so I could write something like the following order Z equals maybe off P so now I can write maybe of P without having to specify any template arguments in here but all I've done is made and maybe and I now want to drill into the object I want to drill into the address and then into house name and only printed if it's not know so how can I do this well one of the things I can do here up above is I can define a function called width which is going to be template type name T func so notice that the type argument here is a function is not just a variable so we'll have a function that I'll have Auto return type not no idea why it's indenting like this order and it's call it with so we're going to take this function as the evaluator and here we'll have all the fun stuff so essentially we may or may not have a context which is the NLL state if the context is not which means we cannot really drill into a structure at all we're not allowed to do it but if the context is okay we can call the evaluator function on the context and drill into whatever structure we're investigating so if the context is not equal to null PTR then what I'm returning is a maybe of the evaluator function on the context otherwise I'm just returning now PTR that's all that's happening here and as a consequence we can jump into our print house name thing and we can do a couple of invocation so if I want the address I will say the following I would say with and here I take a function so I may as well do a lambda here so I'll have a lambda which captures nothing it takes some argument X in this case say person pointer and I return X - greater than address you'll notice that there is no there is no help here there is no code completion at this point it's a bit difficult for the system to figure out what's going on and I can repeat the process by drilling into the house name because I've now changed the context to being inside the address and I can get the house name and finally if I have the house name or if I'm in a null state I want to try and print out what the house name actually is so for this let's make another function let's have a template type named func auto let's call this function do which also takes 80 func action so it's not an evaluator it doesn't operate upon the context it just does something so as long as the context is not no PTR I can call this action on the context and then I commit to and star this we don't change the context here we just stay as we were in this net same maybe so that's let's have it as a func here okay so the final piece of the puzzle is that at this point we can do it do once again taking a lambda which auto X and here X would either be well here X assuming that we invoke this X would be the name of the house so we can see out star X and ly okay so we've constructed the motor the question is how can we actually use this so a typical example is let's suppose I have just a person P and I call print house name providing a pointer to P what would happen is the context would originally be set to the pointer to a person which is valid however as we go into with what would happen is we would check the context against no PTR and because it's no PTR the rest of the entire invocation chain the rest of this whole thing will be a know nothing absolutely nothing will happen at this point whereas if I continue to building a person so for example I will say I'll state the address and also specify the the house name and now be sure to delete them later on them we are actually going to print this out we're actually going to get the house because throughout the entire invocation chain we'll drill first of all into a dress that will drill into house name and those things are not null at any point and as a result this comparison would not know will always succeed such that we'll always call the drilling in function which is provided as a lamp so let me actually try to compile this I hope this this works and gives us the required output array amazingly enough we get the output we get my Picasso and if you try to step through this code you will see that the the process of drilling down happens inside the lambdas so essentially we set the context to a person and then this lamp that sets the x2 pointer to a person and provided that it's not know we get the address and we said that is the context then we get the house name with some others the context and because the context is not know here whatever this lambda actually does does in fact get involved so essentially this implementation of the maybe monad has encapsulated the very idea of drilling into some complicated structure and the this kind of implementation of course is not limited to checking for now I've encapsulated the idea of the presence or absence of something by a null PPR but you can use a boost optional or STD optional instead or you can use you know it's it's amenable to using shared pointers or whatever so you can adapt this approach to actually work for you so I think this is going to be the last thing that I'm going to mention today let me just take a look at the comments here briefly I'll try to answer most of the comments in the blog post that we'll do together with the together with the recording but essentially let's see some of these wondering where I'm pasting this from actually pasting this from the github repo and and just in case you you forgot here is the address address so it's github.com nestor design patterns webinar that's where you can find all the source code code for this entire web we are including the specification pattern which I simply did not have time to talk about and and there's going to be plenty more examples later on in there as I kind of build up on this so in closing what I want to say is that I have a bunch of design patterns in C++ courses up on plural side plus I'm working on a book called a modern design patterns modern C++ I'll let everyone know as soon as that's finished it's going to take some time and I thank you very much for joining this webinar and hope to see you again soon
Info
Channel: JetBrainsTV
Views: 173,218
Rating: 4.8236804 out of 5
Keywords: JetBrains, CPP, C++, Design Patterns, software development, software developer, programming, CLion, ReSharper C++, Modern C++, webinar
Id: j9arNRRoPe8
Channel Id: undefined
Length: 56min 31sec (3391 seconds)
Published: Wed May 25 2016
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.