My students get annoyed at how much time I spend talking about Naming Variables in the intro classes that I teach; but I think it is important to train them from the very beginning so that they don't have to /unlearn/ all these bad habits later.
@harbor.boundary.flight9 ай бұрын
I'm not sure that this is something that actually registers with students to be honest. IMO this is something you learn when working on large projects with other people in a complex domain.
@fifty-plus9 ай бұрын
I would opt to teach people how to think and be good mental analysts of a problem. Building on that will naturally having them questioning their decisions as they develop maturity in their craft. If they're getting annoyed enough that you've noticed, it probably isn't a suitable approach.
@CryptoWulfApp9 ай бұрын
Readability is one of the most important things. Let them create an app and then pause the development for 6 months on it or let them work on code from others. They will understand lol.
@NihongoWakannai9 ай бұрын
@@fifty-plus A teacher in their limited time in a class can't magically turn someone into a good critical thinker, that's too idealistic.
@st9639s59 ай бұрын
I remember my intro to programming class where we had a problem set involving a bagel store. In the program we had to have a variable for the number of bagels. I named it "numberOfBagels". In the same problem set we were supposed to comment our code. I lost points for not commenting my "numberOfBagels" variable. I argued that the name made it clear and adding a comment "// holds the current count of bagels" would have been redundant. In a case of malicious compliance through the remainder of the semester I always added a variable into my code called "numberOfBagels" with a comment explaining what it was doing. Sometimes it was an index variable in a for loop. Sometimes it would be char array. It never represented the number of bagels 😅. To this day I usually include a numberOfBagels variable in my code somewhere, with a comment of course 🤣
@dmisterb9 ай бұрын
I would use Add instead of Create in this case. Because you pass the object that should be added. The Create would fit more if you passed in some arguments and the method would create an object based on the arguments.
@cattman19709 ай бұрын
I too would have used add.
@nmosafi9 ай бұрын
Agreed. Or maybe Insert
@qj0n9 ай бұрын
yes! Create is a method I'd expect to find in a factory, not a repository
@davidmartensson2739 ай бұрын
I would say it depends, for a plain just add the data sure, but if the method does anything more than just storing it as is, like creating multiple rows or signaling the creation or anything, Create is better in my opinion. Both works, but add in my world of though is simpler than create ;)
@qj0n9 ай бұрын
@@davidmartensson273 My issue with Create in this case is that you already have an instance of Customer class before. You don't create anything, no matter how many rows you add - you only persist existing model. We could call it Create, if you pass some CreateCustomerRequest - then this method does create a new customer based on some data. But then, it's not a repository
@persehlin43799 ай бұрын
When I'm upgrading programs that I written several years ago, I realize that naming is one of the keys to make maintainable code. My names are long, but as I see it, they are a part of the documentation. Even if everything seemed to be self explaining at the time you were writing a program, it will not be so clear a couple of years later. Or for others... I agree with everything you say in your video. And... I always use the Async suffix. Just for me to know in the future, or for anyone else that will read my code.
@F1nalspace9 ай бұрын
My oppinion -> Long names are good, especially when the context is not clear without looking at the code. And i fully agree, if something is called "Customers" i expect a sort of collection - not something that "saves" stuff. But i dont like the name "Repository", i would rather call it "_customersStorage" as private readonly, injected in the ctor. Good descriptive names also can make documentation obsolete, because with a good name you dont have to guess what this method/class does.
@billy65bob9 ай бұрын
1:36 without further context, I'd assume some sort of static wrapper around a Data Store (maybe even with a cache) that manages all Customer data. Primarily because it has a 'SaveCustomer' function. It's not my preference, but I find it rather minor as far as weird conventions go - these paper cuts do add up though.
@EricKing9 ай бұрын
"Spoiler, this is actually a Customer repository, which no one should have guessed." LOL I thought it was obvious from the usage and the context. It should have been everyone's _first_ guess. I agree that the naming convention is a bit unconventional, but I think this is being a bit too picky. Also, one of the original definitions of "repository", from Martin Fowler in his book on enterprise architecture patterns, is "A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection." While it's more common to name the repository with "repository" in the name, I don't think it's unreasonable to name it like a collection. The most important thing to me is consistency throughout the codebase.
@thomasjespersen9 ай бұрын
In Domain Driven Design (which made the Repository pattern popular), the Repository pattern abstracts the database as a collection. Also, it's recommended to wrap your repository actions in a UnitOfWork, and only save when you have verified all the domain logic. Often, you need to change more than one aggregate in a transaction, so the repository should not commit changes. So, if you are using a UnitOfWork, I would recommend using repository.Add() and repository.Remove(), and not repository.Create(), repository.Save(), repository.Delete(). And since they don't talk with the database, I would likely not make them Async.
@JasonStorey9 ай бұрын
Glad I wasn't the only one thinking that. This is literally the original definition and use of the pattern. It's was meant to simplify crud operations by simulating an in memory collection and letting things like UoW manage the persistence and transactions against a repository collection.
@AndyMehalick9 ай бұрын
None of this is true
@yupii19979 ай бұрын
@@AndyMehalick elaborate
@thomasjespersen9 ай бұрын
@AndyMehalick It's hard to have a good discussion with comments like that. I read Eric Evans' big blue DDD book from 2004 twice, and I have been doing DDD for close to 20 years now. I just read my comment again, and I don't see where I state anything as hard facts, except that a repository in DDD a repository abstracts the database as a collection. I would claim that is a fact. The Repository Pattern was first introduced in Martin Fowler's Patterns of Enterprise Application Architecture (PoEAA) from 2003, which says: Page 322: A Repository mediates between the domain and data mapping layers, acting like an "in-memory" domain object "collection". ... Objects can be "added" and "removed" from the Repository, as they can from a simple collection of objects, and the mapping code encapsulated by the Repository will carry out the appropriate operations behind the scenes. But the repository pattern was made popular by DDD 2004: Page 151: A REPOSITORY represents all objects of a certain type as a conceptual set (usually emulated). It acts like a "collection", except with more elaborate querying capability. Objects of the appropriate type are "added" and "removed", and the machinery behind the REPOSITORY "inserts" them or "deletes" them from the database. I feel my comment is very well rooted in the origin of DDD and the repository pattern. So please elaborate on what is not true. Today the Repository pattern is used in many other places, and by definition a pattern is not a definitive, which is why I use the "recommend" instead of "must/should". My "personal recommendation" is still use Add() and Remove() instead of Create(), Save() and Delete(), and wrap it in a Unit of Work (pattern also introduced in PoEAA 2003)
@yupii19979 ай бұрын
@@thomasjespersen not worth explaining yourself dude , the other guy has no clue why "nothing you said us true" he is just a troll
@yupii19979 ай бұрын
At my first job as a developer I always argued with my coworkers over this, one even said naming is not important at all. I always rejected pull requests when i did code reviews for variable, field, property, class names, whether it was a bad name or a typo in the name you are getting your PR rejected. Why? Well not only its clearer whats the purpose of the code, but also having a typo in the name is a huge pain when it comes to class names, example you are searching for a class in the file explorer in a large application with hundreds of files, and sometimes we struggle finding it right even when its right in front of us right? And what do you do, you search it, and what happens when you have a typo? Nothing is found, exactly. Also i always put the Async suffix for async methods. No one should guess if the method is awaitable or not based on context or by compiler warnings and errors
@aemarco9 ай бұрын
In fact, in case something is available as Sync and Async, I started to do "Sync" as suffix, because it´s the exception.... usually everyhing is async. Completely on your side with the repo and method naming. Just i have a clash with customer as name :) --> By my own convention, whatever gets returned is called "result".
@ghaf2229 ай бұрын
All my return variables are called result as well
@Shultc9 ай бұрын
@@ghaf222how I see it: var custumer = reg.ToCustumer() - is correct naming. BUT! CreateAsync(...) should return value, wich will be stored in "result" variable, and then returned by function. It will help when Repository generates some fields automatically, e.g. id
@99aabbccddeeff9 ай бұрын
Totally agree with you and really like this kind of videos from you! Thanks a lot for your efforts! About Async, I'm using it everywhere except cases where in the project no one used it before in async code. With Async code more clear and exactly show what you are working with. Also it helps avoid mistakes sometimes. There was funny story of one person, which doesn't prefer to use Async suffix, spent some time to understand, why code doesn't work as expected. It's because that person didn't see clearly, that Async method was called without await :)
@niezbo8 ай бұрын
8:29 Just wonder; for me 'Save' means exactly to save incoming data 1:1, and 'Create' implies there's a possibility of data modification. Like, when you save your file, or game progress you'd expect to have exactly the same data upon loading them back, while 'Create' creates data from something and could alter the end result to fit some kind of requirements.
@KodingKuma9 ай бұрын
You nailed it. Especially this. Some suggestions online is just hunger for spotlight. Don't step on the crap.
@mjenkins659 ай бұрын
Like several others here, I generally like Save vs Add/Create and Update. It simplifies external interactions when I don't have to explicitly determine if this is an insert or update and call the appropriate repository method. If possible, I like to leave that distinction to the repository itself. For example, the repository can tell that the record being saved is an INSERT if the ID = 0 and the record doesn't violate any unique constraints. Even if you want to differentiate actions like RegisterCustomer from UpdateCustomer in your service class, the repository itself doesn't need to differentiate between the two operations. As long as the repository fails correctly on an illegal operation (e.g. violating a constraint) the service can appropriately respond.
@Cornelis19839 ай бұрын
I agree as well. Same with the HttpVerbs. I believe those are outdated as well with having WebAPI 2.0 now. I like using routing so much more because they are (if used correctly) can be much more informative due to using the naming then using the GET/POST/PUT/PATCH/DELETE etc. In my private projects, all my endpoints are post now. In work cases, I simply follow the path that is taken in the project or is normal for the company. But I do hope one day the HttpVerbs are gone. I just fear I might not be living long enough to see that day though which makes me sad.
@Juznik13899 ай бұрын
Always said this and everybody tried telling me I was wrong because they read somewhere about the typical naming convention. Always bugged me how people can't be practical with their naming so that you can see directly what it is. Instead of having go through all references just to figure it out.... Thanks for this video!
@pilotboba9 ай бұрын
I guess my name is "no one" because when I saw that I thought, it's probably a repository. :)
@ChrisWalshZX9 ай бұрын
Bang on Nick. Yes, I still very much use the ~Async suffix as our projects are still far from "everything is async" at this point.
@7th_CAV_Trooper9 ай бұрын
Not everything should be async. Returning task is a huge performance hit. Keep using Async suffix and only return task when you are forced to perform asynchronous operations.
@markovcd9 ай бұрын
@@7th_CAV_Trooper Async suffix was invented by Microsoft because they already had sync version of the api. It is illegal to have methods Task Save() and void Save(), hence async suffix. If you add Async suffix to every method just because it returns Task then you are introducing code smell into the codebase.
@phizc9 ай бұрын
@@markovcduntil the IDE starts coloring methods that return a Task differently to other methods, I respectfully disagree.
@VanDameDev9 ай бұрын
The Async suffix immediately conveys an important piece of information at a glance about that code which is removed when you take away the suffix.
@markovcd9 ай бұрын
@@VanDameDev do add private, public suffixes to your methods, variables?
@Soliber9 ай бұрын
“Because isn’t it our goal to represent a stored collection of customers?” => that’s where his mistake is. Not all collections are to be treated equally, there’s a fundamental difference in the expected behaviour of adding something to an in-memory collection vs a persisted collection. Trying to abstract away the fact that you’re persisting is the same pitfall that led people RPC stuff like CORBA. Adding to an in-memory collections is fast and generally faultless; adding to a persisted collection is slow, introduces variable latency, confronts you with network and other I/O hiccups and suddenly introduces the need for fault tolerance.
@davidmartensson2739 ай бұрын
So true, you should be able to understand if there are side effects or slower code. Its so sad when you find something that looks like just a local property access, like var x = myobject.MyProperty, and then find out that it fetches from a database everytime you access it. Adding the repository name is a clearer indication that this is not a local list or similar but an interface to some external data source, does not need to be a database.
@henriquesouza51099 ай бұрын
@@davidmartensson273 I have bad news for you guys: performance concerns should not be mixed with the business problem being solved. If you gotta add the user, you gotta add the user, if you gotta fetch the user, you gotta fetch the user, if you gotta delete the user, you gotta delete the user, how fast it's gonna be depends what implementation you're injecting into your algorithm. Sometimes a database indexed search can be faster than an in memory List scan, depending on your list size and matching criteria.
@saddamhossaindotnet9 ай бұрын
There is so much bad advice on LinkedIn, Twitter, and some blog posts. As developers, we use LinkedIn and Twitter, and we follow blogs that have programming content. Content creators should have proper knowledge to write content. I think many people just copy AI-generated code. It's bad. Lastly, I love watching Code Cop, but how many videos will you create? Nonetheless, Your Code Cop series is one of the best on KZbin. Love it! Please continue this series for as long as you find those type of topics. Thanks a lot for your awesome contribution!
@thebitterbeginning8 ай бұрын
That "Clean Code Tip" is basically saying to stop naming things based on what they actually are. It's a Repository (which is a specific entity that serves a specific architectural role in the codebase). Naming it as such removes all ambiguity.
@MikeZadik9 ай бұрын
Is there a reason you don't use primary constructors? I find them awesome for dependency injection as it's only 1 line per dependency.
@fredrikjosefsson33739 ай бұрын
I personally never use them for dependency injection because I prefer having them readonly. Also because private fields have white text whereas a variable in a primary area is light blue so can be mixed up with a local variable
@luvincste9 ай бұрын
The repository variable: 1) you can go to definition with 1 shortcut, and return to the previous position with 1 other shortcut; time taken: 0.5 seconds -- which could be avoidable if variable name contained "repository", but still... Second point: you can move the mouse cursor on the variable and it will popup the type, or you can open the popup menu of the autocompletion and it will tell you the type. So sure it could be better, but in this specific case i find it's not that bad.
@MarkusPalcer-u9m9 ай бұрын
Writing these while watching and before seeing Nick's preferences: I would call the first example "Repository" because I'm in the "CustomerService", so it's clear from context that it's the "Repository of the CustomerService", so it's the repository of whatever the CustomerService needs. If I wasn't in something Customer-related already, I'd call it "CustomerRepository". I would only consider naming it "Customers" if it lived in a class "Repositories" that contains all my repositories (although I never had the need for that approach) but then it's clear that it's a repository from the context (access would be through something like repositories.Customers). On an object called "Customers" I would want to access Customers.Add(item) as I also would assume a collection. However - if that causes a DB entry to be created, I might not want/need to know as this might be implementation specific. The second (CustomerRegistration) I would call CustomerService.Request (being a nested class inside the CustomerService). I don't like the async suffix, but I'm used to having to use it as it's mandatory code-style in the projects I'm working it, so I adapted using it in my private projects too.
@djenning909 ай бұрын
I think the …Async suffix convention makes the most sense when there is an API that contains both an async and non-async method that do the same thing. For example, with entity framework and LINQ. When in the broader codebase of an application written as async-first, the …Async suffix is redundant. The IDE generally provides sufficient warning when accidentally calling an Async method without await, so I feel no special convention is needed. The convention is a remnant of Microsoft broadly adding Async methods to a pre-existing legacy codebase with an emphasis on preserving backward compatibility.
@MrMatthewLayton9 ай бұрын
I'm on the fence about this one, although I would generally lean towards CustomerRepository (or customerRepository if it's a private readonly field) 1. "You can split your repository into different responsibilities, so if you have a product, you might have a product catalog, you might have a basket, you might have a pricing repository..." The author's naming convention applies here too. Instead of "Products", they might opt for ProductCatalog (or ProductCatalogue if they're British), ProductBasket, ProductPricing, etc. however, ProductCatalog(ue)Repository, ProductBasketRepository and ProductPricingRepository are clearly more explicit, as you suggested: "I like to be explicit with my naming" 2. "Customers.Save is crystal clear, assuming that Customers is something like a DbSet" Perhaps you meant DbContext (which has a SaveChanges(Async) method), rather than DbSet (which doesn't)? Personally I think this lacks clarity, because I can't tell whether "Save" here means "add/update", or "commit to the database"...maybe both!? (you somewhat covered this in the video when you went on to rename the method "Create"). If they mean "commit to the database", then they have muddied the responsibilities of the repository. Database commits should be a responsibility of a unit-of-work, not a repository. Database commits from a DbContext/unit-of-work ensure that all changes are coordinated and applied as a single atomic action, maintaining data integrity and consistency, much of which is lost the moment you allow every repository to commit its own data independently. For smaller projects it's probably sufficient to have repositories that call SaveChanges(Async), but I think it's still worth mentioning that DbSet and DbContext are akin to Repository and Unit-Of-Work, broadly speaking.
@andreasnaumann40239 ай бұрын
1. Naming is most important for readable code - I'd just have named evrything just as you did. Maybe only using "_repository" because we're in a CustomerService and "single responsibility" should kick in (maybe not considering the LinkedIn guy...). 2. I don't use "Async" any more, because nearly everything is async nowadays... Exceptions are classes/libraries that should implement an async method version besides a sync version of a method (e.g. some industrial machine communications (maybe old school ones) that work like dialogs over blocking hardware interfaces. Where you have to do things like direct communication and message queues at the same time (when not split the library in an async and sync version)) Thanks for the video ✌️
@ryan-heath9 ай бұрын
Ditched the Async suffix for years now, never looked back. Does not add any value in your own libraries. Also ditched _ for privates. If you’ve lost track of what a variable is, your method of class is doing way too much. If I have a single repository injected I’d like to name it repository. Tagging the type name on it feels like Hungarian notation all over again. This is not just for injected repositories but any type. I’d rather name it to its role only than tagging a type name to it. Also another take on repositories, just use EF context directly, you are never going to change your database. If you need to reuse “repository-like” functionaries, you might use extension classes instead for them. Less abstraction can feel like a breeze on a hot summer day! 😎
@medn_8 ай бұрын
I love using the "Async" suffix. Sometimes, I think, it is not really clear if the thing that you are calling should be awaited or not. "Async" makes it clear. Also its common practice in Microsofts APIs. I definitely have had lots of cases where colleagues (or myself) have fogotten to await something, because the naming didn't make it very clear. That is why we have the "Async" suffix in our guidelines now :)
@vchap019 ай бұрын
The "repository as a collection of domain objects" advice is common in older DDD related books when ORMs were not very popular. Back then a repository was a collection like abstraction that allowed you to do multiple CUD operations inside a single transaction with the help of a Unit of Work. Repository interfaces are a part of the domain layer. The implementations would have been in the data access layer. The SaveCustomer method should have been called Add though to follow these conventions. These days repositories often abstract ORM contexts that natively follow those principles as well as include custom query methods, etc; and a lot of times they are just another layer of abstraction. ORMs including EF often map their repository-like properties under the plural domain names such as Customers.
@VoroninPavel9 ай бұрын
If someone can abstract away the details but save the semantics and be consistent, then Repository suffix is just a noise. I am ok with the style.
@TheBuzzSaw9 ай бұрын
I still use the Async suffix. The model of execution for an async method is so different that it's worth calling out everywhere. Also, it's nice to leave room for a non-async name/implementation.
@tomap9 ай бұрын
Totally agree. Newcomers should not be allowed to share what they believe to be true. You are totally right to shame and point fingers. I hope they learned something today I'm not sure it's enough for them to understand how friendly our community can be, if only they provided the right advices.
@jos3roth4759 ай бұрын
This gatekeeping "were smarter than everyone else" mindset is why so many non developers hate developers and see is as arrogant nerds. The whole "newcomers" and "shaming" thing is cringe as hell man.
@MarllonVilano9 ай бұрын
I completely agree with your naming version, Nick! Much more clear.
@rekarpc989 ай бұрын
I love these convention correction videos. Thanks Nick.
@swictor8989 ай бұрын
why the Validate method is async? does it call something external that needs to be awaited?
@davidmartensson2739 ай бұрын
It might. But if it is it should return any problems since exceptions in async code is more complex, especially since the caller could have to dig down into the captured error. I try to avoid using exceptions for anything I expect to happen, so if the Validate for example checks common mistakes that a user could have done entering data, I would not want that to be exceptions since its something that will happen quite regularly I assume. Exceptions are for exceptional things, things you know can happen but that you think will not happen very often.
@charles_kuperus9 ай бұрын
Nick, I absolutely agree with your point, For this specific example it is better to call it on what it is within the Class/Service Context because it is relevant to the implementation details of this Class/Service. Having something that is named like a collection to hide the Metadata of what the service is, gives less benefit to the reader of the code than including the metadata e.g. *Repository. Additionally, I am one to advocate for removal of the async post fix as that does not provide any beneficial metadata. Also pre-fixing class fields with an underscore does also not provide any beneficial metadata as the Pascal casing provides metadata stating that the used identifier is local to the method or class. By my opinion on the usage of an underscore It provides more static in your code that makes it less readable compared to the benefits of the metadata it provides.
@yvesbamani85269 ай бұрын
Fully agree with your video and I am also that strict with naming conventions. It makes more sense to say repository and using underscores for private readonly properties. It tells me everything I need to know straight away
@knixa9 ай бұрын
I like the async suffix, I don't always await tasks but return them and it's nice to know what is happening without having to look at the above method signature
@7th_CAV_Trooper9 ай бұрын
IList or ICollection have all the crud methods you need, so how is a repo anything more than ICollection impl that writes to a persistent store instead of ram?
@Sindrijo9 ай бұрын
Those interfaces are inappropriate to use in this case for a few reasons. - Some actions may be non-synchronous (async) - IList has int indexer, the data may not be indexable at all or at least not by an int. - ICollection has enumerator, the data may not be enumerable, the API contract is also synchronous and if the data were numerable you'd want something like an IAsyncEnumerable instead. You would not want a db call on every enumeration step anyways.
@EikeSchwass9 ай бұрын
Because IList and ICollection *are* stores for items. Repositories *do* store items. You use repositories to access an arbitrary storage, but it is not the storage itself
@7th_CAV_Trooper9 ай бұрын
@@Sindrijo you're absolutely correct. Those are the points I wanted Nick to make.
@7th_CAV_Trooper9 ай бұрын
@@EikeSchwass oh, I like that explanation a lot.
@henriquesouza51099 ай бұрын
@@7th_CAV_Trooper You should be using IQueryable, since IEnumerable, IList, ICollection and even IAsyncEnumerable will fetch all data into memory before doing any processing, while when using IQueryable you end fetching only the final result of the processing (filters, order bys, groupings etc), since they are all done remotely (in case of a database).
@arztje9 ай бұрын
I know this is all very subjective to some, but I hear you Nick. What I would do here: - Customers -> I would use this only if it was a collection type. I see this I am expecting a list or an array at the outset. That also means I am not expecting any enhanced state methods or extensions one would get from a more complex object like a repository. - _customerRepository or _repository for the repo. The first would be for clarity in complex cases where it's not clear what my repo represents - esp with the cases you mentioned in the video. I only use "_repository" if it's a super class with a single repository in the pattern - making it clear that it can only mean one thing. Either way, it's a private member and I name it _lowerCaseName. - Method naming on your repository to me completely depends on if you can control it. If it's coming from EF you likely have no say there, but if you do I agree that SaveCustomer is redundant when you already know what it's for. It would be "_customerRepository.Save(customer)". And for the other methods, I agree with Get, GetById, etc. It comes down to what you can control. Most time I see redundancies in naming due to generated methods. Yes on "Async" at the end of a method name. It tells me immediately that I am getting back a Task rather than the expected type and that I will need to await the result. Not all methods are asynchronous and shouldn't be assumed to be so because asynchronous operations cannot be used in all cases.
@someidiotwithnoname9 ай бұрын
I agree with you. Costumer = Model, Costumers = List, CostumerMapper = mapper, CustomerDTO = DTO class or record etc. etc. everyone knows at the first glance what is it about.
@berrigo29 ай бұрын
I pretty much always use the async suffix, there is no project where literally everything is async, except maybe a vending machine. I think it always promotes clarity. If there is ever a case where removing it makes sense, that can be decided up mutually by contributors
@denisthedev9 ай бұрын
I agree, customersRepository is the way to go. On the other hand, my first guess on Customers was some sort of collection. Second guess was repository. I don't know why, maybe I'm the stupid one, but I would consider it :D
@fifty-plus9 ай бұрын
It was definitely either of those, unless it was very poorly named. Neither of those were outliers.
@JLSXMK89 ай бұрын
It's good advice iff Customers is defined as a List, just like you said. Repo objects would contain code for "Get(string parameter)"? That's kinda cool!
@billy65bob9 ай бұрын
As for the Async suffix, I only bother with it if I'm introducing Async methods into a project that was inherently synchronous to begin with. Everything new that assumes Async by default, I don't bother. It's just noise when you need to await nearly everything anyway, and the bulk of your remaining 'synchronous' ones call the async method to return its respective Task anyway. And while you'll still have occasional synchronous methods, they can be easily and quickly made async where necessary. Only exception I'd make is for a library, in where I'm following microsoft's example to produce both async and non-async copies of all methods.
@mvanhees019 ай бұрын
Actually I use Async at the end for every async method. But I would prefere to use Async suffix only if there is 2 different implementation, one async and one sync.
@tempusmagia4869 ай бұрын
Also for the Customers.Save(customer) I totally agree, that is more like if you were commiting a transaction in a dbset. And adding a parameter makes it confusing not because you wonder what they are saving but its confusing because at least myself, I wonder how they are saving, what they are saving from that thing. And for the Get, definetly a GetById makes things more clear when reading code since there are more than one way to get an object in most of the cases I work on.
@lukewebber55629 ай бұрын
The Async suffix is bloody essential. It tells you straight up that you need (at some point) to await it. Not every method needs to be async, so let's keep that clarity. Please.
@LoicMusic9 ай бұрын
Using Async because it means the Task has started. Without the Async there is no convention that the returned Task is an already running Task, and that may lead the await to wait indefinitely.
@NoName-13379 ай бұрын
I use the async suffix. Makes it more clear. The naming you suggest is great, use this kind of naming too.
@paramjotsingh40199 ай бұрын
I believe that I'd use repository keyword with the obj name if it is part of that particular domain only... I might choose to abstract the repository layer as if i am building a framework for multiple projects thhat have a separate repository layers... which in turn are calling this framework to execute some second operations before their operations... as at the end they r also working the same thing just from a different context... also helps us realise that these r not originally part of the domain that we r working on. And could be used if someone is building a library or a package. I believe that using just customers is kind of abstraction of what the object could be doing... and makes the rest of the code more readable. Thats like uk lists... we dont name list objects like customerlist or departmentlist. Im sorry if i wasnt clear with my words. Not a native english speaker @NickChapsas
@DumblyDorr9 ай бұрын
I actually don't mind calling a repository by the plural name of the entities. The idea is that the fact that this collection is backed by a persistence layer is immaterial to its usage. It shouldn't matter to a consumer whether an interface for a collection of entities where you can query, add, remove, and change entities is implemented with an in-memory storage or a database-storage. A function that determines which entities to add to collection and then adds them shouldn't care if or how the collection is durably persisted. Its job is only the interaction with the collection. A function that queries entities from a collection according to some logic and processes them similarly shouldn't care where the collection gets the entities from. Even transactional interactions aren't an issue, because transactional safety is a matter of whether the collection has shared write-access, independently of whether it has an attached persistence layer. I don't mind naming repositories "[...]Repository" either - but I get the argument that it pollutes the "story" told by the code with implementation details which *should* be irrelevant to consumers. A unit of code (function/method/module/class) should IMO only mention things it is concerned with - and eliminate naming which is there to indicate stuff that is beyond its scope. So I ask myself - "Is it within the scope of the knowledge represented in this function whether the collection it operates on is backed by a persistence layer?"... and I found that the answer is very rarely "yes".
@henriquesouza51099 ай бұрын
THIS
@garcipat9 ай бұрын
I dont like the async suffix even we have to use it if there is only a async version of a method. There is also the cancellationtoken missing if you make it async
@michelnunes44219 ай бұрын
Hey Nick, what do you think about repository pattern, do you like it? Or do you prefer injecting the DbContext into the service directly? My first API to go to production used the repo pattern, but now a days i'm kind abandoning it.
@henriquesouza51099 ай бұрын
I know you asked Nick but I'd like to add I like to abstract the DbContext but not the Repositories individually, since it's all about the context. In this video example you'd have an IAppContext with an IQueryable Customers, then you implement this interface with your DbSetContext and inject it. Accessing it in code would look like "this.context.Customers", see? no "Repository" word and the Context can be implemented using memory (ram), file system or external databases. If not this then I prefer injecting DbContext directly.
@ErazerPT9 ай бұрын
Imho the issue starts "above". It makes sense for the application to have a class Customers which aggregates everything. That class has a CustomerService, which actually does the work. CustomerService has a CustomerRepository where it stores the work. Then Customers.Add(customer) would make total sense, even if that is just an indirection to CustomerService.Add(customer), which in itself is an indirection to CustomerRepository.Add(customer), which is... etc.
@KBoxx9 ай бұрын
absolutely agree. be as clear as possible in code.. don't leave it open to interpretation
@tunawithmayo8 ай бұрын
I don't use the Aync Suffix unless I have a non-async version of the same method that I can't get rid of. For me, the fact that the method returns a Task, is good enough to communicate that it is async.
@kingjustink9 ай бұрын
Returning not nullable Customer seems okay to me. I'd assume in this context if a validation exception is thrown there is some middleware to return a nice response, or if an unforeseen problem occurs during database update just let it return Internal Server Error.
@qj0n9 ай бұрын
yeah, returning null with no message is misleading
@QwDragon8 ай бұрын
Does `CreateAsync` change Id property of its argument? I expect it to be more unusual then naming.
@VaderFaderVader9 ай бұрын
3 hard things in CS: off-by-one-errors naming things :-)
@EricSellers-m3k9 ай бұрын
Yeah, joke (and T-shirt) in my circle goes: Most developers struggle with two things: 0: Cache invalidating 1: Naming things 2: Off by-one-errors
@davidmartensson2739 ай бұрын
I have learned it as: 2 hard things - naming things - cache invalidation - off by one errors (and for anyone not picking up, the 2 things is a direct ref to the off by one)
@woo5459 ай бұрын
In this situation, I would have just named my Customer Repository variable as _repo or _repository. Basically, the repository is being called from the Customer Service, so the default default repo would be related to the Customer. If I need to call other repos within the service, then those would have the extra qualifier, such as _companyRepo. I know it's bad form to abbreviate my variable names, but for me, repo is always short for repository.
@davidmartensson2739 ай бұрын
I do agree, as long as the abbreviation is clear enough and commonly used in the code base.
@wdolek9 ай бұрын
Not using `*Async` suffix (in own apps) - it's noise. In contrary, if I shared library - which could easily happen - I would use it since it's how convention is set in .NET universe.
@radhoinemejai18799 ай бұрын
Nick I heared that we should avoid Enum in the domain layer, and use record instead of that, do you agree? is it really a good practice
@madner2019 ай бұрын
I prefer it when names tell you what it is so you don't have to guess or peek around the codebase for its definition.
@mslucass9 ай бұрын
Beginner here: I use the async suffix because sometimes there are now functions which aren't async but in the future they will be
@Mikael_Puusaari9 ай бұрын
I hope u don't use async suffix if the method isn't async, u should never future-proof by guessing how the code might look in the future, u will create spaghetti code
@mslucass9 ай бұрын
If you never use async as suffix you can't see that an old function isn't awaitable.
@yupii19979 ай бұрын
@@mslucass its not about never using async as a suffix or not. Its about future proofing it what you said "i always use it, if its not async now it might be in the future". If its not async now based on context if im using it i will await it which will result in a compiler error. So if its not async dont use it. But if the day comes when the method needs to be async then you might need to think about how will you approach it.
@ghaf2229 ай бұрын
If I am defining an interface I’ll generally make return types Task and the method names will have the Async suffix. However I’d never otherwise suffix a method Async if it wasn’t. If you need to change it in the future just rename it then!
@yupii19979 ай бұрын
@@ghaf222 well changing the method logic to make it async and renaming is not the best idea honestly. It is a disaster ready to happen, i would much rather create a new async method that does the same thing, then change existing method which is used througout the application and break everything
@kylekeenan34859 ай бұрын
We like using Async when naming methods as we work with a whole swathe of applications, spanning multiple years with some not using asynchronous calls. So when something is asynchronous we call it so.
@CryptoWulfApp9 ай бұрын
Im fine with a field named "repository" if there is only one injected but to name it "customers" is just weird. I also never saw someone naming a repo like "customers" in my 15 years of dev lol.
@yupii19979 ай бұрын
Even if its one i dont recomend naming the field repository or service or whatever. The reason being if its now one it doesnt mean it will stay that way and tomorow we might need to add another one and rename the old one. In cases like this i justify future proofing.
@Mikael_Puusaari9 ай бұрын
I use the Async suffix because no, all methods are not async, most yes, but not all, and many methods will never be, only those where it makes sense I know, I am using the word "never" a bit loosely 😊 If a method is not yet async but u intend to make it async later, do not add the async suffix until it is
@Aaron310569 ай бұрын
I would love to see a UI course for .NET. Maybe about how to do and maintain FluentUI in a Blazor web app properly. Do you know someone that specializes in front-end blazor Nick?
@Ilix429 ай бұрын
CustomerRepo > Customers. We don’t live in the world of 40 column displays and intellisense of some kind is a standard in modern tooling. Names should always be descriptive over short.
@WileeRunner429 ай бұрын
Naming is hard and individualistic. I like to try to write things as self-documenting code utilizing Intellisense and to be short since I've got to type and read them. I don't like variable names to be the same as the class names. What information does "CustomerRepository customerRepository = new CustomerRepository();" give? That's also why I like the new simplifications of new(). 😁
@adamoneil74359 ай бұрын
I'm hesitant to add "type suffixes" like "Repository" on the end of a var name, but I understand the thinking, and I wouldn't make a big deal if that was the pattern I inherited in a code base. And I actually like the "Save" semantics vs explicit Create and Update. Those methods have a place, but the branching logic between them is boilerplate IMO, and there should be a higher level Save method that picks the right approach (insert or update) based on the entity state.
@warny19789 ай бұрын
Something I learned very soon and very fast when i began to work 25 years ago : Name variable, fields, properties to reflect what they are Name methods to reflect what they do. By the time, I worked with someone who named its variables a,b,c , i, j, x, y, z... and used it in the whole module (we were programming in VBA). That's how I understood what code maintenance was, and I figured out very soon how good guidelines were protecting your code.
@NihongoWakannai9 ай бұрын
People who name their variables with one letter are clinically insane. Unless it's a standardized letter like x,y,z positions, r,g,b colors, i,j,k loops etc. then there is no excuse.
@billy65bob9 ай бұрын
it's pretty common to use the acronyms as variables names when using them in a small scope, e.g. `var sb = new StringBuilder())`, `using(var bw = new BinaryWriter(...))`, `var s = someObject.ToString()`, etc.
@davidmartensson2739 ай бұрын
@@billy65bob if the scope fits well within the screen yes I agree. But having worked on projects that have lived for over a decade, I know things change and small methods/loops, tend to grow, and suddenly you are refactoring, cutting and pasting, and woupsie, you have unintuitive variable names spreading. I still use short names, but I try to avoid it. Its so easy to use "i" for index, but then someone adds another loop around and you could get subtle bugs.
@warny19789 ай бұрын
@@davidmartensson273 in that case, being a no nester helps a lot.
@warny19789 ай бұрын
@@NihongoWakannai that's cases where the variables are well named. i and j for iterators are a less obvious, unless for general purpose functions (like sort algorithms or things like that).
@denielalain57017 ай бұрын
Hello! Your advice is better Nick!
@tumelomotsikelane9 ай бұрын
I prefer the Async suffix on awaitable methods. (I left it out for sometime but felt really terrible for doing so)
@kabal9119 ай бұрын
Abbrevehain is a cardinal sin in computer programming unless they are widely understood acronyms or initialisms (HTML, HTTP, etc) 9/10 times naming variables is easy. There are only a couple names, mostly driven by the type. Naming types is obviously the most difficult. I think that if you ask yourself “is this a good name?” you'll come out fine.
@Balgoriusis9 ай бұрын
We use async in our 4.7 Framework coodebase only. Everything in core and later is withou async suffix.
@guai96329 ай бұрын
customers are easy. what if you have a Repository?
@henriquesouza51099 ай бұрын
Let me google that for you: Both octopuses and octopi are acceptable plurals for octopus. Of the two, octopuses is the simpler and more commonly used. The proposed plural octopodes is based on the plural of the Ancient Greek word from which octopus ultimately derives. But it's rarely used outside of the octopuses vs.
@MarllonVilano9 ай бұрын
I use the Async suffix only when I have the non-Async method in the same class!
@markharwood67949 ай бұрын
The naming suggested by the OP immediately screams that the persistence abstraction has leaked. You can assume from the name of the containing function "Register" that we are in the Core (Application or Domain layers) dealing with a Use Case. Once any logic has been dealt with at that level and we want to persist data we then talk to an inverted persistence abstraction which would be something like await _customerRepo.CreateAsync(customer) or await _customerDataService.CreateAsync(customer). At this abstraction level we should NOT be talking to an implementation detail which Customers certainly sounds like. So even if Customers is, as in this case, the repo, it is badly named because it suggests a collection abstraction has leaked. So, I agree with Nick :)
@ernstgreiner59279 ай бұрын
Thumbs up for "Naming is extremly hard!" in the first 30sec (still struggling...). My first assumption was, it must be an Repo, no other things does make sense. I use ...Async
@AlanDarkworld9 ай бұрын
The 3 hardest things in software development: - exactly-once delivery - naming things - cache invalidation - exactly-once delivery Names matter. A lot. I can't get behind the leading "_" for private fields, but that's a C# convention thing I guess. I prefer to write "this." in front to make it explicit that I'm talking about a field.
@AK-vx4dy9 ай бұрын
Looking at methods use, Customers is thought like some DB wraper around SQL, but name sugest it is DB Set or collection, so you are right, i don't know if i like Repository, rather Service with such methods
@computer97648 ай бұрын
I would argue adding the `-Async'` suffix is useless unless the method has a sync counterpart. It would be similar to adding `-Void` and `-Task`, and that's just visual clutter; it takes away from providing actually descriptive names and adds characters for your brain to parse. It may be helpful if you're programming outside of an IDE, but why would you write C# outside of an IDE? As with most things, it comes down to preference rather than what's objectively best.
@bslushynskyi9 ай бұрын
If I saw some variable starting from capital letter and the name is in plural form, I would assume that it is a property and a collection, not a repository. If I wanted an entity to be repository, I would explicitly named a property of a field "BlablablaRepository".
@LinxOnlineGames9 ай бұрын
The problem with naming variables is that it's subjective, what is obvious for you, is not the case for another. For myself, I much prefer writing code that can be verified easily, as the name will inevitably be misleading. What I dislike about the above code is the CustomerRegistration able to create a Customer via ToCustomer() that function is exceptionally misleading on what the intent is. I'd much rather have the service provide the ToCustomer function and CustomerRegistration is passed in.
@pagorbunov9 ай бұрын
I love this phrasing "piece of advise"
@stephajn9 ай бұрын
I always use the Asynchrony suffix because it just fits in line with Microsoft’s guidelines. If I am building something for use in .NET, then I want it to feel like it fits in well with what the guidelines for building for that framework actually are. Microsoft uses it in the BCL and elsewhere, so why wouldn’t I?
@krss62569 ай бұрын
I strongly disagree with the view that Async is merely noise or a code smell. It's crucial for me to know immediately whether a method requires an await or not, because they fundamentally don't do the same thing. It goes beyond simply adding something to a repo; it's about whether that addition is synchronous or asynchronous, requiring an awaitable approach. Some might argue this approach is akin to 'leaking implementation details,' therefore making it a bad practice. However, I see the Async suffix as more aligned with distinctions like GetById, GetByName, or GetByEmail - informative and necessary, rather than just another Hungarian notation, but from another side. My stance is firm: as long as there's a distinct difference in behaviour between 'await DoSomething()' and 'DoSomething()' in C#, the Async suffix remains an essential part of clear and effective coding.
@fifty-plus9 ай бұрын
Naming isn't hard people generally overthink it and try to dream up something instead of calling things what they are, or english isn't their native language and the name gets lost in translation.
@Sindrijo9 ай бұрын
If naming starts to become hard, it's likely that you are abstracting too much or the abstraction has too many responsibilities or an disparate inappropriate mix of responsibilities.
@qj0n9 ай бұрын
The only case, I'd accept a repository to be called simply "Customers" is withing Unit of Work
@emzyempire6589 ай бұрын
The post seems to be made by a dev that has only worked in his code base. And for the naming I usually use Async as a suffix, however if its a Web API I don't think it's necessary as most of its actions would be asynchronous, however if it's like a console, desktop, etc I think it's best to have the suffix
@LordXyroz9 ай бұрын
We all know the best way to name variables is to start with the letter A, then the next variable is B, etc etc. Once you get to Z, the next one after that is AA, then AB, etc etc. 😂 /s
@SamuelSidor9 ай бұрын
Guys, regarding correct naming. What is your opinion in LINQ on using `x` as the name in the lambda. E.g. `customers.First(x => x .id == 5);` I understand that when using LINQ in LINQ it is required to use proper names but when using just a simple one without multiple levels of nesting you immediately know what the X represents based on name of the collection. My colleague has quite big problem with this, what are your opinions ?
@henriquesouza51099 ай бұрын
Well you already seem to know that this gets annoying into multiple levels of nesting, so you're good. You don't need to go "customers.First(customer => customer.id == 5)" though, that's too much for a simple filter, but you can go "customers.First(c => c.id == 5)", it doesn't hurt too much, right? It's how I name 90% of my lambdas. There are places where I use "x": when I'm coding the entity framework configuration for each entity. It gets a bit annoying to maintain all the Property.(entity => ) stuff (even using the first letter only). In short, try to feel if it hurts too much in the following order (in the case you showed): customer > c > x, and choose the best. Hope it helps.
@JohanBenschop9 ай бұрын
I perfer to ommit the Async most of the time, feels redundant and rarely adds value. If I miss an await I'll get a analyzer yelling at me anyways. But yeah, I'm with Nick on this naming thing, and we adhere quite closely to the modern C# guidelines if not for consistency. And for that validation, that should be done in the API handling earlier, because what's this going to do now if it fails the validation? Thrown an exception, and that's.... yeah, I don't like that approach anymore after having used it.
@henriquesouza51099 ай бұрын
You should not inject the repositories directly anyway, you inject the Context (be it dbcontext or not) and then access like context.Customers, with "Customers" being only a container with a collection-like interface (IQueryable preferably) and the context being the abstraction for where the data is at (in memory, filesystem, database...)
@xaberue9 ай бұрын
I'm totally agree with you naming preferences Nick! Regarding Get methods, by the way, considering the name of the param sent as well (id, email...) I would then just name it Get taking advantage of the method overloading, unless there's a type coincidence, so then I would rename them as you suggested. About Async suffix, in a perfect world I would prefer not to have them, however ir creates confusion when you have a mix ot naming conventions: has the dev forgot to add it? Is it then an async but not awaited invocation? I think imho that in the real world, having it avoids misunderstandings and confusions... Again, Great video btw as always!
@davidmartensson2739 ай бұрын
But if it accepts a string, how will you know if it fetches on email, or name, or customer number (in case that is alphanumeric) or ... If you use a plain Get and depend on overloading, the arguments should be domain objects so Get(EmailAddress email) or Get(FirstName firstname) and so on. Otherwise its ambivalent and a very likely source of problems.
@xaberue9 ай бұрын
@@davidmartensson273 that's true and why I've said that only if there is no conflict/collision between arguments (since it's not technically possible) If I have a Get(Guid id) and a Get(string email) I see no problem nor misunderstanding when using them. If on the other hand you need to filter by email or name then I would have something like GetByName(string name) and GetByEmail(string email)
@davidmartensson2739 ай бұрын
@@xaberueI would argue that as soon as the argument is of a standard primitive time you should have a more descriptive name of the method. But sure, if its obvious from the context that a string has be be an email I might let it pass a PR ;)
@tempusmagia4869 ай бұрын
I think I agree with the part of naming explicitly a CustomerRepository inside a CustomerService but I believe there are cases where explicitly sounds weird. Maybe you were refering specifically to the repository inside service but my example is for example the Customer class model having a CustomerId, that just feels too repetitive to have explicit Customer.CustomerId.
@tempusmagia4869 ай бұрын
Ignore this comment, you totally made it clear in the _customerRepository.CustomerCreate() should be _customerRepository.Create(). It is implied but I leave the comment if someone didn't watch all the video and read the comments, which I believe cant happen because code cop is the best series ever
@xcoder11229 ай бұрын
I don't understand why a customer repository is not a collection of customers as to me it is. It's not an array or set of customers but a repository is also a form a collection to me. Okay, maybe some C# thing I don't fully understand, maybe repository has a different meaning in C#. But a general rule for good naming is to not duplicate type information in names. So just as you would not name an array of customers CustomerArray and the name of customer would also not be CustomerNameString (here you could also argue, how would you know it's a string without String in the name), you would also not name a repository of customers CutomerRepository. You also should not use names like Manager, Service, Controller, etc. unless those have a special meaning in your programming language of the system API you are programming for, as every class that manages or controls something is a controller/manager, that adds nothing useful to the name. Names should be useful and represent the purpose and naming an object that represents your entire customer base customers, doesn't seem too far fetched.
@JonasMotiejauskas9 ай бұрын
Not using the 'Async' suffix as it feels redundant
@YuriyShalak9 ай бұрын
I am a naming Nazi myself, so I really appreciate this video.
@80-two9 ай бұрын
Always use "...Async" .. it makes sense to be explicit