Object Oriented Programming (OOP) Tutorial for Beginners

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello i'm bill wagner i'm james sturdivant and we're here to talk to you about object oriented practices i'm a long time software developer i've spent a lot of time working the dot-net space primarily in c sharp i'm the author of effective c-sharp more effective c-sharp i work with the.net foundation advisory council and i'm here to help beginning and intermediate developers grow those skills in object oriented practices i'm here with james sturdivant i'm james sturdivant i'm a technical evangelist with microsoft and i work with students startups and developers to get them exposure to the microsoft platform and i do that through working building code applications and then talking about them i'm also a mcsd and web applications and uh i was a lead developer and mentor for many companies in my previous consulting business and i'm also a community leader and i support developer events and programs and you can check me out at jamesterdevont.com what we're going to do over the next several hours is we're going to talk about a variety of object-oriented practices this course is really designed for people who've had an introduction to these concepts but aren't necessarily sure exactly how they all fit in together so there's seven different main topics that we'll be covering things like encapsulation and inheritance how to work with interfaces and abstract classes then we'll get to some of the other areas like generics delegates events and lambdas we're going to talk about functional programming as it contrasts with object-oriented techniques and how the languages and tools that we work with also support those idioms and then finally we'll leave you with a set of review exercises that you can do on your own to help reinforce the concepts that we'll be talking about the course format that we're going to work on involves james and i talking about some of these different principles we're going to look through a lot of code in terms of showing examples of how they've been used effectively and then we're going to leave you with some work to do on your own to try to really own those concepts and get some practice with those so the target audience that we're shooting for here we're really looking for that beginning to intermediate developer the people that james has been helping in a lot of his work and the people that have been reading my books and working with some of these tools over the years we think a few months to maybe a year two years of experience that's kind of the sweet spot for this material you know if you've been developing a.net for five to seven years i think you're honestly going to find this one a little bit introductory if you've just barely begun programming you may find it a bit more challenging than you'd like but if you've been working on one application for a few months and you're not sure you're doing things the right way this is the kind of things that we'll be going through is how to look at problems and apply some of these techniques and so some of the tools that we're going to be using today is the visual studio 2015 community edition and we'll also be taking a look at the visual studio online which was a place where you can store some of your code and you can pull down different code bits you can also we're also going to be using a little bit of the github accounts that's where we're using uh where we're storing different information uh and open source uh tools and i'd strongly encourage you to have one of those accounts that you can use so that as you're working through the lab exercises you have a place for your code one of the nice things is you'll be able to track changes over time and be able to see some of the early solutions and if you make some modifications to those go back and update them and track those changes and be able to see the history is how you've grown as a developer over the course of working through this content the main thing we want to look at right now just to finish up this first zero with module is look at some of the tools and some of the expectations that we're going to have for you in terms of how everything is going to be laid out so the visual studio community edition is an integrated development environment for net it gives you a bunch of different tools so that you can edit your source code and then build it you can debug it and you can do a lot more stuff with it we're going to kind of go over a few different ways that you can navigate through these large projects that we're going to be working with and then we're also going to be debugging and watching some of the code and while this course isn't specifically about visual studio as we do different techniques with the ide we'll show how those work and how those can help you on larger projects so we'll point out the things we are doing with the tool that you may be familiar with and maybe you'll pick up a few new tips where some of our code goes it's going to be in visual studio online and again if you're an msdn subscriber you will already have access to this tool and it's a place where you can keep and keep track of the changes that you make as you work through the labs and the homework and then finally as james mentioned earlier we're going to be doing some of the things on github a lot of the examples that we're going to use to demonstrate how to use these different techniques come from the open source packages that are part of the microsoft.net framework we're doing that because those are some really really good production examples of using these different techniques it's a code base used by millions of developers worldwide so these are real world examples of how to use these techniques to build a really high quality product they're open source and available on github so we can freely access them and learn from those tools others one of the tools that we'll be looking at one of the libraries is still on codeplex which is another open source repository or home for a lot of open source repositories and we'll point out where both of those are so you can look at and browse the code on your own machine and learn more from some of the other areas of the framework in addition to the ones that will specifically highlight during the next next several hours so next we're going to be talking about the course format we're going to be initially explaining a concept why it's used what problems does it solve and uh how are we going to commute and what does it what do those things mean to other developers what are you communicating to them and this is one of the big things as we're working through these concepts when we look through the code reviews we're going to be reading someone else's code and as you keep growing as a professional developer your co-workers are going to be reading your code to understand your design and why you solve the problem in certain ways and by picking different techniques you're communicating what you thought about that problem and what you thought about the design to solve it so we're really going to be concentrating on by solving it this way this is what you're saying about how this problem exists now and how you think it might change in the future and then next we're going to be demonstrating its use and we're going to be doing that through live production code so we're going to not just be showing some demos we're actually going to be going through some of the net libraries based class libraries that are going to show us exactly how these concepts are being used and show us where they're going to be and show us what they're actually being communicating and then finally at the end of each module we're going to propose an exercise for you the first ones are going to be relatively straightforward because we'll just have discussed the concept and the lab for that module is probably going to use the techniques that we've just covered as we go further into the course the specific problem may use the new concepts but we'll also be bringing in some of the concepts that you've already discussed in earlier modules and you may need to apply to part of the problems as they get a little larger and then finally at the very end we're going to have a large review exercise where you'll have to figure out which one of the techniques to use for different parts of that problem we'll come back after each one of the modules and show a good idea of one solution that james and i made and discuss how it was built and how yours may differ and what kind of things you should look for and why we picked some of the techniques that we picked in different parts so what's next we're going to begin by explaining some of the concepts and we're going to start with encapsulation and then we're going to go through and make sure that the modules are working from one from a simpler complex simpler explanation up to a more complex uh concepts but uh if at any point you feel like you should jump around go ahead and do that if you if we mention a concept that you're not sure you haven't heard before maybe it might be a good idea to jump ahead and go back and then come back and explore the concept that we're talking about currently so we really do kind of recommend following this module right through from the beginning towards the end uh just because the concepts will be uh explained uh in a continuous fashion or at least get the introduction you know if you really feel you've got something you might want to skim a little bit and move forward but definitely i think we tried to build it so that there aren't a lot of forward references saying you know here's something that we'll discuss three modules from now but if you get way ahead you may be missing some techniques that that we expect you to be able to to work with great and with that we'll be back in our next video and we'll start to discuss encapsulation is one of the core concepts behind object-oriented programming hello again i'm bill wagner and i'm james sturdivant and we're working through our next module on object-oriented practices our course topics as i said we're going to have seven different major focuses that we're going to look through during the course of this entire course we're on our first main topic encapsulation so encapsulation is a way to minimize the amount of code that you make visible to other other users and in this module we're going to go over some of the different techniques that we can use to hide some of the implementation details that we're showing those users that's really the main key we want to get across is that by doing this properly what you're going to do is end up with the ability to make changes that are more localized as your program grows over time or as you find performance needs that you need to address or as you add new features we want to minimize how wide sweeping those changes are yes and so what we're trying to do here is really hide the complexity of some of the algorithms that we have and so we can do that by minimizing the amount of code that we show up to the people that are using the libraries that we're using now as we put this particular module together there's a number of areas that we're going to focus on in this particular module we're going to look at the definition just exactly what do we mean by encapsulation we'll look at some guidelines what do we want to try to solve by using these techniques we'll look at some of the practices that will make it possible to be able to implement algorithms and hide that complexity as james was saying from the people that use the algorithms that we create and we're going to look at ways to review some of the code after we've written it and see if we get the results that we wanted and if we get the benefits that we're hoping to get from these particular techniques so the first thing we're going to do is define encapsulation encapsulation is minimizing the visibility of every program element to the smallest possible scope and what this means is that we're trying to hide the complexity of the program that were in the code that we're exposing and we do that by minimizing the amount of scope that goes through so what is scope scope is the ability to minimize the visibility of the components that we're working with so for instance in code you've already read and you probably define local variables in a function the scope for that is just that function or even inside a loop you may add a a variable just for the counter of that loop its scope is just that loop if you change something about it it can affect the rest of the program similarly when we're building classes when we declare private members those are only visible inside that class their scope is limited to that class we have others other different visibility or accessibility keywords that we'll define as we get further but we want to strive for giving everything the smallest visibility possible gives us more freedom to change it fewer things are affected by that change so what are some of the advantages of encapsulation uh i think the first one here is really the number of name collisions that you can run into so if you have a private variable that's inside your class you can name it whatever you want as long as it's private you're not going to be seeing that variable and you're not going to have a name collision with a class that's with another class that tries to use something that's named very similar another great advantage of this is when you're refactoring your code you can um you don't have to worry about the um the way that it's being explored to uh two other things so you know think even going back to name collisions for a second you know if i'm building a library and when we get to our our code review section we're going to be looking at some of the dot-net framework if they change one of the private variables of one of the classes if they change that name or change its type as they find new requirements or they change how it's put together they can do that safely even though there's all those millions of customers relying on the framework because those customers couldn't have been looking at those private variables i mean for those of you that are more experienced yes we can look at reflection we can get the metadata we can really cheat but at that point you kind of asked for it regular customers that are using our public api or even deriving from our classes using protected or other other apis can't see those so we have the freedom to change it and the same thing is true with that refactoring tools if i start changing and moving around the code inside a class you know pulling out the entire implementation of a public method because i'm going to reuse it in another place and now it's a private method or it moves to another class that i work with if it doesn't change the public api i can do that safely i have more freedom to make those changes yeah so that really means that the elements that we hide with our with our encapsulation makes it easier for us to change the code uh in the future right you know imagine if you were working on the framework if you wanted to change one of the variables if it was all global it'd be very hard to do that and even have any hope of not conflicting with all the code that somebody wrote based on the.net framework so we're really trying to enable that kind of that kind of localization of the change that becomes more important more as our programs grow as we're building with more different components you know if i add the dot net framework i may add other nuget packages into my program to solve other particular problems that i have whether it's json serialization which is a nuget package or dependency injection or whatever i can bring those in and they shouldn't collide with the core parts of the framework because they should be minimizing their public names and so we've kind of touched on a few of the different support support systems inside the net framework that we have the first one would be through classes we can make them public internal or private uh and private would be only if we're making the classes inside of another class and then for our member variables so if you're making a property or a variable onside your class you can make them public internal protected internal or private so what does some of those mean right so let's start with public public rather obviously means it's public any program element can access that so those are the most visible possible that's what we want to strive to keep as small of a surface area as we can it's public anyone can access it any change could be considered a breaking change depending on how it's implemented if you change the signature of that it's now a new api it's going to break a lot of existing code when they go compile against it so next up is internal and internal is the code base means that you can only see that inside your library so if i had two libraries if i pulled one in through nuget you wouldn't be able to see that internal class that i had defined inside my library right it's basically maps to an assembly so anything that builds one dll so nuget packages may include more than one assembly each one would have its own internal scope great and then the next one up is private and so what's uh private field mean it means that only the where if you define it on your class then only that class can see that variable and um this is where this is the default for the for most variables and uh it really is probably where you want to start and you only want to kind of move it up the chain from private to internal to public when as you decide that you actually need to be using it and in addition when we think about classes we can build private nested classes so if you have some help or class that's only used inside one type that's part of your public api but doesn't actually get exposed as part of the public api you can declare private nested classes in order to minimize the scope of that type so other elements of the program or other people using your code don't even know that type exists you know maybe an internal data structure to keep track of you know mapping some id to some object or what have you yep and another good thing to note here is although the default is private and you may not see the private uh keyword on that on that stream on that field you it's a good idea to include that there and that forces you to make an actual decision at the time that you're developing code and that's another way where we're communicating back up to our to other developers who are reading through our code that we want to be that we want it to be private and we don't want them to be using it from a class that they inherit from or they try to use it or another class that they're using right that i think in general i always like to explicitly declare the accessibility of different types you know whether it's a type where the default for a class would be internal rather than private right because a private class can't really be seen by anybody but so classes by default are internal and fields and members of a class are private but i just find it better to write that extra keyword that way i make sure you know it's i'm being explicit about what i want and i've communicated that to other developers somebody else doesn't read it and go maybe they just forgot maybe they meant something different yeah exactly that's i think that's a great point is every time that you're you're reading code you want to make sure that you're understanding what the other developer is saying and if they left it off you're not sure if they just left it off on accident or if they actually meant to make it a public variable and then finally the one thing we haven't really covered yet is this idea of protected internal which is the visibility is anded so if i have a protected internal member it's visible to everything in that same assembly and it's also visible to any class that derives from this class we're adding defining this part right here even though we haven't really talked about inheritance yet we'll do that a little bit later but protected means it can be seen by this class and any classes derived from us which we'll define more thoroughly in the next module so now let's look at some of the guidelines around how do we go about limiting accessibility how do we go about structuring things in such a way that we have a fully functional class and yet we do limit that visibility as much as possible so when we're developing our classes we want to strive for really small classes and this is going to help us drive down and make those classes so that they don't have a lot of different components to them so there's a really interesting great quote on this uh grady booch who's one of the leaders of the object-oriented community has this great quote where he says if your program is too complicated make more classes you know which sounds counterintuitive you want to think that if i if if my program's complicated i should have fewer things right but it actually does turn out to be the opposite if i have more classes that have more simpler responsibilities it's easier to put those building blocks together and as a developer reading your code they're going to it's easier to understand a smaller class than if there's you know 2000 lines inside of a class right another good fun exercise that i do with different customers when we're looking at reviewing a large code base is first i ask them how big is too big for a class you know and i'll get answers somewhere in the neighborhood of 500 lines a thousand lines 750 lines and then we actually look at their code base and it's almost invariably two thousand four thousand line classes you know so there we know we want to keep these things small but they tend to grow um so one of the things that we want to do to try to keep that from happening is is to really minimize the size of that public api the fewer methods that are public the more likely a class really has a singular focus you know and there's there's this term called the single responsibility principle where each class should really just have one responsibility or one reason to change because it's one responsibility is now changing you know we have new business requirements its responsibility changes you know and that's that's a reasonable change otherwise we may be want to think about making a new class or making a new type to solve this new requirement if it's totally different yeah and that single responsibility program is a part of the solid principles which is the single responsibility open closed the list of substitution and interface segregation and dependency injection we're going to kind of go over a few of those throughout the day today right and one of those that open close principle applies a little bit here is that a class should be open for extension we can add more things to it but close for modification by encapsulating these things and making them private it's harder for other code to try to change the behavior of the class that we're creating right some of the others we'll talk about later as we get into those concepts as well and that's where the second bullet point on this slide about avoiding unnecessary additions consider creating new classes if we have something new that we really need to put in place and that last one avoiding the extra convenience methods you know i've seen people when they're first starting to do some object-oriented design think of i've got this method and you know we can do opera or method overloading so i can define the same method with multiple different parameter lists and instead of thinking of a small number of overloads that really make sense they start thinking of all the possible overloads i could define to be able to solve the same problem and they end up with a lot more methods and a lot bigger surface area for an api than they really need and so avoid some of those extra convenience methods it's really just more work in a lot of cases keep things as simple as possible and striving for that small class idea and so bill i think one great exercise is to think about a class with a single public api have you ever seen a class with a single function on its api um you know i can think of interfaces which we'll get to later that have just one function that defines just one thing that they do um a class with just a single responsibility or a single api those are pretty rare you know but they you know there's often maybe a constructor that builds it and then maybe one thing that it does you know it executes some piece of work um and then we usually end up having some error handling or some state to work with so there might be some properties or a couple things but really trying to think of that it's it's still a good exercise to try to think of how close can i get to that you know here's just this class that just does this one thing it just adds one thing in it and that gets to is one of those areas where really try to be able to to keep these things simple great so i think uh up next is our we're going to talk about a little bit about the practices that will achieve the encapsulation that we've been kind of discussing here so how do we actually go about um accomplishing this encapsulation and making sure that our apis are small and that they don't expose too much uh information out to the public so that when we do need to make a change we actually can make it without introducing any breaking changes right so i think the first thing that we try to do is i really want to take and minimize the amount of public apis that i do you know and i think one of the things that comes out of this test driven development practice is the idea that when i start building this class i'm going to start building tests for how i'm going to use it first and you know that naturally gets us to try to say all right so here's how i'm going to use this class here's the methods that i would do to put this together or to make it do whatever it's going to do you know maybe i have some some class that's going to compute averages or something like that right i need to give it a set of numbers and i need to say please give me the mean you know and that's it i'm going to want to try to keep that api simple so what you're kind of doing there is defining what this class actually does and not so much how it's actually going to accomplish that that given task right and then by doing that and by writing a test that says here's how i'd like to use it you know i get to think a little bit about api design before i get too far into the problem i get to think about this is a simple way to use a class that would solve this problem and usually i'm actually going to gravitate toward a class with a smaller api because it's easier to understand right how do i want to solve this problem i'm going to take a sequence of numbers and then say please give me the average of it you know i'm not going to go write something where i can add each number one at a time i'm not going to specify how i want to do the average i might just have the one method that says give me the mean whatever right so i get to come up with something relatively simple many other classes are going to have slightly larger business requirements so we may come up with other scenarios where we're using them but the same concept applies i want to be able to create this class and i want to be able to get it to do its work and hopefully a small amount of code that i have to write to use it and when i achieve that i'm going to naturally gravitate toward a smaller and simpler api so another practice that you want to take in to consideration is all the making sure that most of your member fields are private and this is going to give you quite a few different advantages because then you can access those properties and those fields that are uh your member fields to through these properties and you can do various validations and make sure that uh you can that your class is staying consistent and valid throughout the entire access right and here i'd even say all member fields should be private right and i'm always going to get them through properties you know and i think about the big advantage here is if i can always ensure that the state of an object is always valid if i can ensure that a lot of my other algorithms become easier to write this object must be in a valid state right so if i and the best way i can do that is to ensure that all of its data members are private and you can never set one of them into an invalid state right i can never set null as somebody's name i can never set you know i can never take the average of no numbers right it's not valid so i have to construct it with something and i have to make sure that no matter what through the life of that object it always has something and that minimizes my error handling are there any concerns around making all your member fields private you know you if you really really get in in some super high performance situations you may want to look at the fact that if something is private you have to go through some code to change it you have to go through some code to access it and if you're in super super critical super hot path code you may be able to measure that now notice i said super super hot path super super critical code so the only way i would make that change is if i've measured it and then made the change and said see it is measurably faster in these scenarios i actually care about you know i would start with doing something that i know is going to work and i know is going to give me the kind of protection that i want in terms of encapsulating these fields and only if i've measured it and seen i really need that performance gain would i consider making things public you know and that so i'd watch that a little bit of that latency just to make sure that it's not not a concern but i would only do that if i'm really seeing the performance degradation from that extra extra bit of code and the reality is in a lot of cases the jitter will optimize the extra function call away so we really don't see that you really have to try to measure this and and hit something really hard to be able to see that difference yeah that makes sense so the next uh thing that we're going to talk about is the properties these properties that we're accessing the member fields through would uh be able to give us the ability to provide validation so we can make sure that that object is in a valid state and block any changes to the object and to that internal state um through the through this properties through these properties right so like if i think of the idea of say a person object in any number of domains so a person always has a name so anytime i construct it i have to set that name and if i never now that allow that name to change to be null or the empty string or just spaces and my property to allow me to set the first name or set the last name you know it doesn't allow those the rest of the code maybe that prints out reports or um you know does email or tries to write notes to any of these people in my customer database wherever it happens to be stored it can assume that it's always valid it can make sure that it's always doing something reasonable so that's extra code i don't need to write because i can centralize where those transitions get you know get validated only at the point where we're trying to make this change yeah and that les that leads to less code inside some of those extra methods and pushes all the validation and error checking into one central location through these properties right and it's a very natural one i don't have to write this private method that says let's make sure this object is valid because who knows what happened between other other times we called it i can just know it's always valid because i don't let it get there so uh we kind of touched on the this topic of public accessors being a way to uh validate the data but uh we can also um use these public the get methods on the on the object to make sure that the data that we're returning back up to other classes is is valid we can also do some computation on those values so if you had that person with a first name and a last name and you wanted to get their full name you'd use one of these public accessors to get the right the full name right so i can certainly compute different properties that maybe i'm not even storing because they're not expensive to compute but i'll compute them when i need to i can even expand on that algorithm to say maybe this is a maybe i want to do something where say it's a customer database or a customer facing application and one of the properties may be the sum of all their orders for the past year you know and i don't need it in all scenarios when i do i'll calculate it and cash the answer but if i don't need it i won't calculate it until some client code asks for it so i may be able to do some optimization there to say you know i'm only going to calculate that when needed not do the extra work until then so i can hide that and encapsulate whether or not that even needs to get computed depending on the scenario yeah that's a great example so then our public methods that may change the object we've talked about this a little bit we want to make sure that any public method that changes the state of an object does the validation right if an object is in a valid state we're going to do some kind of change it should still be in a valid state throw an exception if we're going to set something that's going to fail and then we can also ensure that the way we write those methods either the entire transformation happens or nothing does so maybe we want to add a customer order to something you know that involves multiple operations right we're going to you know maybe pull inventory from a warehouse or write the code that's going to go tell somebody to do that you know update inventory in stock charge someone's credit card and start shipping it we either want all those things to happen or none of them so if it's one api to say let's go finish this order then we can start something and say okay let's try to see if all these things work if any of them are going to fail then let's not do any of the work so we keep the whole program state valid rather than we started shipping something but the credit card didn't go through or worse we charged the credit card then found we didn't have any stock so they actually didn't get the order and we can keep both object state and the entire program state consistent by watching only those points where public methods can change the state of an object which is kind of that next that next point where we want to keep those things valid they complete or they don't do anything and uh so then i think the next practice that we want to talk about is common code and internal classes sorry bill this is definitely one of the harder ones there's times we may have shared code you know and it may be something that we use in a few places in different classes inside our library right we don't necessarily want to expose it to everybody but we need it in a few different places like maybe we're doing you know a common case that i've seen working in in different engineering applications is there's any number of mathematics functions that we may need maybe we're calculating standard deviation or variation or modeling a 3d surface and trying to smooth it we don't need those everywhere we don't want to make them public but they're part of a math library that we're working with that we want to be able to fill some of those in you know in particular say standard deviation takes some of the squares and the square of the sums so those may be internal utility methods that we share among a few classes so there's this middle road we can use when we're when we've got some things where this library needs this capability in a few or in multiple places but we're still not ready to service it publicly or we don't need to yep and that goes back to that practice where we want to make sure that we start at the default of private and as we decide that we might need to use that and expose it later on then we can move it up to internal or protected and then finally maybe public if that's actually going to be something that we're using outside of the libraries that we're building right and then we touched on this a little bit before we would say that anytime that you're defining what accessibility a program element needs even though the language defines defaults definitely write those down express that explicitly in the code that you're creating makes it more readable the developers who come after you know you made an explicit decision and you're forced to as well and finally we kind of touched on this a little bit before but we can also take some of those encapsulation practices and make them private classes inside of the class that we're developing and this particularly is useful when some of the when we have one class that's only useful to the particular class we're developing and so when's a great time to use this bill different things that we'll do and we'll we'll touch on some of this a little bit later but there's times when maybe i want to implement an interface and i may defer that and have a nested private class do it maybe i have some partial implementation for some of the things that i'm working on let's say let's take that that customer example again one of the things we may do to encapsulate that idea of creating an order and doing all that work is i may encapsulate a class that says here's how i process an order and that encapsulated private class is going to have those different steps to say let's check to see if the credit card's valid let's check to see if we have it in inventory let's make sure we have a valid shipping address and when we have all of those things together then perform a transaction do all of them but in that method that performs all of them you know maybe state has changed in between those two it should be able to roll things back you know and undo what it did and that's only needed inside this one concept of a customer but it doesn't really belong as part of the whole customer class so i want to encapsulate that and package that together and maybe i'll use it later but i'm at least keeping it in just that one spot so it's even more more tightly bound inside that one area and so what are some of the results that we get from encapsulation here i think we're going to be seeing a lot of different things that are great that come out of this encapsulation such as making clear and minimal interfaces right so these are the kind of things that i look for in a code review when i'm looking at what somebody's built right so i have a clear and minimal interface that public interface it says what this class does i can read it i can look at say just the docs or just the public interface and i know what's going to happen and they should be close to invariance i don't expect that to change with each new build right you know while i'm working on something and maybe i'm part way through okay sure we're going to make some changes but once i've released a class you know in our as part of our product i don't expect the public interface to change a lot and new versions probably should mean additions not whole scale changes to that public interface that we've created and another great uh outcome from doing this encapsulation is that the smallest possible uh visibility is is what we see so we have less chance of a leaky abstraction and a leaky abstraction is when we have details and implementation uh the details of the implementation leak through and so suddenly you can see how you're solving this problem instead of just what problem you're solving so suddenly i see oh that's what's going on that's how it happens and then clients will naturally just make use of those details if they can see them so that's why we want to kind of keep that out of there and that that's what ultimately introduces breaking changes from your your api so they become easier to enhance right if you can't see that how i solve the problem i can solve it a totally different way if i come up with a better algorithm later and you don't happen to notice the difference and again that implementation being hidden you know the the the watch word i use is public is what what does this class do private is how how does it do what it does so what's up next we're going to do a code review we're going to go look at the base class library inside the.net framework we're going to look specifically in the core clr where some of this information has been exposed publicly and we're going to be looking at the string builder arraylist and finally i think we're going to take a look quickly at the dictionary and with that we'll be back shortly greetings i'm bill wagner and i'm james sturdivant and now we're going to look at some of those encapsulation practices inside the core.net framework so we're going to spend most of our time on this module looking at code looking at the code that you use every day as a net developer and look at how these practices apply to that kind of a production code base so with that what we're going to do we're going to start by looking at the string builder class in this particular demo section we're going to have five different sections we're going to look at string builder we're going to look at two of the classic collections hash table and array list for those of you that are familiar with generics we chose those two because we haven't covered generics yet after we cover that module we'll update this a little bit to look at those generic type classes then we're going to introduce a lab for you and we'll come back in a separate clip and talk about one possible solution so let's now begin with that first section where we're going to dive into string builder and i was really excited uh impressed that you pick string builder because it's a library that we use uh and that you're probably actually very familiar with and uh when we look at the api it's a really simple api that we can easily use and and build our applications quickly with especially around when we're working with strings but when we dive into the code we'll find that the uh the actual implementation is incredibly uh complex and it's really going to demonstrate how encapsulation works best right that's one of the things that i wanted to do so before we dive right into the code there's a couple different websites that i want to point out to people so you can follow along load the code yourself walk through it and use some of the tools that we're using so first i've got on github here if you go to github.com microsoft you're going to see a list of most of the dotnet libraries that have been released as open source i'm not going to scroll through all of these there's 13 different pages another one to go to is if you go to microsoft.github.io you'll find a list of all the repositories that the microsoft.net ecosystem is involved in and again a lot of these aren't necessarily ones that come out of microsoft but microsoft is supporting and helping to work with for instance some of the node.js work is not a microsoft product but they're working on and actively doing some some of their own contributions too the particular one that we're going to look at today in terms of these three classes in this particular code review is the core clr project so if you go to github.com.net core clr that's the repository for this code so if you want to clone it from here you can see links on the right on the screen here so net github.com.net core clr and if we look in the right we can see areas to clone or find anything here if you're used to github you can search here to find different classes that you think might be part of this project so if i wanted to do the review right on github if i were to search for string builder i can find all the different places where it's used now because it's used a lot i'm finding 104 different code results one of them happens to be the class itself so we can see exactly where it's implemented and how it's put together right here on the web instead of that though we cloned it to the local machine here and i'm going to load it in visual studio because that's the tool that we're most used to and we've got a little bit richer set of tools to work with so first is as jane mentions if we look at string builder we'll start by looking just at its api so this is just the stringbuilder class on msdn and we can see we've got a number of different constructors we mentioned earlier we might want to think about trying to minimize the number of apis we have but they do have reasons for these some for performance considerations that were added over time and some as the class has grown we've got a few different properties to it total of four and then we get to the public apis a lot of them are overloads of an append method so we can add new content onto this string a few others we're going to append formatted content we can clear it out copy things some of the things that it's inherited from the object class we have to work with you can insert in the middle of it basically modify this string that we're going to be manipulating and then finally we have a two-string method that will pull out a static string from this string builder so we've got as james said fairly simple api that we'd be using to build our applications with yes and the reason we might choose to use the string builder class is if we have uh if we're modifying a bunch of strings together that can be very expensive for us to to do and it can cause some performance issues and so if we're going to be modifying a string and appending and building up that class or building up that string as we go this is when we'd use the string builder so let's go ahead and dive into the code right okay so i've got the project loaded in visual studio and the easiest way for me to find the string builder class is i'm just going to do a search anywhere in this project for stringbuilder and i'm going to find a whole lot of places as i said i'm just going to pick the first one and this is declaring a stringbuilder class and now if i press f12 it's going to take me right to that class i'm going to switch into full screen since we're really just going to be looking at code and for those of you that aren't familiar with it that quick launch bar up in the upper right in visual studio i can type anything that relates to any command and quickly get that command to execute i can never remember the keystrokes for full screen so i usually just type it up there so we look at the class inside here you can see we've got a number of internal variables so there's some other classes apparently that would work with string builder in order to do its work we've got some constants as far as just how big is the capacity looks like it starts at 16. we've got some things in terms of how do we work with some of the some strings that we've defined for other things that get stored that maybe can get configured later now if we look at our constructors we're going to build this thing with some kind of a capacity to it and one of the things they're doing here is they're chaining from one constructor to another so they're going to try to minimize how many times they write the initialization code and still give people using it a lot of different overloads to be able to construct this object but they're going to share a common implementation as we keep going down we'll get to that common implementation you see we start with okay here's a bunch of validation okay capacity has to be greater than zero or equal to zero length has to be start at at least zero my initial index has to start at least zero and now we're going to start initializing this thing so we create an empty string if we need to we start creating some storage for all the characters and now we start copying some things in if we need to we're going to copy some of these characters that came in from this string that may have initialized it we're going to use unsafe code to try to copy these characters very quickly so that's quite a bit of work just to build the initial string builder right so we've already hidden all that complexity for anybody trying to use this code yep and down there you can actually see that they've defined and they're using a method called thread safe copy and this is actually doing some copying directly into uh the memory space that they've allocated and if we take a look at thread safe copy we'll see that we're going to be using that piece that piece of code uh throughout the entire application uh and or throughout this class because it's private sorry it's okay uh throughout this class and um and so you can see here that it's a private method and if we were to use the string builder you wouldn't actually have access to that thread safe copy and here you're also seeing that it's being used as as bill has pulled up this fine symbols uh you can see it's being used continuously throughout the entire class and so this this is a great way of doing some encapsulation inside of your class and only just uh and not leaking that uh implementation details out to the outside to the classes that are using it right now so we can construct it we've built some of these buffers we've done some of that work the other one i want to look at is i want to look at at least one of the append methods so this far right combo box will take me to different methods inside a particular class so if i look up here at let's append a string because that's one of the ones that pretty easy to understand it's just going to take a string that we pass it in add it to the current string builder and we now have a string builder that's got a larger internal storage based on whatever string we've just added to it right so we're only going to do this if the value isn't null and now if we look at what it's doing what we're going to do is we're going to grab some things onto um we're going to allocate a set of the string make sure that our storage is big enough to accept the string that we want to append if not we're going to have to go grab some other some new storage copy things into that storage and then set to where that where that storage now contains the new set of characters and that's done by this can be done by this append helper which we dive into and see that's basically calling that append which then adds new characters back onto the characters that we're putting in place and what's the um key stroke that you did there to pull up that little helper dialogue if you pull up alt f12 that gives me a floating window at the definition of wherever i started so here's where we're going to start to set in place you can see the comment that says this case is so common we're just going to optimize it as much as we possibly can there's that thread safe copy again we're going to pull this in place we're going to copy those characters right into the storage of that internal array of characters that we've added in this class otherwise if it's not big enough we're going to copy the first trunk then we're going to grab some more storage we're going to add another chunk and then we're going to keep keep right on going okay what's interesting about this is what's actually happening is it's not continuously reallocating the array once we've filled up one array of characters for some logical size of a string builder instead of grabbing a new array and then copying everything that we've already built and then making a bigger array it's going to keep take making these chunked arrays of characters storing the string as it builds it and then finally we'll look at the last one which is two string which pulls everything out which will then pull the characters out of the string and give us a string with everything that we've used to construct it so the last one that we want to look at is this two string variable method let's do that in the main window here so if we go look at two string what we're going to do is we're going to do some validation okay then we're going to allocate a string of a current length okay this fast allocate string if we look at that that's internal we can only get at that because this code is part of the same core clr assembly as string so that's not a public method that's one of the things that it's able to do just internally and then what it's going to do is it's going to take each one of the current chunks in the string builder and keep appending those characters into the source for that string and again here it's going to leap into some of the things inside the string itself and do some internal things that we can't get out to as as users of the dot net framework but the string builder can being internal so there's quite a bit of complexity that i find that's being hidden inside here from us which i really like right as as we mentioned what we're really looking for here is this class is easy to use you know james mentioned that i've now mentioned this it's simple to use allocate a string builder append things to it pull out a string that's really all we have to do and there's a lot of this work inside to try to keep that very performant this idea of having different chunks that it's going to allocate internally you know it may or may not have been the first design they came up with right because they may have just started saying well we'll have one array and we'll keep adding characters and then they saw there may have been some performance implications there so they could change that internally and come up with this faster algorithm to then be more performant without changing any of the external access needed right um that's just a theory i don't know i've never seen the earlier code before it was open source but that's just one you know possible thing that happened but the idea is that the design enables that to take place right right and so they'll also be able to change some of the uh the implementation details later on so if for whatever reason they move to another platform or they go somewhere else they'll be able to actually change those implementation details while keeping the public interface the same and that's a major advantage to this encapsulation that we're discussing right and some of that may have already happened i didn't see anything in this particular class but you know the net framework now runs on different windows devices it runs on your phone which has a different processor than you know our laptops here our tablets the asp.net vnex project is running on linux also possibly a different processor architecture so they may have changed some of the internals to to support that and those are all possible now because of that encapsulation we don't need to see that ourselves right so up next we're going to be taking a look at the hash table and a hash table is a associative array which allows us to access the information via a key and the reason we want to do this is because if we have a large number of uh information that we need to store but we want to be able to access it in in a single uh in on uh time frame which means that we want to access it at a the rate at a consistent rate then we'd start to use this k this key it's very similar to a dictionary if you've if you've used that in the past right or if you've used javascript you know the anonymous types in javascript that have key value pairs that that's a form of an associative array yes right so again i'm going to do this the same kind of the same way let's look through and see exactly what we can do with our hash table if i look at that class and again we're going to stick with the non-generic version right now because we haven't covered generics we'll look at dictionary and such later in this in this course and again our hash table class we've got different constructors to be able to put some things together we're seeing some interfaces there that we'll cover more later but the idea that i can initialize this and put some elements in the dictionary i can do some things to decide how i want to check for equality which is going to be important in how we work with these associative array are these keys actually equal right and we may need to override that depending on what type we're using as keys we've got a number of different properties notice that again this is code from.net 1.0 so there's a couple of them that are obsolete and we can move back on those later we've got some ways to get out a different element we can get at an item which is an indexer in c sharp by referencing its key we can look get the entire collection of keys for the entire collection of values and then again we've got a set of apis that allows us to add things to the dictionary or to the hash table to be able to see if it contains something copy it to one or another place we can do an enumerator to be able to look at all the elements in a dictionary get back key value pairs so we can look at both and we can remove an element and we can um then some of the extension methods we're going to leave off on the site at this point because they're not actually part of this particular class but we've got once again a relatively simple and easy to use api i've got keys and i've got values i can add something to this hash table by specifying a key where i want to store it and a value which is how i want to get back or what i want to store associated with that key i can enumerate those or i can find a single value out of it work with those and bring those bring particular values out of that hash table and again that implementation is now going to hide quite a bit of those details so let's look at how that's put together we'll go back over to visual studio and again i'm just going to search for that hash table class find an instance of it and again i can find it just anywhere if i find a um an instance of a variable turns out it looks like i've actually found the implementation of it immediately we'll go back into full screen again concentrate on the code again we've got a fair amount of some implementation notes you can see that once we get to generics they apparently grabbed the source directly from here so if we find a bug let's make sure we fix it in both places how they're doing the hash algorithm so that we've got different this is a double hash algorithm so that each bucket can contain either zero or one element and so on we can read that yourselves as to how the hash table finds something when we hit something and we have a bucket that's a collision so what happens here is when we try to build a hash table we have a function that generates a number based on the properties of the key so a bucket may actually have more than one value like let's think of strings okay this would be a very bad hashing algorithm but this is the idea of what happens let's say my hash function for strings were to use the length of the string okay so all strings that had one length would all be in one bucket all strings it had the length five would be in another bucket so then if i wanted to find a key i could look take the key see how long it is i have the bucket and i know what values are there and i can find that particular value that's a bad hashing algorithm because we really want it to be distributed evenly over all numbers so the actual hash function for a string is noticeably different and we'll get a better even distribution okay and then once we do that then we have to find the next algorithm so there's a lot of computer science into how this is going on you can see there's a good page and a half of comments here and i've glossed over a lot of it that's kind of the point we're looking at this encapsulation idea i can use the hash table without remembering how it's all implemented got some of the things where how are we going to store some of these constants work with how the bucket works you can see we have this private structure here once again like we talked about in in the powerpoint i can put together something that's hidden that only hash table uses so hash table uses this bucket idea that has a key as a value and has its hash value it stores the hash code i have a bunch of buckets so i have this array here array of buckets is going to store these things here which have these key value pairs so for every bucket in that array it's going to match one of those hash collision values or hash hash code values and then it's going to have a set of key and values in place we've got our account we've got the occupancy total number of collisions how many things we're getting and then we're going to start building a lot of internal stuff in terms of how our compares are working to try to find where something goes in the hash table now we'll go ahead and put things together you can see there are some properties that we can use to put together a hash table as to what its capacity is what its load factor is which is how big buckets should be before we start splitting them up there's a lot of different computer science algorithms in terms of building a good hash table these are all in place down here and one thing you note is that when you're using the hash table you actually don't need to know all these computer science technol techniques to make sure that this is fully optimized and so that's a great way to demonstrate how this encapsulation is being used in practice inside the core clr right and there's a few things that are documented in the public api which you mentioned that there's order and log n to get elements out of a hash table because that's how we go find them there's order n to enumerate everything in a hash table based on how many things you have in the table those kinds of things are documented and the algorithm that complexity ensures that those those performance metrics are met so let's look at just how do we get at an object for something so if i were to come down here into the hash table if i were to look at that item property which in is in the index there index there this is a great example of where we'd actually use a property to hide some of the complexity of when we actually get the item from the dictionary there's quite a bit of logic to find the hash table to find the hash to make sure that the keys match to make sure that the values match and then finally if all those things match then you can actually retrieve the value out of that bucket that we we saw before right so briefly let's look at that algorithm here's the indexer so it's a method called this in c sharp it takes in a key and it's going to return the value so we've got a few it's going to have a getter checking out some of our our parameters if the key is null this makes no sense okay now we're going to look at all the buckets we're going to find the code for this particular key based on the current number of links in the bucket a seed and our increment value we're going to go find if it is in one of these buckets you can see it has three steps followed by a numbered list of four items so maybe a little comment creep there but calculate the hash and find the slot number compare the hash code if it's equal go to step three otherwise compare the key if they're equal go to step four otherwise we didn't find it step four return the value retained in the bucket okay great so now we'll go through and try to implement that we're going to try to do the read find those things in here spin up to see where else we're running see if we find the hash code this part here is noticing that if there were collisions we said up at the top where we were looking at that bucket structure that it was going to set the sign bit to be able to say oh this is going to equal something so then they equal we found it right yeah and so what's great here is if bill if you scroll up just a touch there you see that there actually there's a point where they have uh if you have multiple threads running and trying to access this you'll run into uh some contention and they're actually releasing the thread so that other things can run so that the cpu isn't being used and so what's great here is that you don't need to worry about that complexity you get that they they found that that was a problem once they started using this and they started implementing it in complex applications and they were able to then uh add that into the um the get method of the the dictionary or the the sorry the hash table and uh they and so that was something that they were able to add afterwards without breaking the the interface right so then again a reasonably large large algorithm to be able just to get something out of this but again very very highly optimized to meet those performance metrics and the setter to be able to get at something is going to end up calling this insert method so we'll hit f12 dive into exactly where that is again a private method to do an insert we've got our key we've got our value whether or not we're going to add to it or only replace so there's a couple different bits of semantics there where i can add something to a dictionary depending on the api i called or only replace something which should throw an exception if i don't find that particular key yet we're going to look through once again try to find where it should be and once again looking at only one writer thread going so we may have some concurrency issues here so we're going to look through some of these things dive through try to find where this should go and again we've got a good 50 to 100 lines of code here trying to dive into some of these particular bits to see where should this element go in this hash table eventually if we find it you know this section is if it's available if we didn't find it or if we did find it we're going to write it we're going to set that value if we're not find doing an add then it has to only be they're well able to do an insert as well and once again we're going to update that bucket set the value to it roughly about 150 lines of code to go just do what we make in one call which is i want to add something to this hash table so that's a really great example of encapsulating all of that logic and all the uh performance implications that they have when they're when they're working with those things so up next i think we're going to take a quick look at the arraylist and an arraylist is allows us to be able to add items to a list adds us items to a list and we are able to grow that list dynamically and again the hash table is one of the details we glossed over looking at some of these methods the hash table will grow as well we can add new items to it and it'll grow its storage as needed so if you look at the documentation for that arraylist class again it's the non-generic version so i've got three constructors i can just create an empty one i can create it and say put all of these items in it and i can create it and say reserve this much space to begin with i've got some properties that gives me some idea just how big is this thing what's in it what's the count how many items are actually stored there i can get or set an element add a specific index and i've got some methods where i can do some add i can add a whole range of items i can search for something to do a binary search which will only work if it's sorted i can do remove all the elements i can do some copy i can see if something's in there and again do some of the standard enumerations to work through some of those find where an object exists if it does exist insert instead of just adding remove items from it i can reverse the whole list i can sort it i can turn it into a fixed size array and i can trim it to a certain size note that with both in there's both this insert and add again and here they're going to be implemented a little bit different internally because of the performance metrics if i want to add something that's just putting something on the end if i want to insert something i'm going to have to open up a slot somewhere move everything else over one and then put the new element in place so now if we look at how that's built again we're going to just search inside this particular solution we're going to look for arraylist and again we're just going to find something that's that has the type there we go i think i actually found the internal class itself or one of the constructors so again public class implements a couple interfaces which we'll talk about later you can see that it's storage here is an array of objects okay and it's got some other properties internal members that give us an idea of about its size i'm not sure exactly where version is used unless it has to do with how it's storing things and serializing itself this private object sync route is going to be used to lock the connection when we have multiple threads possibly accessing it we've got a default capacity and we're going to give a static idea of something that's just empty and now you can see we're starting to build some of the constructors we can see we've got setting some items to this empty array which is this read-only thing that's just empty we're going to be able to have a capacity so we're going to say all right i'm going to build a certain set of a certain class that's got a certain storage internally matching that capacity here we can see one of those performance improvements already notice that anytime the arraylist is going to take the size of zero it's using this default read-only empty array so this class is only ever going to allocate an array of size 0 exactly once it's going to initialize this put it together and then anytime it needs an empty array it's always going to use that same storage so it avoids allocating that rather common empty use case often by always reusing the same storage so that's going to mean that this class has less of an effect on adding and releasing memory and slowing up the garbage collector than it might otherwise have so creating empty arraylist is just going to reuse the same object over and over we can construct it with a collection pull things in place now we can read what that capacity is get at its count and again the things that i really want to look at here we're going to look at that append method or that add method and here this is a relatively simple method but it's going to use a couple things internally so if size is the current length of the array so if the size of the array or if the size of number of elements that we've actually stored is equal to the size of the array that we currently have well we're going to need to make sure that this thing is at least one bigger then once we've done that now i can add items into the size i can increment it and i can return the new size of the array so i'm going to store this thing at the end of the array once i've ensured it's got enough capacity so if you look at that private method for ensuring capacity some comments on there that say all right it's at least big enough to hold this now this is going to take a common algorithm that usually gets worked really well for collections that change size over time what it's going to do is if i don't have enough elements i'm going to either say all right let's just make it the default capacity if it's zero otherwise i'm just going to double it in size okay so i'm not constantly when you're adding elements to array i'm not con or an arraylist i'm not constantly incrementing a new array of one bigger i'm going to grow this thing in sections to see you know and eventually grow it very very big it turns out that that's a very good algorithm for performance so i start at this size you know because we often create small collections say 10 15 20 elements so i don't use a huge amount of storage for that but i'm going to grow it quickly and see that you know if i'm really using something bigger let's make it a lot bigger so i don't keep allocating every time i add something and in addition to that what we're going to see is after we go make that capacity we need to we're going to need to um look back at where we started this should also copy those elements once we create a new one yeah i think that's back up at the top of the in the previous section there okay if we go back to add once we get that in place it should be underneath here because if the next one is just doing a set of because items is just that array yep so it's already got that it's going to put it just in that place if we pop back to add again once we do that ensuring the capacity that should have to do the and close this if that do that and then ah there's y it's inside this where if i want to set it you see we're going to build it and if if the capacity that we're setting it to is not the same as what it was i'm now going to allocate new object a new array of the right size and if our arraylist currently has items in it i'm now going to go ahead and copy all the existing items in so every time i grow the array i'm or the arraylist increase its internal storage i'm going to copy the existing items into the new storage and then i can work with it in its new size good i'm glad i found that i was afraid of that for a minute they were even hiding it from our own code review okay so that's one of the main things there and then finding things out is merely looking into that array and we find different things inside it basically this is a wrapper around an array that can grow and shrink itself and if we look at remove that will be sort of our last part of the code review here so if i want to remove we'll do a remove at because it's a similar but slightly simpler so if the index is not inside our current size of the array throw an exception otherwise well we know this is going to be now one smaller so we'll decrease the size and then we're going to copy everything from the latter half of the array after the index we're removing back over that one slot so like if i'm removing the element at index 5 i take everything from index 6 to the end of the array copy it over so it now takes over the space of 5 and then remove the very last element by setting it to null and then there we are we're at the next point so once again really hiding that complexity so now what we've seen so far by doing this this review is in three different examples we've seen classes that were if we look at arraylist if i go to the end of it 2600 lines to wrap and to encapsulate the api that's mentioned by 15 or 20 different different public methods that we use every day each one of these is in similar size a lot of that complexity is hidden from us we need to as a mental model know what it does we don't need a mental model of how does this solve it every day when we're using it and that's really what we're looking for so now let's look through and let's after finishing the code review let's try to put this in practice ourselves great so next up is our we're going to go over the lab exercise that we're going to have you uh take a take of practice at and with encapsulation encapsulation is a great concept and but it can be a little bit tricky to really um be confident in in your encapsulation and so when you first implement this it may not be exactly the way that we have implemented it and that's okay it's it's all about practicing this and developing that muscle developing that skill to be able to encapsulate things fully so uh our encapsulation lab uh we're gonna ask you to create a student and uh that students can be modeled uh inside a school and there are several key considerations we want you to take into effect when you're designing your class the first one is does each student have must have a name and id number the second one would be that the student needs to have a gpa and when the student finishes the course we want to be able to up update the students gpa and add a new grade to the history of the grades that the student has and one of the things that i want you to work through on these exercises is for each one of these modules we're going to add some features to this library of functionality about a school student and you know we'll eventually add abstractions for teachers and so on one of the ways you should grade your own solutions to these is how much you need to modify as you move forward instead of just enhancing and adding those modifications would be things that would slow you down in a commercial application when you get to release two and three whereas enhancements mean we're just building the new functionality so we're often going to want to continue to do that as we do later releases but we're hopefully not going to want to break apart the things that we've already built so that's one of the keys we want to get through especially starting here with this idea of encapsulation as an object-oriented practice so with that you should take a break try to solve that first exercise build the code james and i will be back and we'll discuss one possible solution and then we'll move on to our next major topic of inheritance see you soon welcome back i'm bill wagner and i'm james sturdivant and let's review one possible answer to that initial code problem that we gave you so we ask you to create a student class be able to set some of the properties in it and be able to compute letter grades so i've got my solution here and we'll let james kind of help walk through this let's show you where you can find the code and you can look at our solutions and compare them to yours so you can download the code here from my github site you'll be able to pull each different branch which will be labeled by modules so it'll have the solution for just this module at this point further labs will come later so now i've got the code on my screen so we'll let james kind of walk through and do sort of a code review see how my solution works and see if i follow some of the behaviors and see how i interpreted some of the requirements all right so i've got everything sitting up here so uh the first thing we see here is that he created a class student for um that that's going to encapsulate all the student logic and then we see that he has a one constructor with an id and that id is being set to a read-only property id so bill can you tell us a little bit why a little bit about why you chose to make that a read-only property right so i was thinking that the student id is something that would never change the idea being that you know once we've added a student into the system that id is probably something we're going to use to find a student later or to print out grade reports or whatever so that's never going to change it will be immutable in the in the vocabulary that we usually use so i said that that should be set at construction time and there's no way in the code to change it and if you look at the implementation i'm making use of one of the new c sharp six features here you notice that this property has no set to find that's what's called a read-only auto-implemented property you look inside the constructor and i'm allowed to set it so i can set it in a constructor the compiler allows me to do that but if i were to write any code that tried to set the id in one of the other methods of this class i would get a compiler error so i'm really trying to leverage the language to enforce that design choice that i made that said when i read the requirements i really think this idea is something that's never going to change great so next up we are going to take a look at the first name and last name that was part of the requirements was to be able to record those names and so it looks like you've given it not only a read-only sorry a read property but you also allow you to set that throughout the design right and there i was thinking two different things one every once in a while some people mistype a name and you shouldn't have to live with that you should be able to change that so i wanted to be able to set it and people do sometimes change their names you know whether it's if they get married take on a spouse's name or hyphenate and do something with their spouse's name maybe they've got a name that really is is uh causing them some problems there's some famous names that have some negative connotations i know a couple people have changed their name because no relation but they just were tired of hearing it so they wanted to be able to change that so that's a possibility i doubt it would happen a lot but i want to at least leave that open great so one of the other uh requirements that we we wanted to have there is to be able to work with the grade point averages um and so i see that you have a function here that's calculating the the various uh grade point average so can you talk us a little bit through that yeah so this this part is the part that really has some implementation in it so first i created an enum for the letter grades so i've got this enum for a grade and if you fail it you get zero and a standard american system of one point for a d and an a is a four point so so that because i've assigned those values you know that would be the underlying integer value of each one of those letter enumerations so then when i go back into the student class first if we look at just recording a class grade so i'm going to say all right so anytime you get a grade for a class i'm going to add that new the integer value of that grade to the total sum of all the classes that you've taken and i'm going to increment the number of classes that you've taken so now i've added one for each of those and now in terms of this calculating your grade point average well if you've taken some classes i'm just going to take the sum of all your letter grades and divide it by the number of classes you've taken and since you can't divide by zero i'm going to say that your grade point average is a zero if you haven't taken any classes i'm not really sure i like that but i didn't come up with a better answer you know it doesn't feel like something that should throw an exception right because that doesn't feel like an error condition it's entirely possible that you know an incoming freshman hasn't finished any classes yet the only thing i might consider changing there is i might think about making that a nullable of double and by making it a nullable then i could return a nullable of double with no value you know in the case when someone hasn't taken any classes yet but this seemed to work for now and if the requirements change then maybe we can make that change but it seemed to be a good a good first cut great so i noticed that you are using some logic in there for the if if then else can you explain that a little bit and why you decided to choose that so there's a couple different things that we did there i i'm using first this this arrow syntax is i'm using what's called an expression bodied member you know so competing the grade point average is one simple instruction you know other than the the check to see if you've taken any classes at all it just performs a division so rather than the extra ceremony of the curly braces the return statement i'm just using an expression-bodied member since i'm using an expression-bodied member i have to use a single expression not a full statement multiple statements like an if block so this question mark and then the colon over here is what's called the conditional operator or sometimes it's referred to as a ternary operator because it's the only operator that has three arguments the first argument is a boolean expression evaluates to true or false and if it's true the first clause immediately following the question mark is what's the expression returns and if it's false then the second expression following the colon is what's returned so this basically says if i've taken some classes perform the division and return the result of that division if i haven't taken any classes then just return to zero great so this does look like it meets all the requirements um i i think your code may not look exactly like this and that's okay as long as you you have some of these similar uh these similar patterns and so i would consider looking at your code and comparing it to ours and our bills and see what was some of the things that you enjoyed in bill's code and what were some of the things that you enjoyed in your own and with that we'll come back and introduce our next concept and start talking about inheritance hello again i'm bill wagner and i'm james sturdivant and we're here to discuss the next module in object-oriented practices we finished encapsulation and now we're going to move on to the idea of inheritance inheritance is one of those really core concepts inside object oriented programming object-oriented techniques it's the idea that something is well like something else and we're going to try to inherit all the behavior from that base class has a lot of interesting techniques that we can use in this one we're also going to start to introduce the idea of risks of maybe this isn't the right answer and how do you see that maybe you're not using the right technique so we'll go through in this particular topic where we focus on inheritance we're going to have five different sub topics here we're going to define what it means we're going to look at some of the guidelines look at some of the practices that enable inheritance and then finally we'll talk it about as you're reviewing code what kind of things you'd look for in terms of seeing proper use of inheritance and what some of the risks are the idea that maybe it's not the right solution for the particular problem that you're working on so let's begin with a good definition of the i of what inheritance means inheritance is the technique of reusing code by creating base classes for behavior that is shared by multiple derived classes that implement specializations of the base class so what does that really mean that's a whole lot of big work yeah that's definitely a lot of big words all right so let's break that down so first we're trying to reuse code right the idea that things that are similar we should be able to put the code that deals with the similar parts in a place where we're using the same code notice we're talking about shared behavior it's a lot more about what an object does or what a class of objects do and what their capabilities are than the particular fields that are stored inside a particular object and then those derived classes we talk about specializations you know the the classic things that we'll often hear is this idea of you know we have an animal and a dog or a cat derives from animal when we're modeling different business objects the same kind of thing can happen the behavior of certain particular specializations may be similar to something we've already built and if only i could reuse that code yeah and i think it's really important here to to note that it's really about the behavior and not the code itself occasionally it's okay to have a little bit of duplicated uh words the letters themselves but it's the behavior that we're really looking after it's really important that it's the behavior so that when that behavior changes we don't have to change it for all of the classes for all those animals for the for all those items that are being changed right so let's look at the advantages why do we try to use this why did this whole object-oriented thing become so popular the biggest one is just this idea of implementation reuse we have all this implementation for a concept if we can reuse it more often we can build more functionality without writing all that extra code it's already there if we factor things out to be able to find the common parts and that shared base class implementation we only have to implement it once we can test it once and it gets used everywhere and in fact if we find a bug or if we want to add a new feature that's common across all these different derived classes if we implement it once properly in that base class we've now implemented it for all the derived classes as well so that's a big big plus yeah and when you are using all that code in one area that also means that you're not duplicating that code and means a smaller code base and a smaller code base means that you need to that you don't need to worry about handling as many changes and working through all that code it's easier to understand it's easier to make those changes right code that doesn't change doesn't break so it's changing in fewer places and then finally we get that polymorphism support that's another one of those words that comes from the computer science vocabulary of this the idea of polymorphism is i can treat an object like any of the classes that are part of making it up right i can treat a cat like any animal i can treat a dog like any animal like any living thing if we went that way and followed the whole you know biology tree so i can write a method that deals with an animal as an object and anything that is derived from animal fits there so in addition to just that reuse of having that common implementation other collaborators that work with a particular object type if it works with a base object type would also work with any of its derived types as well and that will find throughout the framework in different areas so next up we'll talk about the language support for inheritance when we start to talk about this we have classes that can declare a single base class these classes are are the class that implements all that shared logic that you're going to be using and the classes that want to reuse that logic are derived from that class and um there's a few different uh keywords that we can use when we're working with those classes the first one is a protected member and that protected member is going to allow us to allow the inherited classes to be able to access that but not any of the other classes that work with it not any of the public classes it's not public it's just protected so we can't have an interface that's that's exposed to our derived classes i want to go back and add one thing when we talked about declaring a single base class dotnet whether it's c sharp or vb supports single inheritance similar to java c plus plus supports multiple inheritance where a class can can derive from multiple base classes over time we found there's advantages and disadvantages of each personally i like the single inheritance restriction multiple inheritance can get to a lot of very very thorny problems if you're familiar with and have worked with c plus plus so that's one of the important simplifications in net and and java and a few other places is that we have this single inheritance hierarchy and then finally as we move on from protected members we've got this idea of virtual members so we can talk about the idea that an a derived object implements the same behavior as a base object but as we talked about in encapsulation it may do it in a very different way um you know for instance say cats and dogs are both carnivores so they will hunt rodents and things they do it in very different ways cats are much more singular hunters you know in general some are pack animals dogs are much more pack animals and so on so different classes may implement a particular behavior in a very different way and we can define that by saying this is a virtual member any of the derived classes are free to implement this behavior differently so we get a little bit of both worlds we can choose a base implementation or we can override it and do something maybe more specific in practice and in some of our code we may find that a drive class can implement a particular algorithm more efficiently because of its specialization you know or maybe it just has to do it differently because i was put together and then finally we'll talk about in the next module a virtual method can be marked abstract meaning that a derived class must override that method and must do something different because the base class knows that all animals may have a similar behavior but there may not be a common implementation for everything so how do we go about finding uh these uh relationships and the inheritance that we're looking for one of the great ways to go about this is this guideline that we call is a is a model is a item uh something else and so you can say a cat is a animal a dog is an animal uh is an animal and so that's gonna give us a key to the fact that maybe they have some shared behavior right and and one of the things that i do is i'm working with customers and we're trying to design an application or trying to find those classes is we start by defining those those leaf classes the things we know we're going to build and then we look at what's similar and say you know is there an abstraction here that we can put in place to define some of these things so that it's we have some commonality some common base class to inherit from and we look for that common behavior you know finding say if i were you know building some kind of a um some kind of a customer service application you know a customer you know is you know we find we find customers when we find orders we may find you know special orders well special order is an order you know we may find a recurring order recurring order is an order you know we may find um you know other things that we can find you know these things are similar and then there's something that we can find that that seems to be some common ground among them and then as we look for that common behavior and if we start to model it with that is a relationship that catchphrase does really help identify where we can find inheritance to try to move some of this common common behavior into a single place and that's really what we look for when we're trying to put that together but i do think that starting with the leaf classes putting that in such a way that i see the things i have to build then that helps me visualize the things that are common and the behaviors that are common among the the actual physic you know concrete classes that i have to build that are part of the application and so we've kind of uh talked about this quite a bit here but we're looking for that common behavior that is shared between the classes a lot of the times you might see that there's some common storage that you're working they're both classes are working with um but that's going to lead that may lead to uh times and spaces where that uh that common storage isn't actually like a a good example that i've seen in in some code reviews that i've done is i've seen companies build something where they have a lot of entities they store in a database and every entity you store in a database has an id field that's it's it's key index right that's often an integer so i've seen them maybe develop a class that is you know item with id right there's really no common behavior there it's it's an end there's nothing they're really saving and now they're inheriting everything from object with id field and that really doesn't gain anything that's not a good abstraction you know whereas if you look at something like say entity framework where if i inherit or create something that's a db set and inherit from a context that's things that go in a database and there's a lot of behavior to read and write out of that database for different entity types and and i get a lot more behavior and a lot more code that's shared you know something that has a or has the same storage i don't get that same kind of kind of reuse from so that's where that's searching for that common behavior where these things have common stuff you know like the one i was just mentioning where you know if i have customers in orders and special orders and recurring orders the behavior of an order is the same i need to ship it i need to pull it from the warehouse i need to charge someone's credit card for buying it there's behavior there and that's going to pull in some things that we think are common right and and gets us some of that that code reuse that we're looking for and there's a really interesting you know computer science way to do this you know and and i know a lot of developers are coming to you know joining the ranks of developers that don't have a computer science background but i think some of these concepts are important and we'll go ahead and define them so you know our next slide has the list of substituted substitutability principle it's that l in that um in that solid principle that's i'll let phi of x be a property provable about objects x of type t then phi of y should be true for objects y of type s where s is a subtype of t that was actually in the you know the whole principle that wrote this whole paper about it and what that really means if we boil this down into plain english is any place i've got a type t which has certain properties well if type s is derived from type t it has all those same properties there we go it's going to behave the same right so i can substitute an s any place i have a t as long as i'm treating it as the properties of t right i can put a derived class any place i have or ask for a base class as long as i'm treating it like a base class and we've mentioned that is a property and uh it's really important to realize that there's it is a and you want to be careful that it's not almost is a and a great example of this is this square and rectangle and it actually violates this list of substitution substitution substitutability substitutability principle right and how does it do that like what would be a good example of that uh it's it's around the width so you might think that a square is very similar to a rectangle well a square is a rectangle yeah right it's a specification of a rectangle yes i should be able to do this yep um and so if you inherit that square and you try to set the width or set the height those are two functions that you might have available on a rectangle because you might say the the rectangle is five integers high and it's 10 uh it's 10 wide and so uh you might have that rectangle with different widths and heights right but if you expose that functionality to the square now you've ended up with a square that isn't doesn't have the width and the height similar right because a square if in order to be square with the knight have to be the same so i'd probably define that to have just one property for the length of a side because they're all the same so now i've got this extra stuff that's it's not really there you know does width change both width and length if it's a square that probably breaks some code do i try to hide those well it's kind of hard to hide it because it's in the base class it's not substitutability anymore do i throw exceptions that's a really bad idea because now if i'm using this derived class and i call something in the base class i throw an exception those all those things are going to lead to bugs so we really want to get to that if it's like this everything that this base class can do the derived class can do you know we really want to avoid that idea of no no you know this is almost not quite so now you know as we get past some of these guidelines and what are we really looking for how do we put this stuff into practice you know let's start to build some of this idea of what kind of habits do we build as a developer so that when we're working with inheritance we probably do it right and we're less likely to fall into these pitfalls of hitting some of these these cases where it just doesn't work so one of the first things that we do and and this is one of the big ones that i work with junior developers you know we all have that you know control c control v reuse right i've found some code i need i'm going to copy it i'm going to paste it and then i'm going to make them changes because i need something that's almost exactly like this and i want you to stop when you do that because what you're doing is you're you're doubling the code base you know at least if it's a small code base at this point you could be close to doubling it you've now got two copies of this code if there happens to be a bug in one of them you now have to fix it in two places you know that's not good what i want you to do is try to look at the common parts and create that common base class i now have this thing that says these you know this new thing i need is almost like what i have so can i factor something into a base class and then these two new things which are different are both small and derived from one common thing right and now i'm sharing that code and i'm doing that and i'm not going to say that you know copy and paste is always bad you know but it definitely is one of those things when you start finding yourself doing that and saying i'm gonna just pull all this over and make a couple changes you know finish that work and and maybe learn what's common and then try to factor that out so you have one copy of it by the time you're done yeah that copy and paste is that kind of light bulb moment where hey maybe i could actually use one of these practices to implement something right and then one of the things that we really look at is you know look at our base class library there's a lot of things that you're going to find that you can reuse you know one of the areas if you built an mvc application all of your controllers derive from a class in the dot net framework called controller right and that's already built for you you know all of your web api controllers derive from that class all of your razer views derive from a base class in dot net they're going to be a lot of those because it's called the base class library you know a lot of those classes are specifically designed for you to inherit from and extend for specific scenarios that you have and that gives you this really tested implementation of these common patterns that you're going to use you know we have this controller i can just reuse it has all the stuff about the http context all the things about it by authenticated and where are the cookies what's the request object and how do i do the response rights those are all built into that base class i don't need to re-implement all that myself you know that's a really good thing so that's one of the a friend of mine had a talk that he gave at usergroups when dotnet first was released that was just called don't write that code and he was going through this library of things that is already there for you that you can use because it was it was new and people weren't that familiar with it and and now it's it's not so new but there's still this new generation of developers coming there that start building things that are almost like stuff that we might already have so that's one of those those things i really work with junior developers and go you really have to look for these things there's a lot there yeah and um so next up we're going to take a look at another practice where we want to be looking for common behavior and that common behavior might not um be something that is available through the storage we kind of talked about this before a great example of this is the stream classes that we have in the in the base class library there when you have memory you have a memory stream you have file streams and then you have string streams and they all do very similar things working with those streams but the actual data layer that they're working with is very different so like i can write to a stream i can read from a stream it's very common behavior but if i'm just writing to a stream i don't need to know if it's going to locations in memory a place on disk a place on you know a storage for a string um could even be going on a network i think there's network streams too yeah we didn't add on this slide but that's another example of something that has that common behavior and that common kind of implementation yeah and so we can use the inheritance to tie all these items together so that we can have that common right we can have that common read implementations in in one place we control things like buffering you know maybe i write for a while and then eventually it gets flushed to disk or flushed to the network and so on yeah so now for the last section of this presentation let's let's look at okay so if i've built stuff the way i want to what kind of results do i see that are positive on my code base and what are some of the risks that i might see what if what am i doing wrong you know how can i tell if i'm doing something wrong here so you know one of the first things i look for is do i have code that's have i factored out that common code that common behavior you know i'm not duplicating work in different places i don't see classes that look like deja vu i'm reading the same code why is this the same you know and i don't and i don't see that you know that's one of the big ones that i look for you know and especially if i find a new thing that's almost like one of the ones that we we already had these new derived classes can be developed quickly right i just need to leverage what's already there i can make a new one you know that that really works well that's one of the things that i really look for it's hard to see that last one immediately but it's a it's a good idea right when you start to see that you know you've gotten it right another great outcome is when the polymorphism is actually working and you can tell that when you're working inside a class and you're using those implementations and you're not having to you're able to work with that base class and you're not having to check the type to do certain things and to call different functionality on those types and so this is a great example of where the the list off substitute substitutability principle really comes into place you know it's one of those things where if you see if you ever see it you know if type equals if type equals you you know you you didn't really have a good inheritance like a hierarchy because you shouldn't have to make that check right and i think that's definitely true but again you know this is one of those things an inheritance is one of the techniques that we'll work with where there's some really good things we can get out of it and if you misuse it you can start to really see some bad things in your code base so we also want to highlight some of those risks that we want to look at and see you know if you're going down this road you probably need to look at it again you know that that almost is a we talked about you know where uh you know well yeah so i think there's a really great great quote there that says if it looks like a duck and quacks like a duck but it needs batteries then you might have a leaky abstraction yeah yes great way right of looking looking at it there uncle martin definitely put that out and that's one of those things you know if it's if it just doesn't feel right and it doesn't get acted that way you know we do that or if you find you inherit a base class and you have to override some methods to just throw exceptions because it doesn't work in this instance you know that's another good example of this isn't going to work here this isn't the right abstraction it's definitely leaking it's definitely now showing that that's not working another one that i find really interesting that's that is a more modern phenomenon as we've worked through code bases and we started to build really big programs for a while there was this this trend where you know this is probably early 2000s or even 90s where object oriented was the way to solve everything and polymorphism was everything so we made these super deep inheritance hierarchies of you know this inherits from this inherits from this and each one had one new method in it and you get to one of your leaf classes and it was really hard to see what was going on it was super super deep and super hard to work with and these these really deep hierarchies make it hard to use a library you know and if you look through the net framework a lot of the things from you know system.object which is our ultimate base class up to the things we're working with might not be more than four or five levels deep you know we're it doesn't get to this 10 15 20 levels deep that are just hard to manage and if you find that that could be one of those those cases where you just built some wrong abstractions and some of the techniques we'll talk about later today would be better suited to solve your problem another one that you really see that i think is it often shows up in code bases is if i need to downcast if i have a method that takes a base class and i have to cast it to something that's derived from that base class in order to do work because i need something that's in the base or in the drive class that means i've probably got the inheritance hierarchy wrong if i have to know if i've taken an object that's a base class and i have to cast it and do something special that's probably another example of that leaky abstraction that's that kneading batteries thing i thought it was a duck but i need batteries so i have to down cast it to the motorized duct and add the batteries uh and if we see those down casts that's that's a good idea of look for a different way to solve this problem yeah and then and it gets painful really quickly so if you have if you have to be doing that throughout your code then um you're going to be running into all these places where you have all these extra conditionals inside your code and when you have all those extra conditionals it's just another thing you need to be thinking about it's another place where it could introduce a bug right and it's so much harder to test if i have this method that says if derived classes type one do this if derived classes type two do this drive class type three do this other thing that's a lot more tests i have to write you know i have to go through all those cases what if it's a different type what's the space of how i do it with the you know derived class one and so on it just explodes it's really bad and with that i think we've covered a lot of the main points that we really want to look at for working with inheritance in object oriented systems with that we're going to take a break and we're going to come back and do some code review on some of the areas in the bcl that's leveraged inheritance and how you can make use of those in your programs greetings i'm bill wagner and i'm here with james hi i'm james sturdivant we're going to look at some of the code review now for inside areas where the net framework is using inheritance as one of their ways to get a lot of reuse so we're going to work through some code in a different part of the dot net framework primarily part of the web stack we're going to have four different sections here we're going to look at the mvc controller we're going to look at the multi-select list as a base class we'll introduce the lab work for this section we'll take a break let you work through and try to come up with your own solution and then we'll come back and work through the solution we developed so let's start with looking at the mvc controller we'll start let james walk us through that and talk about some of the areas that we can work with inside the mvc controller great so first we'll define what mvc is nvc's model view controller and so what the part we're going to be looking at is the controller and that's really the part that kind of coordinates the requests that are coming in from the website back to uh and gathering data and then passing that off through the model to the view and the view is does the display and so we're going to kind of look at the controller this is where you're going to be using the the base class the controller to extend and add your own views add your own uh end points that you're going to be exploring so so on a website like if i've got a a a set of urls that i want each one of those maps to something in a controller so a url goes to something in my controller right right okay and then it's going to return a view which is the page that i'm looking at correct and because it's dynamic that model is going to be the data that's displayed inside that view that yes something underneath the controller's calculated yep okay and so the controller when you implement your own control you're actually inheriting from this base controller that we're about to show and that base controller gives you a bunch of different features that you automatically begin to use and so we're going to take a look at what a few of those look like so down here i've opened up the controller class i'm just going to hop into full screen here and we can see that the controller class actually inherits from a controller-based class and it's getting a bunch of different features from there if we look down below we've got a few a bunch of different objects and class member variables that are being used internally and so you won't actually have access to these variables here when you're inheriting but you will get access through them through some of the various uh properties that we have exposed so so they're private not protected that's correct can't directly access or change them okay yep and so you can see down here although the uh async manager uh is private up at the top when we scroll down you see that we've exposed the async manager through a get only property and so this means that we can actually get access to it but we can't but we can't necessarily write to it okay so we'll kind of keep going down through the code here and some other things that you might be uh interested in seeing here is the model binders and so uh here you see that's a protected class and so we can actually um get access to to this particular uh model here so if i've done all client development on on desktop what what does a model binder do in in the context of a controller here sure so a model binder takes the um takes all of your so if you make a request on to though to the website you're going to be passing a bunch of strings and so that's the the strings that are coming through are um are just basically key value pairs and so the model binder that'd be like all the stuff on the url after the question mark i've got you know this equals something and that equals something else and and so on yeah you got that right okay yep and the model binder will actually allow you to uh take those strings and put them into an object inside c-sharp so that you can start to use that object inside your code okay so my controller methods don't take just um they don't take just strings i actually get an object that's got those keys and values and the keys are the names of the properties and the values or whatever the value of those properties are oh got it okay and so uh i don't have to write this yes you're right exactly and so this is the kind of code that uh the the base class really brings up to you and surfaces to you uh and then also if you look down here we'll also see the various route collections so we kind of talked about um where those bits of like when you make a request where does it actually end up what what method does it actually look into and so this has a list of those route collections in there internally and it's all implemented for you so a route is how it maps everything in the url after after my host name to the name of the controller the method and the parameters on it you got it okay okay yep so you see there's a bunch of other objects in here if you're familiar with working with a controller these are all ones that you have used inside so if you want to get the current user on your your system uh who made the request this is you're going to go and go controller or this dot user when you inherit from this and so you don't have to worry about where that user is coming from and you also don't have to do all this extra checking for the http context so the controller that base class has got all the implementation to look at the http context that comes up as part of the request and it's figuring out who's logged in either from a session or from some other provider and it's giving me this object to know who it is so it's already done all that work it could be anonymous it could be somebody's logged into my domain it could be it you know um my own site has its own you know the the baked and asp.net authorization for individual accounts any of those and i get this object back that just says who's logged in that's correct and the base controller does that so anything i write i've got access to all that you got it okay yep um and so i think some of the other things that you might see in here there's quite a bit of logic here particularly in the action invoker so which action action are you going to be doing are you going to be calling the get method are you going to be calling the post method within your controller this is going to do all that logic for you and so you don't have to actually implement this every time you work with a controller so that's part of the http spec so if i'm anything i type in the address bar that's a get you know when i've got one of those sites with javascript and ajax or forum post that's coming in with one of those other verbs right you got it yep and so um you can see that there's quite a bit of code in here that when you actually implement your own um controller you're not having to rewrite this code but you get access to that you know i think that's what i find amazing here anytime i i do any of the web development with mvc any of the methods i write are specific to the the actions that i want my controller to resolve right you know i've got my home controller i've got index and about and whatnot or you know i've got a controller to look at a catalog and it's got you know the list and item details and you know whatever my domain is and i don't need to do any of this other stuff that's all in there because my controller is a controller right you've got it okay yep so uh i think the final method here we'll take a take a quick look at is this execute method down here this is a method that's actually called through the mvc pipeline and this this is where it's going to actually call your code and we're not going to go too deeply in here but what i wanted to show was that there's quite a few different things that it's handling for you it's loading your possible temp data that you might be using and that's say you wanted to store some data between two requests you would put it into that temp data and so it's going to actually load that data up for you so you have access to it is that storage server side or does that go back and forth that's stored server side okay okay yep and then it's also going to if there is no action it's going to handle the handle that for you and so if the so you don't have to worry about handling all those use cases where someone might pass the wrong url or make the wrong request to the wrong action they're going to actually go ahead they're going to handle this for you and potent and return that 404 for you so that so that would be if somebody goes you know slash home so they hit my home controller slash some unknown method name maybe they're trying to probe my site or whatever this is going to just give them that default 404. you're trying to find something that's not there you know we won't expose the yellow screen to death and say that that's not here or any of that sort of thing yep and so that's that's a whole bunch of code that we don't want to have to re-implement every single time and so it's been put into this controller here cool okay and now so we just derived from controller and then all that stuff happens and we just have to implement our other stuff yeah you've got it okay so uh real quick here i can actually show a potential inheritance here if i go to find all resources i should see that they've implemented the i think a lot of their test code is going to create real controllers okay i think the test project is going to have a number of them where they create and instantiate a controller that then they use to to get at some of the protected methods and so on yep so we can take a quick chance here and look at this my controller it's inheriting it and this is kind of exactly how you would do it this is the action name here would be method and you can come in here and start to return um a view from this controller and now i've got all that signature it looks like this oh that's set yeah um it would be i uh i think it's view result is that right a few results nope well we'll go back here we can start to implement our logic inside this this controller here and you see that we don't have to worry about how all that other stuff is being implemented okay so okay up next we'll go ahead and move on here yeah so the other one that i find interesting that that we dive into inside the mvc space is when we're building models there's different kinds of things that we're going to send down that we want to display in a page and one of the ones that we picked out to look at there is this multi-select list and a single select list so there's an inheritance hierarchy there where the the team decided that one of those is a of the other thing right so let's look at the multi-select which is one of the objects you can use in one of your models to send down as part of the view and let's look at what's built in there that maps to that particular html element yep great so the multi-select list is if you've ever been to a website and you have uh a box with a bunch of different items in it you can select them that's that's when you'd be using uh one of these multi-select lists and that is implemented as the as the base class and later on is inherited by the select list which only allows you to select a single one and so you can say a select list is a multi-select list so we'll take a quick look here at multi-select list and you can see there's a bunch of different constructors that we're going to be using here we've kind of seen that before you can build these out in multiple different ways but i think the really interesting part about all of this is down when we get down to the actual implementation down here where we uh where we're seeing all the various ways that we can actually access the list and so here they're checking to see if the list is null or empty and then returning the data field and then if otherwise it's going to get a list with all the value items okay so we may have this this item that's there this um field that's that's meant to be what gets displayed as part of the objects we're binding to the list is that how that's working we'd have different parts of it that are that are underneath there let's go back and look at that code again yeah real quick here so so we're looking at this string value for that data value field and then we're going to get the items either with it or without it it looks like yes yeah okay okay and then it's you can also get all the list items with the value field and so this is this is where we're seeing some of that uh encapsulation that we had right so those two are private we're to pull back a list items but how we construct them is going to be different based on whether it's has the data field or doesn't correct cool okay and so you see there's again there's a bunch of different code in here and it's it's very it's very similar but different throughout the whole thing right um and as we go through here we're seeing how all of the um various groups uh if you wanted to be able to get like a set of uh items inside there this is this is one of the functions that's implemented internally to get those groups so we're seeing that throughout the whole thing okay and so if we move up to select list we'll see that select list actually inherits multi-list and we have a few constructors that are overriding those because we can only select one item in this one here so this is sort of interesting this is a case of inheritance where what we've done is the derived class has what feels like less functionality than the base class yeah so we're driving it by restricting some of the things that you can do yep okay that's that's interesting and uh you know let's see how that works yep so if we go down here you'll see that you always have to have a selected value and so you can set that during the construction of the the object but when we come down to the the bottom here almost there once we're past all those constructors yep you see that we can always because with the constructor we always have a selected value we expose this extra object that shows which one is is selected right but now we can't it looks like we can't change that or or no we change it yeah it looks like we can't change it cuz it's got a private setter so when we're sending this down we won't be able to change it once it's been set so this list has got just that single item selected and then we're going to get another call back to our controller with a model that comes back if the user changed that and they're submitting back and then we can then set this selected value through that control so we'll create a new object with a new different selected value when it comes back that's how that's working okay so we're really restricting what we can do there because this is meant to be we're going to create this thing send it down and then you know that our controller goes away because it's the end of the request and then we're going to get another instance coming back and we're going to have another object that gets created okay okay so when you create that when you you can only create this through the constructor you always have to pass that selected value and that selected value can't change once you've instantiated this okay now it looks like once we get to multi-select okay it's got methods that will allow us to select multiple things but once they're selected it also won't let us change them right so you can't really go back and go dive in so because of the way this is set because it's we're setting what's their server side and then when that goes away you know we're with a new request we shouldn't be modifying it later because otherwise i'd feel like maybe i can go around this restriction and say i'm going to use just the base class you know apis to change what's selected and modify that but it looks like those weren't part of that multi-select object either you know unlike in you know i'm going into this little bit just because i think some of our audience may be more used to doing things on windows where we're doing data binding and it's bound in such a way that when the user changes something it changes the object whereas here on the web with mvc we're creating this thing that we're sending across the wire and then our server-side objects go away effectively and then we'll get back into the class request so i think it's important to get that so that they understand how how these concepts work in in a slightly different problem space cool okay now i think um before we go on and introduce a lab exercise um i want to look at one website just because we're doing things now in a different place in an open source project the asp.net web stack at least the all the versions before asp.net 5 which we're recording this in october of 2015 isn't released yet you know it's pre-release we can look at it's open source but we're looking at the version that's from the currently released version of asp.net and most of that code is still on a open source project on codeplex asp.net or asp.netwebstack.codplex.com and that's where this code is where the mvc controllers and so on live so just if you want to grab a copy of the code yourself and clone this repo to look through some of the things that james just showed you it's in a different spot than the earlier versions and with that let's let's introduce what we're going to do for the lab exercise to work with inheritance you know where we want to look through and extend what we built earlier and talk about or think about how to put that into some common code underneath it so for our lab exercise woo hey so for our lab exercise this time we're going to expand that previous lab and what we're going to want to do is we're going to introduce a teacher into this hierarchy so each teacher is going to have a name and once again some id that gets stored in our models and each teacher has a subject area that they teach you know maybe they teach math science or history or maths if you're from the uk we only have one math here in the us each teacher has a list of titles for the classes that they teach and as we put that together think about what could be common with that student object that we already built in terms of both the behavior and in terms of how that could be put together and is there a common base class underneath that and with that time to for you to go ahead and try to work with a little bit of what we've learned put in some simple inheritance we still have a small hierarchy so it's not super super deep and super complicated and then we'll come back and look at one solution and then we'll move on and start talking about interfaces welcome back i'm bill wagner and i'm james thirdevant so let's discuss our solution to adding that teacher class into this lab and see how we can factor out some of the common code so the problem that we gave you was to introduce a teacher that has some of the same capabilities as a as the student object and some other interesting capabilities that are its own so let's look at how we would go about solving that problem and where we end up with the final solution in terms of getting that solution solved and trying to factor the common stuff into a single base class so i've got my solution up on the screen and this is the final solution so i'm going to talk a little bit about how i got there first as we talked about in our when we introduced this concept is i did actually go ahead and copy some of the code from the student object and put it into a teacher object you know the the idea of having an id and having a first and last name i just copied right in and then i implemented the rest of this class you know i've got this this property for the the subject area i've got a private member feel for this list of what classes does this particular teacher teach i've got a method to add a class title and i'm going to look to see if it already exists and if not i'll add it to the collection to try to remove a class title so i'll just go ahead and remove that and then i've got this property to be able to enumerate all the class titles and we'll go through this a little bit more and this is kind of a preview to the next module we start talking about interfaces yeah so i notice here that you mentioned that you copied all that all that features into there but i don't actually see them in that base class right because that was the first thing i did i just wanted to see what was there and see exactly what things were common and once i was all done i found that the things that were common with this idea of an id and having a first and last names that were changeable so an id that's not changeable at all and a first and last name property you know over time we may end up adding more to this but i definitely have some small bits of common common functionality and so i introduced this idea of a person concept you know so we made other people into the this problem as time goes on other different classifications of people so i figured okay we'll call it a person so a person has an id so you can see that this comes straight out of what was in that student class when we started so a person has an id that's immutable we created as soon as the person is created we've got getting set handlers for the first and last name you know and as time goes on we may end up adding some validation here where you know we'll add some extra code so that first name can't be null or can't be empty or can't be blanks same thing with the last name you know we'll make sure that that stays valid right now i don't have any of that here yeah and so that that would allow not only the teacher but also the student to get that function right it would then be in both places at the same time i'd only have to do it once yeah and i think another great example here would be if you wanted to get the full name you could implement this person exactly so you know this will probably grow over time as we add more behavior to it and then we end up using that both in our student class you know this is now smaller than it was before i now have this constructor that if you look this is the c sharp syntax to say i want to call a particular constructor in the base class so i have that colon then base meaning call something in my base class and then i pass that id down so we do set the id in you know in the base person portion of this student object and the first and last name properties are part of a student just by virtue of being derived from that person class and then in the teacher we did the same thing you know it also derives from person same basic construction concept and then it's going to go right down into the implementation that's in the person object to be able to put all those in place and and to inherit any of the functionality that's part of that person object so with that that's that's pretty much what we built this time not a huge lab and again we only have a couple different types right now but as our program grows we certainly add more types and we certainly put more things in here and see more common behavior in this abstraction of of this idea of a person teacher and and student and possibly other classifications but it gives us a good start great and so we can find the code out at your github repository right uh here at bill wagner mva object oriented exercises and this will be labeled for this particular this particular module and with that we'll come back shortly and we'll start to introduce the concept of interfaces another way to get some polymorphism and some reuse among disparate types in object oriented programs see you soon hello again i'm bill wagner and i'm james sturdivant and in this module we're going to start introducing the concept of interfaces one of the other really key concepts of polymorphism and reuse in object oriented programming so as we've been looking at our full roadmap here of all the topics that we're going to discuss we've talked about encapsulation and inheritance now we're up to interfaces defining contracts that act can be implemented by totally different unrelated types then we'll move on from there into abstract classes and some of the other techniques like generics to enable reuse this module is about how interfaces work in object-oriented programming what we're going to look at here will define the topic look at some of the guidelines in terms of what are good practices to work with interfaces we'll look at some of those practices in in some depth and we'll come back and evaluate some of the results and the risks of different areas i think you had a really good comment when we were putting some of the material together about how you name interfaces and how that helps represent what they do yeah and i think interfaces are a great way to communicate to other developers the intention that you want to your class to implement and so it's that intention that the uh the class is going to be performing and so we again we will be talking about behavior here we're not talking about the data we're talking about the way the class is actually working and so an interface is a contract that can be implemented by many unrelated classes and what this means is that uh the interfaces don't really necessarily contain any of that implementation they only define what it's supposed to be doing right so let's look at the actual definition as we work through these concepts and and get what is an interface how are we defining that you know you you just meant went through that that strict definition it's a contract that can be implemented by many different unrelated classes and like i said it's based on that behavior this is some property of some action or some set of related actions that some type performs and when we define an interface we don't define any of the behavior for any of those methods we merely define the signatures for any of the properties or methods that are part of any object that implements that interface right and notice when we haven't used that is a or derives from we don't derive from an interface we aren't you know a type isn't an interface it implements it so the the type has to implement the concrete behavior for that particular type so what does this interface concept give us why don't we just use inheritance everywhere you know if any of you are familiar with c plus plus it doesn't have this separation of the concept of deriving from something or implementing an interface there are two separate language concepts you just derive from a class that may not implement anything so when we introduce this idea of an interface first of all we have a contract definition it's spelled out that this is not a base class there's no real behavior here it's purely a contract and i think that's really important with the contract when you're talking about going across boundaries and so that you have multiple processes and they're maybe not necessarily running inside the same system and you need to have that contract ability to be able to communicate back and forth on a consistent behavior you know and one of the things that i see in terms of interfaces and one of the ones that we'll look at is there's an interface in the base class framework called i comparable which says i can compare two objects to see which is greater or less than it's used for sorting you know and we look at things like you know any number implements i comparable i know which number is bigger string implements that you know the default implementation is alphabetical but any of our types that we define we can set an ordering relation to them and we can say that they're comparable but the base class framework has no idea how to compare say to customers or two teachers or two students we have to implement that ourselves to say exactly how we want to do that so it gets us that but then the base class framework can use that interface and say because you implement i comparable code in the base class library knows how to sort those things and turn and arrange them in the order we want so there's that totally unrelated types that we can work with and and be able to treat those similarly because they implement some particular contract so there's quite a bit of support in the language in c sharp to bring out interfaces are first class citizen in all the.net languages so they may be public or internal a private interface doesn't really make sense it's kind of scoped too narrowly interfaces may extend under other so when we go through the code review we'll look through this in the collection classes that there are different interfaces that are derived from and extend other interfaces that relate to the collection classes and any class can implement multiple different interfaces yeah and that's very different than uh inheritance right that we discussed earlier where you can only uh inherit from one single base class with uh interfaces you can actually inherit or sorry you can uh implement and use those interfaces uh across you can have multiple uh accounts of them right and we sort of saw that when we looked at the mvc controller class it implemented about eight or nine interfaces i saw we're doing the code review we didn't talk about that then because we hadn't introduced this concept but that's one of those things that happens is as we as a type grows you know we're going to implement multiple interfaces even something as simple as string implements i comparable and i innumerable and so on define those exactly what those do or you can look them up yourself in the dot net docs but anytime we do that a class has to implement every single one of the members of the interface it's not a you know implement this interface but skip some of the members you have to put them all there otherwise you get a compile time error so when you say you implement something you have to do it all the way yeah and that that really comes back to that contract uh component where the classes that are using these interfaces need to know that you've actually implemented that code now you can make a base class and we'll get to this in the next module where you implement an interface or declare that you implement an interface and you declare some of the methods as abstract and say that well this is a base class classes that derive from this have to provide a concrete implementation we'll get into that more in the next module but for now understand if you declare that you implement an interface you must provide an implementation for that and you may implement interfaces either implicitly with public or in the case of internal interfaces internal members or you can implement them explicitly which means those methods are hidden unless your object is being referenced through a reference that's typed to that interface so you know in the case where i was mentioning earlier with i comparable if we look at string one of the the methods for the i comparable interface is called compareto if it's implemented implicitly there's a public compareto method on string if they wanted to do it explicitly you would have to cast string to an i comparable and then you would see that compareto method so there's ways to say that i implement this interface but it's not part of the public interface of this class that's often used not quite as commonly it's pretty rare i don't really see that very often the only time i see it is when we look ahead and we see generics there are new improved interfaces on with generic types so the explicit interfaces on some of the classic non-generic interfaces are might be implemented explicitly so they they're hidden from some of the newer types and again still not really common but it is one of the techniques we'll occasionally use in the last module we talked about this liskov substitute substitutability principles see i can't say it yeah and once again it's just that we should be able to treat all these things the same that applies to interfaces so any type that implements an interface with respect to that interface should be treated just like anything else that implements that interface so if i can compare strings and put them in order i can compare numbers put them in order i can compare students if i wanted to by grade point i can put them in order whatever it happens to be if i have that implementation of i comparable i can treat those types as an i comparable interchangeably in any algorithm so that has to apply as well so once again we don't want to be implementing an interface and then throwing exceptions on some of the methods or doing something totally different in certain areas we want to try to keep that pretty solid yeah and i think one of the ways that we potentially make sure that we don't have all that kind of leaky abstraction as we called it before is making sure that our that we implement some pretty good guidelines around when we we actually create these interfaces we make sure we follow some simple guidelines i think one of those those ones we've kind of mentioned in the past uh in the past modules is keeping the keeping everything small and so we want to make sure we keep that contract small and so that way we don't have that uh potential of implementing only partial a partial spread so right so let's go through some of those guidelines in terms of what kind of things can we do in terms of how it what makes a good interface representing a good contract you know as you mentioned keeping things small you know that we talked about in that encapsulation module and then and some of the others that that srp single responsibility principle so it's critically important for interface definitions smaller and more focused right notice i mentioned i comparable has this compareto method it doesn't have methods to test for equality or greater than or equal to and so on because they might not be part of that just comparison relationship you know think of our student example for a moment if i were to compare two students and i want to order them by grade point two students who have the same grade point well they compare the same in ranking but they're not equal they're not the same object right they don't refer to the same actual person you know as the abstraction and they're two different objects they may have different names and so on but from the ordering relation they are ranked the same so by keeping that contract super small and not putting all these other things in we don't end up with this this rule where well sometimes when i compare things just because they compare a certain way these other things that we think might be true may not actually be true so the smaller and more focused we create an interface the better yeah i think that i comparable is actually only one function itself isn't it and that's relatively common there are a number of interfaces in the base class library that have exactly one method yeah or one function or one property and each interface in that sense represents a single feature or task right when we create an interface it's for a particular purpose i want to be able to do something with all objects of a certain type and i comparable it's order and i enumerable i want to be able to walk through a sequence so i want to be able to do that when we have related things and we'll walk through this with the collection classes you might want to consider inheritance of interfaces making the contract extend another contract but as we'll even see that you want to do very carefully because that starts to get tricky and it starts to possibly be that leaky abstraction we want to worry about so keeping those contracts small is definitely a guiding principle you know i didn't walk through the entire framework but i tried to look quite a bit at a lot of the interfaces when we're putting together the areas that we want to look at for code reviews here i couldn't find interfaces that had more than say five to ten different methods in them you know i couldn't find an interface that had you know 50 methods or 100 methods you know that's a lot of work to implement they were mostly small and focused i think that's that's a very good guideline to follow all the way around however you can go too far there's a technique that will sometimes show up that's called a marker interface and in a lot of ways this is something that it kind of can be frowned upon although there are some successful uses so a marker face interface it's an interface that has absolutely no methods so all that we do is check to see that it has and denotes that it implements this interface and then we can treat it a certain way but there's no particular actual behavior on in on that interface or defined methods that say they have to implement so you could sort of put it on anything and uh you know when we were putting this together i said i really don't like those at all but you had some instances where you said they were useful so yeah in domain driven design or ddd um udi dahan has created a instance where there is he uses domain events to be able to pass information up and out we're going to be talking about events a little bit later in our modules but uh in that he actually uses the uh marker interface to be able to uh explicitly mark a role and so um any event would interf uh implement this i any event would implement this uh i domain event interface and even though it doesn't implement any uh logic it allows them to be able to make sure that not anything can be raised as an event right and this is one of those then once you implement that that that library requires reflection to go find the different things that implement that different event to be able to attach to it and and that's where there's it can be found in certain ways um in other areas you know sure why not um but let's look at some of the practices as we build things together there's certainly practices that will help us come up with better interfaces when we're working on our own domain and be able to leverage the interfaces that are in the framework more efficiently and more effectively so first let's get the idea of a common abstraction for a piece of functionality so interfaces provide contracts for functionality so when we think about this you know let's look at that idea of enumerating a sequence so if i have a number of elements and i want to enumerate all of them they could be anything i can enumerate a sequence in an array or an arraylist that we looked at earlier i can look at some kind of a container element you know maybe i have i'm writing a wpf app and i want to enumerate all of the child windows of my main window that's some kind of a container i think of string i can enumerate characters in a string right i want to get the first character the next one next one and so on i can look at lines in a text file i can look at files in a directory these are all things that i can enumerate in a certain order you know i can read bytes from an incoming network packet that's a very common abstraction so we want to develop an interface based class library has that allows us to look at anything that allows us to feed sequences at us and our code will consume that sequence one element at a time and the storage model and in fact what's in the sequence is independent of that abstraction of here's the next item yeah you definitely see that quite a bit with the characters and the in lines so uh you know a line in a file is not the same as a character as a list of characters in the string so that's a great way to show that that you can use these interfaces across things that aren't necessarily related right and then the next big practice that we want to look at is when we're writing libraries often we want to write libraries and capabilities that work with some code that other developers are going to write to call our algorithms now a good example of this is the base class library containers have sort methods well they can only sort if you tell them you know how to define what's greater than or less than for the elements in the in the collection because the bcl doesn't know about those so their contract is if your code implements this interface we can sort it you know if your code implements some other interfaces we can serialize it and write it to disk if your code implements um iview result we can send it to the web as a result you know there are different interfaces defined this is if your code implements this we can treat it as certain things and you can interact with the framework library in different ways and i find that's really good for large enterprise applications as well there's domain knowledge that may be represented in an interface and then other code can keep extending that and keep growing with that and that enables us to write these algorithms that can be open for extensions once we put some stuff in there and we have this generic algorithm and say if any class that implements this interface can work with this algorithm right find the minimum of something you know any of those are possible yeah and so another uh practice that we can start to to use uh interfaces for is for test doubles and test doubles are a way for us to be able to test the the client code that we're working with and a lot of times we might be able to create use using an interface we'll be able to create a instance that doesn't actually touch the database or doesn't actually call out to the a service that i'm working with that um might be down or it might take a really long time to to call and so we can create these test doubles that allow us to um return instances and return the value that we're expecting so that we can test the actual uh implementation of the the details that we're working with right so we're working with something where if i want to write unit tests say on one of my mvc controllers and in order to implement a certain command action i need to make a whole lot of database calls i can provide something that that wraps my database engine whether it's entity framework or whatever and if it implements an interface i can use tools like mock or just mock or any of these others to be able to say act like this thing and here's what happens when you call it certain ways and then i can i can write a lot of unit tests around that that don't rely on the contents of a database which can be kind of brittle over time or i'm always testing with exactly the same data also i can write things like if i'm writing a distributed system with microservices that run on different machines i can write interfaces that act like a service running on another machine and then i can see how my microservice responds if another service isn't available right now which is hard to test sometimes especially if i what i really want to test is i started working with this other service and then it went down how do i respond right that can be really hard to recreate in the lab but with a test double i can probably make that happen so it definitely sometimes those can feel funny because we have this interface that's only implemented by one class but it is a very important technique for modern software development i think to be able to write the kind of unit tests and automated tests that we want and not rely on the entire rest of the of our entire application all the time so having looked at some of these concepts in terms of the practices in terms of what we want to put together so what do we end up with if we if we do this well what kind of things do we see in our app and what what are the risks if we end up you know messing it up and creating some really bad interfaces and we get some of those negative results that we worry about so the first thing i look for when i'm working with a library where we've added our own interfaces is i really want to see some kind of a natural implementation you know so if i create an implement an interface and something is supposed to be able to satisfy that contract you know as as a as an idea as an abstract idea it should feel pretty natural to put those methods together you know the implementation should be obvious right i know how compareto should work right if i did that one um you know i know how to enumerate the characters of a string you know how to do the equate like if you're implementing i equatable you know how two items are equal to each other yep and the corollary is the implementations for those interfaces should be complete i should be able to implement everything on an interface without worrying about gee this one doesn't feel like it belongs to this type that may mean i need to factor out those interfaces a little bit differently you know and again we'll always see that complete implementation of an interface i don't want to see methods with not implemented exception all over the place because we only implement part of this interface the rest of it doesn't apply for this type that may seem like we didn't do a good job and uh you know when i put this slide together i did say never seeing not implemented exception that might be too strong you know as i'm starting to work you know i may have not implemented exception in a few spots but i really don't want that to live in code for a long time especially not in a lot of places yeah so uh with with these interfaces one of the things that is a i guess maybe a potential risk is that because you're not providing any providing that implementation of the code you might be you might be thinking about copying and pasting some of that implementation and so you might get some duplication of that code across multiple classes and so when you when you do see that or when you have that inclination to do that then you want to be maybe reconsidering doing some sort of encapsulation right so this would be you know if we end up with this copied implementation it might mean our contract is too large you know we need to do a lot of implementation that looks the same in different areas things that we can do to fix that is we might produce something like extension methods which we'll talk about a little bit more later they're used a lot in link to make very common algorithms based on a core interface and we have if we have a lot of convenience methods in an interface that's a lot of work to do for all the implementers of it and you know the the term i use is that all an interface all in one interface you know the i do everything interface you know then we have a lot of extra work to try to put those in place and those give us that copied implementation that feels wrong you know and if you have a whole lot of those it may even indicate inheritance would be better than an interface contract right if the shared implementation looks the same in a lot of different disparate types maybe this is really something where there's inheritance involved in terms of a base class rather than an interface contract the idea of an interface contract is it should be totally separate implementations of a similar concept with different types and with that we will take a short break and we'll be back and look at some of the examples that we've been talking about in terms of how they're used in the base class library and in your own code see you soon hi i'm bill wagner and i'm james sturdivant now once again we're here to talk about object-oriented practices let's look at some of the things in the base class library that define and implement interfaces in such a way that they help make it easier for us to work with disparate types through a common contract so we've got a couple different areas that we want to look at one fairly large and one that's going to be a little bit smaller so we're going to look at some of our collection interfaces we're going to look then at i comparable which we talked about quite a bit as we were going through the presentation we'll introduce the lab that we can start to talk about the idea of creating your own interfaces and and how that might work then we'll come back after that and we'll look at the solution to that initial lab so let's start with that first big section where we have a number of different interfaces collection classes it's a lot of different ways to work with collections of data in different contracts so once again i've got that core clr project loaded in visual studio here and i'm going to start with just that base core class or interface we want to work with it's called innumerable one feature that a lot of people don't know about for a large solution if i type if i type it correctly if i type a symbol name up in this search bar at the top of solution explorer it will find all the instances of it anywhere in this particular project you can see that some of them are interfa are our classes that implement this particular interface if i scroll down a little bit i will see that i can get that i enumerable interface definition so i'll start by looking at that there's only one i grab the generic version so we'll come back to that one in a later later version i want to not be in the generic section i want to be all the way down here just in system dot collections we'll close these out where it opens up everything that we saw and we'll look at just the one that i want to look for right there there we go so the innumerable interface has exactly one method get enumerator which gets an object that implements i enumerator so if we look at that interface i enumerator has three methods move next to go to the next item in a sequence it has a property called current that returns the current item in the sequence it has a reset method to go back to the beginning of the sequence so bill i noticed on the the interfaces on the i enumerator there were pretty straightforward to to uh implement right and what's interesting is they separated this into two different pieces one is an innumerable that says okay i know how to return an object that knows how to enumerate a sequence and then the second one is that enumerator that says here's an object that knows how to enumerate a sequence so we've got these two different pieces so what we'll find is the collection classes implement i innumerable and they'll do so in such a way that they return some kind of a private object some class that they've defined usually as a nested class that knows how to walk that internal sequence structure right so if i look at one of the classes that we looked at earlier if i looked in our system.collections classes and if i were to look and find our arraylist class that we were examining earlier so if we go pull that up and we'll look at an implementation of that so if i look at arraylist you can see that it implements ilist so i'm getting ahead of myself a little bit ilist extends innumerable so we're going to have a get enumerator method here that knows how to get something and that returns this arraylist numerator simple and notice that its constructor takes the current object and if we look at that arraylist and numerator simple you can see it's an internal class embedded inside arraylist right or it's a private class that implements innumerable very enumerator it knows what list it's enumerating and it has the methods for move next for current and for reset so it knows how to it's inside array list and it knows how to enumerate an array list so on innumerable we just have to return some object that knows how to return how to enumerate this particular collection and innumerator defines a common way for any object that knows how to enumerate a particular sequence of things to be able to do it so we'll look at one other sample in the same way string as we said knows how to implement i enumerable for the string type and this one i may search for a different way because i think string is going to get used a whole lot here yeah if i go to two string that's going to return a string so hopefully i can f12 on this and find there we go the string class as i said which implements i enumerable so if we look at its innumerable implementation we should be able to find underneath string it's going to have a git enumerator so we'll search for get a numerator and we find that the implementation of that is going to keep going here we go so we've here we see that implicit implementation or explicit implementation we see it's defined as innumerable dot get enumerator so only if i treat this as an enumerable it's going to then return a new char enumerator which again it's an internal sealed class or a sealed class and it knows how to get the current object it knows how to move to the next character or get the current character excuse me and then it knows how to reset itself so two totally separate implementations same names for the same methods so we know how to put that together i innumerable here's an object that knows how to enumerate this sequence innumerator the three methods current move next and reset i know how to enumerate a specific thing and they're often implemented as low sealed classes inside the things that they do now notice that i innumerable and i enumerator work together and all you can do is walk a sequence from one end to another so it's a relatively simple interface and i sort of weighed my hands a little bit when we looked at arraylist because it implemented ilist so when we work through different things we're going to want to say that you know there's more things i want to do with a sequence so there's much more in there so let's look at this from the other end if i look at ilist which outside of the generic i should be able to find the other collections to show me the i list interface and we can see that this inherits from eye collection and if we go to i collection you notice that it inherits from my enumerable so if i want to do a couple more things beyond a numerator sequence well i have i collection it knows how to copy itself to some array or copy to something else it knows how to tell us how many items are in the collection right a sequence may not be able to do that it may just be reading input from a file it doesn't know how you know when that file will get closed it may be reading from a stream or so on and then we have this lengthy one for a sync root and is synchronized so we know if some other thread might be looking at this collection at the time and you can read the documentation for that it's a way to allow for a collection to hold objects and be able to access them from multiple collections or from multiple threads safely in a read-only fashion well so that's only a few more things so that's a a sequence effectively an eye collection is now a sequence that well knows how big it is and can copy itself out somewhere else and so here we're actually seeing the uh that inheritance of multiple interfaces right so it extends i enumerable so it's still a sequence we can still enumerate whatever the objects are in this sequence but now we also know how big it is okay so we've got that and then if we have more different things we want to do then we get all the way up to ilist where now first we have our indexer so i can get an item at a certain index or set an item at a certain index in that particular collection and a number of other methods we've got add methods here i've got a contains method to see if something is in a collection right and only some collections will do that you know arraylist does but say treating a an input stream from uh from a network doesn't um implement ilist because it doesn't know if it's going to contain something because we may not have all the bytes yet you can clear so we can remove everything we can see if it's read only and see if it's got a fixed size that's a bit of a leaky abstraction that i'll get to as we look at a couple classes that implement this and we can see if something's in the collection if so where is it insert and remove now this is where you know some of these things get really hard and even you know as good as the bcl is this is one place where abstractions are just a little bit leaky we have this is read only and is fixed size kind of thing and if i look at arraylist you know it's and we look for its is fixed size i'm inside the enumerator at the moment let's go back up to just the arraylist itself and if i look at its is fixed size method we can see that it's just going to return false because it's not a fixed size it knows how to add and remove items from it so that means the rest of the um the rest of the methods that are part of this contract they're all fulfilled but there's another one and so that's a great example of where we actually need to be able to implement all the various uh components of that interface right so now let's look at array so arrays are fixed size right we can't make them grow or shrink so if we look at its implementation of is fixed size so it's now going to return true and now because it's going to return true in this is array a fixed size if you look at its insert method it throws a not supported exception right so does remove and so does ilist.add if you can see right and once again notice that these are explicit implementations of those interface methods so the only way you get at those for an array is to cast an array to an i list and then you can see those methods but even so it is a little bit of a leaky abstraction and it shows just how hard it is to try to get these common abstractions really factored out super cleanly you know we've lived this throughout the history.net framework most developers are are reasonably comfortable understanding how it's there you know some improvements were made a little bit in the interfaces for the generic versions but it's still it just shows how hard some of these problems are you know and as we get to more advanced problems and more more you know more of the scenarios we come up with in our professional lives the answers aren't always obvious and we kind of hope to get as close as we can often yep and so uh i think yeah that's definitely one of those things where we need to we got to balance getting these implementations correct and actually making and writing code and getting stuff out into the real world right there is one other important part is to all of these techniques is that shipping is a feature you know we have to get to the point where we can get our code in front of our customers we certainly want to do the best that we can so with that let's let's finish on a happier note let's look at that second interface that i comparable interface which is a lot a lot cleaner so if i look at i comparable and here we'll once again let's try to find our definition of it and right here and i comparable you can see it has one method compare two so we get some other so we compare to some other object is this greater than less than or if they're equal or rather if they are equal in terms of an ordering relation then it should return zero now if you look at solution explorer here you can see that there are a large number of different types that implement this interface okay and i've even closed up some of the ones under a couple of the other areas um date time offset for instance i can compare two and i can see you know what what time zone i'm in how far from utc am i and that will determine which one's greater or less than um i can look at the string class would implement i comparable and again here you can see that the compare to function when you when you actually go and look at it it's fairly simple to implement and you know it right away you know that you're going to be comparing with two strings you're going to necessarily be comparing the way that you're working with them so you might see a string and you're going to compare the make sure that the same length you're going to make sure that they are they have all the same characters in them right so yeah if we look at the compare to on string which i just brought up as you were going through some of that some of that description so we can go to compare two and it's going to look and see all right is this comparable if not we're going you know is this a string if not then we're going to dive into this overload of this method that compares it to something else that's a string we're going to go call their um we're going to go see if there and i'll do some simple things there then we're going to see what kind of comparison are we looking at culture here and then we're going to do different kinds of comparison helpers in terms of whether or not we're working with invariant culture the current culture do we ignore case are we comparing based on upper and lower case but the same contract exists we can sort strings in any of these different fashions depending on how we want to do that comparison ants would do the same thing if i want to look at n16 or in 32 which should be down here somewhere in one of these classes and we'll just pop one here let's see if we can get to that there we go so i have it implements i comparable again and again if we can get to compare to we can see that it's going to just go okay so is this null is it the same type if so let's just compare the values and return what our comparison is so totally different types same contract we can use that ordering relationship on any algorithm in the bcl to be able to do things to put different types of objects in order regardless of how they're put together so now let's look at a lab and add some things in our class and learning institution area and work with some interfaces so now let's introduce the idea of a teaching assistant so ta is a student but also has some of the capabilities that a teacher has they have a subject that they teach they have a list of classes that they might work with you know no more than two because we don't want to over burden our tas because they are students and now figure out how you would put that together what would go into an interface that would allow us to treat a ta as both a student and as a teacher at different points in time and where do we want to split out that interface versus that common base class that we put together earlier between the student and the teacher and that person concept so how do we want to factor that commonality out in terms of being able to work with this new concept and with that we'll take a break and we'll be back to show you the solution that we put together for this particular module and see how that compares to what you built see you soon hello again i'm bill wagner and i'm james sturdivant let's look at our solution for this lab exercise on creating interfaces so we asked you to introduce the concept of a teacher assistant and we wanted to potentially use interfaces in our solution and so we're going to go ahead and see what we came up with so what i did i said all right so i'm going to make this i teach interface which could represent any person who's helping to teach with different areas so i've got and i enumerable for the class titles these are the things i help teach i've got a string that's going to explain this is the subject area that i'm i'm good at those came right out of that teacher class that we did before and i've got those methods for add a class title and remove a class title so now i've got those four things that involve anything that can for someone who's teaching if we look at the teacher class all i had to do was i just added the note to say that this does implement that i teach interface and the way i did this just for as folks get used to trying to work with visual studio if i went under the quick actions button you have to do it on the teacher there right oh yep on the teacher class one of the things i'll get is extract interface and i can pick the methods that i want to form an interface and this this also demonstrates really well how you started with a leaf class the teacher class itself right and you saw how you were actually implementing it and compared it to how you might implement it in another class and exactly pull that out and i just pull that out and go this is what i want this other class to do and then i created a new class that was a teaching assistant that i derived from student because a teaching assistant is a special specialization of a student it is a student so i'm going to have now a couple new features in order to implement that i teach interface it's got an arraylist for its set of classes we've got an innumerable for the class titles that will return a reference to that arraylist and this is part of that encapsulation idea notice that i'm not returning it as an array list so i'm not returning a reference to an internal structure i'm just enabling clients to enumerate the entire sequence and see what's in there and so later on you could potentially change that array list into a list of other objects right or a dictionary or a dictionary or some other storage as long as i can still enumerate it i'm fine then i added a string for the subject area i added a method to be able to add a class title and here's where the implementations are somewhat different if we look at our teacher object when i add a class title or remove one i'm just modifying the collection right i can add as or remove as many as i want to if i look at the teaching assignment assistant i said you know if i as long as i don't have two classes yet i can add a new class otherwise i'm going to throw an exception and say you know tas are only allowed to teach two classes and that's a runtime exception you know i couldn't find a way to make an interface that says you can add as long as there's no more than two so that is does manifest itself as a runtime exception i still feel i've got a good interface you know because you can add classes you just have some restrictions on it and sometimes it's invalid and then i have the one to remove a class title so that we can do no matter what a ta can stop teaching if we need to or stop teaching any of the classes so in merely kind of a smaller lab but once again you had to think about how we're going to put this together and how do you want to express those requirements and once again using some of the examples that we just put together so think about some of that design the code itself isn't that hard it's more figuring out exactly how do i want to solve this problem and leverage these techniques in different ways that enable us to build some of the software that we want to build great and so where can we find this code that we've that would be on our same place under our github slides which i think you have on your machine yeah so if we look at that we'll hit github.com right there same place and there'll be a branch labeled for this particular module and have fun compare what you did to what we did and we'll come back and we'll talk about abstract base classes hi i'm bill wagner and i'm james sturdivant and we're helping you gain more practice and learn more with object-oriented practices at this point we've now covered several of the basics in terms of encapsulation inheritance and working with interfaces we're going to finish that section where we're talking about techniques you can use for polymorphism by talking about abstract based classes so in this particular section on abstract classes we're going to look at several different topics we're going to define abstract classes for you we'll look at some guidelines on when to use them and what kind of problems they should solve and why they're there to prevent some other kinds of mistakes we're going to look at some of the practices and we're going to look at some of the results that you get when you use them properly and some of the risks that would indicate that you're using them incorrectly this is another one of those things where there's a lot of different heuristics and a lot of different ideas where sometimes it's the right idea sometimes it's not there's not a lot of code in this it's more really thinking about what what your types really model in your application so it'll be a little bit more discussion we'll walk through some of the classes in the bcl again and then we'll give you a little bit of homework to try to figure out where does it fit in this this hierarchy that we're building so let's start by really defining what is an abstract based class what's the definition of that how do we work with those so again starting with that pure definition an abstract class is a class that provides a common definition of a base class for multiple derived classes it cannot be instantiated and it may also contain abstract methods that must be implemented by non-abstract derived classes wow that sounds like a spec yeah and in fact it is that is the spec so reading like a spec so what does that mean what are we trying to do here well so i'm noticing a couple different um bits in that in that definition there that sound like some concepts that we've already covered in the past in in the in the previous modules i think the first one there was that um it's something that can be a definition for a base class that other classes can derive from so that sounds a lot like inheritance to me right so it is it is a base class it is one of those things that is we'll derive from will create derived classes from an abstract based class so it's a special kind of base class yep and then the other one is that uh there's some methods there that need to be implemented by other abstract classes or so sorry the classes that actually implement that abstract class so so that point it cannot be instantiated so a big word we can't create objects of a type that is an abstract base class right so if i have an abstract base class for you know one of the ones in the framework is the mvc controller it's an abstract based class i can't just make a controller i have to make a a object of a type that derives from controller right so i can't instantiate it on its own and you're right it may contain abstract methods which are things like an interface that i have to implement in something that's going to be a non-abstract derived class okay so there's a few things we have to do there we've got a base class we're going to prevent somebody from making that base class accidentally and we're going to say that for derived classes here's some things you have to implement like an interface and that's basically our working definition of what an abstract based class is great so what are some of the advantages of an abstract based class and some of this we're going to do by contrasting an abstract based class with just a regular base class and with an interface so first we get some implementation reuse unlike interfaces an abstract based class can have actual implementation that we can use so we can put concrete implementation of different things like we saw in the mvc controller class inside an abstract base class it doesn't have to be all empty and that gives us that shared base class implementation for all the derived classes we get all those advantages that's that's good we saw that same polymorphism support that we would look at in terms of i can treat any derived any object of a derived class type as though it were one of the base classes so we're still getting that substitutability principle and we have a contract definition i can define for an abstract based class here are those abstract members that you must implement if you're going to derive from this class and be a concrete or a non-abstract instantiation or derived class for this so uh when when we're looking at deciding between going between an abstract class an interface or going with straight inheritance how do we go about making those decisions i don't know it's a case-by-case basis it's one of those great object-oriented answers well it depends yeah and that's i mean i've just had that conversation quite a few times with developers arguing over whether or not the inheritance or sorry the interface or an abstract class is the right thing to do and the way i look at it is if there's going to be a lot of shared implementation then i'm definitely going to move more toward an abstract based class because i can reuse that implementation as well and i don't have to copy it as multiple different times so that means that once again we do have that is a relationship so that implementation is going to be shared because it's going to be similar and we don't have that just a disparate contract so that's probably my biggest reason as i look at how much of the implementation i can share so let's look at some of the language support that we would have for working with abstract based classes as i said there's not a lot of code we work with here all i have to do is if i take a class and i put the abstract keyword in front of the class keyword i've now got an abstract based class well that's pretty easy that's all i have to do yeah but it's an important design consideration right the hard part isn't typing that word or remembering that it's there the hard part is understanding is this a good candidate for an abstract based class and also what are you communicating to the other developers that are trying to use that class and that's where these next two bullet points are important an abstract based class may declare abstract methods i don't have to so i can declare an abstract class even if all of the methods that are defined actually have an implementation however if a class does declare any abstract method that class must be marked as abstract otherwise it won't compile so once i have an abstract method well my decision is made i have to declare it as an abstract class but if it doesn't have abstract methods then i have to think does it make sense to instantiate this or not and that's kind of where that design decision comes in like i say what am i communicating to other developers the big thing i'm communicating is this type has some shared code but i'm never going to instantiate it directly because it doesn't make sense in anything that we're doing in this application and again i think this is one of the important parts of that substitutability principle it's going to define to our interfaces and our abstract based classes so that same substitutability it's going to permeate everything we do that involves polymorphism i want to treat these things as though they are the other type so now let's look at some of the guidelines how do we you started to introduce this topic how do we decide which way do i want to go with this different design decision so one of the first things that i look at once we've built that hierarchy that we talked about in that earlier module where i said start with my leaf classes i build them out i find common things i move those up into base classes so now i might want to consider my non-leaf nodes should they be abstract classes do they represent something that i don't actually create do they represent something that's just shared among things that actually do exist but it doesn't necessarily exist on its own and if an object can't be instantiated or if i don't want it to be it doesn't make sense in my domain well and i still have that shared behavior then consider making it abstract and my own view is i would usually try to mean make them abstract rather than prefer just leaving them as non-abstract and seeing if they show up later you know might it's easy to remove it later but if something someone else accidentally starts instantiating objects it's hard to then make them abstract later if i make those non-leaf nodes abstract well that means they can't be instantiated i can't accidentally create them so i think that's my biggest guideline is i look for anything that's not that has derived classes maybe that should be a candidate to be an abstract based class not always true but that's one of the things i try to do as we mentioned in that earlier module on inheritance in general one of the risks of inheritance is these super deep hierarchies if though all of my base classes are abstract and i can't instantiate them i'm less likely to get super deep in that hierarchy because i can't create those objects anyway so i'm more coalescing the common behavior so that's just one of the things i try to do it's never perfect i certainly have non-abstract non-leaf classes but i kind of look at those as maybe some some of the candidates so let's look at how this plays out in practice what do we actually do in practice working with abstract base classes so when we have a common abstraction and a common implementation that starts to move away from that interface definition more back into that inheritance where i want the inheritance even if the type isn't isn't something that we instantiate methods have a common implementation now that idea with the controller where we have all these things that you showed us earlier dealing with the http context and the currently logged in user and so on that's all shared implementation for every controller you know contrast that with where we looked at the interfaces for i enumerable and just between array and arraylist or string and arraylist how we enumerate the elements in that sequence is implemented completely different now that gives us a big difference between picking a base class and an abstract class and an interface so why would an mvc controller be abstract that's a great question i think because it's because the controller doesn't have uh any knowledge about what uh routes it's going to be implementing that's when you would choose to yeah yeah how could the bcl know what urls my app uses yeah exactly so it makes no sense to instantiate and route something right to that controller because it doesn't know what to do right so and then we can define those contracts when there's no common implementation that's going to be those abstract methods or that's going to be this is code you can use you can work with and then we'll put those together and that that enables us to really carefully mix this implementation in a contract you know controller i don't think has any abstract methods uh no i don't think it does yes i don't think there's anything you have to implement there but it's that shared implementation we can use and that is a relationship some of the other ones maybe it'll add if you're going to derive from this you have to override this particular method one of the other reasons to make something abstract well correct it prevents incorrectly instantiating it in the case of the mvc controller can't make one you cannot create one it will not be allowed and again that also uh communicates to other developers that hey this is actually probably a class that i might want to override to be able to use right moving forward right but it's certainly not something i'm going to just new up and and start working with yeah exactly so so let's look at some of the results and the risks this is definitely the area where i think this is one of the more interesting parts of this this whole section and or this whole course abstract based classes can be really really useful in a very proper extraction and they can also really be misused and they sit there and go why can't i just make this and use it why do i have to implement these methods so once again and notice that on here where we look at some of our good outcomes and some of our risks it's very similar to what we get in interfaces so in deriving from an abstract based class should model is a just like what we said earlier where deriving from a class should model in is a okay we got that driving and overriding the necessary methods should be obvious like with an interface if i'm going to implement an interface how i override those methods or how i define those methods should be fairly obvious if i have pure abstract methods in an abstract based class it should be obvious how i override those if i'm creating a concrete class if it's not and maybe i have that leaky abstraction again yeah and i think that that is a bit really identifies whether or not you should be using abstract classes versus inheritance and so uh sorry abstract classes as inheritance uh instead of uh interface if the two objects don't actually map to each other like in the is a model then you're going to make sure that you're going to want to be using an interface and if you if they do then maybe and if they need to share some implementation that you want the actual user of that class to implement then you would go and maybe choose an abstract based class right and again the core layer that we have here we said earlier in our last module implementing an interface well that should be complete overriding the abstract methods in an abstract based class that should also be complete you shouldn't be throwing not implemented exceptions in different places there in when you over or when you're deriving from an abstract based class again we'll see that complete implementation if i'm overwriting everything and if i'm putting things together in these abstract based classes i should always apply it methods shouldn't be considered that yeah this doesn't apply here but i'm still going to derive from this and again we're going to get some of these um parts again because we're using inheritance again we can end up with that too deep of a hierarchy you know i can consider adding one one element on every single derived class and create this super deep hierarchy of 15 levels each adding one method and then i can branch off wherever i want and that's going to be really hard to work with and we want to try to keep those generally flat you know not super super deep yeah i think as a rule of thumb one of the things i try to do is make sure that i don't have more than two maybe three uh in my hierarchy because once you start to get up past that it's really hard to determine which class is actually working with uh and which method is actually being called on the classes you know and a guideline i use there is often if i have trouble naming something then i probably don't really understand the abstraction you know i may have to think about it a little bit but if i absolutely can't come up with a name that makes sense you know if i had to write you know abstract controller that includes way to write log messages okay that might not be a good idea for a class that just sounds kind of weird you know or if i have to write something i really have to stretch to come up with a name for this you know and then if it gets too deep it's a controller that can write log messages and send things up and you know who knows but it starts to just feel bad so we try to keep those reasonably flat we try to make it an abstraction that is models is a correctly and look for those contracts that everything that's derived from this must implement so we're sort of combining these two ideas of an interface contract and inheritance and getting that shared implementation and we want to be careful not to make sure that so that people can derive from it without having to slice and say there's there's a lot of this that doesn't apply here and i think those are the big keys there and again everything we're doing with an abstract based class you could solve with a base class and a separate interface it's more that they always have to travel together and with that we'll look at a few of the examples that we've talked about in the base class library we'll be back in a few minutes see you soon hello i'm bill wagner and i'm james sturdivant let's now review some of the things in the code dealing with that abstract based class concept and how you can use it to communicate things about your design to other developers that might be looking at your code or trying to use it so look at different examples inside the base class library once again we're going to look at some parts of the web stack because the web stack has been open source for quite some time and we can really look at the implementation we've talked about some of these when we were going through the presentation parts you've got the mvc controller talked about that one already now action result in view result based james what what are those do in the in in an mvc application what are they part of yeah so action result is a part of the controller that it's actually returning the view part and so as long as you inherit the action result you're going to be able to write out the result from the web request that comes in okay and v result base sounds like it's it's one of the view things part of the view part of mv yeah exactly okay so look at that and then we'll introduce the lab and then we'll talk about our solution after that let's begin with that idea of the mvc controller so james has got that project loaded up again so we'll look at the mvc controller inside the asp.net web stack and cool so what i'm going to do here is actually just show you another technique that you can use to open up various components in your visual studio so if you take a look at my visual studio here if i press ctrl comma i'm going to get a little text box up in the top right hand corner just up here and so i can type in controller and all it's going to do is find out find all the definitions of that controller and anything that that implements that okay so that's like what i was doing but instead of when i search in the solution explorer it finds all the references as well this is just going to find definitions you've got it cool so if i hit enter it's going to bring me right to oh maybe oh i uh you got to make sure you go to the actual c-sharp see the c-sharp the different little symbols there have different meanings so okay so there's controller.cs so we're back now that i've got the controller up here we kind of take a look at this before we took a little bit a look at all the implementations and the implementation deals details we saw but we kind of quickly brushed over the fact that this was an abstract class right so i'm kind of curious so controller derives from controller base is controller base abstract as well well let's go take a look we can do that by pressing f12 on the controller base okay that's going to bring it up and yes it happens to be an abstract class all right now is there anything in there that's that's um any methods that are abstract or is this one just all let's take a quick look uh i don't know if there is i think so if there was we would probably have to oh there we go we go execute car so something that derives from this has to override execute core okay and now notice the virtual keyword isn't there abstract includes this must be virtual right so we don't have to so we don't have to write both okay and so did we talk about what virtual actually means here you know i don't think we did we went through inheritance we talked about virtual methods yeah so abstract means that there's no implementation details but when we have a virtual method we actually provide a base implementation but any classes that inherit from it can actually override that base that base implementation that we have so i could in any over in any drive class i could override that same method have the same signature and the framework would call my overridden method instead of the original one right that's kind of how i can get that polymorphic that different kind of behavior now with that abstract one i notice there's no curly braces there's no it looks like an interface definition yeah it just ends with the semicolon yeah you've got it so we get it and that's because it is very similar to the interface in the way that we think about how they're actually going to be implemented and unlike an interface though i can have these abstract methods with accessibility keywords this one's protected so i've got this abstract method that is only accessible to derived classes but that it's not public yeah that's a that's a great different differentiation from an interface and okay so that would be one of the reasons to look at an abstract based class when we dive deeper into these is if i want to have that thing where i need some accessibility on it i can get that with an abstract based class and not so much with an interface okay what i find interesting is we go back over to the controller method we haven't found that uh does it actually implement it up here i think it will execute core yes okay so it's going to override it so it's it does this so now cool and we kind of already looked at this implementation previously where it's going to load some of that temporary data right it's going to go and uh find the actual action and if there if it can't actually find the action it's looking for it will go ahead and return the 404 for us right okay the 404 for us all right so okay so that's interesting so now in this particular class this controller class it's provided an implementation of the abstract method in the base class does it declare any any abstract methods that we need to override when we create our own controllers in this controller it actually doesn't do that okay so the only reason this class is can't be instantiated is be a web request this uh that base framework itself wouldn't actually know what actual urls and what requests that you want to you want to be implementing and so here it's saying that you cannot be a controller without providing some of that additional information okay so what we've seen so far is that that base controller and maybe there's other are there other things that derive from base controllers it's that's curious to see because what we've learned so far is this ultimate base class for controllers you know it's got an abstract method that must be overridden right but if not well okay then we can't derive from it but then the one that we derive from doesn't have any abstract methods it's just got this this contrast says yeah you can't do that so that's an interesting way to sort of put the chain these two together yeah so if we go back and look at that controller base it there is nothing else that it's uh inheriting from but it does have an interface on it right and that if we go and take a look at that interface all it's doing is providing us this execute right function now are there other drive classes from the base controller you know if we go back to the the controller itself you know if you right-click and if we find um find all references yeah yeah not that one though the folder base yeah okay yeah i think if we go like that all right and see you know are there other so so it looks like there are other things other things that are derived from it as well so other kinds of controllers that we might want to um might want to use for other other purposes yeah it looks like most of this is testing for testing for other things there okay so but if you wanted to provide your own custom controller that you're going to be adding some extra information or uh implementation details that are slightly different than the one provided you could go to so the design is set up for that even if it's not in the same project okay so now the next one that we wanted to talk about we wanted to go into that that action result class that was the second one that we were going to look at so what and you say that's part of the the the views and the results that come out of a controller method so so what have we got there so yeah i'm pulling that up right now using that same technique of using ctrl comma and if we look at this we've got an abstract class that executes the result based on the controller context so given all the information about the controller we want to execute that result and re-hand it back out to uh out to um the the system right who's calling okay so this one i find really interesting for a couple different reasons okay the class is abstract it's got one abstract public method this could easily have been an interface right a public interface i action result with that execute result method right right so i'm really wondering sometimes what do you think that design you know the way they did that why did they make that an abstract base class i mean we don't know we're not talking to the developers but what would be what does that communicate to you when you read that code yeah um i think right here um the one of the reasons we would do that is because we wanted to be able to specify the um that public success that public public accessor so potentially we could um be able to oh we kind of talked about this in the past one but we could also do make it this uh protected and so we could potentially go there but in this case i guess because it's public what we're really trying to do is if you do inherit from action result base then what we're trying to do is prove that uh you wouldn't want you to be able to inherit from something else so we're taking that one inheritance that uh that uh because classes can only have a single base class yeah by defining it to say we want this to be your base class what they're what they're sort of saying is you can't pick a different base class and derive from something else and implement this interface right right oh so they're trying to say this this has to be derived from this thing if you want to be doing this action result got it okay so then where is action result used that's a great question i think it's uh there was one of those we wanted to talk with result yep so now we've got that pulled up here okay we can go ahead and see so it's also abstract it is yep okay and that's because later on you might want to this is only providing some extra information and so we can in a few minutes here we can take a look at what uh actually uses view based results or review result base okay but uh what i think is interesting here is there's it's providing some extra information but if we go all the way down to the bottom here the really interesting part is that it has an abstract function on it okay that's being exposed okay and again that's that protected thing so our derived classes have to put this together and it's it's not public it's only going to be used by view result like things right something that is a view result base okay so let's go and see if we can find out what uses view result base here by going to find all references oh that's a smaller list at least i feel a little better there yeah exactly so it looks like that view result one would be a good one yeah and so this is the review result and this is the thing that does all the handling um for displaying information in your that's going to load my cs html my razer view and then display that stuff okay and you can see here that it actually overrides that protected abstract method that we were looking at before and provides a definition for us okay um and here it actually goes it finds it finds a particular view and if it doesn't find the review then it just passes on the uh the result got it okay and um then down here uh what it's doing is it's gonna spit out so if it doesn't find it it's going to spit out all the places that it looked and so that's going to help us to be able to do so if i forgot one of my razor views somewhere it's like this is what i couldn't find yep go look for this okay and that's i find that that always becomes very helpful for us yeah we've all seen that okay too many times in production yeah no okay so that so that in that view result thing so what i find interesting if we go back to the code for just a second that's a small class that doesn't look like there's a lot in that particular class right i mean if we go to the bottom i mean we kind of went through you know that's 40 lines of code here for my view result base yep because we're leveraging all those things in in view result base and then action result underneath it so that's that's interesting that's again that why we used class inheritance is to be able to reuse that implementation yep right okay cool good things to see so now let's look at what you can do inside your your small hierarchy so we've got one small exercise here and again the interesting part from this is not so much how much code you write you know we when we looked at this code review this was noticeably smaller than the things that we chose for say encapsulation where we're trying to show how we hide a large algorithm but it's more how how do we want to express what we mean for you to do with these different types you know one and as we look at this lab one of the things that i really want in terms of looking through this concept there's a great quote by rico mariani who was one of the architects for the dot-net bcl and in its initial releases because he said that you know success shouldn't be this summit in a far off distance it's really hard to get to we want success to be as easy as falling into a pit you know that's where that pit of success came from okay it should be super easy right you can't do the wrong thing so when we're trying to build classes that we want other developers to use the big thing we're trying to do is we want to prevent you from misusing the code that i gave you right that i developed for you because if you can't misuse it you won't write bugs right that simple so in this section what we want to do we're going to revisit our hierarchy and find out you know any of the classes that we made so far should they be abstract are there types that we just don't think will ever instantiate in this particular application and we really want to think about is that by design did we intend these to be abstract based classes or is it just because the features we've put together we just haven't made one yet and should any of those abstract types have abstract members you know in the code review that we looked at we saw some that had both you know there was abstract classes that had abstract methods you had to override and we saw abstract methods that are abstract classes that didn't have anything we needed to override at all you know both are perfectly valid and they communicate something different to the people trying to use those classes this one doesn't take a lot of code but i want you to spend a little bit of time thinking about it and thinking about if i don't make something abstract what would happen in the future if i do make it abstract how does that change how it could be used in the future and welcome back and it's it's a short summary of what we built and we'll talk about why we made the choices we did and then we'll move on to generics see you soon hello again i'm bill wagner and i'm james sturdivant so let's review what we did in this particular exercise there's very little code but we want to talk about the concepts and the way we got got to the point where we decided what very little code to write here and i think even though there's very little code in this particular instance it's actually speaks quite a bit of volume to what what you're trying to your design and what you're trying to get across to other developers right so right now if we look at the code i've got a total of three or four four different classes that we created you know we've got the person the student the teacher and the teaching assistant well three of those are concrete we already instantiate students teachers and teaching assistants student is interesting because it's both a base class and a derived class right so student derives from person and we create it and teaching assistant derives from student so you know maybe i'd like the idea of student being abstract but that really doesn't make sense now i would have to introduce some new class that is a student that's not a ta that that didn't feel like it made any sense to me at all so i said all right so a student class well okay so it's a non-leaf non-abstract class which at least is something i want to review i don't necessarily want to make everything not abstract but i want to at least review it and think about it but the only one that really ended up having a point of being abstract is this idea of a person class nothing in our model so far creates an actual person object and i thought about that a little bit and i thought about well would we ever create a person object without any other capabilities and the only thing in there right now is that id and the first and last name i really didn't think that was going to be a useful abstraction and i made the guess you know thinking of the future that no matter how this grows i'm never going to create this type of thing i'm either going to enhance it with other behavior enhance more classes around it with other behavior and i didn't think i'd ever actually create it so that said well i think i'll put the abstract keyword on it now and at least for right now no developer can make one of these yeah and because of that i noticed that you put the um the constructor as protected there right so now since i can't instantiate it at all it kind of makes no sense to have a public constructor on an abstract class because i can't instantiate it so i made the constructor protected it can only be called by derived classes okay so it's just a little bit of a just hiding the fact that there's a constructor there because you can't call it anyway at least not directly you can only call it from a derived class so it's just another way to say i really don't think you should be instantiating this so again not a lot of code and again at the moment we have still a relatively small project but the idea of just thinking through exactly and being deliberate in our design decisions and then leveraging the language features to say that if this was my design decision i am going to express it in such a way that the language supports what i was thinking when i wrote the code and communicates it to other developers and hopefully keeps other developers from misusing the type because i didn't intend for you to do certain things with it you know i don't intend for you to create a person object so i won't let you right and with that we'll take another break we'll be back after a bit and we'll introduce one of the really interesting concepts we're going to leave this idea of inheritance and polymorphism and we're going to work on by working with generics and some of the other techniques that we use to build programs other than just inheritance see you soon hello again i'm bill wagner and i'm james sturdivant and we're discussing object-oriented practices we spent the first several modules discussing different ways to do polymorphism in object-oriented programming whether that be different kinds of base classes interfaces abstract based classes and so on the rest of the modules are going to discuss other techniques that are at your disposal when you're doing object-oriented development some of them from a different different realm like our functional programming module for the last one here's where we are in our course in general we've covered the first four modules we're up now to generics which is where we introduce what's called meta programming or type based meta programming we're going to start talking about different ways to allow code to be created more at runtime than at compile time we're going to move on to delegates and events functional programming and finish with some review exercises here we're primarily going to be focused on generics which can be generic methods or generic classes so different ways to instantiate part of a method or a class and let the runtime fill in some of the parameters depending on how we want to use it it's a very very powerful technique and is the basis of things like link different kinds of collection algorithms different things involving the task-based threading library and so on so let's walk through and let's understand a little bit of how this works we're going to go through the same four kind of kinds of areas that we've done in our previous modules we'll define what generics mean both in a strict sense and in a practical sense of what it feels like when you're working with generics we'll look at some of the guidelines to create generic objects look at some of the practices that will give you and guide you toward proper use of generics and then we'll look at some things where if you're reviewing code you can look at to see is this a good use of generics and a good place to solve a problem with generic types so let's start with that definition of generics so generics allow you to define a class or a method that specify a type of arguments or return values at the time of instantiation now that sounds like another one of those definitions where we don't have where it's hard to understand but in fact uh as a developer you're actually using these probably in your everyday programming so when you instantiate a list of integers or a list of strings you're actually using generics there and when you do that you get some type safety out of the generics which allow you to not add the wrong type of objects to your list so if you instantiate a type of string if you instantiate a list of strings you're not going to be able to add integers to those strings and that's some of the really strong advantages that we get out of generics right one of the ways that i've described that to different developers that are new to the concept is you know you can think of the idea of if you were to write that whole class specifically to write a list of strings and then if you were just to do a text substitution in every place you saw string replace that with end that's what generics do but the compiler does all that work for you so you write the generic class once and the compiler replaces that type parameter you know that we see list of t usually and it replaces that t with specifically string or ant every place that you've used it in the definition so it's a way to let the compiler do that copy paste kind of reuse that we might have previously tried to do but let it do it in such a way that we only have to maintain one copy of that code so that's the kind of reuse that we're getting with generics so some of the language support that we get for generics is through generic methods we get it also through interfaces classes and then finally we'll talk about constraints so generic methods allow us to specify the arguments that go into the method as a generic type and we all can also specify the return value and this allows us to be able to specify the amount the type that we're using at the time that we're calling the method and that allows us to really make that really generic uh algorithm and use it uh how we want to at the time right so if we looked at some of the things we looked at yesterday we looked at that interface for i comparable which has that compareto method you know and in the classic non-generic version the parameter to compare two is an object and inside the implementation we were looking at the base class libraries what the code has to do is take that object and down cast it to the specific type to see if it matches the type that we're working on so the you know compare two for string has to take an object and cast it to see if it's really a string we'll see later as we look through the generic code review that we can see generic interfaces for i comparable of t which has a compare to where that parameter is now a type parameter it's named t in the source code and and what that does is it allows us to be able to access those properties on that type at the time we're accessing them so we can check that to see if the string has a length we can check for the functions we can use any of the functions that are on that type that we specify right once we've specifically made that it's compared to with a string then it'll match that method and then the classes would be things like list of t where maybe one of the properties or fields inside that class is one of the type parameters so you end up like james mentioned list of t when he was doing that first example it's like an array list but instead of storing system.object references which could be anything it will store specifically integers or strings or teachers or students or whatever in our different exercises and then finally constraints to define those in net when we write a generic method or generic class that type parameter could be anything right that's sort of what we're trying to do with generics and when we write it that way the only things that the compiler knows about that would be there on that particular parameter would be the methods in system.object because that's the ultimate base class of everything at net so by specifying constraints we can say whatever this type is it must satisfy some other contract you know whether that be implementing an interface having a particular base class being a class or a struct or having a constructor those are the kinds of constraints that we can specify on a particular generic type parameter so what kind of things we do in general with generics as james madison you've probably already used them we're going to talk about why they were used in certain areas and why these are the kinds of different problems generics really are a great solution for so in practice what we'll see when we create methods is that there are type parameters for at least one argument or for the return value and sometimes for both you know if you've done any link queries you've created instantiations of several generic methods you know there's funk of t which is a a function type that returns a type t you know which is used in say a select method is this one that's got two parameters one that comes in one for a different type of t that comes out there's a select which would be a funk of t comma bool so it has to return a boolean but the input type could be any type that's coming in on your selector system.link.enumerable has got a lot of those generic methods that are used to fill out all the rich functionality in link so that's one of the big areas where we see a lot of generic functions and generic methods i comparables another there's some from task task method based methods for creating a task that's finished or running a task those are different generic methods um yeah and you see that specifically on the count in the on innumerable the lincoln enumerable interface you actually see that with the count method you don't need to necessarily know the type to be able to count the number of items in the list and so that's a really great example of this function where you can you can use that as a method to count the number of items in the list so then in addition to generic methods there's a lot of examples in the framework of using generic interfaces so that's a type where we have a type parameter for at least one of the arguments or the return value once again for a common contract of unrelated types you know we've talked about one of those already that i comparable of t which would contrast with i comparable there's also i equatable of t which compares two different objects of the same type for equality um enumerable of t which provides the basis for link once again those are some other examples that we can look at and see exactly how some of those work again it's an interface and at least some of the methods return or take type parameters as their arguments that will be filled in when you instantiate it in a particular way and then finally we have those generic classes so in those one of the big distinctions is that type parameter is going to be used for some field or some property in a class and one guidance that i give a lot of developers is that if you're creating a generic class and you never use the type parameter as one of the fields or one of the members consider making those generic members of that class instead of making the entire class generic because there isn't any actual storage in an object that is required to use one of the type parameters and the methods can be instantiated multiple times on just a single instance of the non-generic class and again we have examples there for things like list of t which we've talked about task of t there are different dictionary classes as well dictionary of string comma int or whatever that we can use and once again we'll get different types there and we'll be able to use those type parameters as part of the storage used by that object yeah so one example that i i'd like to use from uh when i've worked with clients in the past is i had to build uh a box builder that would take a bunch of different items and put them into the box and now i didn't necessarily know the much information about the items so if they said i needed to put an apple into that box i could check the volume of the apple and then compared how much space was left in that box and if there's enough space i could put the apple in now the the requirements changed over time and so i had to put an orange into the box and so uh that i looked at that generic algorithm that i did with apples and it was the same same kind of thing where an orange has a volume and i knew how much was left in the box and so i was able to pass that type into the bot into that algorithm that calculated the the the location and how much space would go how much items could fit into that box and so i was able to make that a really generic uh instance there okay so your idea of that likely leads right into our next topic where we talk about constraints so constraints define some of the requirements on a type parameter so the kinds of things you can specify as a constraint is you can specify that any type used as the type parameter must support a certain interface or any number of interfaces you can specify a single base class you can specify that it must have a parameter list constructor and you can specify that it must be a class or it must be a struct you can't specify both of those they're mutually exclusive so in your example there it sounds like you would probably have to define some kind of an interface to be able to say that anything i'm going to put in the box must have a method to calculate the volume that's correct so i created an interface called i packable and i put that on apples i put it on oranges i put it on brownies i put on all the things that were packable we also had a this idea of being able to deliver these boxes around and so in our code base we actually had a object called a vehicle and that vehicle wasn't packable and because it didn't have that interface on it i wasn't able to actually be able to uh add that into i couldn't pack that with my algorithm because it didn't fit that interface right and that that definitely makes sense that's by having those constraints you can be as generic as you want to be but you don't have to accept absolutely everything as as something that you you want to work with um sounds good and then so let's look at some of the guidelines in terms of how do we look at problems and say this is something where generics is the right solution right how do we how do we find some of those and how do we know we're using these correctly when we when we work with our different designs so the first guideline i try to give developers is to just be as generic as possible and and that can be hard when you're first coming up with an algorithm so maybe we can go back to your your box example where you know if you start with something specific and you see how some things work you know you see that this is useful and then you can find okay now now i think this is useful in other places so how just like we were talking in the early modules about factoring things into base classes here we're looking at can i factor this functionality out into a generic type with a type parameter and then reuse it broadly across a spectrum of all kinds of different things yeah and so we actually saw you do that with the the teacher example and one of the solutions that we came up with you started at the the higher level of the teacher and you saw hey this looks very similar to what i'm going to be using for our teaching assistant and so you started there and then you extracted those specific components back out into an interface and so we can do the same thing here with generics right and i think this is how a lot of these techniques work together in different ways right if i want to build a generic that's not so broad-based it accepts absolutely everything like some of our examples from the framework and i want to specify constraints what i need to do is define some interface contract that's that's small and well contained which can then become the constraint for some set of algorithms on top of this very generic type now that supports a certain interface contract so i can get some some functionality there and i can say this is what has to be there for this to work okay and and over time as we as we do that more that's that last idea and this be as generic as possible we learn to separate specific from general algorithms and we'll really stress this as we go through the code review when we look at the collections like list of t for instance there's a generic part of that algorithm which is i want to take a linear storage block and store some sequence of items in that linear storage block i want to let it grow when i add new items i want to be able to shrink the storage when i remove items okay that's very generic i can put anything in there and the specific part has to do with what kind of thing can i put in this list and how do i make sure that i can only put certain kinds of things in this list you know sorting is another one it has that generic part which is if i can compare two things and know which one is greater than the other i can put them in order but there's this specific part that says in order to compare two things and put them in order i need to know which one of these two is greater than the other based on how i want to order them and when we start to separate those then we get a lot of the power out of these generic generic structures generic classes that we can build yeah i think that's one of the things that keeps on coming up in every single one of these modules is that we're trying to learn to separate general from specific and then we're seeing all these different techniques that we're able to use whether it's generics or interfaces or abstract classes to be able to accomplish that in our code and one of the things we're trying to do here is determine which is the best implementation which this best practice we should use to approach that and i have to admit there's times when i worry about that best practice word it makes it sound like there should be no argument about this right yeah this is the best way to do it and and for any problem that i've seen there's usually a range of different ways that you could solve it and you know as we stress when we've been talking about some of the review exercises there may be you know your solution may not look exactly like ours and that doesn't necessarily mean it's wrong it just means you looked a slightly different way and and this gets to one of the last things that i want to kind of lead into on this guideline is this idea that one of the ways that we can handle that specific part of the application is by using delegates which is going to be the focus of our next module where if i can define a specific delegate for a specific need and then i can create this generic algorithm that's almost all the way done but needs some little bit of code or some little bit of work from a specific type in a specific instance and again sorting i think is the classic example of that you know i can sort things as long as whatever type that i'm sorting can specify which one comes first and which one comes later and delegates can define that specific capability that i need for a certain certain algorithm so with that let's move on to that practices section what are we trying to do when we're actually writing code and we try to put this together and deliver things i sort of hate to start with this in a way because of what we spent the last few hours doing but i think it's because of habitum because object oriented has such a history of saying you know everything's about polymorphism is to really think about preferring generics to polymorphism if you look at the classic example of the containers they work because what they stored was references to system.object so i could make an arraylist and i could put absolutely anything in that arraylist okay i could make one arraylist that contain teachers students tas and you know maybe a class definition and maybe a you know a grade for a particular assignment that may sound like bugs actually because i'm putting all these different things in this one list and that's probably not what i intended yeah and when you do that in particular you're going to be starting to add all these if statements and else statements to make sure that you're handling the right particular object right and so this is where being able to use generics uh is going to be able to help you avoid some of that if and if right and the design is really that i wanted to make a list of the entire faculty so it's really a list of teachers and i just made a mistake by adding a student into it so by being generic and by specifying a type parameter once we get to compile that code that says this is a list of teachers well then we're able to go with just that object and we avoid that down casting idea which is i've got system.object and i need to downcast it to the specific derivedcast it is which is exactly what you're saying i need to look and see if it's a particular type have an if statement and go well it is that type then i can do extra work that's a lot of extra code that hopefully the language can mean we don't need to write and then the other big practice that we look at we talked a bit about your one example there is that we start with those specific algorithms we start with something that we know works and solve one problem and then we look at that solution and we say does the code that we've written apply in other instances and if so how right how can we take this one algorithm of putting apples in boxes and making sure the certain number fits and then say well what do we do with that now if it's other things that we want to sort whether it's oranges or pineapples or ears of corn or everything else how do we structure that algorithm and separate generic things from the specific stuff and when the opportunity presents itself to build those generic types then we get code that's much much more reusable and that's one of the things we want to do but i think it's really hard to see a problem and see only one specific instance of it and then know gee this should be generic right yeah i think over time um you as you practice these uh these various implementations of generics and interfaces and all those kinds of things you're going to be able to see that a little bit easier but when you're when you're first starting out it's going to be very hard to be able to identify where you should potentially use the generics and so by building it out the way that you know how to initially later on you can then come back to it revisit it and take a look and say hey this looks exactly like an algorithm that i've already implemented and any of that any time where you feel like you want to do that copy paste to move that algorithm in that's a maybe a good opportunity to take a look at generics and that's actually i think one of the big keys as soon as i find myself copying a large section of code hitting copy paste and starting to modify i really want to stop myself and really look at and say is there a way to is there a different tool here to do this without doing that copy paste part and and with that then one of the last things to do because it isn't just a it's really a continuum of how generic is something is we'll start to think about what are the constraints on a generic algorithm so i want to leverage those constraints so that my algorithm still works i still have the capabilities i need of any object i'm working with and i instead of maybe downcasting it to something i should specify that as a constraint right like in your example where we were working with the volume of of a box or a volume of what goes in a box you know i could have downcast it to something and say okay if the thing i'm trying to put in is you know an ipackable then i can do something with it otherwise throw an exception but by specifying the constraint on the generic algorithm you say the only thing you can call this with is something that supports that interface and then we can try to keep those constraints in place to say this only works with certain types that have certain capabilities we do want to keep those as minimal as possible because that does provide as much reuse as we can get but we do want to use them to make sure we're not adding extra code to do type checking inside a generic algorithm yeah when you start to talk about adding too many constraints onto uh your generics what happens is you start to go back to only being able to use one type with your with your class and so um if you do find you you can only use the specific base class or this single leaf class that you have then you're going to maybe go back and rethink whether or not you should actually be using generics here are you adding too much complexity to the code right by adding generics in okay and with that let's look at some of the last section of what what are the good outcomes with generics what kind of things do we see in our code when we're doing them correctly and as a counter example that what kind of things would we see in our code this is maybe this is a place where we should leverage generics better so one of the first things we get it's it's again sort of a computer sciencey word but we get that reuse via meta programming so i get type safe reuse i'm letting the compiler copy and paste and replace that t or t1 t2 with a specific type and i get to avoid that idea of saying this works with system.object and i'll downcast it when i when i use it we still use system.object but only when that's really what we wanted and we avoid that copy paste and modify the parameters kind of reuse and that's what we see is when we say all right if i see that then this should be a generic and those are really some of the first ones that i really look for seeing that reuse when i'm reviewing someone's code base and they asked me how it could be better and yep and then i would say the next really nice outcome that we get from using generics is that we minimize the down casting that we have to do so we no longer have to cast that object into the interface that we want to use or the object that we want to use and we kind of touched upon this already but when you anytime you have to start checking for the types you're you're potentially violating the liskoff principle and that's going to cause any that's going to cause some sort of bug long term for you because you might not end up with the right type at the time that you get it and so these generics really give you the ability to use that type safety that we talked about and use it to the best advantage so that you don't have to worry about casting and doing all that kind of stuff right because those downcast can fail at runtime and then we're going to throw exceptions and then we have to somehow recover at runtime you know if i can make it fail at compile time you know i i can't deliver that code i don't have to have qa test it there's no way a bug gets found in the field because i can't deliver the code that doesn't compile so that's where we're trying to stress that to push that toward letting our tools find those statically as we're doing the development and with that i think we've covered generics pretty well so a lot of the concepts we'll come back in a few moments we'll look at some of the examples that are inside the.net framework and how they've extended algorithms to make them more generic and provide some examples as to how you can use them in your own code see you soon hello again i'm bill wagner and i'm james sturdivant now let's look at some of the examples of using generics in the dot net framework in the core based class library now one of the things that we want to do as we walk through these demos is understand that earlier we walked through those non-generic versions of some of the same classes that's because historically.net 1.0 did not support generics that was something that was added in the second release that's why the the team had this choice of where they had some of these you know we call them classic style containers and so on before generics were introduced and that's why we see both in the framework it wasn't they wanted to necessarily provide both but just the generics weren't part of the initial release so the language didn't support it the clr didn't support it but in the next release when it was added all these capabilities were added there's four different areas that we're going to look through in this code review we're going to look at list of t and we're really going to contrast that with that arraylist class which is its counterpart in the non-generic world we're going to look at task of t which is a new type that's part of the task parallel library we're going to introduce the lab and then we'll come back in the second clip and we'll discuss how we went through and one possible solution to the lab for you great so we're going to start out by taking a look at the arraylist class in the msdn documentation and then we're going to compare that to the list type of tee so down here we've already kind of seen this before what we're going to take a look at here is just a quick reminder of what this looks like so in the constructors we have the couple simple arraylist constructors uh that initialize the various collections and then potentially uh the size of the array and if we come down we've got a few of the properties such as count and capacity and when we go down to the methods we'll see that we have methods like add object um and binary search and we're passing in the object type into those methods now we're going to take a look and compare this and a classic i compare yeah and a classic eye comparer there and so we're going to take a look and compare this to our list type of tee and when we go and look at that here what we see is when we come down to the constructors we now no longer are passing the type of object but we're actually passing the type parameter here and we also see that in list of t we see we have some very similar properties and then when the methods come in we have the the t type parameter now what i'm going to do here is actually compare these two lists of methods you can see when we look at the add method here we have object and we have t type t on the right for the the list type of t and what happens here is we can actually almost uh do a control find for object and replace it with t and so that's a that's a key component to kind of identifying some of these these methods here and that's effectively what the compiler does that when you instantiate a list of some type that's not t the compiler replaces it with the specific t with a specific type great so next we're going to go and actually take a look at what list type of t looks like inside the inside the code and up here what we're seeing is the public class defines this type parameter here and this it actually implements i list of t so we'll actually dive down in and take a look at what i list of t looks like i think that would be something like i list right you got it so ilist looks uh very similar but what you can see here is instead of just finding an integer or the object it's actually using t in place of those things and it's also implementing type of i collection so we'll take a quick all right i collection of t yes uh which is then uh re is also implementing i enumerable and so you're starting to see this inheritance of all of these interfaces uh and the generic interfaces that they they represent and it's all the same type parameters so i list of int would implement i collection event which would implement i enumerable event and so on right because that's it's bound to the way that i list of t is defined that it's whatever t it uses is going to be the same type parameter for the i collection part and the i enumerable part yep you got it and so when we start to look at these interfaces it's a little bit easier to see here that this t is where we would actually put the object and so um now when we specify integer anytime you see this t is where we actually uh would conceptually identify it as an integer or a string or any or a student or whatever the type parameters for that particular object if i made a list of or a collection of of customers or a collection of packables that would be an ipackable yep so let's go back up to list and take a look at the sort method inside list because that's a really great example of where this these generics kind of work very well together so i'm going to go ahead and find this sort method so down here we see there is a few different sort methods but the one we're really interested in is this one down here when we take a look at the the method signature what we see all the way down to the right here is we actually get that i compare of type t and so this is where we saw the um before we would see the the non-generic version of that comparer and now we actually have to use that generic version of the compare here which allows us to get that type safety even at that that interface level right so if i'm sorting a list of strings my compare has to be something that compares strings that's that same type parameter okay cool so um is there anything else you wanted to take a look at inside the inside of the list there's one other thing that i wanted to um to look at in there did we so we looked at sort we looked at some of that now that one only takes one type parameter so it's always just got list of t and i think one of the things we really didn't cover if we looked at say our dictionary of t key comma t value we can have multiple type parameters so we can and they don't have to be the same so i think that may be one of the things that's that's worth kind of looking at just a little bit okay just to contrast that because it was one of the things that we we um you know we looked at the hash table class and this would be kind of the non or the generic equivalent of that so i think that that ends up in the same solution as well so i'm just taking a look for the dictionary let's see if we can find that hopefully we can find that without too much trouble yeah but i think that would be one of the important ones to take a take a good look at hey there we go so i think we even find getting using it we can here's the dictionary so we're going to go right to the definition f12 there we go okay so now right so that's got so now i've got two generic parameters and and i think that would mean they don't have to be the same type right i can make a dictionary where my keys are strings and my values may be you know customers or websites or whatever and and it's going to distinguish when the compiler is going to do that work unlike say the hash table where my keys were system.object and my values were system.object and i might make the mistake of mixing them up in some api somewhere the compiler will make sure i can't do that here with this type right and so you can also see down here that they've included a private structure down here and they're using the key with the type uh t key and over for the value they're using the t value and so they're getting those from the two type parameters that are specified in the class up there and so you get that type safety when you're trying to access the key in the value even in the private fields that they're using internally they're making use of that same kind of type safety right okay getting that same kind of reuse from that generic algorithm great so i think next we're going to take a look at the task class so i'm going to switch back over let's talk about task of t is you get that code loaded so task of t is meant to represent some asynchronous work in the task asynchronous protocol so a task of t is some work that's being done asynchronously and when that asynchronous work finishes the result of it is going to be an object of type t so like if it were say a web request the result might be the string that comes off the stream from the network stream if it's a file read it might be the bytes that got read from the file something like that right yeah okay so how does task of t work and what what why is the generic stuff helping us there and i notice there's no task well there is a task class but the task class doesn't have a result so it returns it's it's a task that does work but doesn't return a value so there isn't a non-generic like task of object anywhere because that one is new enough it didn't come into play before generics were in the language so there's just the the generic version right yeah so we're going to take a quick look here at the msdn documentation for task the task of type t result and so you can kind of name that that generic parameter however it makes sense for you to communicate what this is actually doing and so here we're actually saying it's the result that's going to come back from our asynchronous processing and we're specifying what the type value might be and so we can specify whether it's a string or an integer or some student or some other object that we have created ourselves right so there's nothing magical about just using t or t1 or t2 it's just sort of a convention because it stands for a type it what goes in there is a a type not a not a not a variable like not you know name or age or something it's the type string or int or whatever yeah that way when you're working with it you actually know that it's a type and um and they in this particular instance they're doing t of results so that you know that's a result returning from it right okay a operation so sort of like that interface to start with i generic type parameters start with t yes just a convention okay exactly so back on the documentation here we can see there's a variety of different constructors and we're actually seeing some of those delegates that we kind of briefly touched upon we're not gonna we're gonna kind of brief uh briefly go past that for right now because we're gonna touch upon that in the next uh module that we talk about but you can see that we can pass different types of results and get them to return right so for right now just think of that as a way to that funk of t result is the work that's going to be done asynchronously it's some method yep and so you can also see there's a whole bunch of properties that we get access to we can find out the state that the object is in we can find if there was any exceptions that were thrown during this processing and if there was any results and what the status of this task is if we go down to methods the result would be of type t result yes that's one of the places we can see that right here that it says it gets the result of the value for the the t result that was specified when this this class was instantiated and there's a whole bunch of different methods that we're not going to dive too deeply in here that allow us to be able to continue on with other actions once those results come back so let's go take a quick look at the code switch over to visual studio here and i've got my task class loaded i'm going to bring us back up to the top and oh nope i think i'm in the wrong space so oh okay so there's actually two uh classes here that okay that kind of work uh in in parallel this is that task class that you mentioned before but um what we actually are looking what the one we want to be looking at is actually in this future class and because it represents uh a task that has been uh returned from uh some uh operation that we ran in right so so somebody took the name task.cs and they had to just come up with a different name yeah okay yeah yeah naming things it's always hard exactly it's one of the hardest things right right uh so on our public class here we have a task of t result implement inherits from tasks so we're pulling in all of those features that we just saw from that task class that i was kind of moving around in there and i think again the nice thing that we can notice here is that this t result is something that's going to be stored internally okay and so we see that the uh object is being used inside of the class and this is that member variable and this is where we were kind of talking about in the previous module where the result if you're not using the result internally then you potentially could just use a uh method right yeah so here we're storing it's going to have its default value so it's going to be null since the tab if the task hasn't finished yet and then i'd assume somewhere along there as the task completes it's going to store that value so i can retrieve it with that result property yes so maybe we'll take a quick look at that um result property oh i think actually a better way to do this is to come up here and come look through here now test.result there we go and so there's a bunch of extra information in here but you can see at the very end um at the end of this property we're going to be getting the actual value if we check to see that it's actually been completed if it's been completed we're going to do it otherwise we're going to try to figure out if it's supposed to do it and and for people that have used the task then that part in the middle there's something interesting where if the task hasn't completed and you're trying to get the result it's going to block until it's uh completed oh wow so what will happen right so if you've got a task that's running and you look at its result property that code will block until it finishes either successfully or by throwing an exception yeah okay cool so that's that's what that code is doing is if it's and that that first part is whether or not it wants to if um wait notification is is enabled so if it's not you can set that not to work that way but in general that's what will happen yep and so you can and just so you can see that we're actually returning the the t result type there so okay i think the next thing we want to take a quick look at is um the task of uh task from results so yeah there's that i find is a great convenience method for when i'm working with tasks and i don't know exactly what it is that you know or when i'm testing and i want to mock out something that maybe say a network call that's going to return a task of stream and i want to write unit tests for it i can create a task that's already completed and has a result that i want so that's kind of where where i find that one really really useful okay so yeah so let's go ahead and take a look at the code here we have uh this this is a static function on that task object that we had originally seen and what they're doing here is allowing you to pass in a type and then create a new task of the task of t result from it and this is a great example of using generics at the the method level and not at the class level right so it's kind of using both here that task.firmresult is a static method so it's going to be a generic method and because of its its types and when it returns it's going to implement or it's going to instantiate a task of whatever type we want and then return a task that's already got a completed value in it and its state is set to already run to completion successfully okay yeah and so i think what's important here is that um this task can run and return any type of information uh but the in the async infrastructure that's relying underneath it is gonna stay the same so right so once again as we talked about with it walking through the powerpoint some of the concepts around this is the all the infrastructure in the vcl to be able to say i'm going to start a task that does a whole bunch of work and all the infrastructure to say that task finished or that task faulted because it generated any one or more exceptions running asynchronously or that task is still running it's not done yet all of that is very generic no matter what the particular task is doing the part that would be specific maybe to our code is what result gets generated from that asynchronous work and what type that is and how i'm going to process it once it's already back and that's that t result parameter so from the generic standpoint a task returns some object eventually and now we can have type safety around that some object eventually part so and with that let's let's look at what the lab exercise is here so when we built our our code in the first three modules we stayed away from generics because we hadn't covered the concept so now what we want to do in this lab is i want to revisit the implementations that we've put together so far and look to see if using generics would get us more typesafe code in the things that we've built is our implementation using the classic collections anywhere you know a couple of them we looked at yesterday and they are we want to replace those with the type safe version with the generic version of those collections to avoid being able to put the wrong things in those collections and we want to look at those type parameters carefully so that we can preserve the polymorphism i want you know like if i want to be able to treat a teaching assistant or a teacher the same that would mean that my type parameter should be that interface that we we developed or if i don't want to if i want a specific only the main instructor which has to be a teacher object well we should put that in place and in fact once again if i want all the students would that also include the teaching assistants because it's derived from it it would right because if i make a list of student because teaching assistant is derived from student you know i can put a teaching assistant in that list because a teaching assistant is a student right so i have i don't have to always pick just the leaf classes of something i can pick a base class in my hierarchy where i want the polymorphism so i want a collection of all students which includes the tas so that would be one of the things that we can we can look for as well in this lab and with that we'll let you work on that for a while come back and we'll discuss the solution that we built hello again i'm bill wagner and i'm james sturdivant and let's go over our answers for this particular lab exercise so we ask you to do is to work through looking at what we've built so far and see if using some generics would actually really help so let's look at the code that we put together and let's see where there were some places where we were not making use of them particularly well and it's primarily in the teacher class and in the teaching assistant class in both cases we had that arraylist where we were storing all the list of classes that an instructor would teach so i replaced that with making it a list of string so now that has to be a string parameter when we go to add class titles note that now that code really didn't change at all because we were casting from a string down to an object and since the string is an object that was fine same thing in remove and now this property where we're retrieving all the class titles that a particular teacher would teach is now typed as an i enumerable of string because i want to return the actual type of what's what's really there you know note that we could if i wanted to i could keep this property still as the old i enumerable and if i remember to include that uh classic namespace you know that will still compile so because i enumerable of t does eventually inherit from i enumerable and i could still return all of those lists of titles which are strings i could still return them as an object a list of objects but i don't really want to so we want to leave those back as the strongly typed innumerable string that lets us look at that correctly and so did you do this also in the teacher class i did so i started by doing the exact same set of changes in the teaching assistant class which also can teach classes but in the ta case it can only teach two so once again i made that list of strengths as to what classes the teaching assistant can teach we've got the property to return the innumerable string which has the classes in place and then if i look at add and remove remove is pretty much the same add here looks a little interesting to me in that what we did is i have this okay so if it contains the title we're just going to return because i don't want to have duplicates in this and now if the count was less than 2 well then i'll go ahead and add this new title however if we already have two titles i'm going to throw an invalid operation exception because teaching assistants can teach no more than two classes you know that was our business role when we put that that teaching assistant class together so that was my first pass here so so what do you think of that yeah that looks really really interesting uh one of the things that i noticed is that with the teaching assistants you you're only going to be able to have two classes but here you're actually returning an infinite number of string classes that you're working with or it could be right i mean that list is going to grow it's going to get up to four certainly the storage could put whatever we wanted into so my my internals don't really match my business rules really right yeah and that was what i thought too after i started working on this a little bit so i said all right i'm gonna change this and do a slightly different different approach so i made a second version where i said you know let's let's make sure that we really are only teaching two classes if i'm really only teaching two classes as a teaching assistant maybe i don't really need a full container at all so i just have two strings for class one and class two those are the only things i can teach if we look at removing a class i just look to see well is the class i'm removing one of the ones that i'm working with in which case set that one to null so now it's that would indicate that i i'm not teaching this anymore if we look at add i'm going to say a little bit different logic if the class i'm trying to add is one of the two that i have you know so i'm not walking this entire arraylist i'm just doing or this entire list of strings i'm only looking at the first two elements here and then if it's already one i'm teaching will return otherwise i'm just going to look to see if one of those two slots happens to be null and if so i'll assign it so that part worked pretty well where i had a little bit more work to do and it introduces a new language feature that we'll work with more in the next module but it does point out our encapsulation idea is i needed to rework that method that returns i enumerable of string that indicates that i'm teaching what i'm teaching now so if i look at this i enumerable string and i should point out one thing we haven't done in our code review is i did update that interface for i teach so now it's it's typed to have an innumerable string for the class titles rather than an innumerable because we are returning the class name or the teaching class names and now if i want to return as an innumerable of string those two titles you know i could create an array or create a list and put the two titles in it and then return those but there's a really nifty feature in c sharp called yield return that creates an enumerator method so if we look at this code here inside my get method what i'm doing is i'm saying well if i have an object for that first class that i'm teaching i can do a yield return of that and what that does is the compiler creates something that can act like an enumerable okay so it creates an object whose first element is going to be that class one and when move next gets called there's some compiler magic that happens and when move next gets called we'll execute this code so move next gets called and after we've yield return to the first method we jump back into the same method again to execute the next piece of code and so this seems to be like a shortcut to be able to uh create that innumerable object that we had created in the in the past classes right so instead of actually getting that enumerable from a collection class that already knows how to enumerate it i can write this code to just yield return this you'll return that you'll return the other thing and the compiler generates an i enumerable and an ion numerator that knows how to return those things in sequence right so i'm leveraging the compiler to be able to encapsulate the fact that even though it says i have this innumerable string for the titles i have a property that is here's the classes that i teach i don't need to store that as a collection i can use some compiler magic to say well i'm going to return this object that knows how to enumerate the different the different classes that i have and knows how to create that list or to create that sequence when you ask for it cool and so one of the other things i notice here is that this looks to be more of a function than what you had used in the previous example that's right so before when we had that expression-bodied member which i still have on the teacher by the way where i had that expression-bodied member where i'm just returning a reference to my internal storage but typed as an eye enumerable of strength here this is now a full-blown method to implement that get access or on the property so that it's computing or creating the object that knows how to enumerate these two strings at runtime so yes there's a little bit more work being done here still validates the contract and again it's showing that encapsulation principle from that very first module you know and as we go through more and more of the last two modules we're going to see some of that more and more where the things that we were doing early are still part of the techniques that we're using in order to solve these problems yeah and so we're building upon all the the concepts and techniques that we've been using previously uh and that we've covered in the past modules and they're we're seeing how these those really basic concepts that we worked with are starting to really help us develop these more complex uh algorithms and and concepts that we're working with right and because i keep the same contract here you know now i have changed it as part of being generic to be able to be i enumerable of string now but the internal implementation is still exactly it can be totally different and client classes don't matter in fact if this were in a very very large production code base what i would probably do is i would also probably still if i was worried about a breaking change i would still have an eye innumerable and i would say i want to return an innumerable um for class titles and i might try to have a separate interface there to say you know to explicitly implement the old interface and still have it right because what i want to do is say gee if i'm going to return this i want to be able to still support the old the old versions but since i enumerable of t does implement i enumerable i haven't broken any of the existing code right because an eye enumerable of string is an innumerable so clients that were still using the old interface could actually still still use this so by encapsulating that change i ensure that i haven't made any breaking changes for any of the code that's using this [Music] cool so that's where we came up with and the code once again is on on the same github site as before you'll find two branches for this module i wanted to show two both two both steps that i went through that we demonstrated here and with that we will take a break and we'll be back shortly and start talking about delegates and events and outbound interfaces see you soon hello again i'm bill wagner and i'm james sturdivant and we're here to continue our discussion of object-oriented practices and different ways and techniques that you can leverage the tools that we have to build great applications so we're getting close to the end we've got two more topics to cover on this tour of different application techniques working through object-oriented programming and object-oriented design and building programs this particular module is all on delegates and events we're going to be talking about ways to have the what we call outbound interfaces where you're creating a class and creating an algorithm and you need some code from the client objects that are going to work with your application in order to fulfill that entire algorithm a classic example is sort that we talked about and we've seen that in terms of the interface of i compare that has effectively a delegate or a method on it we're going to expand on that definition in terms of other ways classes can communicate outbound with other objects and other types that haven't been written yet and make use of those and work together with those so this is all about delegates events and lambdas are a type of syntax that make it easy to create delegates and events so we've actually seen them already in that expression-bodied member that i used in one of the a couple of lab samples to create a very very shortened version of a function we find a very very concise clear technique for implementing what would be an outbound interface where something else is going to call some method into into what we're working with in this module we've got four different sections again we're going to define both of these terms and we're going to stress especially the distinction between delegates and events they're very similar and they have some nuances that are not well understood especially by people approaching it for the first time we'll talk about some of the guidelines is that how do you pick which one of those to use how do you know when to use either of them what kind of practices are going to be part of effectively using them and we're going to look at what kind of code comes from effectively using them correctly and being able to see what kind of things and extra error tracking maybe you don't need because you've picked the right tool let's begin by looking at the definition for both a delegate and an event so a delegate is a type safe method reference and it's used for defining these outward bound interfaces what it's really letting us do is be able to specify a function so that we can use that function later on so we can specify the parameters that are going into the function and the parameters that are coming sorry the return result that's coming out of the function so we don't actually write the function but in terms of a delegate definition we specify its signature right so um and so then next up is an event an event is a delegate with a specific format so it's built on top of the the delegate format but you have to specify the sender and event args to the uh the at the parameters that are going into the function and it's used to define the outward outbound notifications and so what we're trying to do here is we're notifying the users of our class that something is going on a classic example of this is the click event and when when someone clicks on a button uh it's going to fire an event so that the classes that are surrounding it and using it are going to be notified that the event has been fired so it's interesting if you and and the key word here on the difference you notice these two diff these two definitions look a little similar the first one we said it defines an outbound interface and the second one we said for an event it divides an outbound notification if someone clicks a button and no one's listening for that event nothing happens right but if i go to try to say sort a list and i don't provide a delegate or i don't provide an implementation for the specific ordering function that's going to throw a null reference exception sort needs to know that information the button is more than happy to raise the event and say okay for anybody listening it just got clicked but if no one's listening a button's fine with that you know just like there are other events on button for on enter on blur mouse move if it's inside its borders and so on that may be optional may be part of your code but if you don't need to you don't need to subscribe to those right and so um there's different ways to be able to exp define and implement these delegates and events one of the ways that you can do that is using these lambda expressions so a lambda expression is a shorthand syntax for for these expressions and they can be used to define the delegate instances or event handlers and this is really just a shorthand way of defining a function uh in line with uh in an easy way to uh to describe what that function does and some we use these a lot when we don't want to go through the whole ceremony of creating a whole function uh outside on another class or something give it a name you have to have all this and and when someone's doing a code review they see this function they wonder where it is where it's called it's only being called to attach to this delegate handler it's it's definitely keeps the code more concise and keeps that that definition of the handler or the delegate for a particular algorithm exactly with where it's used rather than some other place in the file it does over time as you get used to the syntax it certainly makes it somewhat more readable i think yes so let's look at the difference i think contrasting those delegates and events as i said they're very similar we both are saying it's a way of defining the signature for something you know a class that raises an event is going to call the event handlers on it a class that has takes a delegate may call that method you know in both cases they define those method signatures they define the arguments we define what the return value is we haven't introduced that that next topic that single cast and multicast for a delegate so what that means is a delegate can have multiple subscribers attached to it and that's especially important in events there may be multiple pieces of code that operate when that button gets clicked so multiple listeners can be listening for those notifications and a delegate a variable of type delegate can be null if we wanted to yeah so one of the things that i asked you when we were preparing for this class was what's the difference between the delegate where it defines a method signature and the difference between a method signature pattern right so so with an event if i'm going to define an event there's typically a pattern that says an event is a specific type of delegate it's going to have a void return so there's no value returned from raising an event because there may be nobody listening and it has this particular pattern where the first parameter on any event is the object that raised the event and the second parameter on the event is of some type that's derived from system.event args that will have information about a particular event you know in some instances it may be event arcs.empty which has no particular event in some instances let's say in a button it may be exactly where it got clicked you know in other events it may be exactly you know in an event for say a logger it may be the message we want to put in the log and so on so it but it has a very specific pattern the compiler doesn't necessarily enforce this you can use the event keyword to define an event and have a different signature but there's a lot of code out there that's going to assume that something that looks like an event is going to have a signature with exactly those two parameters first ones of type object and it defines the sender and the second one is of some type derived from system.eventargs and that is all the information that is passed along in the event and a further part of that pattern is it may be true on any number of event styles that one of the properties inside that event args derived object is for the event handler to communicate back to the code raising the event um this will be common in a um in systems where you may have an on button click let's say or on leaving a window or on closing a window is actually one so there's in the window class for desktop programming there's an event for on closing which happens when the user starts to click the close button but the window hasn't gone away yet and one of the return values from that or in the event args is a a cancel flag so if you have unsaved work you can cancel that and say i want to rate you know raise a message box and say you know do you want to save your work or not and set that cancelled flag and then the the object that raised that handler will look and say oh somebody wants to cancel this i won't continue closing the window other events like on closed which is after the window is closed won't have that kind of a pattern but there is a way to be able to communicate in a return value kind of sense because the event handlers don't return a value so that's the way they can communicate back if we need to great so we kind of looked at the differences uh in the way that these delegates and events look but how do we start to look at how you're actually going to use them inside your code delegates generally are defined as methods that you'll you will be calling with your class that has defined that method and so you're really relying upon the the calling class to define that that method for you so when i look at at any api that i'm using and one of the parameters is some kind of a delegate i expect that i have to fill something in there you know i may i would not i would expect that if i pass null in on that it will probably do something bad like throw an exception or do something and if there's a type that has a member that's a delegate i'm supposed to set i would probably expect that if i don't set it bad things are going to happen in my code and that's probably because the calling the code that define that delegate is actually using the that method that you're that you're supposed to be defining and if it's not defined it's going to throw that null reference account right it's going to call that delegate that's part of its general contract right and we can contrast that with events so they'll be defining that outgoing notification and it may or may not be called as part of its regular use and that's up to the the code inside it we'll call that if you subscribed to the event or if other code is subscribed to the event but if there are no subscribers it won't try to raise the event and it should not you know throw a null reference exception or some other kind of exceptional behavior yeah so your class is really not dependent on the definition and the implementation of that event right so like when i create a window object i don't have to subscribe to all the events that it's going to raise or that it may raise i only need the ones there's quite a few out there there are quite a few so you've got the mouse click you've got the mouse closed you covered a whole bunch of right move and all kinds of things there's there's dozens so we don't want to have to do that so that's that's really that um what you're communicating to developers reading your api about the difference between those two an event is something that someone may be listening to and a delegate is something that this class is going to call because it needs to in order to get some of its work done okay so i think i got a pretty good understanding of what delegates and events are where does the lambdas fit into all those what about lambdas so lambdas allow us to define that method at the point of its use so it's much much simpler it's much more concise if i don't want to use the lambda syntax what i would have to do is create some method inside a class you know whether it's private public static whatever i would have to create that method give it a signature give it a name now it's going to be part of whatever developers read somewhere else to wonder where is this called how many places is it called and so on whereas if it's only called when i'm attaching it to a delegate variable or attaching it to an event handler if i define an inline as a lambda expression when i'm reading that code i can see that the only place this is used is as part of this delegate or in this event handler you know it becomes a much much simpler way to see that this piece of code is only used right here right so really when we uh i definitely have run into that before where i've found functions on classes where i just can't find where they're actually being used and what happened was that they ended up being used uh for one of these uh delegates out there particularly in maybe some kind of uh method uh that's taking that function in and um so it's really great to be able to define that method right on the on that uh define the method and the functionality right inside that method that we're implementing right because the flip side of that is then when you're looking at the code that that uses that function as a delegate you're reading this thing and you're looking at it and you see one of the parameters is the name of this function somewhere else in the class so you have to you know we have nice tools in visual studio to be able f12 and see what the definition is but it doesn't flow it doesn't read as well right it does it's it's harder to see okay here's this this query and now it's calling this function that's somewhere over here and i have to go look for that and find it now i understand that now i'm coming back to this and and just as we're reading things it's harder to process you know so it it it makes it more difficult for us as developers to read someone else's code and see exactly what it does which you know as we said in our introductory module that's one of the big keys about understanding how and what we're expressing with any of these concepts is we want to make our code easy to read for other developers as part of our team or as people who may come behind us to add more features into the code that we write and and that's where i tend to trend toward using these lambda lambda expressions which is where i just have that parameter list then the the big fat arrow the equal sign the greater than and then the implementation body right there it's easier to read because i see semantically what the implementation of that delegate is at the point where i pass it to this other algorithm so next up i think we're going to talk about a few of the the guidelines when we're implementing delegates events and lambdas so i think the first thing we're going to be taking a look at is when we have notifications that we need to push up to other classes we want to make sure that we're raising events so your class is going to define the event and the protocol that is going to be the receiving side of the um event and then your code when one of these events happens when the button is clicked when the form is closed it's going to raise that event up to all your subscribers and so subscribers will actually uh register and they can also unregister to any of the events that they're interested in and so we kind of touched upon this already but events you don't necessarily have to have a subscriber and you can have multiple subscribers so you can have one two three maybe even all the way up to 10 or 15 or you know right you know i don't know how often in practice i've seen a dozen subscribers but it's certainly possible right if something's coming inbound it's an event the the implementation of the event and delegate object in the base class library will automatically take care of handling multiple subscribers so we don't have to worry about that in in the code we write but yes by having that event there may be zero so there may be nothing attached to the event and we'll have to implement that inside our class you know we'll see an event handler that event object is null and then we shouldn't raise that event but once again we define the protocol we say these are things you can be notified about if anyone wants to be notified they can subscribe and one of the key things i think about this by using this event-based model there are no restrictions or assumptions about the type of code that's subscribing to an event right we don't have to have to find an interface to say you must implement this interface if you're going to subscribe to the events we don't have to describe a base class we there's no restrictions whatsoever any other code in our application if we have a public event can subscribe to that event and process whatever work it needs to do when the event is raised yeah and that really makes your code a little bit easier to extend so you don't necessarily need to know all of the use cases for this event firing off and so you can easily add an assist this other event that's going to do this new implementation for you that you had no idea was something that they were going to use it for when you were implementing the class and it creates a very very loose coupling right i can build this object and i can build this class and it will raise events and i don't have to make any assumptions what's wrong or introduce any constraints on the subscribers of that event right so that's one of the big keys there i don't have to introduce any any constraints anywhere there's no assumptions any code can can work with it's very loosely coupled [Music] okay and then the next thing then we and we led into this when we're starting to talk about generics is delegate arguments for different methods they can express the missing piece of an algorithm right we write these generic algorithms we were talking about that earlier and how do we fill them in well that looks like a delegate it's a small piece of code and we can define generic delegates to meet our need and we'll concentrate on some of that more in our functional programming section because it's a key building block there and for right now delegates can define the specific capabilities for a particular api that we need to use in fact the term functional programming comes from the idea that a function is a piece of data that can be passed around just as other bits of data you know just like here's an int no here's a function okay so delegates to find those specific needs great and so i think uh we see this quite a bit in the the link library where if you need to order by a particular uh particular property you're going to pass that property as a expression or in the delegate and that allows us to not necessarily know what that that is at the time we're against breaking out that specific from the generic and the specific is when the client is actually using the code right and where is another good example so there's an expression a delegate you have to pass to where you know and where is basically a filter so if i want to say you know in our in our lab i could define a query that says i want to see all teachers who grade easily right so that i could write a where clause and say this expression is going to return true if most of their grades are a b or above and it returns false if the average grade they give is a c or below and now i have to define that delegate that takes in a teacher and returns a boolean so it's a small little function to go to the where clause to um to filter the for the results that i want and the idea behind this and where i think we're going with this is again it's very very loosely coupled i can add that functionality later with very minimal requirements i just have to match that delegate signature that we talked about in that definition section you know in the case of order by it has to return a single property and that property has to implement i comparable of t for whatever type t that property is in the case of where it has to be a method signature that takes in the type of the sequence as its single parameter and returns a boolean okay it's a simple signature anyone can write that simple function and what it means is by using delegates now instead of some of the other techniques we talked about earlier you
Info
Channel: TechCode
Views: 93
Rating: undefined out of 5
Keywords: object oriented programming tutorial for beginners, object oriented programming tutorial, object oriented programming for beginners, oop tutorial for beginners, oop for beginners, morioh, code geek, object-oriented programming, learn oop, object-oriented programming practice, object-oriented practice, object oriented practice, learn oop python, learn object oriented programming, object oriented programming, learn oop from scratch, oop python, oop in java, oop in c++, oop
Id: uQJMQYKqPIU
Channel Id: undefined
Length: 403min 47sec (24227 seconds)
Published: Mon Nov 29 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.