I've created a custom filter for my MVC application, [LogAttribute]. Action methods are decorated with this and it has the responsibility to create a LogEntry object to pass into some type of provider - ILoggerProvider.
My question is, where should ILoggerProvider and it's implementations sit (I'll be wanting to use a DI technology on it)? Should they go in the domain model, the UI project or a separate class?
Unless your software's primary function is Logging or Auditing, it should be an Infrastructure LoggingService.
And unless your logging implementation is tightly-coupled with your Domain Objects (I hope it isn't!), I would suggest a completely separate assembly.
I'd generally contend that ILoggingProvider should sit within the domain model for a few reasons. From a logistics and sanity perspective, your domain classes probably need to reference the logger. From a DDD perspective, given the world of SOX and such we live in, one can argue that logging is a core domain feature for regulatory compliance.
Now, the implementations can definitely sit off in your infrastructure projects, no need to clutter the model with all that.
Since logging has nothing to do with UI, this is definetly the wrong place.
The domain model is there for data representation in my opinion.
So i would do it in a seperate class or even a seperate project.
I have a MVC application where i have a seperate project for a logging service. In my structure it is in the most bottom layer (data access) since it directly logs to files and all other services are using it. I also use DI on it with use of the MEF framework.
This has been working fine for me for a while and i didn't want to change it since then.
I had other solutions which i skipped after a while because they were not as elegant to use as my current solution.
Hope that helps you with your decision.
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.
I have recently done some analysis of ASP.Net Boilerplate (https://aspnetboilerplate.com). I have noticed that the domain layer (MyProject.Core) has folders for the following (these are created by default):
Authorization
Confirguration
Editions
Features
Identity
Localization
MultiTenancy
etc
Why would you put all of this in the Domain Layer of an application? From what I can see; I believe most of this code should be found in the Application Layer (which could also be the service layer).
Good question, if you just look at the folder names. But I suppose you haven't investigated the source code in the folders much.
First of all, I don't say it's the best solution architecture. We are constantly improving it and we may have faults. Notice that our approach is a mix of best practices & pragmatic approach. I will try to explain it briefly.
You are talking about this project: https://github.com/aspnetboilerplate/module-zero-core-template/tree/master/aspnet-core/src/AbpCompanyName.AbpProjectName.Core So, let's investigate the folders:
Localization
It does not include any localization logic (it's done in framework level, in ABP. Thus, it's in infrastructure layer). It just defines localization texts.
While normally it can be easily moved to web layer (no direct dependency in Core project), we put it in the Core layer since we think it may be needed in another application too. Think that you have a Windows Service has only Reference to the .Core project and want to use localization texts, say to send email to a user in his own language. Notice that Windows Service should not have a reference to Web layer normally. So, we have a pragmatic approach here. We could add localization to another dll project, but that would make the solution more complicated.
Authorization
Mainly includes User, Role.. entities and UserManager and RoleManager domain classes. Similar to localization, it does not include actual authorization logic. It also includes some other classes but they do not make much. We thought putting these here would help us if we have more application layers. As you know every application can have it's own application layer as a best practice.
Confirguration
AppConfigurations is here to share 'configuration reading' code between different apps (Migrator and Web app). Again, this could be inside another "Shared Utils" library. But we wanted to keep solution structure balanced, so it reflects major layer and structures yet is not so complicated for intermediate level developers.
Editions
Just includes EditionManager class which is a domain service for Edition management.
Features
Just includes FeatureValueStore which is a repository-like adapter class. See it's code, it's already empty.
MultiTenancy
Includes Tenant entity and TenantManager class which are already parts of domain layer. Again, nothing here includes infrastructure-related multi-tenancy features (like data filtering or determining current tenant).
... and so on...
So, do not just see names and have idea, please check the project deeper. Some code can be moved to upper layers or an utils library, but I think general structure is good to start a DDD architected application.
What you see it is called Module Zero, it aims to implements all fundamental concepts of ASP.NET Boilerplate framework such as tenant management (multi-tenancy), role management, user management, session, authorization (permission management), setting management, language management, audit logging and so on.
Module-Zero defines entities and implements domain logic (domain layer) because it is part of the configuration context of your system.
I will try to explain in as much detail as possible. There may be similar questions here on SO and I've gone through all of those but none of those have what I needed.
So, I'm starting out with a large scale C# MVC5 based Web Project and I want to organize everything in as much decoupled way as possible. For the database part I'm going to use Data Access ORM from Telerik (Previously known as Open Access) because I will be using MySQL for my project.
So far I have organized everything as below. I have defined solution level folders to divide the projects because I think there may be a possibility to have more projects in one layer in future.
**Solution**: td
- Business (Folder)
-- td.core (Project) (Contains Services and ViewModels)
-- td.interfaces (Project)
- Data (Folder)
-- td.data (Project) (Contains Database Models i.e. Telerik, Repository, Context Factory and Unit of Work class)
- Presentation (Folder)
-- td.ui (Project) (MVC5 Project, also Implemented IoC here)
- Shared (Folder)
-- td.common (Project)
Generally, when you bind models in your MVC project, if you have just one project in your solution, it works pretty easily without an issue.
i.e. in a MVC Controller
var obj = new TempClass();
return View(obj.getAllUsers());
and then in the corresponding view you use this at the top
#model (model type here)
When I separate all these layers in their own projects as mentioned above. The data layer would be the one directly communicating with the database hence I will generate the Telerik Data Access rlinq schema in my Data node where it will also generate the classes for the tables in my database (Default config)
Now, from the setup above, from the controller I'm supposed to call the Business layer to fetch the data and which will communicate with the Data node.
The question is that in the controller and in the view I will need the data types / references of the model I'm binding to. So, should I keep my automatically generated classes still in the Data node or can I move ONLY the generated classes to the Shared Node and then use those for the binding in the Controller/View? Which one is going to be a good practice? as I don't want to reference the Data nodes directly in the controller otherwise there is no point in separating everything like above.
Another quick question. I would be integrating so many third party APIs via REST/SOAP. In which layer should these best fit?
If anyone has any other Architectural suggestion or something that I'm missing here, please do suggest.
Thanks in advance everyone.
UPDATE!!!
Please see my updated architecture above.
Here's what I did so far.
I have added Repositories, Services and IoC.
In my Global.asax, I'm initializing the IoC which configures the Services etc for me.
My controller has an overloaded constructor now having the service from the business layer as the parameter.
Controller calls the service to get the data and the service calls the repository for it.
I have followed the generic repository path instead of creating repositories manually for each type
For 3rd party APIs, I will use the data layer and business later won't know where the data came from. It just needs to ask what it needs.
All this was made easier with the help of a dedicated Interfaces project which is being referenced from both the Business and Data layers when needed. Because as both want to implement abc interface I cannot declare it in either Business or Data layer since there would be circular referencing then which prevents me to reference both (Business/Data) projects to each other.
So, with the help of above changes, I can easily do what I want now and Everything is working perfectly as I want. Now the last question I have is
Is there any flaw in this architecture?
For a domain-centric architecture where it's easy to add another type of UI or change persistence technology and where business classes are easily testable in isolation, here's what I'd do :
Business layer with no dependencies. Defines business types and operations.
Data layer with data access objects/repositories that map from database to business types. You can also put your third party API accessors and adapters here. Depends on Business layer where repository interfaces are declared.
No Shared layer. Business types are the basic "currency" that flows through your system.
UI layer depending on the data access interfaces declared in the Business, but not on the Data layer. To decouple UI further, you can introduce an additional UI-agnostic Application layer.
You can read more about this at Onion Architecture or Hexagonal Architecture.
As it is, your architecture is pretty much data-driven (or Telerik Data driven) since the business and UI layers are tightly coupled to the Telerik schema. There's nothing wrong with that, but as I said in my comment, it enables other things such as quick development from an existing database schema, over full domain decoupling, framework agnosticism and testability.
Whether your Telerik generated model lives in the Data or Shared module makes little difference in that scenario IMO. It is still the reference model throughout your application and your controllers will be coupled to it anyway. The only thing I would advise against is moving the generated files manually - if it can be automated all the way, definitely do it or don't move the files at all.
I'm nether an expert for your special technologies, nor would I regard this as the ultimate answer, but I give you some hint's of the possibilities you may have (depending on your technologies):
Business should have exclusive access to data
Currently I don't really get, why your controller and view need access to any data-base related stuff at all? Shouldn't your business layer handle all of that and hide it from controller and view? But let's assume it's necessary for some reason.
Ways to split the data layer
You shouldn't move generated classes manually. You could change your generation-settings, to generate them elsewhere partially. But manually cherry-picking and moving them, results in an architecture which is hard to maintain.
The cleaner solution would be, if you can change the visibility of your classes. Can you generate classes with project or folder visibility instead? Or can you only export defined packages or classes in the project settings?
A workaround which requires more maintenance is the local extension. You could create new classes in your shared folder, which derive from the data layer classes.
Stucturing external APIs
Give them one or more own projects, so they are easier to change later. I know approaches where you have one main folder for each API. This makes each of them easy to change, but clutters your workspace. The important project will only be 4 out of 1000 projects. I normally prefer one folder containing all APIs. Thus the APIs are slightly harder to change, but your workspace stays clean. Your decision depends on two facts: how often do you change, add, remove or just study the APIs. And does your IDE provide a way to "hide" folders/projects from your workspace.
Hope this helps a little :)
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'm using the Unity IoC framework and have a Bootstrapper.cs class in my host MVC layer to register all components. However in my architecture I have a 'services' layer below the MVC layer, that too uses DI and there are repository interfaces injected into it (repository interfaces are not used in the MVC layer - it has the services layer Interface injected into its Controllers).
So my question is the following: can I still register the repository interface to it's concrete type in the MVC/UI layer for the entire app, or do I add another reference to Unity and create another Bootstrapper.cs class in my 'services' layer to define Interface types for that that specific layer uses?
Even if the answer is I can register the Interface in the UI layer, I'd still like to know the common practice too. The thing I don't like about registering that type in the MVC/UI layer is I would have to add a reference to the Repository layer just to make the registration, even know it is not used in that layer. It's used in the services layer.
Thanks!
Each application should have its own Composition Root, the place where you configure the application (see this answer for details).
It depends on the context, but generally speaking, if you split your container configuration among the layers you are going to make decisions about the configuration of your layers too close to the layers and you'are likely to lose the general view.
For example, in one of your business logic layers you'are registering a service:
container.RegisterType<ISercice1, MyImplementation1>(new PerThreadLifetime())
But when using that layer in a web application you could decide that a PerSession or PerRequest lifetime would be better lifetimes. This decisions should be in only one place and not spread through the layers.
I turn your question on its head.
If you add a reference to Unity in your class libraries, you would have added dependencies to the framework you are using. That is quite the opposite of what you are trying to achieve.
The only adaptation your classes should need is to support constructors or using public properties - on interfaces. That's it!
So your application entry point should do all the 'bootstrapping'.
Note that a entry point could be different applications, as well as different test projects. They could have different configurations and mocking scenarios.
If your bootstrap.cs gets large, you could split it up into smaller parts for readability reasons. But I reject the idea of classes having any knowledge about the fact that they are being bootstrapped/moqed/injected and by what.
Consider re-use. Your current libraries is using Unity. They may be used in a project using StructureMap. Or why not Ninject.
In short, yes it is possible to keep the configuration at the top of the process or localized to each module. However, all dependencies must be resolved for the entire object graph in the process.
Localizing the configuration by keeping it in each module (assembly) is often a good idea because you are allowing your service layer to take responsibility for its own configuration. My answer to this question, IMHO, is a good practice.
Yes, application should have one composition root at entry point. But it can be a good practice to keep registrations of a classes inside a layer where they are implemented. Then pull these registrations from layers at composition root, registering implementations layer by layer. This is why:
Registration within layer can be redefined in other place, for
example at entry point. Most of IoC libraries work in such a way
that registration done later erases the registration done earlier.
So registration within layer defines just a default behavior which
can be easily overridden.
You don't need to reference IoC library in all your projects\layers, even if you have registrations defined inside these
layers. A very simple set of wrapper classes will allow you to
abstract away from IoC specifics anywhere except your entry point.
When your application has several entry points, reusable registration will greatly help to prevent repeating the same
registration. This copy\paste is always bad. And applications have
several entry points quite often. For example, consider the scenario
of cross-platform application having a separate entry point for
every platform it targets. Or business logic reused in web site and
in background process.
With reusable registration, you can build a very effective testing system. You will be able to run a whole layer from tests,
mock whole layers in automated way, and do it very effectively,
minimizing efforts on writing tests.
See my blog article illustrating these points in more detail, with a working sample.