In our system we have a database where many tables have with a lot of columns, in some case more that 300 columns. Lets use an example - a car. We have a car table which contains 300 columns. Besides the id of the car, the rest of the columns contain data related to the car fx. the dimensions of right seat.
The question is how to we map this table into a DDD aggregate without loading all columns?
DDD says the repository loads the entire aggregate, but in most cases the customer only wants to see a small part of the aggregate. The car aggregate will also have a lot of methods calculating a variety of things and some cases the data needs to be loaded from other tables.
How do we implement this the DDD way? Domain services?
Are we barking up the wrong tree? Should we be using CQRS instead?
Please disregard the fact; the database is a mess.
It seems that your problem is that you map the aggregate and the view the user wants to see 1:1. Solely because we talk about an aggregate it's not 1:1 the view. (you said it by your own "but in most cases the customer only wants to see a small part of the aggregate").
A benefit of using CQRS (or "only" CQS) is that you can concentrate on the domain, means you can model you commands and views (e.q. query) from the user/customer perspective, disregarding you current database design.
Take a look at effective aggregate Design by Vaughn Vernon, possible it helps.
In simple oop, if you find some behaviour need only a subset of the fields, you may extract them to another Class and delegate the implementation to it.
In your car case, you could do the same refactoring. Then you could use lazy-loading: Load car first and load other local entity of car when needed. I think this is more an infrastructure issue than domain driven design.
And of course, if you find the persistence infrastructure hampers you from modeling. You could use sperate persistence objects. But this requires more resources at the beginning.
On the other hand, if you have a legacy database, I think it's harder to adopt CQRS. This may bring your team too much burden.
CQRS and DDD are not mutually exclusive. The domain should focus on actions/calculations/"real" work. You probably want to use a read/query layer to get to that subset of data the user would like to see.
Try not to query your domain. If you find yourself asking the questions you are asking now it usually means you are, or are considering, querying the domain. That just leads to pain.
So DDD and CQRS can work well together. There are also various levels of CQRS so you will need to get the balance right :)
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 realize this doesn't necessarily apply to MVC exclusively, but bear with me.
Working with entity framework and models, I've read several articles on "best practices" where some people claim using repositories and unit of work is better, others claim it's overkill and using your models directly within your controllers with linq is better, so on and so forth...
Then we have view-models and lazy loading methods, but then with linq we can use joins to add multiple "models" to our data retrieval to fetch whatever we need directly in our controller or helper class.
I realize a lot of this ties back to the "separation of concerns" that is MVC and we can create multiple layers to map our data back whichever way we want, which is great, but let's say for argument sake my app run exclusively on MS SQL, with no chance of ever transitioning to another database type, will adding all the additional layers of separation to map data back give me any real benefit? I'm just trying to understand at which point does one conclude it's better to do it this way over that way? I know some of this might consist of personal preference, but I'm looking for REAL LIFE scenarios where it's easy for me to conclude one way it better than the other AND what questions I should ask myself when deciding how many mapping layers do I need to get my data from my database to my view?
One of the real benefits is when your models or your UI need to change independently of each other. If your view is only tied to a ViewModel instead of your entity, then you can make all of the mapping changes in one place (your controller) instead of needing to go through every view that your entity is being used and making changes there. Also, with ViewModels, you have the benefit of combining multiple data sources into a single object. Basically, you get a lot more flexibility in how to implement your UI if you don't tie it directly to database tables.
In DDD, as far as I understand it, it helps or guides you on how to structure complex application. Now in an application, you should identify your Bounded Context. Say you have more than 10 BCs.
I read somewhere (forgive me I cannot give any links), that its not ideal to have 1-big database for a complex application. That it should be separated for each BC. If that's the easier route to take. How should one structure an app if each BC have their own database.
I tried searching on github but cannot find one.
It depends if they only share the same database or also some tables - i.e. data.
Sharing a database but not tables can be perfectly fine. Except if you aim for scalability and intend to make your BC's independently deployable and runnable units like microservices, in which case they should probably have their own data store instance.
I see a few more drawbacks to database tables shared by 2 or more Bounded Contexts :
Tight coupling. The reason we have distinct BC's is that they represent different domain spaces that are likely to diverge their own way. Changing a concept in one of the BC's might impact the underlying table, forcing the other BC's that use this table to change as well. You get rigidity where there should be suppleness. You might also have inconsistencies or "holes" in the data due to the multiple possible sources of change.
Concurrency. In highly concurrent systems, some entities and the tables underneath are subject to strong contention. Bounded Contexts are one of the ways to lighten the load by separating different types of writes, but that only works if they don't lock the same data at the end of the day. Same is true for reads in non-CQRS systems where they query the same database where writes are done.
ORM friendliness. Most ORMs won't allow you to map to 2 or more classes from the same database table without a lot of convolutions and workarounds.
How should one structure an app if each BC have their own database.
To some extent (e.g. that may include the UI layer or not), just as if you had multiple separate applications. Please be more specific if you have precise questions in mind.
The idea of having this vertical slice per bounded-context is so the relationship of each BC to every other BC and the communication between them should be considered and designed based on the domain knowledge and not on the technical merits of a persistence technology.
If you have a Customer in 2 different BCs it causes a kind-of actor pattern situation. If the Support BC needs to know about the new Customer when it is created in the Sales BC, then the Sales BC needs to connect up to a known interface on the Support BC and pass it this new information. One domain talking to another. It models quite closely how things work in real life when people from different departments talk to each other.
If you share a big database (you're talking bespoke enterprise software here so there won't be many examples in the wild) then the temptation is to bypass all the domain expertise that is captured in the domain layers and meddle in another BC's database. Things become a big ball of mud very quickly.
Surprisingly I see this sort of thing too often in the real world and I consider it very bad practice.
It depends a littlebit on the reason why they are their own database. THe idea of a bounded context is that you have a set of entities that are related together and solve a problem together. if you look at the link Chaim Eliyah provided you can have a sales and a support context.http://martinfowler.com/bliki/BoundedContext.html
Now there is no reason a product for sales,and a product for support should look the same in a database. What is important is that if support wants to add a property (say "Low quality") that it can do so while sales might not want that property. Also downtime on your sales application should probably not affect your support application.
That said entities don't care where they are stored. If you already have a huge product database you can certainly build your entities for different bounded context based on the same database. The thing to remember is that database table is not the same as entity. Entities is what your business/application needs. Database is just what's needed to store things.
That said, separate if you can. If that's not feasable try to define ownerships. You make your life a lot easier if everyone agrees that product is the product as defined by sales and that support can have a "productfactsheetTable" augmenting the product. That way you avoid conflicting changes from each bounded context. (also a followup is that support can only read products but never write). Table prefixes might help here to make this clear.
And this problem already exists with 2 related bounded context. By 10 you'll have a nightmare if multiple context try to write to the same table.
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?