I am learning how to implement onion architecture using .Net core API. I understand that the focus of Onion architecture is more on flow of dependencies rather on how the layers interact with each other. But I found that domain entities are still accessible in the presentation layer (API layer). This is because the presentation layer has a project dependency on the application layer and the application layer depends on the domain layer where domain entities are defined as public. We cannot define it as internal because the entities will not be accessible by the application layer. This way anyone in the team mistakenly access the domain entities instead of the corresponding DTO.
One solution proposed on Udemy Q&A that we can define domain entities as internal and we can specify the assemblies that can access these internal entities by using the below build configuration
<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>NameOfProjectToGainAccess</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
But this is causing error in the MyApplicationDbContext file in the Infrastructure project. The compiler flags error in the below code
public DbSet<MyEntity> MyEntity {get; set;}
It says that the DbSet is less accessible than the public property MyEntity.
I get the similar error in the repository contract definition as base interface is less accessible.
public interface IMyEntityRepository : IGenericRepository<MyEntity>
I want domain entities should not be accessible in the presentation/API layer. This layer should only access DTOs.
Please advise if there is way to do this.
One option to address the access problem is to package by component. This technique is described by Simon Brown in the clean architecture book, chapter "the missing chapter", page 318.
The main idea is to use the access modifiers to ensure the architectural constraints. Simon Brown puts all the "use case" related stuff in one package. He can then reduce the access modifiers for all classes and interfaces within the component to hide them from the outside. This would also apply to the entities, even they are not explicitly shown in the diagram.
I guess (I'm a Java programmer) that in C# you would use assemblies to implement the package by component, because the access modifier internal is used to control access to classes within the same assembly. I hope that this is correct.
Questions I anserwed that might also help:
Should layers be visualized in the code structure?
Who must create services with package modifier if I implement architecture from "Clean Architecture" book
Another option is to use tools that scan your source code to ensure architectural constraints or code reviews. Finally I guess we have to ensure it using code reviews and tools, because even with the package by component approach programmers can change the source code and replace the internal access modifier with public. They usually prefer the fast implementation approach over the long lasting and you often have to do a lot of effort to convince them.
If you have your base repository i.e. IGenericRepository<MyEntity> internal, then you can't have the extended one public, your IMyEntityRepository, will also be internal to fix your compiler issue, and same goes for your DbSet, the class is internal, how can you make the fields public? Nobody can reach the class, hence it is less accessible than the DbSet itself.
Edit comments space ran out so here...
Move your Dbmodels inside your Persistence project i.e. the project that only has your DbContext and Entity Configs, now your infrastructure project depends on persistence, which only needs the DbModels and not the DTOs(since DTOs are in Core Project, DbContext don't have access to it either way). Now your consumer e.g. WebApi/WPF don't have DbModels, but only Models(DTOs/ViewModels).
To Sum it up:
Infrastructure depends on Persistence and Core.
Core has all the Models(DTOs/ViewModels), repositories and/or Commands/Queries(in case of mediator pattern), custom exceptions, or even fluent assertion classes.
Infrastructure implements Core repositories, Commands/Queries(in case of mediator pattern), and repositories are designed in a way to only return Models from the core.
Persistence project has the DbContext, EntityConfigurations, and the DBModels(entities).
Nothing depends on Infrastructure(basically the whole point of following this structure lol), Consumer(Web Api/WPF) and Infrastructure depend on Core, and persistence only need DBModels and/or efcore so it depends on nothing, infrastructure depends on Core and Persistence.
Now do some creative coding to register all of this in your DI ;)
Even though access modifiers (internal keyword) and proper packaging already help with dependency governance, specific tools usually give greater flexibility for describing particular rules.
One commonly used tool to analyze .Net code is NDepend.
Another helpful tool to implement dependency governance is NsDepCop.
And of course you can also use Roslyn to develop your own code analyzers and integrate those into your build pipeline. An example analyzer checking for "invalid" assembly references you can find here: http://www.plainionist.net/Dependency-Governance-DotNet/
Related
I am dealing with some architectural design concerns that is needed to be sorted out. My current architecture can be seen below. Each box is a project in visual studio, and they together forms solution.
My Core application is coded in WestCore.AppCore Context, and I have another project group called CSBINS (which includes system web service integrations) CSBINS is an merchant product that is why I found it better to seperate it to another project and only depend it with most commonly used interfaces from WestCore.AppCore.
Right now WestCore.Api does not have any logic in it. All the application logic is handled inside AppCore and AppCore.Csbins
The Problem is I sometimes have need to use WestCore.AppCore.Csbins services inside WestCore.AppCore which causes cross referencing issue.
the best approach right now that I think is to add Endpoint Services into WestCore.Api and move cross platform logic to Endpoint Services.
However I would like to get suggestions and design concerns about going further on this since I am very sure that there would be many design choices.
I am also considering to move common AppCore Interfaces and Classes to WestCore.AppCore.Common so that I wont need to reference whole WestCore.AppCore project to WestCore.AppCore.Csbins.
Why are you using services inside other services - this is probably a bad thing and needs refactoring.
Those CORE projects look like are application services projects, it might help calling them 'WestCore.ApplicationServices', Core implies it belongs at the domain level.
It sounds like you need to impliment an anti corruption layer to integrate with the 3rd party vendor rather than creating a whole new 'domain' context. This should be as straightforward as degining an interface in your domain layer (personally I use the *Gateway suffix to identifiy interfaces that interact with external systems)
Not knowing anything about your domain I would probably start with something that looks like this: (I've assumed the csbins is some sort of payment or accounting gateway)
Also, I would strongly recommend avoiding "Common" and "Shared" libraries at the domain level, you shouldn't need them. Your interfaces and classes are DOMAIN objects and belong in your DOMAIN library. The Application Services should be using domain models directly and having implementation of domain interfaces supplied via Dependency Injection. Hopefully your Domain Models are fleshed out enough that your application service classes are just orchestration wrappers.
So I'm in the middle of rafactoring a small to medium sized Windows Forms application backed by a SQLite database accessed through NHibernate. The current solution contains only an App Project and Lib Project so it is not very well structured and tightly coupled in many places.
I started off with a structure like in this answer but ran into some problems down the road.
DB initialization:
Since the code building the NHibernate SessionFactory is in the DAL and I need to inject an ISession into my repositories, I need to reference the DAL and NHibernate in my Forms project directly to be able to set up the DI with Ninject (which should be done in the App Project / Presentation Layer right?)
Isn't that one of the things I try to avoid with such an architecture?
In an ideal world which projects should reference eachother?
DI in general:
I have a decently hard time figuring out how to do DI properly. I read about using a composition root to only have one place where the Ninject container is directly used but that doesn't really play well with the current way NHibernate Sessions are used.
We have a MainForm which is obviously the applications entry point and keeps one Session during its whole lifetime. In addition the user can open multiple SubForms (mostly but not exclusively) for editing single entities) which currently each have a separate Session with a shorter lifetime. This is accomplished with a static Helper exposing the SessionFactory and opening new Sessions as required.
Is there another way of using DI with Windows Forms besides the composition root pattern?
How can I make use of Ninjects capabilites to do scoped injection to manage my NHibernate Sessions on a per-form basis (if possible at all)?
Terminology:
I got a little confused as to what is a Repository versus a Service. One comment on the posted answer states "it is ok for the repository to contain business-logic, you can just call it a service in this case". It felt a little useless with our repositories only containing basic CRUD operations when we often wanted to push filtering etc. into the database. So we went ahead and extended the repositories with methods like GetByName or more complex GetAssignmentCandidates. It felt appropiate since the implementations are in the Business Layer but they are still called repositories. Also we went with Controllers for classes interacting directly with UI elements but I think that name is more common in the Web world.
Should our Repositories actually be called Services?
Sorry for the wall of text. Any answers would be greatly appreciated!
Regarding 1:
Yes and no. Yes you would prefer the UI Layer not to be dependent on some specifics of x-layers down. But it isn't. The composition root is just residing in the same assembly, logically it's not the same layer.
Regarding 2:
Limit the usage of the container. Factories (for Sessions,..) are sometimes necessary. Using static should be avoided. Some Frameworks however prevent you from using the ideal design. In that case try to approximate as much as possible.
If you can currently do new FooForm() then you can replace this by DI or a DI Factory (p.Ex. ninject.extensions.Factory). If you have absolutely no control on how a type is instanciated then you'll need to use static to access the kernel like a service locator and then "locate" direct dependencies (while indirect dependencies are injected into direct dependencies by the DI container).
Regarding 3: i think this is somewhat controversial and probably often missunderstood. I don't think it's really that important what you call your classes (of course it is, but consistency across your code base is more important than deciding whether to name them all Repository or Service), what's important is how you design their responsibilities and relationships.
As such i myself prefer to extract filters and stuff in the -Query named classes, each providing exactly one method. But others have other preferences... i think there's been enough blog posts etc. on this topic that there's no use in rehashing this here.
Best practice to implement for situation like yours is to use MVP design pattern. Here its the architecture that i can offer to you.
MyApp.Infrastructure // Base Layer - No reference
MyApp.Models // Domain Layer - Reference to Infrastructure
MyApp.Presenter // Acts like controllers in MVC - Reference to Service, Models,
MyApp.Repository.NH // DAL layer - Reference to Models, Infrastructure
MyApp.Services // BLL Layer - Reference to Repository, Models
MyApp.Services.Cache // Cached BLL Layer(Extremely recommended) - Reference to Services, Models
MyApp.UI.Web.WebForms // UI Layer - Reference to all of layers
I will try to do my best to explain with the example of basic implementation of 'Category' model.
-Infrastructure-
EntityBase.cs
BussinesRule.cs
IEntity.cs
IRepository.cs
-Models-
Categories(Folder)
Category.cs // Implements IEntity and derives from EntityBase
ICategoryRepository.cs // Implements IRepository
-Presenter-
Interfaces
IHomeView.cs // Put every property and methods you need.
ICategoryPresenter.cs
Implementations
CategoryPresenter.cs // Implements ICategoryPresenter
CategoryPresenter(IHomeView view, ICategorySevice categorySevice){
}
-Repository-
Repositories(Folder)
GenricRepository.cs // Implements IRepository
CategoryRepository : Implements ICategoryRepository and derives from GenricRepository
-Services-
Interfaces
ICategorySevice.cs
AddCategory(Category model);
Implementations
CategorySevice.cs // Implements ICategorySevice
CategorySevice(ICategoryRepository categoryRepository ){}
AddCategory(Category model){
// Do staff by ICategoryRepository implementation.
}
-Services.Cache-
// It all depents of your choose.. Radis or Web cache..
-UI.Web.WebForms-
Views - Home(Folder) // Implement a structure like in MVC views.
Index.aspx // Implements IHomeView
Page_Init(){
// Get instance of Presenter
var categoryPresenter = CategoryPresenter(this, new CategorySevice);
}
I'm not sure if i got your question correct, but maybe give you an idea:)
I have a project with the following structure:
Project.Domain
Contains all the domain objects
Project.EntityFramework, ref Project.Domain
Contains Entity Framework UnitOfWork
Project.Services, ref Project.Domain and Project.EntityFramework
Contains a list of Service classes that perform some operations on the Domain objects
Project.Web.Mvc, ref to all the projects above
I am trying to enforce some Business rules on top of the Domain objects:
For example, you cannot edit a domain object if it's parent is disabled, or, changing the name of an object, Category for example, needs to update recursively all it's children properties (avoiding / ignoring these rules will result in creating invalid objects)
In order to enforce these rules, i need hide all the public properties setters, making them as internal or private.
In order to do this, i need to move the Project.Services and Project.EntityFramework inside the Project.Domain project.
Is this wrong?
PS: i don't want to over complicate the project by adding IRepositories interfaces which would probably allow me to keep EntityFramework and Domain separate.
PS: i don't want to over complicate the project by adding IRepositories interfaces which would probably allow me to keep EntityFramework and Domain separate.
its really a bad idea, once i had this opinion but honestly if you dont program to abstraction it will become a pain when the project becomes larger. (a real pain)
IRepositories help you spread the job between different team members also. in addition to that you can write many helper extensions for Irepository to encapsulate Different Jobs for example
IReopisotry<File>.Upload()
you must be able to test each layer independently and tying them together will let you only do an integration tests with alot of bugs in lower layers :))
First, I think this question is really opinion based.
According to the Big Book the domain models must be separated from the data access. Your domain has nothing to with the manner of how storing the data. It can be a simple text file or a clustered mssql servers.
This choice must be decided based on the actual project. What is the size of the application?
The other huge question is: how many concurrent user use the db and how complex your business logic will be.
So if it's a complex project or presumably frequently modified or it has educational purposes then you should keep the domain and data access separated. And should define the repository interfaces in the domain model. Use some DI component (personally I like Ninject) and you should not reference the data access component in the services.
And of course you should create the test projects also using some moq tools to test the layers separately.
Yes this is wrong, if you are following Domain Driven Design, you should not compromise your architecture for the sake of doing less work. Your data-access and domain should be kept apart. I would strongly suggest that you implement the Repository pattern as it would allow you more flexibility in the long run.
There are of course to right answer to whats the right design...I would however argue that EF is you data layer abstraction, there is no way youre going to make anything thats more powerful and flexible with repositories.To avoid code repetition you can easily write extension methods (for IQueryable<>) for common tasks.Unit testing of the domain layer is easily handled by substituting you big DB with some in-proc DB (SqlLite / Sql Server Compact).IMHO with the maturity of current ORMs like nHibernate and EF is a huge waste of money and time to implement repositories for something as simple as DB access.
Blog post with a more detailed reply; http://ayende.com/blog/4784/architecting-in-the-pit-of-doom-the-evils-of-the-repository-abstraction-layer
I am building a asp.net mvc application, the projects I have in my solution so far is:
Solution.PROJECT1
PROJECT1.Web
PROJECT1
PROJECT1.Tests
PROJECT1.Data
PROJECT1.Data.Tests
So PROJECT1.Data has all my nhibernate related code: entities, mappings, and repositories.
PROJECT1 will have my service layer, and will reference the nhibernate project.
Web will then only reference the service layer.
My question is, what if I have some objects that I need to put in both PROJECT1.Data and PROJECT1 ?
And example of that is a Logger class I wanted to created.
I want to avoid recursive assembly referencing etc.
Should I create another project with these classes?
Hi your design seems good, i would have a .Core class library project for logging and other common helpers, every project can reference it.
I would also have a separated .Interfaces and .Entities pair of projects, it happens often you want the UI to know an entity only by its interface so ui will not need to reference Entities but your servicelayer does.
I woul put the custom exception classes you could need in interfaces or common or entities. common is probably the best but it is lower than other two so it depends if you need one of those interfaces already.
In addition to what #Davide said:
I would consider extracting Entities to their own project, which will NOT reference Data or nHibernate.
That way you make sure that your domain model isn't dependent on the data representation.
Also I think it's advisable that the UI layer doesn't interact with the domain entities, but with DTOs (or presentation objects).
This wil further reduce the dependency between business logic and UI logic, and will also make it easier for you to send to the client only the things it needs (for example- the User entity may contain fields such as PasswordHash, Salt, LastUpdated. But you only want to display the user's name and last logon date. It's easier if you're using DTOs to create one that contains only what you need, and have your service layer return that.)
I am setting up a project structure for an upcoming internal application trialling the Onion Architecture proposed by Palermo (http://jeffreypalermo.com/blog/the-onion-architecture-part-3/).
I have followed his guidelines, however I need some verification on the structure of the project so far.
Before the diagrams, the questions:
I think the References are all correct (set up as per the diagram where an arrow means 'has a reference to')
but some verification would be good.
What should I put in my dependency resolution layer? Is this where
Helpers go? This has a reference to all other projects?
How do the web services & UI, communicate with the DAL? (Through the core? How?)
What should go where? [Broad question I know...]
The simplified conceptual diagram is as follows (Folders represent namespaces):
I think the References are all correct (set up as per the diagram where an arrow means 'has a reference to') but some verification would be good.
1 It looks OK but I am not sure it's a good idea to insert dependency resolution into the diagram.
What should I put in my dependency resolution layer? Is this where Helpers go? This has a reference to all other projects?
2 I believe dependency injection stuff would be here.
How do the web services & UI, communicate with the DAL? (Through the core? How?)
3 It is core according to Palermo's diagram. In core, you will have repositories talking to DAL and domain models, and services (not web services) dealing with repositories and domain models. And UI/web services will mainly talk to services.
What should go where? [Broad question I know...]
4 Again, I think the answer is in Palermo's diagram. But in my opinion, organizing projects can be different and trivial when there is full understanding of the architecture.
Onion architecture became obvious to me once I understood DDD and necessary design patterns such as MVC, Dependency injection, Repository/Service, ORM.
Yes they are, expect for the Dependency Resolution. These dependencies should be the other way around.
As the name (and the corrected references) implies it's purpose is to host
some kind of IoC Container solution. It is no place for Helper
classes, expect helper classes for resolution purposes.
The Core defines Interfaces for DAL or Domain Services. DAL and
WebServices implements these interfaces. Inside the UI you would use
the DAL or Service implementations through the defined interfaces.
the correct implementation would be resolved through the help of the
Dependency Resolution component (have a look at the concept of
"Inversion Of Control" or "Dependency Injection").
As described in 3. the main thing is, that in Core you put the interfaces that will be implemented inside DAL and Web Services. And in Core you would implement your real business model. this model can make use of the DAL and the Web Services via the defined interfaces (with the help of the Dependency Resolution component).