Become a Patreon and get source code access: https://www.patreon.com/nickchapsas Check out my courses: …
31 Comments
Leave a Reply
You must be logged in to post a comment.
Become a Patreon and get source code access: https://www.patreon.com/nickchapsas Check out my courses: …
You must be logged in to post a comment.
What kind of IDE Software that you use in this Video?
I try to use prefixes like: Get.. Set.. Update.. Is.. Perform.. Do..
orsuffix: ToSomething.. FromSomething.. As… – but it doesn´t always match.Hi Nick!
At the end of the video there is a method 'public async Task<User> GetUserAsync()' which returns the result of awaiting of '_userService.GetByIdAsync(Guid.NewGuild()'.
This is very common scenario. But will it be better or worse or the same if the method will be like: 'public Task<User> GetUserAsync() { return _userService.GetByIdAsync(Guid.NewGuild()); }'?
I find it astonishing that most C# developers would shudder at the idea of using Hungarian notation to denote the type of a variable, but the moment they want to denote its scope, they tag member variables with an underscore; this is equally as bad! The mistake you made was at the moment you said "…if the method is quite big…" – Methods should NEVER be big; "The first rule of functions is that they should be small. The second rule of functions is that they should be smaller than that." – Uncle Bob Martin (Mr "Clean Code"). A variable's name is no more responsible for denoting its scope (underscores) than it is responsible for denoting its type (Hungarian notation). As someone who also codes in Java and Kotlin, I can only assume that you don't follow the same underscore convention in those languages, simply because it's not the accepted convention, whereas it is in C#…but it's still wrong.
Enum names should be singular when their intent is to be used as a singular value (i.e. ConsoleColor), but should be pluralised when their intent is to be used as multiple values (i.e. BindingFlags)
I awalys name my methods and properties with lowerCamel to distinguish them from Unity's methods + distinguish them from ClassUpperCamel. No more of this insanity:
public Engine Engine;
Engine.Engine.Engine();
So far "each line in separate file".
Think it's "member", not "my" btw.
m_ stands for member (as in "class member") from the days of Hungarian notation and intensive C++.
I've never understood why "everybody" puts attributes on the top of the class. The future user of the class won't care about the internals, actually nobody should except the author, and then maybe at the beginning of its building. Actually the future user of the class will be firstly interested on the constructor. I don't know, maybe I'am missing something big, but I don't get it. I think it is something that started with the Java coding style, and C# adpoted. However, there are various coding style guides predating C# that differ, such as: https://users.ece.cmu.edu/~eno/coding/CppCodingStandard.html
Can you enlarge your environment font?
How about solution setup … what projects do you make? I seem to work with people who create tons of projects and I'm not sure why (I don't think they know either)
Regarding the Async suffix. If the methods in a class are mainly async i don't use the Async suffix but put the Sync suffix on those methods that are not asynchronous.
You missed out the most important one – tabs vs spaces!
Was hoping for your logic behind using Allman instead of K&R/OTBS.
I always prefer using this. instead of _ for the reason that they are easier to spot and select.
Another reason is that _ feels like an old custom and the code looks more messy.
I took time to decide which one to stick to, and I went for this.
If you arent used to using var in c# think of it this way: you dont want to be declaring the type of an object in two places if possible, because if you go back and want to change to another type/interface, you dont need to rename mulitple places. Also it is less code 🙂
How you decide for your project structure between "clean architecture" and the one, that in this video?
a video about formatting, for example long linq statements would be awesome
I also always use
var persons = new List<Person>();
instead of
List<Person> persons = new List<Person>();
But since C#9 I've switched to
List<Person> persons = new();
Nice and short, just like var, but still the type is clear.
Everybody wins.
Didn't know an "implicit operator" was a thing. But then again, I didn't know lots of things were a thing until I watched your videos.
Regarding the var type. The official C# conventions from Microsoft state that if you can't tell what the type is from the right side of the assignment, then you should use the explicit type.
That Task that returned "GetUserIdAsync" didn't use the "async" keyword and wasn't await'd? Was it actually an async method solely because it was "Task"?
When I am naming things, (serializing JSON into a model in c#) resharper hates the naming because it isn't Pascal. The name is usually lowercase because it is coming from a JavaScript style object. My model classes always have to use the ignore naming comments for resharper.
I agree with just about everything you said here (and we use them with our project at work) except for "var". I personally hate the use of var for just about anything except when returning anonymous objects from a LINQ query. We spend so much time with standards for variable and method names so developers can easily tell what something is, but for some reason when it comes to declaring variables we are ok with making it generic and having to do something to see what it is. But…. that's just me. And other members on my team do not agree, so we don't have any standard around it's use. But as always, great video!
I tend to agree with using var where possible. I program more Rust than C# at my job, but the same trade-offs seem to apply to both. FYI, Rust variable declarations go like this:
let userId: Guid = …; // explicit
let userId = …; // implicit
In Rust and C# 9.0 there are also target-typed value expressions, for example:
List<uint> nrs = new(); // C#
let nrs: Vec<u32> = empty().collect(); // Rust
(This is not the normal way to create an empty Vec<u32>, just an example of target-typing (because new is not a keyword in Rust). "vec!()" or "Vec::new()" are the normal ways. But collecting the empty iterator works for many types, "let map: HashMap<u32, u32> = empty().collect();" is another example.)
The question that I struggle with is this:
If I have to choose between a target-typed place-expression or a target-typed value-expression, what should I do, any why?
I have not been consistent with this, and cannot decide on a preference either. Often I suspect that the ambiguity will go away when I refactor later that day, but it would be nice to have a guideline to follow.
(I think that C# might use the name "L-Value" for place-expressions and "R-Value" for value-expressions, like C and C++ do. I'm not sure what terms C#-programmers are more familiar with.)
The C# example of my question would be this:
var foobar = new(); // ambiguous
var foobar = new T(); // option one
T foobar = new(); // option two
Great material as always. Even though I already follow and mentor most of the practices you use, I still watch your videos to learn something new or challenge my thinking.
One change I would suggest is to the service layer. I'm always uncomfortable seeing the service layer in the same project as other layers. I much prefer a separate project for each service. It finally clicked for me why that is…
When you combine services into a single project, or combine in a project that is not a service layer, you run the risk of code leakage. A developer will eventually create a class that supports multiple services which starts to bind the services together in what initially is innocuous but slowly evolves into something more difficult to disentangle. Separate projects allows the framework to guarantee the absolute separatation of concern that ultimately leads to cleaner more supportable code.
Projects can be viewed as nothing more than folders which enforce isolation. Anytime our architecture dictate a separate area of concern, that area should be a separate project with clear interfaces and boundaries.
what do we use for non private fields?
m_ means member_, so basically exactly what you mean, but now that stuff can start with _ instead of needing to start with a letter it's shortened to that.
Any chance you could use a larger font? It’s difficult to view on an iPad for us old timers. Ta
Models should be Model as each thing inside it is a Model. A Little like database tables. While logically that should apply to Services, Controllers etc, I generally pluralize them. In writing this I just realized I don't know why.
I always thought the m in m_className or mClassName stood for 'member' no 'my' 🙂