In what layer of a project do common extension methods belong? - c#

I'm curious what "layer" of a system common extensions that are global to the application belong in. For instance, I may have extensions that let me use the Rails-like "DaysAgo", "MonthsAgo", etc. type of extension method on integers. What layer of a project does this typically belong in? I was thinking Infrastructure, but that seems to mean database-related (e.g. base repositories and data access). I have a "Core" library project, so maybe it belongs there?
I understand that you want to group extensions that are related to a specific group of classes, but these are essentially used across the entire application. In the days before extension methods, they would be in a Utilities static class or the like, so where should they live now?

You can (better) create multiple infrastructure projects based on scope for example:
Infrastructure.Common (here comes the general infrastructure - best fit for extension methods)
Infrastructure.Data (Data access)
Infrastrcuture. bla bla bla

I would put these methods at the lowest possible layer where those objects/entities exist.
either in the interfaces, or in the entities or in a core assembly, the lowest the better so all upper layers can use it :)

I would put them in a base project (something like 'Core') that is referenced from all other projects. If you start a new project in some time you can reuse these extension methods easily.
I would think about the namespaces you will use for your different sets of extension methods. If some really belong to Data, just put them in a Core.Data namespace so your code in other projects won't be cluttered with extension methods that have no meaning in that context.

Consider putting logic that is outside the scope of the entire application in its own assembly or assemblies.

Related

Where should I put common utility methods in an Asp.Net Core MVC-project?

I currently have all my common utility function methods in a base controller, which all of my controllers inherits from. These are methods for functionality like uploading files, resizing pictures, deleting files, sending e-mails, generating random passwords, hashing passwords, etc.
What is the recommended structure for these kinds of things?
In that case you shouldn't put all these utility functions inside your base controller. You will face a lot of problems if your project grows. Changes and testing of these methods can become difficult, all your inherited classes need to use the same utility methods, etc. Have a look at Composition over inheritance to see another approach.
Somethimes I tend to organize my projects in the following manner if that might help you:
Simple helper methods: Create a folder and a namespace (e.g. namespace [...].Common") inside your web project and put one or more public static classes inside it (e.g. class "FileHelper.cs", "StringHelper.cs", etc). If you need one of these methods in a controller action simply put a "using ...Common" statement at the top of your controller class and call e.g. FileHelper.MethodName.
If I can define a closed subject area with a group of methods I try to encapsulate these methods in a service class (maybe even outside the web project if I have a feeling that I might need this functionality in other projects too), define an interface for that class and plug that functionality into controller classes by using dependency injection. If you don't know about that concept you should definitely read Dependency injection in ASP.NET Core. Dependency injection is a vastly used major concept in ASP.NET Core projects that brings you a lot of advantages and - if used correctly - stears your work into well-organized projects.
More complex organizations are always possible depending on your needs. Have a look at multitier, hexagonal or onion architecture if your projects grow.

Is it bad practice to have two separate MEF plugin containers?

Let's say I have a class (not a static class), A, that in some way uses plugins. I use MEF to manage those plugins, and add methods for my users to add parts catalogs. Example usage:
var myA = new A();
myA.LoadPlugins(new DirectoryCatalog("path/to/plugins"));
myA.DoStuffWithPlugins();
In the same namespace as A is class B. B also uses MEF to manage plugins, and has its own CompositionContainer. If a user wants to interact with B's plugins, she must use B's plugin management methods.
B is used just like A is, above.
My question is, is this bad? Should I care that there are two separate places to load plugins in my namespace? If it is bad, what are the alternatives?
My question is, is this bad? Should I care that there are two separate places to load plugins in my namespace? If it is bad, what are the alternatives?
Not necessarily. There is no reason you can't have two completely separate compositions within the same application.
That being said, there's also no real reason, in most cases, to have more than a single composition. MEF will compose both sets of data at once. In your case, you could compose your importers and your reports with the same composition container, which would have the advantage of allowing somebody who is extending your system to only create a single assembly which extends both portions of your application.
One potential minor red flag here is that these are two separate types within the same namespace, but each of which have their own plugin system. Typically, a framework with a full plugin system is going to be complex enough that I'd question whether they belong in the same namespace - though from going by type names of "A" and "B" it's impossible to know whether this is truly inappropriate.
I don't see any problem with that. I would recommend a base class for class A and class B to reuse methods.
class A : BaseCompositionClass {
// implementations
}
class B : BaseCompositionClass {
// implementations
}
You could use a single CatalogExportProvider and then query that provider for the matching imports and exports. You could then use a single CompositionFactory from which classA and classB request compositions.

Structure of a Medium-Large scale project

I'm a beginner programmer, apologies for any stupidity.
Having come from a python background creating small projects with only a few classes, I would have all of my code in one file most of the time.
I've been learning c# recently, and I'm writing a reasonably large console application (10,000 lines +). I obviously can't put everything in one file here, but I'm not sure how I would go about separating the project into smaller segments.
The way I have done this so far, is to create a new project for each namespace within my solution, and split each class into a separate file accordingly. So far, I have around four namespaces. I have written each namespace independently, with a view to use each one going forward in other projects.
I'm at the stage now where I would like to piece together each namespace to build my console application. How do I go about doing this ?
Also, am I structuring my code in the right way ?
Also + 1, is it possible to use files located in a completely different directory within a project ?
Many thanks in advance.
When you start with a namespace, you'll usually use your company or organization name (say, "A"). If you have multiple products/projects and are creating code for that item, you'll want to add a qualifier (say "B", "C", etc., so you'll have A.B, A.C, etc.).
Then general approach is that you want to group types together in a namespace that are related. If you create a type and it is general purpose/utility/one-off solution to a common problem, you'll want to keep it in a broader scoped namespace. When you find you are creating a number of types to support some feature or purpose, you may wish to create a narrow namespace to contain those types. For example, let's say you need to write several data access components for A.B, which contains data transfer objects, data access objects, etc. You may wish, then, to put those types in something like A.B.DataAccess.
However, remember that .NET uses an OOP paradigm. One OOP paradigm is code reuse. So if you access data in both A.B and A.C, you'll do well to create reusable data access components to encourage code reuse in both projects. In that case, you may wish to have a project such as A.Common, which contains common types used by any of your products, that contain general use, generic, or abstract concepts that can be utilized in A.B, A.C, etc.
Let me try and go further with that example.
Project: A.Common (name of assembly)
Purpose: Reusable types for any project
Namespaces: A, A.DataAccess
Types: A.DataAccess.DataAccessObjectBase
Project: A.B (name of assembly)
Purpose: Types for product "B"
References: A.Commmon
Namespaces: A, A.B, A.B.DataAccess
Types: A.B.DataAccess.DataAccessObject (implements A.DataAccess.DataAccessObjectBase)
Project: A.C (name of assembly)
Purpose: Types for product "C"
References: A.Common
Namespaces: A, A.C, A.C.DataAccess
Types: A.C.DataAccess.DataAccessObject (implements A.DataAccess.DataAccessObjectBase)
That's a pretty simplistic and crude example, but hopefully it will help you visualize the relationship between assemblies and namespaces.
Some other tips:
Don't go overboard with creating namespaces, especially when creating deep namespaces (such as A.B.Something.SomeMoreStuff.EvenMoreStuff), unless it sensible. It makes it a little harder for you to find things.
Namespaces should go from broader purpose to narrower purpose. Furthermore, if you create a type in a narrower namespace that relies heavily on stuff from a broader namespace, be sure to place it under the broader namespace. e.g. A.B.Broader.Narrower.
Finally, you should continue to create only one type per source file.
Sounds more or less on the right track. Addressing your questions/structure:
1) Don't need to have each unique namespace be represented by its own project; you can (and likely should) have multiple sub-namespaces within the same project if it helps organize your classes. In your case, it sounds like each one is being programmed as its own stand-alone component, so a project for each one makes sense.
2) Your splitting each class into a separate file is good, keep doing that.
3) Not sure about what you're asking about piecing your code together. Do you mean how to go about physically referencing/linking the projects in Visual Studio or best practices to code/access your API? If the former, you can right-click the "References" item under the project and point to the project (not its compiled DLL). If the latter, there are a variety of programming patterns you can follow, but generally you'll want to abstract a nice API out of the projects so you aren't concerned by the inner-workings of your code.
4) You can definitely reference files from a completely different directory. Just right-click on the project or folder, choose "Add -> Existing Item" then browse to the file. You'll probably want to add it as a "link" so it doesn't physically copy the file: http://msdn.microsoft.com/en-us/library/9f4t9t92%28VS.80%29.aspx
Here's another StackOverflow question that goes a bit into possible solution structures: Solution: Per application, or per application suite
Namespaces help you to organize your code and provide separation of concerns. It could be done also by creating folders or separate projects. With good logic separation you can build maintainable and scalable applications.
When you taking decisions whether to create new folder, or new project you should rely on common sense. For example, creating several projects for hello world application is an overkill. Creating folder for single class is overkill too. But when you have several classes closely related to each other, consider to separate this particular concern from other application. E.g. if you have CustomerRepository, then you add OrderRepository and VendorRepository. Its good decision to highlight concern, which they are represent. Create Repositories folder and move all those classes there.
With large applications its common to separate such concerns as business logic, data access logic, and user interface. Usually classes which relate to these concerns go to separate projects. Keep in mind, that separation done to make your code easier to understand and maintain. So, namespaces should describe concerns to you and to anyone who will maintain your application. E.g. you can use three projects:
FooCompany.BLL
FooCOmpany.DAL
FooCOmpany.UI
Thats acronyms of Business Logic Layer, Data Access Layer and User Interface. There is no 'standard' names. You can use anything which will describe your code better. Here is example of project structure I usually use for company Foo product Bar:
// Assembly for business logic
Foo.Bar.Domain
Foo.Bar.Domain.Model
Foo.Bar.Domain.Services
Foo.Bar.Domain.Repositories
// Assembly for data access
Foo.Bar.Persistence.NHibernate
// Assembly for application services
Foo.Bar.Services
// Project for presentation
Foo.Bar.Presentation.Web
Foo.Bar.Presentation.Web.Controllers
Foo.Bar.Presentation.Web.Views
Btw common practice to start namespace name with name of company you are developing for. SeeNamespace Naming Guidelines. That allows to avoid names conflicts when you have two classes with same name in different namespaces.
I'll begin from last question to first. You can use files located in a completely different directory within a project. I think you go in the right way. About different namespace you can use this code
using System;
using namespace1;
using namespace2;

Assembly, Namespace, DAL; What classes belongs where?

I would like to understand a few basics about Assemblies and Namespaces. I've reproduced an NHibernate tutorial, and everything works fine. But I'm not sure if I agree on what classes go where. So look at Solution Explorer image attached..
Domain and Repositories (with classes in folders) are namespaces. And here both are in the ...DAL assembly.
Is there any logical reason to put it there? Product is a POCO class. Shouldn't that more naturally belong outside the DAL assembly?
Is it correct to put IProductRepository in the Domain namespace? And if you suggest to move the POCO classes, would you also move the IProductRepository?
What would I need to do if I wanted to make the DAL usable by both C# and VB.NET projects?
Is there any logical reason to put it
there? Product is a POCO class.
Shouldn't that more naturally belong
outside the DAL assembly?
The argument for putting the POCO class in with the persistence implementation is to simplify deployment and reduce the total number of needed assemblies.
That is not to say I agree with the practice.
It is a better practice, and perhaps even more conventional, to place the definitions of the domain objects in one assembly, and the implementations that depend on the persistence technology in another.
Clients can then reference the assembly of domain object definitions without being tied to the implementation strategy.
Is it correct to put
IProductRepository in the Domain
namespace? And if you suggest to move
the POCO classes, would you also move
the IProductRepository?
Yes, it is correct for the definition of a Repository to be in the Domain.
Repositories are a domain concept, they are not generic - at least not the interface they expose (the implementations may in fact be generic).
The interfaces for the Repository should live with the definitions for the Entities (whether they are POCO's or just interfaces) and with all other domain objects.
What would I need to do if I wanted to
make the DAL usable by both C# and
VB.NET projects?
Nothing special. You can reference the assembly from either C# or VB.Net, whether the DAL and/or Domain assemblies were written in C# or VB.Net. This is a large advantage of .Net as a whole and is quite intentional and by design.
Typically I would put the POCOs in their own library, something like MyProject.Model or "Domain" as you call it. The reason being is that I might want to use them outside of the DAL as well, somewhere higher on the food chain without referencing the DAL assembly. For example I might front the .DataAccess with a .Business project, which will return the same .Model (Domain) objects. Typically my repositories live in MyProject.DataAccess.Repositories for example. You should be able to reference a .NET assembly (no matter if it's C# or VB.NET) from any project without any problems.

Resolving Circular References (C#)

I'm having a couple of problems with circular reference/dependency that I've been sitting on all day. Something must be wrong with my thought process, I just don't get it.
Here are my projects:
Flip.Main (ASP.NET MVC)
Flip.Domain (C# DLL)
Flip.Services (C# DLL)
Flip.Utility (C# DLL)
Current References/Dependencies:
Flip.Main -> Flip.Domain, Flip.Services, Flip.Utility
Flip.Services -> Flip.Domain, Flip.Utility
Flip.Domain -> Flip.Utility
I wanted to structure my project in a way that my services project has all services, my domain project the model, repository and 'fluent' extensions to query the model, and the main and utility project are pretty much self explanatory.
Problems encountered:
1) I have an EmailService in my Flip.Services project, which needs to send out localized emails. All localization is done in Flip.Main's App_GlobalResources. No idea how to get the strongly typed emails and other localized resources now to my service layer as Flip.Main already depends on the service layer and therefore I can have it depend back to the Main project.
2) I have business classes, e.g. CustomerSearchFilter which represents a strongly typed search query. I want those business classes outside of the Flip.Domain project because they are not part of the domain model. However, in my CustomerSearchFilter class I have domain class instances (e.g. CustomerGroup) so it needs to know about domain classes. At the same time my Fluent interface in my Flip.Domain project needs to know what CustomerSearchFilter is so I can apply it to my IQueryable interface. Circular reference again.
3) I have a custom [AuthorizeSessionState] attribute which I use to decorate specific controller actions in my ASP.NET MVC Flip.Main project. This is an ActionFilterAttribute which needs to instantiate my SessionService who resides in my Flip.Services project. I can't put this into my Utility class though (because Flip.Services already references Flip.Utility). I don't think they should be in Flip.Main either - do I have to make another project for this!?
(20 more)
I feel like I'm making a mistake somewhere down the line, especially when I read that others usually don't encounter circular reference problems. Help?
Use interfaces for all non-trivial classes. Place interfaces in a different assembly from implementation.
The question comes down to what you separate by namespace and what you separate by DLL. If you have a good reason to keep EVERYTHING modular, you have to work really hard. But if each of these dlls only have a class or two in them, perhaps you could merge them together?
Take a few minutes and sort out the procedures ... create an identifier for each project (FM, FS, FD, FU). List each publicly accessible procedure on a page and then add an identifier for a project, if that project uses the procedure ...
Then you can see which procedure needs to be in (or accessible to) which project.
Hope that helps!
You can put your localized email strings in Flip.Services. The downside is that you have two places to maintain localized resources. You can also have a separate dll for all your resources to minimize the place to edit resources.
You have to move the fluent interface to an other dll or make CustomerSearchFilter part of the domain.
You will need to add more projects or rearrange your structure and use namespaces to create the separation.
It sounds like your building on concrete implementations instead of interfaces/contracts. As Ima suggests define interfaces that describe what a certain class should be able to do. Use this interface when you declare properties, parameters and the like. Keep the interfaces separate from the implementaion and both the implementation and the projects that uses the interface can reference the interface project.
You then get the nice option of using dependency injection making your code easier to test as an a side
In the "tiers" of a domain, repositories and services live at the same logical level, above the domain in an infrastructure role. I would suggest moving your repository implementations (queries, etc.) outside of the domain itself. That solves #2 at least.

Categories

Resources