I am studying Onion Architectures and I have a point.
Onion Architectures aim at isolating the Domain from technological artifacts. Therefore, the guideline is to let the Data Access Layer (DAL) reference the Domain Layer (BL). This way, I should be able to transform entities into storage artifacts. Referencing the BL should probably give me a "snapshot" of my Domain, but without a change-tracking system I will loose all chronological events to know whether inserting, updating, or deleting items in the data-store, to be able to correctly rehydrate the model afterwards.
Do Onion Architectures always need some change-tracking systems, or even something like an event-store ? Am I missing any other pattern ?
Does the domain layer know when it needs persisting?
For example i might have a new/update customer screen that saves a new customer when i press finish. At that point i don't care about change tracking, i want to just store everything that i have. and my DAL can figure out if i already have a customer with the same name in the database or not (if it should emit insert or update queries).
Same thing applies to to an event store. And event store if an technical implementation if your domain cares about events, being able to undo event, etc etc,
What might happen is that your Domain Layer always consist of a complete in memory up live mutating system. In that case there isn't even a snapshot.
The onion architecture just describes to separation of artifacts. Which artifacts they are will really depend on particular requirements.
The Application layer is supposed be in charge of that. An Application Service implements a use case by orchestrating calls to the domain. Domain entities created or modified as part of the use case must be held in memory in one form or another for later persistence.
The typical way to do it is to place them into a Unit of Work (whose implementation resides in the Infrastructure Layer). It tracks the modifications made to domain entities. When the Application Service ends the business transaction, the Unit of Work will translate the entities state into something flushable to a persistent store.
Related
Im new in DDD and I would like yours advise.
In my UI I need to view data from 2 aggregates.Im using EF Core and as I have read its better to keep only one navigation between entities so not to mix two aggregates and avoids serialization issues due to circular references.
How should I make the query?
Do I need to create a new view whenever I need data from 2 aggregates?
If needs to create views in which layer this view can exist? In infrastructure persistance layer or domain?
Thank you
How should I make the query?
With the simplest and fastest technology you can use. I mean: if building the query with EF Core requires several steps and a lot of extra objects, change approach and try with a direct SQL request. It's query, something you can test fast and you can change equally fast, whenever you need to do.
Do I need to create a new view whenever I need data from 2 aggregates?
You don't. With a view you hide away (in the view) the complexity oft the data read (at the code to change the DB every time the data to show should change), with the illusion/feeling that you manage an entity. Or course it should be clear that the data comes from a view. A query, on the other side, is more code related (to change the data shown you just change the query), but you also show "directly" that that data come from several sources.
Note: I've used EF Core years ago, and for a a really simple project. If with view you mean instead a view of the EF Core, than I would say yes. But only if building it doesn't require several steps/joins to gather the information. I would always think about a direct approach, when it looks that the code starts to be a bit too complex to show some data.
Here, anyway, the things can go really deep: do you have all your entities (root) in the same project? Or you have several microservices? With microservices, how do you share the data and how do you store it? Maybe a query is not viable, or it reads partially old data. As you can see, there're several thing to take into account when you have to read the data.
If needs to create views in which layer this view can exist? In infrastructure persistance layer or domain?
As stated before, if you mean a view within the EF Core, I would put really close to the layer where you're going to use it. But, it could depend. You could have a look here.
Personally I use 3 layers: domain, application and infrastructure. My views are in the application layer, because I have several queries that I reuse for different purposes. But before going into the infrastructure (where the requests are) I transform the results into the format required for UI.
DDD is about putting together all the business logic that otherwise is spread around several entities, services and even controllers. With this solution, all the actions that the domain offers could be performed without requiring extra logic outside the domain itself. Of course you need to implement the services that the domain is going to use, this is obvious.
On the other side is clear, at least for me, that the reuse is limited to the domain itself. I mean:
I can build a big query, that collects a lot of information from different sources, and reuse it for several UI views, but I've to be ready to pay the price of something that I have to touch every time something in the UI changes (anyway I need to transform this into a view related object);
I can build small, specialized queries that I use for 1, 2 (if they are the same) UI views, paying the price of more code (but simple and specialized, and really fast to test!) to maintain (here the query can produce close to/equal to view related object).
The second approach is the basic of CQRS, and I prefer that one. Remember, you can do CQRS even without event store and eventually consistency: you just take part of it, not the whole. We design to simplify our lives, not to make them harder.
I have been pondering this problem for a while now and cannot think of an acceptable solution. I have an application that is planned to become very large. Because of this I am trying to make it modular. It is based on MVC4. I have not decided on using a ORM or mapping everything myself. I would like to have the following structure:
----------------------
| Database
----------------------
| Data/Data Access Layer (Class Library) (Objects reside here)
----------------------
| Core MVC Project (User and Session are stored here)
----------------------
| MVC Modules
I want to keep the validation of the UpdatedBy field as close to the database as possible, possibly in the Data/Data Access layer. The problem is I want to store the user in the Session and do the validation in the class library (where there is no Session). I also want to avoid as much as possible passing the user all over the place. Is there a way to store the user in the Session and have the Data Access layer access that info without being passed the user? Anybody have any recommendations on how to do this elegantly?
EDIT: I want to keep validation, and CRUD activities as close to the Data layer as possible where the Core MVC project just calls Save() on an object and the Data layer validates the object, figures out what user modified or created it and saves it to the DB.
EDIT 2: It is imperative that the Data layer have absolutely no dependencies in the MVC layer.
The LastUpdated can easily be implemented with a Trigger on DB Insert/Updates, but the UpdatedBy is a bit trickier.
A key question is "does your business layer require knowledge of who is using it?" If so, then the interfaces can be designed to require that a Username is provided when making actions. If not then you need to make the data accessible from within/behind the business layer, but without being explicitly provided to it (such as with Dependency Injection, or by providing a Context that is availalble throughout).
You could consider creating a seperate audit-trail using ActionFilters around your controller actions, which provides easy access to the Session, and can create a running history of actions your users take. This may or may not correctly 100% to your database records, but does provide a clear history of the actions of the application--which is valuable in its own right.
You could also consider using a Command pattern, whereby the application generates specific commands (e.g. an UpdateWidgetName command) that are enacted on the business/data layer. In some regards this is how MVC already works, but having an explicit Command which captures the user and date is still a useful addition to your business layer.
Also be aware of the shortcomings of keeping this on the record itself. You'll only know who last edited the record--you won't be able to tell specifically what they edited, or who edited it previously. For relatively simple scenarios this is usually sufficient, but it is far from providing actual historical data for the record.
If you really want 100% auditing you should look at the Event Sourcing design pattern, where effectively if an action isn't audited then it didn't happen. It's a very different paradigm from the typical CRUD approach, but is very powerful (albeit more complicated to design initially)
One other note: consider seperating your business and persistence code into two layers. Tying them together makes the business logic tightly coupled to persistence (bad), which will prevent it from being reused. Look into implementing a Repository which is dedicated to persisting and retrieving your business objects. It pays off.
If you use a structure like this in your application, you can define some core interfaces that can be used throughout your application (like ICurrentUserProvider), and then you can implement those interfaces in the parts of your application where they are best implemented, without creating a tight coupling or dependency to that specific part of the application.
When your web project is initialized, it can initialize your DI framework so that your controllers get their dependencies injected into them. That way your controller gets the Business Layer services it needs, and those Business Layer services have the data-layer implementations they need (without actually having a direct dependency on them), and the data access object gets the service that can tell it who the current user is (without depending directly on the MVC layer).
I'm working on a project which has basically three layers: Presentation, business and data.
Each layer is on a different project and all layers use DTO's defined in another project.
business layer and data layer return DTO's or Lists of DTOs when querying the database.
So far so good, but now we have to query views and those views of course do not match an existant DTO. What we have done until now is just create a special DTO, business- and data-layer classes so they were treated like normal entities (minus insert, update etc.)
But it does not seem correct. Why should the be treated like normal entities when they are clearly not. Well the DTO seems necessary, but creating "business logic" and a datalayer-class for every view seems rather akward. So I thought I create one generic business- and datalayer class which holds the logic/code for all views (I still would have to create a DTO for every different view, perhaps I could use anonymous types)
What do you think about me idea or how would you solve this issue?
EDIT: 9. August 2011
Sorry, the post may have been unclear.
By views I meant Views from a sql-server.
I feel your pain completely. The fact is that in almost every non trivial project with decent complexity you will get to the point where the things you have to show to the users on UI overlap, aggregate or are simply a subset of data of business entities. The way I tend to approach this is to accept this fact and go even further - separate the query side from the business logic side both logically and physically. The fact is that you need your entities only for actual business operations and keeping the business constraints valid, and when does this happen? Only when someone changes the data. So there is no need to even build entities when you display the data.
The way I like to structure the solutions is:
User opens the view -> Query is performed only to get the specific
data for the view -> Returned data is the model (although you could
call it a DTO as well, in this case it's the same thing)
User changes something -> Controller (or service) builds the full entity from repo,
business logic action is performed on the entity -> changes are
persisted -> result is returned
What I want to say is, it is ok to treat your read side separately from write side. It is ok to have different infrastructure for this as well. When you start to treat it differently, you will see the benefits - for example you can tailor you queries to what you need on UI.
You can even get to the point where your infrastructure will allow to build your queries with different techniques, for example using LINQ or plain SQL queries - what is best for certain scenarios.
I would advise against using DTOs between layers. I'm not convinced that there's any benefit, but I'll be happy to take instruction if you think you have some.
The harm comes in maintaining multiple parallel hierarchies that express the same idea (business objects plus multiple DTOs between layers). It means lots more code to maintain and greater possibility of errors.
Here's how I'd layer applications:
view <--- controller <--- service <--- + <--- model
+ <--- persistence
This design decouples views from services; you can reuse services with different views. The service methods implement use cases, validate inputs according to business rules, own units of work and transactions, and collaborate with model and persistence objects to fulfill requests.
Controller and view are tightly coupled; change the view, change the controller. The view does nothing other than render data provided by the controller. The controller is responsible for validation, binding, choosing the appropriate services, making response data available, and routing to the next view.
Cross cutting concerns such as logging, transactions, security, etc. are applied at the appropriate layer (usually the services).
Services and persistence should be interface-based.
I've dropped most layered architectures like this as they are a pain to manage all the transformations and are over-complicated. It's typical astronaut architecture. I've been using the following:
View models for forms/views in ASP.Net MVC. This is an important decoupling step. The UI will evolve separately to the model typically.
No service layer, instead replacing it with "command handlers" (mutating operations) and "finders" (query operations) which represent small operations and queries respectively (CQS - Command Query Separation).
Model persistence with NHibernate and ALL domain logic inside the model.
Any external services talk to the finders and command handlers as well
This leads to a very flat manageable architecture with low coupling and all these problems go away.
First off, I am using web forms without any ORM framework.
I have been struggling with how to make my domain objects as "smart" and "rich" as they can be without allowing them access to my service and repository layer. My most recent attempt was in creating a model for gift certificates for a online store.
The main recurring issues that I am seeing is that:
More and more logic keeps being introduced in the service layer. All the calls to the repository must pass through the service layer and each time the parameters are validated (eg - exists in db, etc). As a result my service layer is growing, but my domain objects just have some simple contractual validations. Even object validation is in the service layer since if the ID of the item is null, it will check the db to ensure that the code is unique. IHMO, the consumer of the system should not care if the functionality they need deals with persistence or not.
I have a separate POCO for transaction log entries for when a gift certificate is redeemed. I assume that I should put a list or collection of these transactions as a property of my Gift Certificate model, but I am still unsure of when that property should be filled. Do I add a separate method on the service for loading the transactions into a object on demand (eg - LoadTransactions(gc object)) or should the transactions be automatically loaded any time a existing gift certificate or list of gift certificates are requested (or maybe a option in the getGCs to load transactions as well)
What about computed fields like "Available Balance"... should I even have properties like this on my object? Anytime I am working with the object, I will need to keep updating that property to insure it is up to date. Right now I simply have a service method GetBalanceByCode(gc code).
Even actions like redeeming a gift certificate are basically 100% data-centric (take some input parameters, validate them and add a transaction log entry to db).
More and more logic keeps being
introduced in the service layer (...)
Even object validation is in the
service layer (...)
Validation is not the best candidate as domain model element. Input (my personal preference is that it's represented as commands) should be validated at application service level. Domain logic should model how business work and assume that all the arguments are valid. Good candidates for domain logic are computations for example: you want to have them in one single place and have them well tested.
I have a separate POCO for transaction
log entries for when a gift
certificate is redeemed.
This kind of object is known as Event. You can learn about Events from Eric Evans 'What I learnt since the Blue Book' presentation. Event is basically an entity which is immutable. Events are quite often aggregates on their own because usually there's lots of them. By making them aggregates, you don't have any problems with lazy loading them as part of other objects's collection.
What about computed fields like
"Available Balance"... should I even
have properties like this on my
object?
Computed properties are kind of logic that naturally fits in domain model, however it's debatable if a better approach is to compute the value each time or compute it when object changes and persist it in the DB.
Even actions like redeeming a gift
certificate are basically 100%
data-centric (take some input
parameters, validate them and add a
transaction log entry to db).
This action would be modeled as creating a CertificateRedeemed event. This event would be probably created by Certificate aggregate or some other object. This blog post by Udi Dahan can be helpful
This is not an entirely easy question to answer given the fact that domain models are very subjective, and rely a lot on your...well, domain. It sounds like you are actually creating something similar to The Onion Architecture (and Part 2) described by Jeffery Palermo. This is not a bad pattern to use, though DDD purists will tell you it leads to "anemic" domain models (where your domain objects are basically Data holders with no behavior). The thing is, that may be exactly what you need in your scenario. A "full, rich" domain model may be overkill for what you are doing (and given your last bullet point it sounds like that could be the case).
You may not need a domain model for your system at all. You could be well served with some View Models (that is simple data models to describe your view) and have your UI send some DTOs to through your services to put the data in the database. If you find something that requires a more complex approach, then you can apply a richer domain model to that component. Also remember that you don't necessarily have one domain model in your system. There can, and in many cases should, be different models that describe things differently (often grouped into Bounded Contexts). The overall goal of DDD is to simplify otherwise complex systems. If its causing you additional complexity, then you may be taking the long way round.
There is an approach called DCI (data-context-interactions) which is supposed to be alternative to the old school OOP. Although it does not address explicitly the issue of persistence ignorance, your question brought it to my mind, because it deals with similar issues.
In DCI domain objects are small data-holders with only a little logic, like in your case, and interactions between them are implemented separately. The algorithm of interaction is not spread through small methods of several objects, but it is in one place, which might make it more lucid and understandable.
I think it is still rather academic thing than a solution we should start implementing tomorrow, but someone who comes across this question might be interested.
The past few days I have done a lot of research using the DAL/BLL/UI approach without a very clear understanding of how it will apply to my project. In the past, I have left out the BLL connecting my UI directly to the Data Access Layer (LINQtoSQL dbml). But, I do not think this is a good idea where I work now(or maybe even in the past) because we have a lot of different applications and I'd like to use the same DAL/BLL as they are built.
My question is, how does the BLL help me when, in most of my applications, all I really do is use the LinqtoSqlDataSource/GridView to connect to my datacontext to take care of all the updating/edit, etc. Also, each new web application will, at some level, require unique changes to the DAL/BLL to get the require data, possibly affecting other apps using the same DAL/BLL. Is this reuse of the DAL/BLL the right way of doing this or am I missing something?
I think the BLL comes in when I need to build, for example, a security classes for the various web applications that will be built. But, when I use the Linqtosqldatasource, why would I bother to connect it to the BLL?
DAL
LinqToSQL dbml DataContext.
Does using LinqToSQL change how I should use this design?
BLL
Security for various website used by company.
Query DAL return what(?) when using LinqToSQLDatSource., functions that handle various results sets(I am really unsure how this should work with BLL, sorry if the question is unclear)
UI
Reference only the BLL?
The DAL and BLL are separated by one often subtle, but key difference; business logic. Sounds moronically simple, but let me explain further because the distinctions can be VERY fine and yet impact architecture in huge ways.
Using Linq2SQL, the framework generates very simple objects that will each represent one record in one table. These objects are DTOs; they are lightwight, POCO (Plain Ol' CLR Object) classes that have only fields. The Linq2SQL framework knows how to instantiate and hydrate these objects from DB data, and similarly it can digest the data contained in one into SQLDML that creates or updates the DB record. However, few or none of the rules governing the relationship between fields of various objects are known at this level.
Your actual domain model should be smarter than this; at least smart enough to know that a property on an Order object named SubTotal should be equal to the sum of all ExtendedCosts of all OrderLines, and similarly, ExtendedCost should be the product of the UnitPrice and the Quantity. In many modern programs, your domain forms part of your BLL, at least to this extent. The objects created by Linq2SQL probably shouldn't have to know all this, especially if you aren't persisting SubTotal or ExtendedCost. If you rely on the Linq2SQL DTOs, you've basically tied yourself to what's called an Anemic Domain Model, which is a known anti-pattern. If the domain object can't keep itself internally consistent at least, then any object that works with the domain object must be trusted to keep it that way, requiring all those objects to know rules they shouldn't have to.
The UI should know about the domain, or if you prefer it should know some abstracted way to get the data from the domain for read-write purposes (generally encapsulated in objects called Controllers, which work with the domain layer and/or Linq2SQL). The UI should NOT have to know about the DB in any program of moderate size or larger; either the domain objects can hydrate themselves with a reference to objects in the DAL, or they are produced by custom objects in the DAL that you create to do the hydration, which are then given to the controller. The connected ADO model and interop with GridViews is admirable, but it doesn't allow for abstraction. Say you wanted to insert a web service layer in between the domain and UI, to allow the UI to be located on a mobile app that worked with data in your warehouse. You'd have to rebuild your UI, because you can no longer get objects from Linq2SQL directly; you get them from the web services. If you had a Controller layer that talked to Linq2SQL, you could replace that layer with controllers that talked to the web services. It sounds like a minor difference; you always have to change something. But, now you're using EXACTLY the same UI on the mobile and desktop apps, so changes at THAT layer don't have to be made twice just because the two layers get data different ways.
This is a great question that I have been mulling over with our catalog app for a year now. A specific instance for me might help you with the pattern.
I have a page to display the contents of a shopping cart. In the 'early days' this page had a grid populated by the results of a SQL stored procedure that, given the order number, listed the items in the cart.
Now I have a 'cart' BLL object which contains a collection of 'row' objects. The grid is the same, but the data source is the cart's rows.
Why did I do this? Initially, not becuase of any fancy design patterns. I had so many special cases to handle based on fields in each row AND I had other places I needed to show the same cart-content data, it just made more sense to build the objects. Now a cart loads from a repository and my pages have no idea what that repository does. Heck, for testing, it's hard-coded cart data.
The cart then uses a repository to load up the rows. Each row has logic to maniuplate itself, not knowing where the data came from.
Hopefully that helps?