I'm looking at adding functionality to a DDD project but I'm unsure of the best way to fit it in.
The needed functionality is tagging and user groups manipulation.
As many things will be taggable (users, journals, documents etc) it seems anti-DRY to recreate that functionality in each AR. Would it be sensible to have a Tag Repository which maintains a central tag table, then have various many-to-many tables for the different tagging types needed (i.e. associating tags to userId, journalId etc) or perhaps even a single many-to-many table which records the relationship type. If so, would the domain object have to be modified to hold the link to the tags?
The group functionality is similar. There is a need to allow users to create user groups, and then assign groups to non-public entities (journals, documents etc) to give them view access.
What would be the best way to add this new functionality to the project?
Design separate bounded contexts for tagging and the group functionality.
The DRY principle is stated as "Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.".
By separating, you promote the unambiguous and authoritative representations of the knowledge DRY is all about.
Related
Environment: ASP.NET MVC application with EF (Database-first with control over the db design) and Sql Server.
I have a lot of entities that have user-generated properties. I need a way for the user to be able to specify the order of these elements.
Slightly more detail: The user can create a "template" that they can then add "properties" to. These "properties" need to be ordered. There is also >= 4 other different entity types that also require user-specified ordering.
I have no problem with the front-end aspect of this, but I want to know what is the best way to persist the element order in sql server.
The obvious solution to me is to give each entity a column "Order" (or another non-keyword name) and, upon a reordering (eg. moving element #4 to #2) update all affected entities.
Is this the best way to solve this problem?
This doesn't sound like a small project and you might have various other dynamic customizations on top of the SortOrder property.
Adding an SortOrder column to your entity table is certainly not a bad approach, but this approach might clog up your data with information that doesn't necessarily belong to that entity (especially if multiple users can customize the same instances).
So I've got an alternative idea for you:
Add a CustomizationNode table (or something similar) to your database
Here you store SortOrder and potentially other kinds of metadata and user customizations which are not necessarily part of the conceptual entity.
Then, should you need to add/change/remove any customization info, you'll only need to do so in one table rather than several. And you don't need to migrate your entities whenever you change the customization capabilities.
Depending on your situation, you can link them in one of several ways:
1. Add a single column CustomizationNodeId to each entity table
This pertains to having a single customization per entity instance and is the simplest solution.
Also one customization could be shared across multiple entities of the same type (or even different types, though that probably doesn't make much sense)
2. Add multiple columns EntityXId, EntityYId to the CustomizationNode table.
In principle, only one of these ID fields would be filled and the others will be empty. Can seem a bit "off", but is not necessarily a wrong way to do it.
While you lose the ability to share a customization across multiple entities of the same type, you gain the ability to have multiple customizations per entity and additional FK's such as the UserID. This would allow you to have a per-user customization.
3. Add a link table between each EntityX and CustomizationNode
This is the most complex but also the most versatile solution. It embodies adding a table with a FK to each table you wish to link.
One important benefit you gain is additional decoupling. Customizations and entities don't know of eachother's existence and change without impacting one another.
Furthermore you can add additional metadata to those link tables, such that you can have things like versioning on top of everything mentioned above in 1 and 2.
The bottom line is, if your application is highly dynamic and customizeable then you might want to store "metadata" separately from your actual "data".
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.
I am building an MVC (Microsoft) application that uses repository to access data.
I have a requirement where based on user role, you may or may not have access to certain pieces of data, or certain rows within a data table that contain flags or values.
Basically I need to customize the data coming back from the repository based on role.
What do you suggest?
1) Create a 'public' and a 'private' concrete repository from the same IRepository and customize the logic in each, then intantiate at the controller based on role membership.
2) Create private methods inside my one repository and choose the correct one based on the public/private role membership.
3) Other?
Thanks.
Other
Make it data driven, or you will end up in a word of pain.
Roles tend to grow
Update
Create table that maps roles to properties use flags if there's more to property-role relationship than can/cannot, then create Factory that can produce objects based on input from that table, then define interface, and create control mechanism for handling these role based properties.
Yeah now it sounds somewhat complicated. :)
A repository by definition does CRUD, there should not be logic in it (from what I know).
The queries that hit your repository should deal with not retrieving X information since your user Y doesn't have the right to see it.
If you keep business logic out of your repository you will find it much easier to maintain.
Edit : It's just an opinion, I'm far from an all-knowing mighty Jon Skeet ;)
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 :)
I thought I would rewrite this question (same iteration). The original was how to wrap a repository pattern around an EAV/CR database. I am trying a different approach.
Question: How could you code a data repository in a "factory" design pattern way? I have a fixed number of entities, but the attributes to these entities are fairly customer specific. They advertise Products which are all similar, but each customer attaches different information to them based on their business model. For example, some care about the percent slab off waste while others care about the quantity of pounds sold. Every time we find another customer, we add a bunch of fields, remove a bunch of fields, and then spend hours keeping each solution current to the latest common release.
I thought we could put the repository classes in a factory pattern, so that when I know the customer type, then I know what fields they would use. Practical? Better way? The web forms use User Controls which are modified to reflect what fields are on the layouts. We currently "join" the fields found on the layout to the fields found in the product table, then CRUD common fields.
Previous question content:
We have an EAV/CR data model that allows different classes for the same entity. This tracks products where customers have wildly different products. Customers can define a "class" of product, load it up with fields, then populate it with data. For example,
Product.Text_Fields.Name
Product.Text_Fields.VitaminEContent
Any suggestion on how to wrap a repository pattern around this?
We have a three table EAV: a Product table, a value table, and a meta table that lists the field names and data types (we list the data types because we have other tables like Product.Price and Product.Price Meta data, along with others like Product.Photo.) Customers track all kinds of prices like a competitor's percent off difference as well as on the fly calculations.
We currently use Linq to SQL with C#.
Edit:
I like the "Dynamic Query" Linq below. The idea behind our DB is like a locker room locker storage. Each athlete (or customer) organizes their own locker in the way they wish, and we handle storing it for them. We don't care what's in the locker as long as they can do what they need with it.
Very interesting... The objects passed to the repository could be dynamic? This almost makes sense, almost like a factory pattern. Would it be possible for the customer to put their own class definitions in a text file, then we inherit them and store them in the DB?
As I understand it the repository pattern abstracts the physical implementation of the database from the application. Are you planning to store the data in differing data stores? If you are happy with Linq to SQL then I'd suggest that perhaps you don't need to abstract in this way as it looks to be extremely complex. That said, I can see that providing an EAV-style repository, i.e. a query would need to be passed Table, Field Type, and Field Name along with any conditional required, might offer you the abstraction you are seeking.
I'm not sure if that would still qualify as a repository pattern in the strictest terms as you aren't really abstracting the storage from the application. It's going to be a toss-up between benefit and effort and there I'm unable to help.
You might want to take a look at the Dynamic Linq extensions found in the dynamic data preview on Codeplex.