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.
Related
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 am trying to understand the concept of layered architecture correctly. I think I understand most of the concepts, but there is one or two things that are still unclear to me...
So I understand the purpose of each individual layer: Presentation layer is for UI and user interaction, application layer coordinates application logic and domain objects, domain layer is where all of the business logic goes, infrastructure layer is for persistence and access to external services such as network capabilities etc.
I understand that each layer should only depend on the layers below it, and that layers should be separated with interfaces. What I have a hard time understanding though is the interaction between domain layer and the infrastructure layer...
I am developing a database centric desktop application. My initial approach was to pull all of the information out of the database into an in-memory domain model. The model would then live there for the duration of the application, and then be persisted to the database only once the user saves. I am having my doubts about this approach though... From what I have read, it seems that I should only pull data out of the database when as needed. In other words, pull a information into an object, edit the object, and push the object back into the database once done. What confuses me though, is that the objects become disconnected from their state once they leave the database. So lets say I pull object A out of the database, and edit it. Before I commit it back to the database, another part of the application also pulls object A out of the database. The same two objects are now living in my domain layer, with different references, and with different states. This just seems like a nightmare to me. Am I missing something? Should I only allow one transaction at a time to avoid this issue?
Was my initial approach of pulling all of the data into an in-memory model wrong? My application could have as many as 10 000 records, so I suppose it could lead to memory issues?
A side note: I am not using any ORM at this stage.
Any help or insight would be appreciated!
infrastructure layer is for persistence and access to external services such as network capabilities etc.
Persistence layer is for persistence and infrastructure layer is usually a cross-cutting layer (i.e. it spans vertically across different layers) which may include stuff like logging or what you mentioned.
Your concerns regarding data updates are a classic concurrency problem, not specific to a layered architecture. There are many solutions, a typical one is optimistic concurrency control, which checks that the old values haven't been modified before updating with new values. A similar approach is using an auto-incremental value instead the old values.
I am getting my feet wet with DDD (in .Net) for the first time, as I am re-architecting some core components of a legacy enterprise application.
Something I want to clear up is, how do we implement persistence in a proper DDD architecture?
I realize that the domains themselves are persistence ignorant, and should be designed using the "ubiquitous language" and certainly not forced into the constraints of the DAC of the month or even the physical database.
Am I correct that the Repository Interfaces live within the Domain assembly, but the Respository Implementations exist within the persistence layer? The persistence layer contains a reference to the Domain layer, never vice versa?
Where are my actual repository methods (CRUD) being called from?
Am I correct that the Repository Interfaces live within the Domain
assembly, but the Repository Implementations exist within the
persistence layer? The persistence layer contains a reference to the
Domain layer, never vice versa?
Yes, this is a very good approach.
Where are my actual repository methods (CRUD) being called from?
It might be a good idea to not think in CRUD terms because it is too data-centric and may lead you into Generic Repository Trap. Repository helps to manage middle and the end of life for domain objects. Factories are often responsible for beginning. Keep in mind that when the object is restored from the database it is in its midlife stage from DDD perspective. This is how the code can look like:
// beginning
Customer preferredCustomer = CustomerFactory.CreatePreferred();
customersRepository.Add(preferredCustomer);
// middle life
IList<Customer> valuedCustomers = customersRepository.FindPrefered();
// end life
customersRepository.Archive(customer);
You can call this code directly from you application. It maybe worth downloading and looking at Evan's DDD Sample. Unit of Work pattern is usually employed to deal with transactions and abstracting your ORM of choice.
Check out what Steve Bohlen has to say on the subject. The code for the presentation can be found here.
I was at the presentation and found the information on how to model repositories good.
Am I correct that the Repository Interfaces live within the Domain
assembly, but the Repository Implementations exist within the
persistence layer? The persistence layer contains a reference to the
Domain layer, never vice versa?
I disagree here, let's say a system is comprised of the following layers:
Presentation Layer (win forms, web forms, asp.net MVC, WPF, php, qt, java, , ios, android, etc.)
Business Layer (sometimes called managers or services, logic goes here)
Resource Access Layer (manually or ORM)
Resource/Storage (RDBMS, NoSQL, etc.)
The assumption here is that the higher you are the more volatile the layer is (highest being presentation and lowest being resource/storage). It is because of this that you don't want the resource access layer referencing the business layer, it is the other way around! The business layer references the resource access layer, you call DOWN not UP!
You put the interfaces/contracts in their own assembly instead, they have no purpose in the business layer at all.
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.
Can the domain model and the repositories be in separate dlls?
In a 3 tier architecture I guess I would put the domain model in the business layer
and the repositories in the data access layer.
I get confused as it is my understanding that the domain model uses the repositories while the repositories should return objects from the domain model, which would cause a circular dependency.
I must be misunderstanding one or more of the above concepts.
Any clarification would be greatly appreciated as this has been bothering me for a while, thanks.
I don't think you should let your domain assembly reference anything from your own application at all. It should be the innermost assembly, that is totally ignorant of anything on the outside. It just sits there and knows the domain logic.
Your domain model shouldn't be using the repositories, the application services should.
(If the domain entities actually needs to use a repository, it should be injected from the application services. Some people would argue, that this should not be necessary though - and I think so too).
Try looking at it this way: Your have an application service which is the primary way your client/frontend/controller can use the domain. The application services defines the operations that can be done on your application.
The application service use a repository to load the domain object that it needs to work on, call the necessary method on the domain object and returns the result (if the operations return a such). The domain know nothing about the application service or the repository.
A nice way to get started organizing your application this way, is taking a look at this series of blog posts: http://jeffreypalermo.com/blog/the-onion-architecture-part-1/
And take a look at dependency injection, it can help you solve other problems, where it seems like, you would have a circular reference.
Ask if you have any questions.