Main

C# with CSharpFritz - Windows Forms and the MVP Design Pattern for Unit Testing

In this episode, Fritz starts by answering some questions about getting started with C# and constructor overloading. We take a look at the C# Jupyter notebook and discuss constructor interactions. Next, Fritz continues by bringing up the calculator sample from the previous episode and refactoring it to use the Model-View-Presenter architecture. Using this approach, we introduce unit tests and add some features to make it easier to use the calculator sample application 00:05:15 Introduction 00:13:10 Parameterless Constructor and overloading discussing 00:40:00 Windows Forms Refactoring and Unit Testing Samples are available on GitHub at: https://github.com/csharpfritz/csharp_with_csharpfritz Get your questions answered on the Microsoft Q&A for .NET - http://aka.ms/dotnet-qa​ Learn .NET with free self-guided learning from Microsoft Learn: http://aka.ms/learndotnet #DotNet

dotnet

2 years ago

[Music] [Music] so [Music] [Music] so [Music] so [Music] [Music] [Music] [Music] there we go good morning good afternoon good evening whatever time it might be where you are out there welcome back to the live stream my name is jeff fritz and this is c sharp with c sharp fritz we're going to be learning about about c sharp programming language about some dot net frameworks and we're going to be building we're going to actually be learning a little bit today about um a design pattern and testing i
had a question come through asking hey can you cover a little bit more about testing so we're going to talk a little bit more about unit testing and some patterns today my apologies i wasn't able to this is my first day back uh back at work this week i didn't get the youtube configuration set up right before we got started so this will be available on the youtube uh as a youtube recording we're not live streaming out to youtube right now that's okay we'll get that all set up and ready to go uh
for next time we'll be back online with that so how we doing there room let me say hello to the chat room they're right over here how's it going there shy sharp is here bob ross rtx good to see you arshia hello hello uh cti geek good morning to you in virginia charles glooly good morning bob ross it's good afternoon in the uk oh my goodness i hope you're having a great monday even after a little bit of disappointment yesterday um my goodness i i have such a i have such a problem when when athlet
ic competitions when sports when when the finals of major competitions get down to the very end and and it ends up going to a shootout it ends up going to something that isn't inherently showing the skill of the players and they have to go to this modified not the same as what you were doing for the last 60 minutes 90 minutes um of a match and it's it's it's not quite the same it's not as uh it's not the same experience it doesn't feel very fulfilling when you have that change and in in hockey h
ere in the states when we saw them bringing the shootout exciting but not not fulfilling gosh we're not seeing how the players play the game anymore it's it's clearly it's competition of only two people skill to decide a match and it's it's a little underwhelming to me so so this is my first episode back so i i didn't have a lot really scrolled out and planned um as far as where to go new new content to teach but i did want to answer this question around unit testing unit testing is something th
at i do a bit of um and i'm very familiar with and i wanted to go through and show a little bit about applying unit testing and design models to the project we left off with a few weeks ago where we built a we built a very simple calculator using windows forms i want to dive back in there and talk about adding adding unit test hooks refactoring for testability how we can take advantage of some design patterns in particular there's a design pattern that i like to use with windows forms called mod
el view presenter i also use this pattern years and years ago with web forms asp.net web forms some folks take a specialized version of this pat design pattern called model view view model and they'll use that as well always open answering questions here the the ama tag is on you can ask questions here um just had a question on season one with commenting uh on episode two sure what do you have arshia uh go ahead and you can ask a question we can back up and take a look at any topic and uh and di
scuss further as we wanna get into the session today always it's it's particularly for this stream um it's much more important to answer your questions to have these discussions to make sure that folks that are just starting their c-sharp journey feel comfortable that they are learning about the technology and they're enjoying what they're seeing here so uh let me know what what questions you might have i'm happy to pause and take a look at that um oh curious drive see getting right into some so
me deep questions here design patterns aren't entirely my thing but we can discuss what's the difference between model view view model and model view update so the way i understand it the way that i see this and we're going to get to let me get to our shea's question after this the way that i see this model view view model you have three objects that you're working with a model a view and the view model object so you typically have three different objects that you're working with and they're wor
king in concert with each other a model that is housing the data that we're going to present we're going to interact with so that's our our data container our view that's how we're presenting that's a very dumb piece of code that all it does is display the contents that we want to show and the view model takes feedback from the view and handles some events like button presses or or drop down uh but drop down box selections turns those events into actions from the view pro and decides what to do
with them hands interactions off to the model where model view update there's only a model and a view and the model knows how to handle all of its interactions and the view knows how to update and change its presentation and they work together that's what i understand model view update to be i haven't worked with it specifically there's some coming interactions here with a uh with a framework that's going to better support model view update mvu it's it's not something that i have expertise in bu
t i definitely want to spend some more time practicing and learning about that's the way i understand the two to be i could be wrong on model view update though because i haven't done it yet or she has a question here about there's a parameter parameter easy for me to say parameter list constructor that made is enrolled to true way back in episode two of our first season um that isn't working for arshia so tell you what i'm gonna get some i'll get the music playing here in the background let me
bring up and we can go back and take a look at that uh that notebook and we can learn more about that i'm opening my browser right here and we're going to get some music playing this is stream beats from harris heller and this is the synth wave playlist this is some groovy music that's just cool to listen to easy on the ears dmca free royalty free you can listen to it wherever you'd like uh twitch youtube facebook doesn't matter check it out streambeats.com there's playlists for all the major mu
sic services uh thank you so much harris for letting us listen to your music today so i have the uh the notebooks opening over here we'll take a look at this there we go it's opening up right here parameter list constructor in notebook 2 to set is enrolled so way back when we were doing this we had um and and we're going to get back into the basics there's going to be another basics of c sharp season that we're going to get into here there it is there we go so this is building a container and la
unching it for us on binder is the name of the service that we're using here so uh the notebook was updated during the session so you won't find it unless on youtube all right launching the server and come on show it to me let me get my gunners on here it makes me feel comfortable looking at the screens for a long period of time uh let's go i want to see it there it is so way back in episode two there was a con a parameter-less constructor so we have students here and we have students that are c
reated so i'll just execute this code control enter will execute the code it's going to start up there we go so i have mary contrary and i have codex nfg codex is our other person here so and i want to change that out to a more generic name in this notebook um so let's talk about parameter list constructor starting and defaulting to is enabled i'm sorry is enrolled this is a student object that has a first name and last name and age and is enrolled now a boolean by default has a false value so i
f we don't set the is enrolled i'm going to get rid of codex here um [Music] if we don't set is enrolled here so i'll just comment that out and we run this is enrolled defaults to false see that because boolean is by default false so how do we default it to true with a parameter-less constructor you can set an initializer for a property like here to force it to default to true instead of the parameter list constructor defaulting it so now it defaults to true when we create a new instance of our
student it has this default value and i can set default values for other things right i can say well the default value for the age of our students is 10 years old by default the students that are brand new to our school are 10 years old um [Music] and there there it goes so i made a student class with parameter list and another constructor with parameters but if i put is enrolled true it returns false so if we start up up here and we say uh is enrolled equals true i can also initialize it up the
re and it it sets it to true um and i did something in the youtube video where it returns false well right the the default codex down here was initializing is enrolled right so if we if we force the value with by setting up a property here after we create then it will force it to that value so um [Music] now there is a the ability to overload for sure there's the ability to overload um so if we don't have is enrolled set here um [Music] and if we default and say up here is enrolled equals true w
e can also create a student here with first name last name and we can have it fail over and say also execute the other constructor and i can say first name equals let's make this a little bit clearer this dot first name equals first name this dot last name equals last name and it will take these values and assign it to the property and overload and set that so now uh oh shoot i can't just comment that stuff out um so that still gives me merry contrary and by default is enroll true up here so let
's get rid of that bring it down here so american jury is false but i can also ah shoot i jumped ahead i can also create um right so let's create f equals uh new student um jeff fritz and now if i say display f now is enrolled defaults to true because it it's coming through [Music] this configuration and setting it and which will trigger the other constructor up here which sets it to true so i said it to true why is it false now um [Music] i need to see a little bit more about the state of what
you're looking at so i can pull that apart can you take a screenshot and and share a link to your screenshot take a screenshot post it somewhere we can take a look at the context um screenshot you won't be able to copy an entire block of code into chat uh okay and we can pull that apart and make sure that that we understand where you're going um you have to go back to work but super interesting stuff you're a beginner with c sharp it's really nice to see working hard to teach c sharp to others l
ook forward to catching more streams thank you black mage i appreciate that um and we're gonna get into wwpf next week um one more week after that we'll do wpf on the 26th and we're gonna get back into i think we're gonna get back into c-sharp in august i think that's where we're gonna go um links are disabled in this channel i can i can turn them back on briefly here hyperlinks are turned on you can you can post hyperlinks so um is that uh ralvarador ralvarador asks uh so using this it's like t
he word instruction super in java um super lets you reach into the base object of things um so super in java right is that isn't that what that does um this is saying call the other constructor without parameters i'm right isn't super right uh java super keyword let me remember my my java yeah super refers to parent class methods and without parents yes refers to the constructor okay yes um so it is allowing me to refer to i can also refer to the base object if there's a base constructor i can r
efer to it like that but i'm referring to the parameter list constructor in this same um student class so you see down here in with joe bag of donuts um has this this overloading starting to happen where i'm starting to set some of these values um wow the telephone spammers are starting early today um surgdev asks does the parameter list constructor overload the parameter is enrolled true which was instanced true before um so let me come back up here does it overlook well no it doesn't overload
overload is is not using correctly here um the parameter list constructor when you go through there it isn't setting that value so it's going to output as false so mary contrary who's created without that runs through to false um so that's why that value is is coming out of this um [Music] if is enrolled is set up in here then any student that's created and you don't set is enrolled explicitly gets solved set to [Music] true so a couple different ways to to come through and do this and of course
right if we default it by setting it right here right we we initialize is enrolled to true doesn't i don't have to initialize or set it anywhere it's just always true without any interaction i specifically i have to explicitly go through and set that value to false um mr noted you're right having a default value eliminates unambiguous possibilities is the student auto enrolled or some action create the enrollment very good point in in my student management system here if you're creating a stude
nt by default the student is enrolled there's some at right i don't care about about folks that are just wandering around out there that aren't students in in my school once they enroll in my school once once they communicate and they start interacting with me then they become a student and a student by default is enrolled in order for a student to depart right a student graduates a student leaves school for whatever reason at that point that action of graduation or or leaving school abandoning
school would flip the is enrolled property to false i right i'd great you know hey there's there's joe bag of donuts out there walking the street i'm not going to create a student record for joe bag of donuts because they're not enrolled in my school they're not they're not a student so why would i create a student object so things to understand and manage and if you write this is if you don't need it don't build it so by default it makes sense that we're going to create students that are enroll
ed and right maybe it makes sense to have some sort of a method right maybe maybe this is protected and we have some sort of a method [Music] for them to graduate and when they graduate is enrolled equals false right so by default new students are enrolled and jeff fritz graduated and jeff fritz forgot to type a semicolon and jeff fritz is no longer enrolled different ways to manage data types and designing and deciding when and how to do those interactions benny has a question here not out of s
cope ama is turned on always happy to answer questions we're already stepping a little bit outside of the topic for today and that's okay i want to make sure i answer your questions um do i consider would i consider doing a stream around design patterns in c sharp strategy factory mediator um this is a little bit more advanced than what i like to cover in these sessions i really like to prefer to cover the basics of using the frameworks testing is very much an important pattern that folks use an
important technique that we use i have done sessions on continuous integration i have done session it deleted the link nope i've got it here i've got it arshia i've got it hey i know that guy i got the link you're good this was happening to me last night i was putting a link i was sharing a link on another stream and it would delete the link for me but other folks were able to see it that's messed up that's pretty weird right there um okay so i will show that in just a second but let me to fini
sh and and we'll take a look at finishing arshia's question here but to benny i i have covered some other um design patterns mvc we covered of course with asp.net mvc with some of those i've shown a little bit of repository pattern um i would i would look at bringing somebody else in to help discuss and go into design patterns there's many different ways that we can go with these uh many different directions we can go to with these let's let's um let me put a pin in that topic that might be some
thing that that would be interesting to come back to and and show a couple of the design patterns um as a little bit more of an advanced topic i do want to get into before we get back to the basics of c sharp i do want to get into an advanced session talking about attributes talking about uh analyzers i want to talk about building analyzers and code fixers those three topics that i think are very interesting for advanced c-sharp developers because now you get into writing code that writes code f
or you that checks your code and reports back information about your code so i think we'll take a look at that maybe maybe we do that for end of july so if we do wpf next week maybe for the 26th i'll do that kind of and i'm just scratching the surface on wpf uh maybe for the 26th we'll do [Music] we'll do analyzers and code fixers yeah let's do that um okay so here i have uh the image captured from youtube so here are shia is asking um ah okay so um oh my gosh you are too kind arshia thank you s
o much so the question here is why is it when we create a student here where we specify the age why didn't the enroll get set so let me let me reset here so oh if we go up here i'm gonna get rid of this and if we say and there's already the correct answer in in chat so if we say is enrolled equals true when we just create a student right so now when that runs let me get rid of this call now all of my students are enrolled by default because i have is enrolled equals true but what i had done ther
e in the sample was i had created a second constructor here where i could specify the age and i would say this dot age equals the age so now if when i create my new student here right um i'm going to create a new student who's 30 years old they're going back to they're going back to class um first name equals jeff um last name equals fritz and i'm using initializers there so now is enrolled equals false why did it why did it get set to false so what's happening because i'm using when i create th
e merry contrary student up here and i use this constructor it enters the student through this method because it has the same signature it doesn't have any arguments so this executes this method this constructor when i created the new student for jeff fritz i created it with a different constructor specifying age of 30 which means it's entering this way it's only executing this method so it never sets is enrolled to true and i kind of solve this problem by doing this cascading of my constructor
by in this second this third constructor by calling this parentheses here so if i do that it says execute this method then execute this method so i could come up here and say display is enrolled and it it ran and it ran in exactly the opposite order that i thought it did i this is even i confuse this the the order that this happens so i created a new student 30 called jeff fritz it goes into this method instead of it going through and calling the age and and executing this it first went and exec
uted that and came back and executed these okay so it walks into the other constructor executes all of those things first come on highlight it right fritz and executes these and you can see that because when it displayed is enrolled from inside my constructor it was set to true it it had finished the other constructor you get it fantastic so uh galdutis asks display is the same as console writeline in jupiter notebooks it is yes it serves the same purpose so and right there's all kinds of tricky
things you can do with constructors bouncing back and forth between different different signatures so you're not writing the same code every time and you can ensure the same properties the same configuration is applied to all of your classes as you work with them all right um galdudas has a question here um let me back up to that and i'm gonna go back over to the chat room over here asking do i have access to the beta of the github co-pilot i do um in fact all the members of the live coders hav
e access to it um as well as many microsoft employees um really neat what they're doing with it um definitely need some tuning the interactions with it are uh they can be a little overwhelming because when i'm when i'm writing code it all of a sudden wants to finish a whole bunch of other stuff that i'm i haven't necessarily thought through yet so now where my thought process would be here i'm typing i'm thinking things through all of a sudden there's this suggestion that i haven't thought throu
gh yet so there's something there that we need to [Music] i need to learn how to reconcile i i think there's a little bit of a collision with some of the other tooling inside of visual studio code where it gets a little bit tricky to continue using regular intellisense or intellicode because as you start typing code copilot comes in and just blows away anything else you're writing and says i know what you meant and lays out all this code that can be a little daunting that can be a little overwhe
lming so really neat tool it is in beta that we're going to see them iron out some of the issues with it i think it's going to be a very important tool and tools like it i think it's one of the first of this next generation there's other tools folks have written to analyze and suggest code um but i think we're going to see a very interesting path forward with the ability to to meta develop where we're not so much writing code as we're saying here's what i want it to do and some generator generat
es more of this for us so yes the solid principles and the o open for extension closed for modification yes so all right hey sam good day to you hope you're having a fantastic evening there in australia um all right i wanted to get into talking a little bit more about design patterns for unit testing and i wanted to pick up from the calculator sample that we had last time and talk about bringing the model view presenter pattern or even model view view model pattern they're they're very similar u
m into that code and and how that can set us up for unit testing because by default uh windows forms a little bit tricky to unit test how do we test that how do we actually go and click a button to do a thing so let's talk about that let's get into that let's i'm gonna head over to the other set uh it's it's right back there you can see my laptop over there and we can get into this and uh next week we'll talk we'll we'll talk about wpf in the week after that we'll get into that final advanced to
pic i think that that i wanted to cover yeah um analyzers and code fixers for c sharp because this is this is like linting for javascript out a whole nother level um so let's do it all right so i'm gonna grab my coffee i'm gonna grab my phone in case there's any messages that come and we're gonna switch microphones there we go i think that's better uh let me head over to the other scene and i'll be right well hang on grab the grab the chat move that up and you know what i'm realizing i don't hav
e my mouse over there do i do i have my mouse i think i put it i'm gonna put it on the floor when i was i was sorting i was sorting through uh things on the table and i forgot to move things around no matter we'll head over there and we'll get things started here we go right yeah i don't have my second mouse over here for the other machine there's github uh co-pilot is off to a pretty cool start it is ah there it is i knew i put it down here right where's my good good good i do have the mouse so
i i have my mouse run on uh wireless mouse so i can still get back to the chat room and interact with you over here so this is um of course our github repository this is the list of projects we have and we're right down to the end um i wanted to do a second unit testing stream i wanted to talk about attributes we did talk about null references features um async await in tasks maybe we can get into that next time as well at the end of the month um but we're going to do this unit testing a little
bit of unit testing here with windows forms and attributes we'll do way at the end of the month okay so github.com c sharp fret slash uh c sharp with c sharp frets and we'll go back and and we're gonna loop back over our sessions here that we did uh last year tuning improving we're even going to get into c-sharp 10 as we get into november we're going to bring dotnet maui into the discussion a little bit later this year and uh tune and improve and this is just going to be an ongoing cycle of lea
rning and and remembering that we're going to be doing as we continue through these sessions that coffee is hot oh my gosh that coffee is hot really really you're gonna you're gonna try and pull this um oh no that was someone else okay let's do this so last time we were we were building a calculator we built a very simple calculator um let me grab that source code and i'm i'm actually just going to dupe it here see look i even i put it in the wrong place can i let me go back to maine pull those
changes thank you um no uh huh thank you all right no you're not gonna show it to me are you fine be that way be that way um so i'm going to create a new folder here i'm going to call this 0502 winforms patterns and testing and i'll paste my app into there no thank you let's create a solution file uh you can't see it down here my apologies dot net new sln and i have a solution file now um.net sln i'm gonna add my app to it i'm gonna create a unit test project to go with this um before i do that
let me take a quick look at the project file here my project file is dot net 6. that's fine so let's create a unit test project that we're going to work with here dot net new x unit and i'm just going to call it test framework is going to be net 6.0 not 6 6.0 dash windows ah you that's fine since it's a windows windows forms project we need to create it with the windows uh the wind the dash windows uh sub sub framework so that it knows this is windows only so i really hate how far over this this
goes over here because right now it's like you're looking over here um so let's see here uh um i could run visual studio code right here let's do that let's do this development with visual studio code yeah why not why not let's break all the rules building with windows forms with visual studio code um because i can so there's my projects over there now my test project i need to make yes i know go short you go ahead and do that see it's net 60 by default here where my windows forms application i
s net 60-windows so i'm just going to make my test project the same version of that target framework so that it runs on windows and open this back up there it goes um so let's go into what do we have right yeah and um i'm going to net add reference to my app so now my test project has a reference to my application okay and my application write has this wonderful um let's do this and i'm gonna shrink that a little bit move this over and inside here let's go into my app and it's hiding over here i
'm just gonna dotnet run it and this is going to finish running there it is and there's my very simple calculator with the numbers in the wrong positions it doesn't look like a numeric keypad looks more like a phone that's okay you make your calculator how you want whatever um some ways to earn money as a programmer build an application build a library build a tool that folks want to buy charge money for it there you go build a website that folks want to visit put advertisements on it there you
go get a job working for a company that needs software developers that'll get you started as well so i've got this fritz's wonderful calculator that we built here some time ago and it it lets me do things here right i can add three and three and i get six yay right these types of things right multiply times six and gosh that that didn't work at all um 66 times six see if that that's not working i don't have a reliable clear button any of these types of things so let's write some tests let's refa
ctor this a little bit so that we can interact with our calculator we can verify that it behaves the way it should with some unit tests build a game there's another good way absolutely the game's just a it is just another piece of software that you can sell so um compiling c-sharp to webassembly check out blazer and how we do stuff over there with blazer alright um so i want to introduce the model view presenter pattern inside my project now i could do this by introducing another library and act
ually putting everything over there that's not a bad idea it's it's not entirely a bad idea so let me do this over here i'm to go up let's uh create a new class library and i'm going to call this my app dot um core right uh i forgot the dash oh my app.cor okay so now i have my my project that i'm gonna put all my business logic in all of the the guts of how my application works let me go into the test project and i will uh dotnet add reference to myapp.cor i'm gonna do the exact same thing in my
app add a reference to that there as well okay so now everything knows about myapp.cor and what i'm going to do is i'm going to define the pieces necessary to run a calculator inside here now there's there's different parts to this architecture right we think about model view presenter we have a model that's the data that we're interacting with the view that's the user interface that we interact with and the presenter that's what pulls those two pieces the data we're interacting with and the us
er interface pulls those together and defines the business logic of how the view updates the model and how the model gets painted onto the view so that's how we're going to work with these um yes c is a a garbage collected language just like java just like c plus plus c plus plus has garbage collection now as well so one class per file that's right so why do we need a class library that's a great question arshia and why do we need a class library the class library lets us refer to those classes
from other projects multiple other projects directly instead of having to reference and load up that one main project so let's take a look at this um i can actually let me go back into my app i can actually refer not my app uh into test let me remove the reference to that project okay i thought i just deleted that um that there we go all right so i'm going to create and i'm going to define how i interact with with this calculator object so i've got some sort of a model and just for the purposes
of making this easy to follow i'm going to call this model and it has uh some sort of a value a current value that we're working with so i'm going to call that a decimal current value and it's got those properties the ability to get and set it and you can't see it because it's hiding here behind me there we go get in set now that's fine i also have i have a buffer that i can interact with right because when you when you start punching numbers on your calculator right you you start typing five pl
us well it takes that five and it puts it into memory somewhere so that it can bring it back later and interact with it that buffer actually i i think belongs more with our presenter where the business logic is taking place so i also have a view right so i'm going to create an interface for that and i'm going to call it i calculator view now remember from our discussion on interfaces interfaces define a contract for how a class is going to interact with the rest of the application so i'm going t
o define a view here that knows how to how to present the value that's been being interacted with here so let's uh create a string and this is our screen display okay and so we have a get and set on that now i'm going to move this to another file there we go and i'm going to rename this file to model okay so i've got this ability to have a display i have the ability to show the values now i need to put together the various interactions that we can have with our view i can press buttons that that
do things so what happens when those when when those number buttons are pressed when those operator buttons are pressed how do we interact with them so that's something that we're going to start providing for um and let me just think for a second if i do this i don't want to do expose the button object specifically no uh i want to have this is a very simple view very simple model um when a when a button is pressed though i want to i want to trigger some sort of an interaction with my model that
comes from the view so and we need to update the display in the view so we need to put together a presenter and i will call this presenter now the presenter knows how to interact with all of our objects in fact we're going to create our presenter and pass into it our model no we're going to create it and pass into it our view it's going to know how to go get the the model itself sometimes you i set up the presenter so it receives a repository so it knows how to interact with a database in this
case i'm not talking about database i'm doing very simple so we'll interact with our model i'll write it locally here so i'll use my constructor that's the constructor snippet that ctor tab and it generates a constructor here for me so i'll tab over the parameters i want to receive are in i calculator view and you'll see why we're using this in just a second i'm going to store a copy of that okay let me be explicit and i'm going to create a read-only field called my calculator view called unders
core view for my calculator view so now i know what it is and where it is going to be placed now i'm going to start wiring this up to the form directly so you can see how this view comes into play and then how we're going to build our tests around this so we can test exactly how this form works so i'm going to take this and make it an i calculator view say that and generate the appropriate using statement and now it's saying i've got a red line here that says oh you haven't implemented the featu
res of the view it has a a screen display we don't know what that is so i'm going to implement that interface now of course this is a property with get and set here and typically throughout this this series i've been generating properties which is get set with an automatic value that we're storing in memory behind the scenes now it's time to have this get and set with something somewhere else let's introduce some other business logic that'll actually get in set the screen display with where the
screen is actually displayed so here we go instead of getting throwing a not implemented exception my screen is actually a text box right here and i can interact with the text property of it to set things on this display properly so if i want to get the value of what's on my screen display i can just return the text value and when i want to set the value right i can say calculator screen text equals the value that we're setting so now now we're starting to abstract and move things away from inte
racting here live inside my windows form i've just set up this little bit of indirection here we call it because i'm not going to work with this box i'm going to work with the screen display so that i can say screen display set this value get this value from the screen display and do something with it let's continue so i have this number button click method here that goes and does something with it what i'd like to do is pass this off somewhere else so that it knows what to do with those number
buttons and then we can go and test out what it is so really what we'd like to do is do something like um say number button pressed and pass into it the text that was on the button button dot uh and button is sender so right i gosh i'd really like to do something like that right so that i'm passing that somewhere else and i can then inspect and put this logic somewhere where i can test it and verify that in the right state it's doing things properly um 3d polywrath asking a little bit further do
wn here thinking through the the configuration a little bit here would you want to set it up with the value it set it up set up that value is only set if source is different from value i'm not quite sure what you mean let's let's continue here and i'll show you a little bit of and we'll talk through some of the other logic and then we'll be able to write some tests to validate that logic i don't know where this is going to run yet but it's going to run somewhere and here's my operators right for
the various operator buttons and i've got all this business logic for how to run all of these mathematical operations so this this is too much for a form to be doing there's too much thinking here for my form i don't when you're doing this much thinking right processing and deciding inside of a form first off it's in your user interface which doesn't make it too testable it's not something i can repeat and test it's getting confusing here and it's very much coupled to my user interface instead
of to other programmatic constructs that i can reach into and interact with so let's move this out as well i'd i'd like to move it somewhere where i can i can call uh operation uh operator button click and um right i i want to figure out what this operation is right operation is something here so i'm gonna do something like that i don't know what it is yet i do know what it is but we're gonna see how we move this and make this testable in just a second but these two methods are the methods that
we want to call inside of our presenter object so after i initialize component up here um i'm going to say presenter equals new presenter and i'm going to pass in this and let's create that as a read-only field up there okay now operation and buffer don't know what they are just yet um uh i don't oh i didn't set the operation anywhere else that's fine okay um i only wired up plus okay so what i want now so i have a presenter my presenter is going to know how to do these interactions and my prese
nter is a class over here that can be unit tested so i'm moving all of my logic out of my form so that my form is going to be just these two method calls that becomes easier to work with so let's change this so this calls i thought i just saw the cat no is the cat in here last thing i want is cat to be running around under foot um underscore presenter number button pressed so let's go and generate that method and i'm going to take this pull it out of here i don't need that anymore and i'll go to
this right so there's number button pressed and i'm receiving the text right the text of uh the number button value but it's a string i need to do something with that okay so what do i do um well instead of button.text right i could just push this onto the screen like this and calculator screen text is now actually underscore view dot screen display okay so now now i can test that when you press a number button what does it set the display value to in my calculator now i have a way to inspect t
hose and see when you press buttons number buttons what does it do to the display and there's my very simple logic for how it updates the display um we need a service manager then in larger applications you sure do you sure do in larger applications peter but uh for something this simple no no um or shia that's correct control dot makes suggestions available yes as you're as you're typing in in visual studio uh in other code editors visual studio code and others as you're typing here i can hit c
ontrol space uh carnac um i can type control space and why is it on that corner that's hang on karnak's in the wrong place you up there and now karnak's not running at all it crashed nice try that one more time i thought i had karnak working properly on this machine here no it's putting it in the wrong location and crashing when i try to save nope not gonna work for me um okay i'll put on screencast mode so control space we'll open this up control dot that's and get into [Music] really yes there
we go because that is way too much stuff there only keyboard shortcuts please so right when i control space it'll do the autocomplete for me but you can also have it give you suggestions in visual studio in visual studio code visual studio for mac um i think ryder and some of the other editors do this also where you can do control period and it will give you code actions to take so if i go back over here to form one right i've i have all these dimmed out using statements if i control dot it giv
es me a suggestion hey let's remove those unnecessary usings and it simplifies now not entirely necessary to remove those at compile time they'll get removed uh so it's not a performance hit to have extra using statements it just looks sloppy it's it's it looks it yeah it it looks like you you had a party and you didn't clean up from the night before you know what i'm saying so um yeah carnac shows keyboard shortcuts and for some reason it isn't quite loading properly um something like this to m
inimize property changed calls uh oh yeah you can do that absolutely it does make for an angry linter it's not it's not considered couth to go into somebody's open source project and clean up their using statements and not provide any other suggestions like your you're modifying a lot of lines of code without actually providing new functionality i had somebody do that to one of my open source projects it sent a pull request and it was they changed all the files all the c-sharp files in the proje
ct and all they did was go through and said format code and removed using statements and was like it was a lot of work for me to review that pull request and there was no value given other than they said format code like i appreciate what you're doing but i didn't really need that so like it's fine to clean up as you're delivering new functionality but uh our friend steve smith he's a microsoft mvp um you can find him on twitch he's our dallas a-r-d-a-l-i-f he's written a lot of the a lot of cod
e a lot of samples and documentation that you'll find on docsmicrosoft.com steve refers to the boy scout rule when you open and work with a line of code a code file leave it in better format in better shape than when you found it don't go and by that he means don't go and clean up everything inside of a project only when you go in and work on a file clean it up a little bit remove some some unnecessary comments some old to do methods in there that need to be removed that are no longer valid remo
ve excess using statements at that point only when you're going in and updating it so you've learned from your mistakes no it wasn't you there was it was somebody else that's right code contributor code contributor versus a code made we don't need a a made we don't need a housekeeper coming through to clean up our code that's something that we could actually have tools automatically do for us let's be careful in how we do that yeah or dallas a-r-d-a-l-i-s yep pluralsight courses he's got a numbe
r of really good ones out there so now my form is a calculator view so i know how to interact with it the buffer and the operation are going to end up getting moved out because i'm going to put my presenter over here to handle the operator button click interaction and i'm going to control dot and it's going to tell me hey let would you like me to generate that method for you don't mind if i do and now there's a method in my presenter class for operator button click so and it's going to pass in w
hat's the current operation more on that in a minute so let's grab this logic right that's a lot of logic there ooh and i'll go over to my presenter and i'm just going to move it right here there it is so i'll just replace these now calculator screen text we know that is our view screen display right view screen display same thing here because i'm hitting that level of indirection right this is just regular operation and this is view screen display all right now i still have this buffer hanging
out here i'm going to move the buffer from here into my presenter because i want all of those interactions to take place in the presenter so let's go over there and right that's that's a piece of business logic we need to remember all right now the operation i want to be passed in from the text of the button our operator buttons so i'm going to go back to my calculator view over here and where this was being passed in from this operation value up here i'm going to remove that and instead i'm goi
ng to pass in the current text just like i did up here for the button so that i know here's what you what i want to do which means i need to change the signature of this and i'm going to rename this i'm going to press f2 and i can rename it everywhere i'll rename it to operator and that goes through and renames all of my uh my code now it's testing against single quotes here because it was a character right [Music] um let's do this uh oh rats not alt uh no no oh wow that wasn't what i expected n
ope i was hoping to get the yeah oh there it is alt shift check this out hold down alt and hit shift and drag creates multiple cursors that you can start to type with um i'll replace this there we go okay so i've effectively migrated everything and we've passed in an operator here and we need to decide and actually store what the last operator was so we know what to do with it when we press equals or something else alt shift and arrows also works and that was actually copying things for me look
at this right alt shift down and it's copying it down i wasn't expecting that so okay i've now moved all of my logic for my calculator look right i have a a display that's being output i have my number button click that hands off to the presenter and i have my operator buttons that hand off to the presenter as well at this point this is where i and and where i describe in a model view view model or in a model view presenter architecture my view is dumb it doesn't know how to do anything it's han
ding everything off to some other object somewhere and says you figure this out i don't know what to do when a number button is clicked you go figure this out mr presenter number button was pressed i don't know what to do when button 13 is clicked hey mrs presenter ms presenter um here's the text of that button go figure it out and now we can go and interact and put our tests against our presenter class and make sure that it behaves the way that we want our calculator to behave because right now
it's not behaving properly we're clearly seeing an issue in here so let's write let's write a unit test to test our calculator doing just two plus two equals four right actually pressing the buttons to plus two equals and see what it puts on my screen display so let's take a look let's write that first unit test so i'm going to i don't i don't have to look at the form anymore the form doesn't do anything the form is dumb and we don't need it anymore i don't need a view anymore either so i'm gon
na go down into my test and i'm gonna start here with test one and let's write our our first test here and let's call this uh sum uh four four and uh no some two and two i'm not going to use in my the normal given when then architecture for this just because i want to get through and show some of these samples a little bit more um a little bit quicker than having to go through the whole thing so i need to have a view that is going to provide that screen display my view is just a it's just an int
erface now i could i could come down here and create a class stub view that implements i calculator view right and why don't you know what that is why don't you know what that is i thought i told you yeah it knows what that is right reload window come on you're not gonna give me that come on no still not gonna give me it wow wow that should fail yeah that's what i thought and visual studio code isn't giving me that all right fine i'll put the using statement in myself you're still not going to g
ive me this nope it should give me the ability to go and implement the interface fine we'll roll over to full visual studio visual studio code doesn't help me with this so loading the project let me add the other two existing projects so we can see them all okay so now they're all in my solution explorer so i was in unit test thank you see now oh no you can't see now it's got the red underline over here implement that interface so i could create a little stub view here that i could inspect and w
ork with you can do that there are frameworks that you can use out there that will allow you to fake that will allow you to create these types of things conjure them as you need so that you can just say well give me one of those things and it'll just be there for you because of how simple this is and in or in order to um avoid going into some of those concepts around stubs and fakes i'm not going to bring in a a fake a uh a dupe framework right now there's some great ones out there and i'm i'm t
rying to remember the one that i use all the time because i i just it's in the project and i don't create a new one anymore um um it is oh my gosh i i do this in the blazer web webforms components it is really fritz and it's good to have a large selection of uh code out there that you can go through and mocks a mock framework is what i'm thinking of and it's uh mock you mo yeah right this yeah moq is a framework that i typically use for this type of um unit testing stub generation and it will cr
eate this and make it available to you but for the purposes of what we're doing since i only have the one thing i'm not gonna get into how to build and work with this so i just have a little screen display here that we're working with so some two and two we're testing the presenter so i need i'm going to follow the uh 3a configuration for how we build our unit tests arrange act and assert so arrange act and assert those are the three parts of all of our unit tests so arrange um i'm going to crea
te a presenter and i'll call it i'll call it s-u-t the system under test is what you'll see us name these it's very english in orientation but most coding is english i guess so system under test in it's a new presenter and the view that i'm passing into it is a new stub view that i have down below so now i have my presenter let's act on it so now i can say system under test number button pressed so what number button am i pressing i'm pressing two and then i'm gonna press an operator button and
i'm gonna press well it's not just plus is it right if i look at my form it's plus slash equals right system under stress that's s-u-s that's sus uh there you go plus slash equals so i you know what i could say um right let's put it like that that's the button that i'm pressing and number button pressed is two again and i'm going to press that same plus equals button to end things and i want to assert i want to check assert equal and i'm going to inspect my view let's actually put this up here u
m oh let me use that let me show you that that same control dot refactoring works up here also so if i highlight stub view control dot introduce local so it introduces a local variable called view um good and i'm going to put a var there just to make it a little bit shorter to read so now i can say assert equal what am i expecting i'm expecting four because i just added two and two that's what i expect to be on the screen and the actual what am i actually inspecting here well i'm going to inspec
t view dot screen display and see what it says so i'll save that and i'll run.net i'll run.net test here at the command line just so you can see that it works but i'll bring up the live unit testing inside visual studio and you see my refactoring didn't quite work expected four but it got zero why did it get zero let's go back so operator button click when it when um and i can actually add more assert equals in here so i can test it along the way so if i go into here operator button click helps
a few there we go right so it inspects the operator if it's empty space the operator is plus otherwise switch buffer plus current value is string so what we need to do is we need to inspect well here's the button that was clicked and set this is the current operation somewhere and we had that previously but it moved so um i'll say current operation and that will be empty space so now i can say if current operation is the empty space then we're going to default current operation equals plus uh no
we shouldn't say plus current operation equals well let's let's parse what was passed into us and we can figure that out so let's say um let's start with operator if it contains plus then we'll make it plus otherwise we'll say operator zero with character because it'll be the x it'll be the slash it'll be the minus the subtraction and that's what we'll put into our current operation so now it knows the current operation current value we're going to parse the screen display and instead we're goi
ng to pivot on current operation say now i these were right the first time all right and after it's done operating we'll reset the current operation to black so i'll run the test again and it runs properly two plus two did report four on the screen i didn't actually press the buttons but i ran all the operations that the buttons do so i've moved around i know i'm using very large uh very large uh text here so that we can see everything and i know a lot of folks that are watching the stream uh or
the recording on youtube are are using their phones so having large text like this is going to make it a lot easier for folks to be able to see what's going on production wise and right hard code that hardcore development i'm not using fonts this size i'm doing this strictly for teaching so i mean really the font is as big as my head uh but you're right marvin uh only 14 lines of code at a time is not a lot all right um so now i know right i can come back over to here and i can run my applicati
on and i know that even though it's using this new pattern i can do two plus two and i get four i have that assurance now that it works but what about multiplication right let's right if we do write a unit test for multiplication make sure that that works right so i will um cheat and copy and let's make this multiply three and three right and i could be using theories for this i know um maybe we'll look at that in a second right so i'm pressing three times three plus equals and i expect it to sh
ow on the screen nine now let me do the unit use the unit testing tools that are here inside visual studio so if i go up to test i can say run all tests and it has this cool test runner here that'll run and show me the results of my tests right here there you go you see the little the little uh line going by status bar and that works i can even pin this down here at the bottom of my screen so that i can see my tests are running and i can even get the error messages out of here and verify that th
ings are working properly um good that's kind of what i expect these how i expect these things to work so what happens if i go and act put a third operation on the end of this right um right i did multiply three and three uh i did sum two and two so now let's add a third operation right uh add three numbers right so now let's do two plus equals three and four two plus three plus four should be nine let's make sure that works now i haven't even saved the file yet and look at this down here it kno
ws there's three tests not only that it's showing hey i haven't run this test yet i've recognized it but i haven't run this test yet so i can set up my configuration here to say run tests after build so after i'm done building my application build succeeded it's going to go and run all of my tests automatically and it comes up oh no my test my test failed and let me come over here so you can see it test failed let's scroll down and see what right message insert equal failure expected nine actual
ly got zero so right now we can do more testing now we can make the features of our calculator better by writing feature definitions right we can write our tests with methods like this and we can see our calculator is working or it isn't right and i can prove out that that is in fact how the calculator runs i'll i'm running dot net run over here so if i do right two plus three plus four two plus three plus four see it's right and and i can't i can't change that number do that one more time two p
lus three plus four and that last one it actually added on to the end of it it didn't let me continue with the next operation right so there's something there that isn't quite kosher isn't quite in the right state so if i go back maybe on operator button click plus equals maybe we shouldn't be clearing the current operation right if we leave that current operation the way it is right and we don't and we don't set the buffer to zero right if we let the buffer equal the current value then we can c
ontinue processing we can move on so maybe we move that and if we change buffer and we say um right did uh i should move this let's do this uh underscore buffer equals and i can get rid of all these two strings and i can change this and say right view screen display equals buffer history um zero so now does that how does that affect my unit tests right i just changed a whole bunch of logic well i can rerun the tests and we can find out i have to clear the buffer really in a calculator only when
you press that c button do you clear the buffer right i don't want to clear the buffer no my build failed uh what that's a neat trick oh it's still running over here stop that so it still has my one failure but now it got 59. hmm because it got five and we didn't what did we not do right two plus three plus four so current value decimal parts it's resetting it here of current operation so we're not there so view screen display this i can't believe i'm not i'm not getting this working properly um
it's not javascript um can i do some unit testing with blazer oh sure we can do that um so view screen display um is the current value you're right i want to clear i want to show the output of that and consequently when you press the next button i want to clear the value of it right because you're hang on think this through my goodness why am i messing this up why am i not getting this straight in my head i press two and it puts it on the display i press plus and it clears the display and it pu
ts it into the buffer so why am i why am i not thinking this story i'm i'm trying to juggle too many things here in my head um you key in the value press plus it and it's it stores what the current operator is puts that two in the buffer you press three it puts and it it has and you pressed plus plus equals well it knows what the current operation is so it's saying that equals so it goes and does the plus puts that value in the buffer so now it has five in the buffer so that it sets as the value
as the value on the display and i want to clear the operation at that point so then when you press five current operation is empty no when you press five it's gonna it's not gonna clear the screen it's like i want to clear the i want to change the button press so that if you just finished pressing equals if you just finished clear the screen so let's go back up here right it's adding on the value here so let's put a boolean um completed operation right so if it's zero or completed operation and
at this point we're done that and down here yeah completed operation equals true now let's see if that has it run my unit test see if we got that last one am i clearing the display value well that's just it i need to clear the display value after you press it ah darn it nope went back to zero this should be a simple problem that i can solve and i'm not getting it right yes i do work at microsoft how can i help yeah microsoft did open source the the code to the windows calculator you can go and
download that um after you complete the operation show with the value that's right so if we write all of my other tests where i'm doing just two values it works just fine and it clears out the operator at this point actually no i don't want to clear out the operator i want to save the operator i don't want that so that it continues it but then i'm never right without a clear button it's never going to go away but i don't have a clear button there we go so now adding my three numbers works so now
i need a clear button right i need a clear button so i can clear the buffer and reset the operation and start working again so let's create a clear button right here and that's going to do something else so now we're introducing capabilities writing unit tests because we're defining right i mean really what i should do here is create a test uh clear button reset uh and uh resets the screen um actually here's where i can do a given when then given uh two on screen when clear button pressed then
the screen shows zero so let's do that same type thing arrange act assert so i'll copy this in so now stub view presenter those are defined so i'm going to press two and now i need a clear button clear button pressed i don't have a clear button pressed method yet we're going to write one and it should return to show zero right so i need to create one of these my presenter now has clear button pressed if i run this test now you see it's already showing me four tests there if i run it right and he
re's the essence of test driven development i've defined the new feature as a test i've written a a failing test that tries to execute that given two on screen when clear button pressed and it raises an error not implemented exception i haven't written in yet so test driven development folks would say now i go through and i'm going to write that little bit of code that says view screen display equals zero that's not the only thing the clear button should do but that's the only thing that i have
a requirement for it to do so now when it runs my presenter functions properly four for four my unit test passed now i need to go back over to my form and actually make this a clear button so i'll change that so that where's the text oh right there i'll change it so it has c on it for clear and i'll go over to the events and it doesn't have an on click yet and i'll just say presenter clear button pressed once again my form is dumb i'm not it doesn't it isn't actually thinking i'm handing off ope
ration to the presenter so uh design how did i bring that uh yeah that sentence was horrible um cce we could do that later certainly dev i'm trying to make i'm doing these simple um here we can get more sophisticated certainly um how did i bring up the design if you double click on a windows form by default it'll bring up the designer that you can interact with if you right click on it you can say view code or view designer and it'll take me right into the c sharp code that goes with the windows
forms designer so um great so my screen display gets cleared when i press the clear button okay right and i i know that works i'll run my windows form over here and okay if i do the same thing press two and hit clear it resets it but we know there's more to a clear button than just resetting it right we also want to clear the buffer the bar it shouldn't remember my current operation in these things so how do i write a test that verifies that reset it back to nothing so really this is when i wou
ld start writing that that gherkin cucumber syntax that's a an open source framework that folks use for this uh type of behavior driven development that we're getting into where it's not just test driven but we're using this this um nomenclature this acceptable language around our features to define exactly how the requirements should behave given this scenario when i do this thing then i expect this result then you see all of the requirements defined in this given when then syntax so i i you wi
ll see me do a lot here not wrong wrong wrong i wanted a folder i'll create folders name something like given um something right given um value on screen i'll create a class inside that and this will be when clear button pressed right so i'll make this a public class now i'll go back over to unit test and where i had the really ugly name there and i did see the question dj squared all i i will where dj squirts question come to i'm gonna pin that and i'll get back to that in just a minute this is
it's not quite fluent um the fluent design is something different uh this is more a test naming scheme so i'll just do some control dot to get my using statements in here there we go so now when i run the tests the test report becomes a little bit more right instead of just add three numbers multiply three and three sum two and two now when you read the test ah let me rename that test method come here now it reads um let me there's one more configuration we can do here uh group by i want folder
in there namespace should be in there as well take project out yeah namespace class why didn't it show why isn't it showing the namespace oh given value on screen so given value on screen when clear button pressed then the screen shows zero so i can add other tests inside that same class that verify there's a value on the screen these are the other things that i'm inspecting and i can move some of this arrange and act elsewhere in the test right to make it reusable so i'm not going to get into
testing and building out clear any further because i do see that i am running low on time have i used fluor fluent assertions before yes i have they're a little um they're a little confusing at times um and i get what they're trying to do um but i i think it adds an extra layer of complexity on top of these that we don't really need um because it it does a lot with attributes if i remember fluent assertions correctly and um oh no no wait wait that's something else no fluent assertions is it has
a bunch of english-like methods that that do the tests instead of saying um right instead of saying assert equal i forget you could do is or is equal and it is the name of the method and it gets rid of the assert there altogether yeah you can do that yeah fluent validation i think is what i was thinking of so there's a lot that you can do with this we've we're just scratching the surface of this but what i hope you're seeing is we're inspecting the interactions with the view when we interact wit
h the presenter in the same ways that that the ah form on i want to view the code that the the form would now there's there's other tricks that folks play right with um with this type of model where these event handlers here in wpf you can actually wire these directly up to your presenter or your view model at that point you expose directly into the markup the viewmodel object and you declare call this method when this button clicked and it does that interaction we do something very similar with
unit testing in blazer as well and the unit test framework b unit that our friend eagle hanson built for blazer so you have a lot of options for how this works you'll also see some folks with web forms and win forms at times instead of having the event handlers here they'll actually define those event handlers inside the view so that you wire up your interactions to the of the so that your um presenter is listening to the event handlers and the event handler this code is actually in the present
er instead of here in the form and this form becomes empty you can do that it's a little bit tricky but can be done um what i worry about at that point is some of these concepts that are very windows forms based start rolling into your um start rolling into your presenter code right um how much time do i have four minutes we can do this we can do this um so if i go find are you kidding uh i calculator view right if i added here an event um of course the public event right zoom in a little bit th
ere right i could add a number button number button pressed right come on i need an event handler for this it doesn't matter i'm going with the default event handler give me that using statement so now if i go back over to the form implement that right so now the event is right there number button pressed so i would actually um hand off that to the presenter when that event happens why am i not thinking this through right because i want to say number button and go over there i'm not doing this r
ight there's a there's a way to do this and i'm not doing this right um no wait a sec hang on up in here i could say what are the number buttons back over here right so right like that's button three that is yeah button three so i could do something like uh button three dot on one click oh come on yeah there it is right and instead of calling button three click right come here you um i i can pass it right into presenter number button pressed right so um it's going to be a sender right and i can
say that and instead i can say button three dot text or i could even just hard code it right there and [Music] do i need a full parenthesis around this where am i missing one yeah there's a way to do this a little bit more functionally and i'm not getting it quite right yeah there it is plus equals like that so now instead of having these method handlers down here i just wire up the events right there and it knows how to do the interaction so your choice you got to declare it somewhere but by pl
acing it here like this some folks like that because it's a little bit more declared versus um letting it be over in the windows forms designer your choice how that interacts we are out of time friends oh my goodness i spent way too much time talking about that that was so much fun writing tests getting it running um so my proper architecture senses are unconsciously what surpassing my knowledge to put ui code in the presenter yeah yeah so but the idea is we've moved that ui code we've made it u
m as simple as possible so that it knows just how to interact with the user interface and our business logic is over in another class in another class library where it can be tested and reused in other services we can take that same class library now and move it into move it into a xamarin or a.net maui app so we have it in a mobile application in the future maybe move it into a service so it's now a web service your choice all kinds of great things that you can do with that and you now have tha
t flexibility you have that option available to you thank you so much everybody for tuning in i know it went a little bit long we lost everybody over on learn tv that's okay those of you that are watching on youtube hope you have a fantastic rest of your day happy coding to you and those of you that are here on twitch let's set up a raid let's go connect with somebody else who's streaming on the big twitch tv network and uh share some love check out some other folks that are out here streaming [
Music] and oh my gosh i see a friend that i know we want to raid right off the bat [Music] yeah let's do this let's set up the raid we're going to go see our friend and she's a member of the dot net foundation board let's go tune in to layla codes it thank you so much friends for joining me um i will be back tomorrow over on my stream we'll be working with blazer we'll be working on azure and building cool things on azure with blazer um hope you have a great rest of your day i think if i saw my
schedule right i think we might have a game show here later this afternoon we're gonna bring if i if i read it correctly we're gonna have the visual studio community team game hour and you're gonna get to see some of your favorite hosts from the visual studio channel playing games against each other so i hope you tune in i'll be here so that'll be a little bit later this afternoon in about two hours i think i'll be over on my channel tomorrow get ready to say hi to our friend laila codes it and
uh i will see you then take care [Music] you

Comments

@sergiokml3141

If the "Presenter" is instantiated in the constructor of the form. Where would you put the services that are already initialized with Dependency Injection?

@Tengil

Do you have a session when you build the calculator

@ragtop63

Very entertaining video! I personally like my views to be completely ignorant of the presenter.

@user-fv4ht5qy4m

Off topic 4 almost an hour