Bug Tracker Architecture - ddd-repositories

I am creating a Bug Tracker application (toy one) with DDD in mind. I have a BugRepository with methods like Add / Delete / Save and a user Repository having the same kind of methods (Actually both derive from IRepository). Now Bug has a Property called "Assigned To" which is a column in DB where the ID of the user is stored.
Now I need a method called "FindAssignee" or rather I want to know who the bug is assigned to. Where do i put that?
I was thinking that I could say --> In BugRepository add a method called "FindAssignee". But that would return a "USER" object. Is that OK? Aren't repositories for an aggregate root (Bug this case) supposed to return ONLY their entities (Bug again) ?

Is that OK?
Yes.
Aren't repositories for an aggregate root (Bug this case) supposed to return ONLY their entities (Bug again) ?
Yes.
But your query isn't to a aggregate root.
Your query is against a specific Bug which has one or more Assignees.

Related

What is the type should the create method of the repository return?

I am trying to implement the CQRS pattern.
Following the CQRS pattern, the Command should return nothing, as the void type in Java.
The create() method in the repository is the command in my opinion and it should return nothing following the pattern.
But I am struggling to build the function which needs to create and use the new entity.
For example, I have to build a function assign new child category. In this feature, the client can either send the parent category id or new child details to the server.
The parent category id is an easy case, but the problem is in the new child details case.
I have to create a new category base on the details first, then use that entity to assign the parent id to it, and finally save it. Currently, I am not able to get the newly created entity, because the create() method returns nothing.
And I can't create a new entity, assign the parent id and save it, because the entity can't be created without an id and the id is only assigned by the ORM I am using.
What should I do to solve this problem? Does the method create() of the repository return an entity other than void violate the CQRS pattern?
It depends on scenario & business needs. All the design patterns, approaches, etc. just give you an idea of possible solutions to common problems. There is no single good principle to follow that works for all the scenarios across different business problems. If after executing the command, each time you need to execute some logic based on the result - then return that result to avoid unnecessary calls. It all depends on the problem you try to solve & trade-offs you are ready to make.
For more info you can check this question.
Following the CQRS pattern, the Command should return nothing, as the void type in Java.
I don't know where this is coming from, it's been years that people believe this, but it is not true.
For entities creation, or you tell the storage the id for the new thing to store, or it creates it for you and you can get it (or the entire entity) as a return, it doesn't violate anything.
Returning an entity doesn't violate CQRS Pattern.
In your Command Model add this:
public record CreateCommand : IRequest<ModelVm>
Which ModelVm is the model you want to return.
And in your CommandHandler class add this code :
public class CreateCommandHandler : IRequestHandler<CreateCommand, ModelVm>
And instead of returning Unit.Value You should return ModelVm in CreateCommandHandler.

Retrieving a value object without Aggreteroot

I'm developing an application with Domain Drive Design approach. in a special case I have to retrieve the list of value objects of an aggregate and present them. to do that I've created a read only repository like this:
public interface IBlogTagReadOnlyRepository : IReadOnlyRepository<BlogTag, string>
{
IEnumerable<BlogTag> GetAllBlogTagsQuery(string tagName);
}
BlogTag is a value object in Blog aggregate, now it works fine but when I think about this way of handling and the future of the project, my concerns grow! it's not a good idea to create a separate read only repository for every value object included in those cases, is it?
anybody knows a better solution?
You should not keep value objects in their own repository since only aggregate roots belong there. Instead you should review your domain model carefully.
If you need to keep track of value objects spanning multiple aggregates, then maybe they belong to another aggregate (e.g. a tag cloud) that could even serve as sort of a factory for the tags.
This doesn't mean you don't need a BlogTag value object in your Blog aggregate. A value object in one aggregate could be an entity in another or even an aggregate root by itself.
Maybe you should take a look at this question. It addresses a similar problem.
I think you just need a query service as this method serves the user interface, it's just for presentation (reporting), do something like..
public IEnumerable<BlogTagViewModel> GetDistinctListOfBlogTagsForPublishedPosts()
{
var tags = new List<BlogTagViewModel>();
// Go to database and run query
// transform to collection of BlogTagViewModel
return tags;
}
This code would be at the application layer level not the domain layer.
And notice the language I use in the method name, it makes it a bit more explicit and tells people using the query exactly what the method does (if this is your intent - I am guessing a little, but hopefully you get what I mean).
Cheers
Scott

Prevent deleting a Core Data NSManagedObject

I have a NSArrayController subclass which sets an instance variable of a newly inserted object and prevents the user to remove it if this variable is zero.
I'd like to do this inside an entity subclass. Setting the variable is possible in the awakeFromInsert method. Is there a way to prevent the deletion, a sort of:
if (self.testVariable == 0) return; ?
I didn't find it, but maybe I missed something.
Implement this in your NSManagedObject:
- (BOOL)validateForDelete:(NSError **)error
based on a few tests, i believe the validateForDelete will not work to prevent deletion as desired.
validateForDelete is used to perform added validation prior to delete. essentially, the method name is misleading. Just like for example, for
moreover, prepareForDelete is called prior and will delete any Cascade relationships and mark null any Nullify ones. hence, those have to be 'backed out.' or alter your data model to only permit Deny that will leave those relationships alone in prepareForDelete. which is applying a stiff backhand to your business model and logic.
further, a Deny relationship is 'denied' when the user saves the data -- which might be too late for the user to undo and rectify the situation.
i believe the best option is to unactive the Remove Button that is bound to the canRemove method in the Controller.
Some solid opinions
Some possible solutions at SO

DDD - How Can I Avoid Crossing Aggregate Boundaries Here?

We're working on a new project (re-writing existing app), and I'm running into problems with my domain model / repository design.
Here is a (simplified) version of two key portions in our domain model:
As you can see, I have an abstract concept of a Post, which can be things like a Review, a Discussion, a Photo, a Video, etc. Posts can also have comments.
I also have a abstract concept of a Location, which are obviously things like Streets, Cities, Neighbourhoods, etc.
Now, this naturally looked to me as two clear aggregate roots.
So I created two repositories, one called PostRepository, and another called LocationRepository.
This was all working fine, I can add/get any type of Post (or comment), and add/get any type of Location via one of these two repositories.
But now im in the scenario of a "landing page" for a City (for example).
On this page, I need to basically show "all posts for this location".
How is that defined? Well, a Post can be (optionally) tagged at a Location. Implementation detail, so I don't want to go too deep into data (as that's not what DDD is about), but essentially there is geospatial intelligence to work out which posts are contained in a particular location by the shape file of the location, and the latitude/longitude of the tagged Post.
But how can I retrieve this information without crossing the boundaries?
Which repository do I use? Do I need a new one?
If it matters (or for the curious), this is a web application (ASP.NET MVC), with a SQL Server 2008 database and Entity Framework 4.0.
If you need any clarification, let me know.
EDIT
We currently use a modified version of the Specification pattern in order to retrieve domain models.
For example, this is the code in our BLL to retrieve all Review's where Score >= 4:
var reviews = postRepository // GenericRepository<Post>
.Find() // IQueryable<Post>
.OfType<Review>() // IQueryable<Review>
.Where(x => x.Score >= 4)
.ToList(); // List<Review>
But now I need some code like this:
var reviews = postRepository
.Find()
.OfType<Review>()
.Where( //lat long, or Locations FK )
.ToList();
The problem is I don't know how to do the above query without adding an intermediary join-entity (LocationPost - as it's a many to many), and add a FK to the Post domain model to that.
But by doing that, I am crossing the aggregate boundaries - aren't I?
Why is this a problem?
According to Evans in his book, one AR may very well reference another AR.
(You may not however reference a child element in an AR from another AR)
Also, are locations really aggregate roots?
The definition of an aggregate root is that it acts as a boundary of concistency.
Does that fit the definition of a location?
I'd say a location is a value object.
There are pretty much two camps here regarding repositories and AR associations:
One that says that all aggregate roots have to be fetched through their respective repository, and AR's should use soft relations, eg ID's between them
And one that says that aggregate roots may very well fetch other associated aggregate roots and that a repository is merely a way to find aggregate roots.
I would bind post to the location at creation time so that for each location I can get (through a repository) a list of associated posts. It would look like this:
Creation:
var p = new Post(latitude, longitude);
var locations = locationRepository.FindByCoordinates(latitude, longitude);
foreach (var l in locations)
{
l.AssociatePost(p);
}
session.Save(p);
Retrieval:
var associatedPosts = postRepository.FindByLocation(locationId);
foreach (var p in associatedPosts)
{
Display(p);
}
Under the hood, the association between posts and location would be implemented as a many-to-many table relationship. There is one problem with this solution: adding a new location requires to scan all the posts and assign them to the new location (if applicable).
Hope that helps.
Let's say you used the Specification pattern, could you build a Post Specification using a Location object? Then you just pass the Specification to your Post Repository, and get back the result.

Accessing Aggregate Entities without Lazy Loading

I want to follow the DDD philosophy and not access entity objects of an aggregate directly. So, i have to call the root object to get the associated entity. But In other cases I dont always want every associated entity to load when the root is called. Is that the purpose of lazy loading?
How do I access entity objects through the root without loading all the associated objects everytime if i disable lazyloading feature of linq?
EDIT:
For example, If I have a Person as the Root Entity, and the Person has Name, Addresses and OwnedProperties. If I want to get a list of People so that I could display their names, I dont necvessarily want to load up Owned Properties every time on the call to the Repository. Conversely, on another page I may want to show a list of OwnedProperties, but do not want the other information to load with the call. what is the simple way of just calling the Person without the owned property entity other than creating a new person object without that owned properties?
I don't thinks that's possible without lazy loading.
Getting all data at once: Eager Loading
Getting data when accessed: Lazy Loading
According to your edit:
What I do in these situations, is create a 'View' class or a 'DTO' class which just contains the properties that I'm interested in.
For instance, I could have a 'PersonView' class which just has a Name property for instance.
Then, using my OR/M mapper (I use NHibernate), I create a HQL query (or Criteria query) which works on my 'Person' entity. Before I execute the query, I tell NHibernate that I want 'PersonView' objects as a result (I specify a projection). Then, NHibernate is smart enough to execute a query that only retrieves the columns that are necessary to populate the PersonView instances.
One way to avoid lazy loading is just using the object 'id'

Resources