I have an interface of global variables like so:
public interface ClientSettings{
DateTime CurrentClientTime;
string ClientImageFolder;
}
The concrete class is persisted using settings files or a database table.
These values must be accessed by entities and services, both in the domain and the application layer. I have been using DI in my application layer, so access this from there is no problem.
But now that I need to access this interface from the entities I'm not sure of the best way to do so. I don't really want to inject this into my entities. Is the service locator pattern appropriate here? Or do I have another option all together?
In this type of situation I would try to design the entities and the application layer such that the application layer provides all required settings information to the entities when operating upon them. Settings are normally an application concern and should therefore be managed by the application layer. Furthermore, an application level settings container object, such as ClientSettings may contain settings for various parts of the application which may not be applicable for a given entity. This is another argument for relieving the domain entities of the responsibility.
Related
I have a desktop app using Onion Architecture where the user should be able to create and edit local files on disk.
I have the following layers:
Presentation->Application->Domain Infrastructure->
I want to be able to present issues when working with files to the user so the user can take some action like choosing whether to overwrite a file if it already exists. But as I understand DDD the application layer should have no knowledge of the persistence specifics in the Infrastructure layer. My thought was that an exception (e.g. FileExistsException) could be a part of the Interface contract in the Application layer and thrown from the implementation in the Infrastructure layer but then the Application layer would know about the storage type.
Is this perhaps ok since working with files is a part of the Application scope?
My questions is mainly regarding exception handling but I see that there could be other information to be shared as well.
Update:
To expand the question a bit and be more specific the user works with data models that is saved as a JSON file so I have those data models in the domain and the concept of File is only used in the infrastructure layer when actually persisting/changing the file.
If, in the future, I would like to give the user an option to change the storage from local disk to a database where they would get completely different types of exceptions to handle, would the necessary database specific info also be added to the domain?
In other words can implementation details be added to the domain if it is necessary for the user to interact with even though it is not necessarily a part of the actual business?
In my mind the way the user stores information is implementation detail and should stay out of the domain?
Since File is a concept in your Domain the FileExistsException should be inside your domain.
But the actual persistence mechanism should be in your infrastructure layer.
You can achieve that using repository: in the Domain layer you can define a FileRepository which is an interface with some method and in the infrastructure you define the actual implementation for example LocalDriveFileRepository.
Update:
How you persist your data is important only in the infrastructure layer so your application layer cannot handle an exception of type FileExistsException because it should not have knowledge of something outside domain and application layers.
You should remap your infrastructure exception into domain exception.
For example a FileExistsException could be remapped to a UserAlreadyPresentException or some other exception that have some meaning in your domain.
When using MVC5 I add a domain layer and storage layer using dependency injection for all the business data. But I have always left the ApplicationDbContext in the main MVC application layer project.
I've read a great many posts on SO and see many people recommend moving the ApplicationDbContext out of the MVC project. I'd like to understand why ApplicationDbContext should or should not be moved. Are there any reasons to not move this context?
On the one hand, ApplicationDbContext uses a data model which suggests it should be moved to the storage layer but that will require large DTO's. On the other hand, ApplicationDbContext really relates primarily to application access and I have a separate roles/permissions functionality for the business data anyway. Several SO posts also suggested checking roles in the application layer, not the domain layer, but that seems suspect; don't we want to check business roles in the domain layer?
So I'm confused and before I go to the work to move the ApplicationDbContext to a different layer, I'd like to make sure I'm making a sound and informed decision.
It is not a must, but it is advisable if you are doing DDD and your project tends to grow large.
Although DDD is not about implementation details, DDD asks for a clear separation of concerns. Then you should separate domain logic from infrastructure.
You could achieve that separation in many ways. One way would be to have a single project with folders for Domain, Application and Infrastructure, and have your DbContext reside in the Infrastructure folder. This is suitable for small projects.
In large projects, however, I would recommend you to evaluate the Clean Architecture, which will take this separation to project level.
I'd like to understand why ApplicationDbContext should or should not be moved. Are there any reasons to not move this context?
It can be moved, there's no rule against it. But the tooling will then require you to specify both startup and database projects as parameters, like this:
dotnet ef database update --project <path> --startup-project <path>
But since you're using MVC5, you're probably not using EF Core. In case of EF 6 or lower, you'll be using the Package Manager Console (PMC) to manage migrations and database-updates, which will make your life easier in that regard, since you can mark you MVC project as the Startup Project from the context menu, and select the target project from a dropdown control in the PMC.
Several SO posts also suggested checking roles in the application layer, not the domain layer, but that seems suspect; don't we want to check business roles in the domain layer?
Yes, roles are related to permissions, which are business rules. People probably recommend checking that in the application layer because you need to pull this data from the database, but you could do it like this:
Use the Specification Pattern to represent roles and permissions as an specification in the Domain Layer. But the IRepository interfaces would best be defined in Application Layer, as they represent infrastructure (which will be concretely implemented in the Infrastructure Layer). So you would start the role-checking in the Application Layer by using repositories to retrieve data, but the actual permission validation would be done by an Specification in the Domain Layer.
That would be one way to do it.
I have an entity factory which requires access to the file system for construction of the object. I have created a IFileSystem interface, which is being injected into the factory.
Is the the correct way to use an infrastructure service? If so is it recommended to do the same for the entity itself, since important methods on the entity will be required to manipulate the file system also.
It is hard to answer this question without knowing what domain you are working on. It does not seem right though because this would be similar to injecting something like IDatabase. File system and database are persistence technologies and domain logic should be as persistent-agnostic as possible. So you might want to reevaluate this design if your Ubiquitous Language does not include the concept of 'file system'. You can simply restate your intent in a more domain centric terms like ICustomerConstructionInfoProvider. And then inject this interface implementation similarly to how you would inject repositories implementation.
I have a system that talks with the database using repositories. What is the correct definition when it is a remote service? Or better,
Repository is for databases as [...] is for external Web-Services.
I found in many places about ServiceAgents but I don't know if this is the correct definition.
In DDD, Repositories represent a virtual collection of entities (aggregate roots in particular). So, if you have 10M persisted customers, you would work with a repository as if it were a collection of all 10M in memory. Repositories generally only deal with the same types of operations you would find on a collection: Add something, Remove something, Find something in the collection.
If the actual persistence of the data occurs via a Web Service, the implementation of the repository might interact with a Web Service proxy rather than with a database. The fact that the persistence involves a web service doesn't drive how it should be expressed by your domain however. That is to say, whether the data is persisted via direct database calls, an ORM, a Web Service, or a courier pigeon is an implementation detail.
Now, if your domain model has dependencies to be facilitated by external services (e.g. credit card validation, address verification, etc.), this should be expressed as a Domain Service in the form of an interface which defines the required operations in terms of the domain model. To be clear, Domain Services are operations which are logically part of your domain, but don't fit cleanly for some reason or another on a given entity or value object. Behavior facilitated by an external service is just one example of when you might use a Domain Service, so don't think of Domain Services as "the repository pattern for Web Services" or some such thing.
Not sure if this is the official term but I'd refer to this as a "Service Proxy".
I'm just begging to wrap my head around most of the DDD principles but my understanding is that Repositories are generally used to abstract databases but they could be used to wrap anything that behaves as persistent and/or queryable store. So in short I guess what I'm suggesting is that if your service behaves enough like a database then I don't see any problem with using a repository to abstract access to the entities that it deals with.
Otherwise, if the web service doesn't directly deal with data or behavior that is in your domain, then perhaps your case may be a candidate for an infrastructure level service in your application layer.
If anybody has any objections then please comment as I would like to know if I myself am misunderstanding the intended use of repositories.
I have only recently started working with the MVC approach, so I suppose this is an easy one for you gurus here:
Where do I put access control?
In a view? I don't want to have any logic besides switches and flags in my templates, so that sounds like the least viable option
In the model? Should each business object decide what data it will reveal about itself based on who's asking?
In the controller? That's where I have it now but it makes it hard to keep business rules consistent
Or is there another option?
This will depend on what framework you're using as that and the language will dictate a lot of the tools you have available to you.
From a high level, you should have access security configured at points-of-entry. And you should double-check access security at every level that could be considered autonomous or reused from multiple parts of your application (who knows if security was checked by your co-worker's portal that uses your logic layer? etc.). The other thing to worry about is data security, and that belongs as close to your data as possible (so, yes to your #2 above, but understand that it's separate).
This is akin to the difference between application logic and domain logic, which I'm fond of talking about. If there is any logic that is specific to one particular application (web app compared to a windows service, or whatever) then that logic should be defined in that application only. If some logic crosses the boundary between applications (is reusable between applications) then it qualifies as domain logic and should be defined in your model. Your applications can make use of domain logic, but they should not own it.
For Model (aka data) security, the Model would "control" the access and the Controller would "facilitate" the access. This provides for the reuse of the Model independently of the Controller and minimizes if not negates the general code replication necessary across dissimilar Controllers which use the Model.
For example a Car, a Driver, and a Key. (Model, Controller, API respectively). By virtue of a very small interface (key == API), the Model permits or denies Controller access per API (key fob). Different types of access are permitted (Valet key, Owner Key, Owner FOB). Using the Valet key interface, the Controller will not have access to some of the data/function of the Model such as the glove compartment, the trunk and the gas tank. This is essentially role based access implemented by the Model through identifying and categorizing the Controller with a very small API/command surface area.
This means that the Model can be used by other controllers (car with different drivers) which only need the basic authentication to access the data of the model (functions and compartments of the car).