I actually like being able to look at one file and read how the application is configured. Plus I have to admit, I like large source files as it makes me feel like I've done a lot of work. 😆
I like extension methods like these, especially organizing in terms of modules. My reasons: - readability - reduced merge conflict problems - many times somebody from my work team happens to wipe out some configuration, while resolving a merge conflict in that class file - if we keep the modules and their "module installer" extension methods in separate projects, that also helps with being strict about the direction of dependency between the projects. I've seen how Clean architecture is the overall goal, but there is room for violating that when the API project, being the running instance and having the Program.cs class, has reference to every other project and package dependency for the service registrations. Why? Because sometimes you might be "in a hurry" (lazy) and work with the infrastructure directly - in certain controllers/endpoints, in background workers etc. So I'm in favor of project per module. As for the module installer methods - either in their respective module project, or a separate "all knowing" DI configuration project for the whole application.
Thank u! I have a question: Whats the difference(or sense behind) when we use void and instance(IServiceCollection) as return type for extension method?
When you use IServiceCollection instance, you have an ability to do so called "method chaining". As Amichai shown that in the video, we can write builder.AddServices().AddPersistence().AddSwagger()... and etc. It you were using void, it would be like that: builder.AddServices(); builder.AddPersistence(); builder.AddSwagger() and so forth. P.S. It's usually a matter of convenience, but that specific thing is widely used with Builder pattern (in fact, we have a builder.Build() call in Program.cs, so consider this as Builder implementation)
Returning IServiceCollection enables the fluent/chaining style that Amichai uses in the Program.cs ie. builder.Services.AddServices().AddControllers().
Hello Amichai, thanks for the sharing. I've used that all my entire career and really like that approach. Also, how do you think it profitable to register services via reflection directly to the DI instead of classic approach with registring every service manually? i mean someting like: var types = typeof(DI).Assembly.GetTypes() .Where(x => !x.IsInterface && !x.IsAbstract && x.IsAssignableFrom(typeof(IService))) .ToArray(); foreach (var type in types) { services.AddScoped(type); } return services;
Perfectly fine to do that when you want to register services in bulk (e.g validators) that all implement the same interface. You take the performance hit of reflection on startup and that's it.
How is that? It is highly modular. You you choose to initialize the modules you need in a short and precise manner. Your modules are initialized with a single call to the extension. Even Microsoft uses this exact approach in their code: every aspect/module of the web application and hosting are configured through extension methods that precisely declare the intent and type of module to use (i.e. AddDbContext(i => i.UseNpgsql()) or AddLogging(i => i.UseSimpleConsole()))
@@amantinband what specifically? The viceo creator here nicely explained how to organize the extension methods. Each covering the configuration of a single module.
I agree with you. I curious what Efe is suggesting as an alternative.
3 місяці тому
@@cn-ml Modularity can be achieved in two different ways. You can define your modules based on technical aspects or domains. I always prefer to go with the second way. Each module can have specific dependencies. I prefer to define separate dependency installers for each module, and that helps manage dependencies. You should stop comparing Microsoft with other projects. There is a huge difference between Framework development and typical business projects. Even from Microsoft's point of view, we can say each NuGet package is a module, and the .NET Framework team creates separate extensions for each of them, BUT it doesn't mean you can create a lot of extension methods. if you want to keep maintainable your project, you should be fan of the simplicity.
The evolution has made its turn and now we are constructing back our Startup class manually.
Tbh its not the same since when we had to have Startup class we did the same stuff with organizing our application via such extentions.
I actually like being able to look at one file and read how the application is configured. Plus I have to admit, I like large source files as it makes me feel like I've done a lot of work. 😆
I like extension methods like these, especially organizing in terms of modules. My reasons:
- readability
- reduced merge conflict problems - many times somebody from my work team happens to wipe out some configuration, while resolving a merge conflict in that class file
- if we keep the modules and their "module installer" extension methods in separate projects, that also helps with being strict about the direction of dependency between the projects.
I've seen how Clean architecture is the overall goal, but there is room for violating that when the API project, being the running instance and having the Program.cs class, has reference to every other project and package dependency for the service registrations. Why? Because sometimes you might be "in a hurry" (lazy) and work with the infrastructure directly - in certain controllers/endpoints, in background workers etc.
So I'm in favor of project per module. As for the module installer methods - either in their respective module project, or a separate "all knowing" DI configuration project for the whole application.
Hello Amichai, what tool are you using for the colored lines and circles you are drawing on your screen when you are describing your code?
Presentify (it's MacOS only. ZoomIt is a good windows alternative)
Thank u! I have a question:
Whats the difference(or sense behind) when we use void and instance(IServiceCollection) as return type for extension method?
When you use IServiceCollection instance, you have an ability to do so called "method chaining". As Amichai shown that in the video, we can write builder.AddServices().AddPersistence().AddSwagger()... and etc. It you were using void, it would be like that: builder.AddServices(); builder.AddPersistence(); builder.AddSwagger() and so forth.
P.S. It's usually a matter of convenience, but that specific thing is widely used with Builder pattern (in fact, we have a builder.Build() call in Program.cs, so consider this as Builder implementation)
Returning IServiceCollection enables the fluent/chaining style that Amichai uses in the Program.cs ie. builder.Services.AddServices().AddControllers().
@@winchester2581 Thanks!
@@curtmantle7486 Thanks!
Hello Amichai, thanks for the sharing. I've used that all my entire career and really like that approach. Also, how do you think it profitable to register services via reflection directly to the DI instead of classic approach with registring every service manually?
i mean someting like:
var types = typeof(DI).Assembly.GetTypes()
.Where(x => !x.IsInterface
&& !x.IsAbstract
&& x.IsAssignableFrom(typeof(IService)))
.ToArray();
foreach (var type in types)
{
services.AddScoped(type);
}
return services;
Perfectly fine to do that when you want to register services in bulk (e.g validators) that all implement the same interface. You take the performance hit of reflection on startup and that's it.
What tool do you use to draw on the screen?
Presentify
Hi,
I personally prefer partial Program.ABC.cs classes instead of boilerplating my project with folders and separate files
Great video!
Nice Thanks!
This approach causes mess of extension method and classes for mid/large size projects, I prefer go with modularity.
How is that? It is highly modular. You you choose to initialize the modules you need in a short and precise manner. Your modules are initialized with a single call to the extension. Even Microsoft uses this exact approach in their code: every aspect/module of the web application and hosting are configured through extension methods that precisely declare the intent and type of module to use (i.e. AddDbContext(i => i.UseNpgsql()) or AddLogging(i => i.UseSimpleConsole()))
care to elaborate?
@@amantinband what specifically? The viceo creator here nicely explained how to organize the extension methods. Each covering the configuration of a single module.
I agree with you. I curious what Efe is suggesting as an alternative.
@@cn-ml Modularity can be achieved in two different ways. You can define your modules based on technical aspects or domains. I always prefer to go with the second way. Each module can have specific dependencies. I prefer to define separate dependency installers for each module, and that helps manage dependencies. You should stop comparing Microsoft with other projects. There is a huge difference between Framework development and typical business projects. Even from Microsoft's point of view, we can say each NuGet package is a module, and the .NET Framework team creates separate extensions for each of them, BUT it doesn't mean you can create a lot of extension methods. if you want to keep maintainable your project, you should be fan of the simplicity.
gonna be honest..just put it all in the one file its much simpler
why do this when you can #region ### SERVICES ### hehe
Extension methods nonsense should be banned
Imagine writing c# in vscode kek