The Perfect C# Console Application...Or Not.

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
there are certain best practices every c-sharp application should follow right probably dry solid logging dependency injection separation concerns and unit testing at the very least these seem like obvious things that every application should have now in this video we're going to do something a bit unique I'm going to show you how to do all those things and I'm going to show you why you shouldn't always do those things we're going to build the ultimate hello world application you definitely won't want to miss it now if you don't know me my name is Tim Corey it's my goal to make learning c-sharp easier I do that by providing videos here on YouTube multiple times per week plus I have with a podcast I also provide courses on c-sharp web development and much more at I am Tim corey.com the profits from those sales are what pays the free content here on YouTube so everyone can have a great education C sharp not just those who can afford it now this video as of my most my videos I'm going to create some source code you can like a copy of that source code use the link in the description all right let's go to our Visual Studio here we have Visual Studio 2022 and we're going to create a new project we're going to create a console application and recall this ultimate hello world we'll call it ultimate Hello World app I'm going to hit next n.net6 now right out of the box Microsoft has given us some code if we were to run this let's run this we can see it says hello world and it closes the application but you know if you look at this it's not following any best practices I mean I'm talking a little tongue-in-cheek here but there is no logging there's well if there's an exception that happened what if you wanted to have a different message besides hello world what if you wanted to have it in a different language depending on the language the user what if and the list goes on so today what we're going to do is we're going to build the ultimate hello world application to see how to apply all of these best practices to this application now I want you to pause right here to say that there's a reason why I'm doing this now part of it is you get to see a little bit of everything you're going to see unit testing and um dry and even translations for wording and how to do interfaces and Depends the injection inside of console applications there's a lot of stuff we're gonna pack in here in a short amount of time but the other part here is I often get people that look at an application and say that application is not good because it doesn't do X it isn't dry or it doesn't follow all of solid or it doesn't have you know isn't break everything out into its own nougat package or and the list goes on of the things they've seen and this really comes down to a mindset that best practices aren't suggestions they are requirements you have to do all these things in order to make your application the best so the the misunderstanding is that the best means having best practices and all of them in your application and that's not true so we're going to do today is see how we can turn really what turns out to be one line of code into something a bit more all right so we're gonna get rid of one a lot of code because that's not good enough for us we're going to redo this into a proper application so the first thing to do is with any good application and again I'm talking tongue and cheek here but at the same time if your application is of a larger size these are actually all good things to do so at the end we're going to wrap up and talk about when you'd use each of these things at what size now it's not a specific at 300 lines you do this but there will be some discussion on when to use and when not to use certain things so don't um stick around to the end because it's important to kind of wrap this up at the end but for any application we need to have a class Library the class libraries can separate out your business logic and your data access from your user interface so a new project and this will be a class Library and we'll call this um uh hello world helper or hello world Library about that yes we'd say net six and we'll get rid of class one right away we don't need that we don't want that now from here we're going to do is I think we first need to Define our data so let's right click on hello world and say add and we're going to say new item and we're going to search for a new type item called Json it's just JavaScript object notation and we're going to call this file let's call it a custom text and where I get rid of the sample data inside of it and just have our curly race I'm sorry actually get really clear braces too start of the beginning where I start with square brackets for an array inside that we're going to have curly races and we'll say language equals en so we have English language this is the English language translations so this is a file that has the the various languages and their translations for each thing so we're going to have translation section and in here we'll say greeting and that will be hello world okay and that's all we'll have in there but now we can do is I can copy this whole thing and let's create a a Spanish version as well so es for Spanish and instead of hello world the translation of that would be Ola Mundo there we go uh actually let's capitalize m there we go so that's now our our translated version of hello world it's hola Mundo okay so now we have this translation file let's make sure it's included in the build so we right click and go up properties and we say we want this to copy if it's newer so every type build is going to copy this to the output if there's been changes made and of course the first time it will copy because there's no file there already so that takes care of for us our our translation file but now we need to have a model to put this into when we load it so let's right click on our our class Library we're going to say add we'll say models new folder and then in here we're going to add a class and let's call this class custom text to match our our Json file and that's just a you know naming preference don't have a name that way but we'll do our semicolon here to do file scope namespaces and make this public now as we go I'm doing a lot of stuff pretty fast and if you go whoa Tim I want to learn more about that I do have larger videos that cover I think every bit of these topics so if you want logging we have multiple videos on YouTube I have multiple videos on YouTube that cover that if you want uh reading right from Json files we do that in multiple different places if you want unit testing to have videos on that and on Dental list we go up to Pansy injection and so on so a lot of this has covered other places if you are a student that's taking the C sharp Master course then all of this is covered in that so in our custom texts us our model we want to have a string that is a language and we want to have a dictionary of type string string that is translations okay and that matches up language and translations match up to language and translations now notice this is lowercase whereas in my model or uppercase and that's because the fact that this is the C sharp standard whereas this is the Json standard so Json is camel Case by default whereas in C sharp for models we have Pascal case so we're gonna have to figure out how to translate from one of the other and I'll show you how to do that when we look those up so now we have our our text and we have the model to load it into let's create a a method that will actually do the the work of loading up that information so to do that we have to right click on our our project and we'll say add and let's put this into a folder because we're trying to be good citizens of everything we do and so we're going to organize these things and this will be the um let's call this the business logic foreign class messages and we're going to do the same file scope namespaces and again I cover this in other videos why this does this but save us four lines of uh or four spaces on every line make it public and here we're going to do is well we should probably do uh up I'm not prop um a Constructor ctor I blank there from it ctur for Constructor and we're bringing an ilog we're teaching log everything we do I logger and view control dot here then we can have um actually it's not going to find uh what I want and I want to do I logger of messages like so sometimes it finds a new package sometimes it doesn't there we go if you do I logger of type messages which is this class then it says oh you probably want to install the package microsoft.extensions DOT log into abstractions if I installed as version yep that's what we want to do so that now adds that nuget package which if you right click on here and go to uh manage nuget packages you'll see the same thing installed now is Microsoft extensions.logging.obstructures you could go on go on here browse for it found it installed it and then used it and added the using statement up here but that kind of shortened things up for us we're gonna say log control dot to create a signup field there we go so now we have the ability to log our our work now I think we need to do is we should probably create a generic and let's make it private but we say private uh string look up custom text and by key and by language all right so what it's going to do is we want to be generic we want to not repeat ourselves right keep this uh dry so we don't want to say hey look up this particular key we want to be generic and say what key do you want that's the one I'll look up and of course we only have right now one key and that's greeting and there's the the value or there's the value but we're going to do a lookup this way because that way we can expand later and so we'll say hey let's do a lookup well first we need to uh actually do a deserialize well in order to do that we need to say I want to have a a list of custom text which that's going to add a using statement at the top notice it adds the username up here for our models and it needs to be nullable and we're going to say message sets because it's going to bring back um a list of custom text because there'd be one for English and one for Spanish at this point I'm going to say equals Json serializer which add another using statement for system.text.json this Json serializer is a little different than newtonsoft.json this is the newer Json serializer deserializer so I say Json serializer Dot deserialize and it's asking hey do you want to do a let's unpin this a list of custom text well yes I do but not with the key so let's um go to the new line here and the key is not the key instead I want to and let's bring this per run down the next line and we'll say file dot read all lines from customtext.json all right so that's going to read all lines of the custom text.json but we need to go a bit for that and why does it yell at me now oh it's not read all lines Tweedle text so with that so real text just gets it puts everything into one string and so we're gonna take that and put it into our deserialized method but we have a problem because this is not going to match up properly because of the fact we have a casing difference in our names so remember we have Pascal case versus camel case so we create options so Json serializer options call options equals new and I'll put clear races on a new line we'll say property name case insensitive equals true and then that'll be it for semicolon the n and then after this file we can say comma options all right and so we're passing in these options we create up here to say it's a case insensitive property named match so now we should have our message sets loaded in this method now we've got to make sure that we protect ourselves in case there's any uh problems so let's do this let's wrap let's actually cut this out and we're going to wrap this in a try catch and we'll catch the exception so and we're going to put that code in there and then we should also log this so log dots um log dot log error and I'll say error looking up the custom text and we'll pass in the exception okay so that will log it we will throw it again though so we can say hey we logged it but we still want that to go up the chain to actually be handled saying hey we can't find this custom text or something went wrong and the uh the exception method or exception object will show you what went wrong so now you've got that wrapped now the next we can do is say custom text we're gonna grab just the custom text we need so messages equals uh message sets and make sure it's we say if it's not null then where and we'll say x Arrow x dot language equals the language you passed in notice that's right up here I believe nope it didn't add a link there for me um okay and now you've got that that's going to return a i innumerable but you don't want that you want the first one you're going to say well Tim if it doesn't find it it's going to throw an exception right yes it will inside of our try which we will log and then pass up the chain because if you pass in let's say French FR well guess what it's not going to find it in this where Clause therefore can't return the first one therefore from exception they couldn't find the first one which is what we want we don't want to say oh well it's null and then put a null accustomed no we don't want to do that because we could end up giving a message that's just blank and thinking that we succeeded when in fact we failed because it was a missing message there was no uh message set to read from so we want the exception to happen so we're kind of embracing that but then down here we're going to say if messages is null we want to throw new null reference exception and say the specified language was not found in the Json file now this should never be hit because the fact we do have that first up here but that just protects us again we're being very protective here the more we return messages dot translations now we have we got to this point we actually have a valid messages object and we're looking for the translation of this key so we're going to say translations of key and that should return the value of the translation which if we come over here to our custom text.json the translation of say greeting will be hello world if you passed in EN for the language if you'd pass an es the translation of greeting would be hola Mundo so that's our custom text lookup but now let's create a helper method a method that is actually public we're going to say public string greeting because we don't want to have these uh these magic strings all over we want to kind of hard code them somewhere and so we're going to hard coded into this method so you're going to pass in language and then we're going to do in here is say string output equals lookup custom text and the key is greeting and then we pass in the language that we passed through so all this really does is we're going to return outputs so all it really does is it creates a method for us called greeting which we say okay give me the greeting text now I could say well let's match the the method name up with the key and then we will do um the name of here I think that's probably Overkill um but Overkill sometimes over underrated um so if you want to do it you could um you could say name of uh greeting like so and that would pull this method in here but again I think it's probably Overkill I just wanted to say greedy and then that the only place we'll ever have this text so there we go and now we could get a little crazy we could create a one place to have all these things matched up and no this is good so now we have this greedy method and that's where all the things we think we're gonna do in this messages we're going to put this into passing injection now so we should probably have this be mockable so we're going to create an interface and the interface will have just one method greeting so we hit okay and now we have iMessages so with iMessages we can now throw us into our depends injection system and make sure that it properly uh Works through and gets the information including eye logger and we can again mock this if we need to for unit testing we haven't gotten to yet we'll get there in just a minute but first let's keep working on this let's actually put in our dependency injection system which means we have to go back to our console which is right here ultimate hello world go to dependencies and add some nuget packages and the first we're going to add is Microsoft dot extensions dot dependency injection s I'm sorry not the abstractions and for whatever reason I don't know if you noticed this but when it first loaded it loaded like this if this happens to you where you're looking for Microsoft extensions that depends the injection the first one up is not the exact match look at the the bar over here on the right for whatever reason mine is loading one tick below the top so scroll back to the top and there you go it's weird I don't know why it's happening I'm not sure if it's just for me or if it's for everybody but to look at make sure that progress bar or that uh slider to the top so Microsoft on extensions that depends the injection we're going to install that okay we have one more though and that's Microsoft extensions dot hosting now again watch you see how it's got that progress bar or that sorry that vertical slider is not at the top scroll backup one and there's Microsoft extensions.hosting the exact match so if it's happening to you just note that if you don't find the exact match in there make sure you scroll back to the top so let's hit install on hosting these two packages will help us with dependency injection and setting it up okay so now we have that done let's go back to program.cs now in program.cs we have a blank slate so we're going to first of all right click on dependencies and a project reference to the hello world Library and let's add a using statement hello world Library uh dot business logic and I don't know that we need to have one for models so we're going to leave that off for now and then we also need to have a a using for uh microsoft.extensions dot depends the injection and another one for microsoft.extensions DOT hosting the other nuget package we just added so now you can say using I host equals create host Builder args Dot build okay now create host Builder let's make sure I spill it right well this is silly I got ahead of myself I have to create the create host builder of course so static I host Builder create host Builder and we're going to do the curly braces for this and we'll say return host dot create default Builder pass me args so what we're doing here well this is if you've worked with let's say asp.net core products like Blazer or MVC or API you'll probably have seen this in the program.cs file where we have something similar where it creates a host Builder and sets some things up that's what we're doing here what the house Builder does the default host Builder if you Mouse over it um is it sets up things like eye configuration eye logging Factory and um so much more for setting up our our default stuff uh and in this case we're going to do is include in a dependency injection so we're going to say in a new line dot configure services and we'll say open in one parentheses open a second one and we're going to have a discard character for the action and then Pat say services okay and then we're gonna say Arrow and then in here we can say services dot add transient add Singleton and so on let's add a Singleton for our I messages and the implementation is messages like so and now we have dependency injection configured and so with that we can now when it builds we'll have depends the injections set up for application so with that the only thing you need to do is we're going to say using and notice I'm using these usings here what this does it says um when we close out of the application make sure to properly dispose of this uh this uh variable there you go that's the name so it dispose of this variable properly at the end it releases all the resources let's say using VAR scope equals host dot Services dot createscope it's going to create a scope for a depends injection which is basically the scope of the entire application but that determines for us uh lifetimes and things like that so with that we are now ready to say VAR services equals scope dot service provider and we can have a try catch here and we'll say catch EX and we'll just route to the console if it fails so that will allow us to not crash our application entirely it's just going to end the application running but it won't make the application have an unhandled exception that closed the application so but again it will close the end of this because there's no code after this clear brace this is a method it's a local method but it's a method so that is what's being called right up here so with that we can say Services dot get required service or ask for required search we don't have yet called app I'm going to create this and then we're up say run and pass in our arcs okay so what's this well this is a class we need to create because we need to have an entry point for our application since the console program.cs isn't the entry point it's going to call an entry point so let's create a new class we'll call it app and we'll do our semicolon here to use file scope namespaces and we're gonna make this public and for our app we're going to do is we're going to have um a run method before we do that let's bring in through a Constructor where I'll bring in iMessages and that is add the using statement at the top messages so it's asking depends injection to give me my iMessages interface and we're going to say that um actually let's create it this way just control Dot and create a set of the field so now we have our messages we can we can call and down here we can say let's create a method called public void run and we're going to pass in a string array called arcs now why am I passing in a string array here well if you notice we're actually passing this in from here which we got from here which we got from actually what's hidden behind this program.cs which is the we used to have a static void main that had args well it's still kind of there it's just hidden and args are the command line arguments that you pass in when you call this application so if you called it from the command line then you could pass in arguments to it and we're going to want to capture one of those so what we're going to do is we're going to say string Lang equals en so by default we're going to have an English language and let's the very bottom here say string message equals messages dot greeting and pass in our language and we'll say console right line message like so now this just takes in EN for now it's hard coded we want to do better than that so we're going to read from the arguments that are passed into our console application at runtime so we're going to have four and we're going to say uh args dot length like so so now we're going to Loop through every argument looking for if args I to lower starts with and it's a dash Lang equals okay so we're gonna that's gonna be our kind of our keyword there to look for and if that's the case then we're going to say Lang equals that's our our variable up here Lang equals arcs I substring I think it's uh I think it's six so one two three four five six so we say substring of six that should um that should make sure we skip over the dash line equals and get just a value after the equals and that will be our language and we can just say break because you have to keep looking through our args if you find the ARG that matches so and what happens here is if you were to call this like say this will be um ultimate hello world dot exe we could say Dash Lang equals uh yes like so and then it's gonna that's gonna be the parameter I think it's passing any spaces means another parameter so you could say test and now you have two arguments this one and this one and if you were to get sloppy and say something like this it this would not be one argument it'd be three this this would be one this would be one and this would be one so you can't have spaces there which also means you couldn't say something like um Spanish language that would work we want to have it short and sweet anyways so yes so that's how we'd call our are executable if with the parameter to change this to Spanish so with that we now have our run method and if you come back over here program.cs app is still uh red squiggly so we control dot here to add the using because this program.cs does not know about the ultimate hello world namespace because nothing uses it until app does so therefore we have to add the using for even the root namespace now with this I think we've got something that should work let's run this and it says no service for type ultimate hello world.f ah we have not registered our service for it Services dot add Singleton but it's going to be for app let's run it again there you go we have successfully created a hello world application but we're not done yet because how do you know it really works the way you want it to work we create some unit tests for it now I could have done it in the tdd manner and create um the unit test first and make sure it failed and then make sure they pass after I wrote some code but we're going to just create them now so right click on solution and where I say add new project and we're going to create a let's search for X units wait for it wait for it there we go X unit and hit next I like X unit personally uh n unit just as great Ms test not always is great but is close so we'll call this um hello world tests and net six create and for this let's go ahead and just delete unit tests one and I right click and say add class and actually we should probably match the the folder structure so let's right click and say add new folder uh business logic and then right click and say add class and we'll call this messages tests and we'll do our semicolon here and make this public and we're going to have well first we have to add a reference and dependencies add a product reference to our hello world Library oh we already have that great that's awesome oh it has the wrong spot right click here under Patsy under hello world tests and reference our library there we go that's much better so now that we have this we can create our first fact and we'll do facts we could do um we could do theories here but I think facts will work just fine so we're going to do public void greeting underscore in English and we're going to say we create an i logger to impersonate the logger and the way I do that is we actually create no logger we could do a mock or we could do something else but a no longer works fine that's actually built into what Microsoft provides us with the abstractions um nuget package so I logger of type messages and we want to have the add the using statement for that so that's right up here now we're going to say logger equals new null logger notice it's microsoft.extensions Dot login.abstractions and we're going to say messages so it's add this using statement here and if we look I believe it added a nuget package as well oh no it's already built in sorry um it's built in maybe um a transitive but it is built in um to have abstractions in our unit test project so with this we've now created this new logger which if you notice that matches up with what we're looking for an eye logger of type messages but it's a a no longer which means it just basically eats the looks that's what does and that's good enough for us for this demo we are cut a couple cores here we could go again further in depth make sure our logs are working properly and so on but we're gonna for the sake of time cut that corner so now we can say messages call it messages equals new and pass in the logger now normally we instantiate messages through dependency injection but instead we're instantiated manually and passing in the uh the thing it needs however just note that If This Were a real application there's another Corner we're kind of cutting a little bit is this might have inside of it dependencies that also need to be instantiated from depends injection and down the list it might go if that were the case we would either need to manually instantiate every one of those and up here or we can create our own dependency injection system inside of our test Suite that has that injects the the mocked versions of all those things into our our class here but we don't need to do that since we're only passing in logger and logger doesn't have any further down depancies so now we have our messages class we can say string expected equals hello world and then string actual equals messages dot greeting in the English language okay so you might say well Tim we're hard codings and things here we're hard coding hello world we're hardcoding the English language yes that's what unit testing is all about it's hard-coding those things and so you have an expected input so therefore we hopefully get an expected output and if that's the case a search dot equal expected and actual if that's the case where what we expect is what we get then the unit test passes and if it's not then it failed we have to look into why is our expectation not being met if we pass in a known set of inputs we should get a known output and if we don't something weird is going on okay let's copy this fact that's why I say it could have done a theory because there's actually another one we can say which is Spanish and if we pass in es we should get Ola Mundo and make sure that's correct and then one more that I'm going to paste it in but really it's going to change invalid so we're going to pass in something invalid and let's even get rid of our expected and our assert and even the assignment here and we're going to say us actually let's put on a line above here a search throws invalid operation exception that's the exception we're expecting and then two parens and then our Arrow and then I'll pass in this right here and let's um let's put this on a new line like so okay so we're saying assert this is going to throw this exception so if we call this not with en but with let's say FR we don't have French if we call it French it should throw an invalid operation exception because we don't have French and that assertion is going to say did it throw an exception and if it did then we're good we had an expected output or an outcome based upon a given input so we gave it bad data we should expect back an exception of this type so let's now go to our test Explorer and run all three tests if you don't have task Explorer open you can go under the tests menu and go to test Explorer and we get three passing tests we have success in all three tests the English return what I was supposed to let's go over here and we can also crunch this down a little bit so that was successful the Spanish was successful and so was the invalid all right so we now have unit testing on our class so at this point we've got a pretty good system we've got it's dry it does not repeat itself so when you want to want to add a new message the custom lookup will handle it and we can create a new method to handle that new message if you want or you could turn this into public and then we could call it from anywhere really and just pass the key in that might be useful as well and we should probably put some tests against that if we do we also have dependency injection set up and properly with rapid try catch so that even if we do something weird it will work it will not crash the application but it will not continue running with bad data and we're asking for this app in this depends the injection which actually properly asks for the iMessages from Japan's injection and that gets pulled in we check the command line r if you haven't shown that yet but we can run our application from the command line and pass in a different language and it will properly get that new language and give us the value back so all of this should work properly and we can prove that by running it and yes it does in fact let's go to our ultimate hello world right click on it and say let's go to Open folder and file explorer wait for that to load somewhere oh there it is and go to our bin directory debug net six and then we have in here our hello world let's um right click and say open Terminal all right that's a long terminal but or a long line but we can say ultimate hello world.exe Dash Lang equals ES and it says the ultimate hello we're all we're in Powershell that's why uh let's do this let's clear the screen first and I believe it is dot slash all right the short switch Lang equals es is not defined in the switch mappings at the command line configuration I believe this is actually because the dash let's go ahead and fix that real quick we can close this out we'll leave the terminal open um let's change this to just take a dash off and that means five characters and let's rebuild the project rebuilt and now let's clear screen and run it again and we get that same error which is interesting because we don't have that Dash Lang equals ES oh yes we do we just called it how about that hola Munda okay so now if we run this and pass in the language of es we get hola Mundo and if we were to run again and pass in the language of En for English we get hello world so this now works even the command line passing in the different languages so we now have what really can be the ultimate hello world application that is flexible It's ability to it can grow over time if we had different language we could just punch that into our um into our Json file and would just work now our unit test test for friends we probably shouldn't do that but um which probably tests for something worse like test um let's do that that's invalid data okay um so now we can come back over here and run our test again just make sure they run again they do um so with that we could put French in here and we could come back to our terminal and run again and get the the French version really quickly so let's validate this so we're going to put a let's copy this whole section I'll paste it we're going to put FR for Fringe and I'm going to copy I'm not gonna begin to butcher that with my pronunciation but there's the what Google says the the French translation for hello world is so now let's build this again let's rebuild it we can actually just build but let's bring back our terminal and I actually closed the terminal down but if you reopen it it does have your history on here so English make sure it runs hello world and Spanish hola Munda and now fr and the the French translation so now we have this flexible hello world application that can even say Hello World in other languages so we can grow and change over time and this this thing will just work and you know what in some ways that's admirable it's admirable we have such a powerful flexible application but do you notice all the complexity we have here so we have let's look at this we have three different projects we have the hello world Library hello world tests and ultimate hello world so three different projects in there we have in the main application we have two classes in the hello world test we have two classes in the library we have one two three four files uh two classes an interface and our Json file so we get a lot of files and then inside there is a lot of logic so you have all of this you know 54 lines of code here and we have another 29 lines of code here another 31 lines of code here we have well we want Count testing but 44 lines of testing um and you know we have a model there's a lot of stuff going on here and the end result after all is said and done is it prints out hello world so I want to ask you is all of this better than the first application we had the first application we had had one line of code and I said console right line hello world is this better than what we had and the answer is it depends it depends on your ultimate goal if your ultimate goal is just to have a Hello World application then absolutely not this is awful compared what you had because even though this is so powerful it's so set for the future it's all this stuff this is a maintenance nightmare because you've got a lot of code that the end result is it prints out one line of text it would be much better to have the console right line hello world and be done and this is why if you create a a function project so if we come here on a solution and say a new project and search for Azure functions all right and let's just create a function app demo function and in here it's going to ask us what kind HTTP triggers fine basically it's a tiny little API um use Azurite to run storage count sure not docker authorization is function level sure okay we hit create if you notice that the Azure function has in it just this one Function One Dot CS which of course you should rename to something else but it has it one file and in here we have a total of including the curly braces in all spaces 35 lines of code that's the entire Azure function and if we were to really you know kind of trim us down a little bit if you make it a little bit smaller but that's it that's our entire code base for this Azure function now tell me do we need to make this more complex by adding dependency injection um by which by the way we could add quite easily but do we need to probably not do we need to make sure we have you know a lot of extra stuff around this make it dry make sure we have you know class libraries against it and all the probably not because we really have about 20 lines of code that by the way already has logging just so you know um so we're already pretty good um but that's all we needed to worry about with our application so we probably should try and keep this as simple as possible and if we can have just this one file because even though we may have a little bit of repetition even though it could abstract something away it's probably not ideal to do so okay so maybe we could say hey you know what we've got this this query that's got a magic string you know I realize they say the word magic Story the phrase Magic string yeah we do it says name you know what we're gonna have to have that string somewhere so here is probably the best place for because it's right next to the code that uses it if we abstract this away into a dictionary file with static resources and and bring that in with you know some kind of a new or something that just makes it more complicated so I want you to start thinking when you're looking at Best Practices we're looking at design patterns when you're looking at even something as simple as dry do I really need to do that do I really need to be more dry do I really need to have that additional stuff because if you're not careful you end up creating hello world applications like this now yes this is a an overly dramatic example of what it can be because really it's a lot more subtle than that it's it's something that you say well of course we need to have be very careful whenever you say that because there are very few things that you absolutely have to have sometimes you can get away with not having them and it may be better it may be better not to have because it reduces your complexity and reduce complexity is an evaluable thing to have so the things I've shown today are very very good things they're things that I would encourage you to consider on all of your projects but do not ever get into the place where you say I have to do X in every project don't do that don't get so locked in that you actually hurt your own projects in the name of doing what's right being a developer is about being able to be pragmatic what is best for this particular situation this came up when I built my website I'm not sure if you saw that yet the new I am Tim corey.com has been built we built that with HTML CSS and a little bit of custom JavaScript vanilla JavaScript I didn't use angular I didn't use react I didn't use view I didn't use C sharp I didn't use Blazer and people were aghast astounded and amazed that I hated C sharp so much that I wouldn't use it and that's not the case but what it is is I was trying to be pragmatic we're going to have more content coming very soon about my decision making process with that about how I worked through the idea of what is the best uh tool set for this problem so we'll get there but I want to kind of take this opportunity here we have seen this a lot with developers I get locked into I have to have X there like I said there's nothing bad in this entire demo these are all great things and these are all great practices to follow but be careful you don't shoot yourself in the foot trying to do what's best because sometimes what's best is to have one method with a few lines of code and that's it for the entire application or sometimes it's best to have console rightline hello world and that's it okay so I hope you found this valuable like I said there's this was kind of a weird one because there's I'm gonna show you a lot of great stuff and how to you know start into those things I like to Pansy injection and unit testing and logging and all the rest but I kind of touched just the tops of them we have videos going into them and more depth but on the other hand I want to make sure that when I show you these things that you don't say okay I have to add these in every project okay so be careful that be careful that you um know the balance look at the pros and cons and make sure that you don't get locked into I have to do X in order a best because again so that's the best is one line of code all right thanks for watching it thanks for coming along this ride hopefully you've got a lot of valuable tips and and tricks and ways of doing things out of this video leave comments down below it helps the video and helps spread the word but also let me know if you you know what your thoughts were on this is is there more things I missed I'm sure there definitely are I could have wrapped these things in new packages and so on but one of the things that you would throw in there to make the ultimate hello world application what extra things would you add um if you want this code I will bundle it up and make sure that's available use a link in the description it will send you an email with the code okay thanks for watching and as always I am Tim Corey [Music] [Applause] thank you [Music]
Info
Channel: IAmTimCorey
Views: 46,855
Rating: undefined out of 5
Keywords: .net, C#, Visual Studio, code, programming, tutorial, training, how to, tim corey, C# course, C# training, C# tutorial, .net core, vs2022, .net 6, tdd, localization, unit testing, dependency injection, console
Id: dZSLm4tOI8o
Channel Id: undefined
Length: 59min 20sec (3560 seconds)
Published: Mon Oct 03 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.