Deall all,
I'm designing a vehicle registration system using DDD. It is required to archive the registrations of all vehicles so that the registrations of a vehicle over its lifetime can be easily read.
To implement this requirement, I am going to simply treat "REGISTRATION"s as a collection in a VEHICLE, as shown below:
//The Aggregation Root
public class Vehicle
{
GUID id;
List<Registration> registrations_;
......
public Vehicle() { ..... }
...
}
//The Value Object
public class Registration
{
Vehicle vehicle_;
decimal amount_;
......
//The calendar interval for a single registration.
Period period_;
public Registration() { .... }
}
Could anybody kindly comment on whether this implementation REALLY fulfill the above-mentioned requirement? Any improvements needed?
Data are going to be persisted in SQL Server 2008 with NHibernate or EF using the code first approach!
Thanks!
Nathan
Given such a simple requirement, this solution would seem fine. Hard to say much more without knowing the context. You mention the requirement was to view archived registrations so you should consider using that language in the code (registrations should be archivedRegistrations or previousRegistrations etc)
Related
I have a Survey model class which has the following four value objects:
id
creationDate
comment
answeredDate
The survey expires after a fixed amount of time, let us say 48h. Then I need to model this, but I don't know where to place it.
On creationDate like a method hasExpired(now: Date)?
As a function of the entity itself, checking creationDate?
Other solutions?
I dont know which language you are coding but I will present some sample code in C# but I think it's clear enough to show what I mean. I recommend you to calculate and persist expire time once you create the object because you can use this property in order query your survives based on expire time.
public class Survey
{
public DateTime CreationDate{get; private set;}
public DateTime ExpireDate{get; private set;}
public Survey(...,DateTime creationDate,..)
{
//Validations...
//Some Property Initialization
this.CreationDate=creationDate
this.ExpireDate=creationDate.AddHoure(48)
}
}
now you can abstract your business rule as a specification, in your case:"If the expire time is passed so the survey is expired". I will show you what I mean by an example:
public class TheSurveyHasBeenExpiredSpecification:Specification<Survey>
{
public Expression<Func<Survey , bool>> Expression => x=> x.ExpireDate <= DateTime.Now;
public bool IsStifiedBy(Survey entity)
{
return Expression.Compile().Invoke(entity);
}
}
now you can have fun with your Specification, you can use it either alongside your ORM to retrieve expired surveys records or in your code to make decision if the survey is expired or not in my sample you should pass the entity to "IsStifiedBy" method.
good luck
Solution 1
Mix of option first and two, here is a pseudo-code:
class Survey {
public bool hasExpired(now: Date) {
creationDate.modify('+48 hours').isLessThan(now);
}
}
Solution 2
You can also go for different solution. Your aggregate should have lifetime field which will be given when Survey is created. This solution will give you great flexibility.
Let's assume that when you start your project, default lifetime of Survey is 48 hours. So all new Surveys have 48 hours lifetime. But in the meantime, the business want to change it, to 7 days.
Now with previous solution you have a problem. What about current Surveys which did not expire yet or just expired?
I think Surveys created before changes should have still old lifetime (48 hours). If you have lifetime set in your Survey, you have no problem with that. Old Surveys will still have 48 hours but new will have 7 days. You just need to use lifetime field in the method hasExpired(now: Date).
Solution 3
There is also third solution. It is called Policy. Policies can have encapsulate logic of calculating the lifetime of Survey. So you can have different policies. This will give you even more flexibility.
I'm learning DDD approach step by step with imaginary business domain by reading books of Eric Evans and Vaughn Vernon and I try to implement it using in my project using PHP (but it really doesn't matter here).
Recently I've been reading a lot of Aggregate, AggregateRoot and Entity patterns for models that should be defined by a domain. And, frankly, I'm not sure I understand all definitions well so I decided to ask my questions here.
At first I'd like to present my (sub)domain responsible for employees' holidays management which should make answers for my questions easier.
The most trivial case is that the Employee can be found in many Teams. When the employee decides to take few days off, he has to send a HolidaysRequest with metadata like type of holidays (like rest holidays, some days off to take care of his child, etc.), the acceptance status and of course time range when he's not going to appear in his office. Of couse HolidaysRequest should be aware of which Employee has sent the HolidaysRequest. I'd like also to find all HolidaysRequest that are sent by Employee.
I'm quite sure that things like DateRange or HolidayType are pure ValueObjects. It's quite clear for me. The problems start when I have to define boundries of entities. I may have bad practices of defining associations by nesting objects in entities, so, please, tell me finding out the definitions of responsibilities here.
What is an entity here? What should be an Aggregate and where's the place for AggregateRoot?
How to define associations between entities? E.g. an Employee can belong to multiple Teams or HolidaysRequest is authored by Employee and assigned to another Employee who can accept it. Should they be implemented as Aggregates?
Why I'm asking these questions? Because few weeks ago I've posted a question here and one of answers was to think about relations between Employee and Teams, that they should be in the single Aggreate called EmployeeInTeam but I'm not sure I understand it in proper way.
Thanks for any advice.
The main thing about DDD, is to put focus in the domain, that's why its called Domain Driven Design.
When you start asking about relationships, aggregates and entities without even deeply exploring what consists your domain, you're actually looking for database modeling instead of domain.
Please, I'm not saying you're asking wrong questions, nor criticising they, I think you're not wrong at all when trying to put in practice while studying.
I'm not DDD expert, I'm learning just like you, but I'm gonna try to help.
Start by thinking what situation's may arise about Holydays Management. When you have different rules for something, you could start by using strategies (I'm saying is the final solution).
Building a nice and meaningful domain, is very hard (at least for me). You write code. Test it. Have insights, throw your code way and rewrite it. Refactor it. In your software's lifecycle, you should put focus on domain, therefore you should be always improving it.
Start by coding (like a domain's draft) to see how it looks like. Let's exercise it. First of all, why do we need to manage this stuff? What problem are we trying to solve? Ahh, sometimes employees ask some days off, we want to control it. We may approve or not, depending on the reason they want "holyday", and how is our team status. If we decline and they still go home, we'll late decide whether we fire or discount in salary. Enforcing ubiquitous language, let's express in code this problem:
public interface IHolydayStrategy
{
bool CanTakeDaysOff(HolydayRequest request);
}
public class TakeCareOfChildren : IHolydayStrategy
{
public bool CanTakeDaysOff(HolydayRequest request)
{
return IsTotalDaysRequestedUnderLimit(request.Range.TotalDays());
}
public bool IsTotalDaysRequestedUnderLimit(int totalDays)
{
return totalDays < 3;
}
}
public class InjuredEmployee : IHolydayStrategy
{
public bool CanTakeDaysOff(HolydayRequest request)
{
return true;
}
}
public class NeedsToRelax : IHolydayStrategy
{
public bool CanTakeDaysOff(HolydayRequest request)
{
return IsCurrentPercentageOfWorkingEmployeesAcceptable(request.TeamRealSize, request.WorkingEmployees)
|| AreProjectsWithinDeadline(request.Projects);
}
private bool AreProjectsWithinDeadline(IEnumerable<Project> projects)
{
return !projects.Any(p => p.IsDeadlineExceeded());
}
private bool IsCurrentPercentageOfWorkingEmployeesAcceptable(int teamRealSize, int workingEmployees)
{
return workingEmployees / teamRealSize > 0.7d;
}
}
public class Project
{
public bool IsDeadlineExceeded()
{
throw new NotImplementedException();
}
}
public class DateRange
{
public DateTime Start { get; set; }
public DateTime End { get; set; }
public int TotalDays()
{
return End.Subtract(Start).Days;
}
public bool IsBetween(DateTime date)
{
return date > Start && date < End;
}
}
public enum HolydayTypes
{
TakeCareOfChildren,
NeedToRelax,
BankOfHours,
Injured,
NeedToVisitDoctor,
WannaVisitDisney
}
public class HolydayRequest
{
public IEnumerable<Project> Projects { get; internal set; }
public DateRange Range { get; set; }
public HolydayTypes Reason { get; set; }
public int TeamRealSize { get; internal set; }
public int WorkingEmployees { get; internal set; }
}
Here is how I quickly wrote this:
Holydays may be granted or not, depending on the situation and
reason, let's create a IHolydayStrategy.
Created an empty (propertyless) HolydayRequest class.
For each possible reason, let's create a different strategy.
If the reason is to take care of children, they can take days off if
the total days request is under a limit.
If the reason is because the employee has been injured, we have no
choice other than allowing the request.
If the reason is because they need to relax, we check if we have an
acceptable percentage of working employees, or if projects are within
deadline.
As soon as I needed some data in the strategy, I used CTRL + . to
automagically create properties in HolydayRequest.
See how I don't even know how these stuff are going to be stored/mapped? I just wrote code to solve a problem, and get piece of information needed to resolve it.
Obviously this is not the final domain, is just a draft. I might take away this code and rewrite, if needed, no feelings for it yet.
People may think it's useless to create an InjuredEmployee class just to always return true, but the point here is to make use of ubiquitous language, to make things as explicit as possible, anyone would read and understand the same thing: "Well, if we have an injured employee, they are always allowed to take days off, regardless of the team's situation and how many days they need.". One of the problems this concept in DDD solves is the misunderstanding of terms and rules between developers, product owners, domain experts, and other participants.
After this, I would start writing some tests with mock data. I might refactor code.
This "3":
public bool IsTotalDaysRequestedUnderLimit(int totalDays)
{
return totalDays < 3;
}
and this "0.7d":
private bool IsCurrentPercentageOfWorkingEmployeesAcceptable(int teamRealSize, int workingEmployees)
{
return workingEmployees / teamRealSize > 0.7d;
}
are specifications, In my point of view, which shouldn't reside in a strategy. We might apply Specification Pattern to make things decoupled.
After we get to a reasonably initial solution with passed tests, now let's think how should we store it. We might use the final defined classes (such as Team, Project, Employee) here to be mapped by an ORM.
As soon as you started writing your domain, relationships will arise between your entities, that's why I usually don't care at all how the ORM will persist my domain, and what is Aggregate at this point.
See how I didn't create an Employee class yet, even though it sounds very important. That's why we shouldn't start by creating entities and their properties, because it's the exact same thing as creating tables and fields.
Your DDD turns into Database Driven Design that way, we don't want this. Of course, eventually we'll make the Employee, but let's take step by step, create only when you need it. Don't try to start modeling everything at once, predicting all entities you're going to need. Put focus on your problem, and how to solve it.
About your questions, what is entity and what is aggregate, I think you're not asking the definition of them, but whether Employee is considered one or other, considering your domain. You'll eventually answer yourself, as soon as your domain start being revealed by your code. You'll know it when you started developing your Application Layer, which should have the responsibility of loading data and delegating to your domain. What data my domain logic expects, from where do I start querying.
I hope I helped someone.
Currently diving into DDD and i've read most of the big blue book of Eric Evans. Quite interesting so far :)
I've been modeling some aggregates where they hold a collection of entities which expire. I've come up with a generic approach of expressing that:
public class Expirable<T>
{
public T Value { get; protected set; }
public DateTime ValidTill { get; protected set; }
public Expirable(T value, DateTime validTill)
{
Value = value;
ValidTill = validTill;
}
}
I am curious what the best way is to invalidate an Expirable (nullify or omit it when working in a set). So far I've been thinking to do that in the Repository constructor since that's the place where you access the aggregates from and acts as a 'collection'.
I am curious if someone has come up with a solution to tackle this and I would be glad to hear it :) Other approaches are also very welcome.
UPDATE 10-1-2013:
This is not DDD with the CQRS/ES approach from Greg Young. But the approach Evans had, since I just started with the book and the first app. Like Greg Young said, if you have to make good tables, you have to make a few first ;)
There are probably multiple ways to approach this, but I, personally, would solve this using the Specification pattern. Assuming object expiration is a business rule that belongs in the domain, I would have a specification in addition to the class you have written. Here is an example:
public class NotExpiredSpecification
{
public bool IsSatisfiedBy(Expirable<T> expirableValue)
{
//Return true if not expired; otherwise, false.
}
}
Then, when your repositories are returning a list of aggregates or when performing any business actions on a set, this can be utilized to restrict the set to un-expired values which will make your code expressive and keep the business logic within the domain.
To learn more about the Specification pattern, see this paper.
I've added a method to my abstract repository InvalidateExpirable. An example would be the UserRepository where I remove in active user sessions like this: InvalidateExpirable(x => x.Sessions, (user, expiredSession) => user.RemoveSession(expiredSession));.
The signature of InvalidateExpirable looks like this: protected void InvalidateExpirable<TExpirableValue>(Expression<Func<T, IEnumerable<Expirable<TExpirableValue>>>> selector, Action<T, Expirable<TExpirableValue>> remover). The method itself uses reflection to extract the selected property from the selector parameter. That property name is glued in a generic HQL query which will traverse over the set calling the remove lambda. user.RemoveSession will remove the session from the aggregate. This way the I keep the aggregate responsible for it's own data. Also in RemoveSession an domain event is raised for future cases.
See: https://gist.github.com/4484261 for an example
Works quite well sofar, I have to see how it works further down in the application though.
Have been reading up on DDD with CQRS/ES (Greg Young approach) and found a great example on the MSDN site about CQRS/ES: http://msdn.microsoft.com/en-us/library/jj554200.aspx
In this example they use the command message queue to queue a Expire message in the future, which will call the Aggregate at the specified time removing/deactivate the expirable construct from the aggregate.
I'm refactoring a project using DDD, but am concerned about not making too many Entities their own Aggregate Root.
I have a Store, which has a list of ProductOptions and a list of Products. A ProductOption can be used by several Products. These entities seem to fit the Store aggregate pretty well.
Then I have an Order, which transiently uses a Product to build its OrderLines:
class Order {
// ...
public function addOrderLine(Product $product, $quantity) {
$orderLine = new OrderLine($product, $quantity);
$this->orderLines->add($orderLine);
}
}
class OrderLine {
// ...
public function __construct(Product $product, $quantity) {
$this->productName = $product->getName();
$this->basePrice = $product->getPrice();
$this->quantity = $quantity;
}
}
Looks like for now, DDD rules as respected. But I'd like to add a requirement, that might break the rules of the aggregate: the Store owner will sometimes need to check statistics about the Orders which included a particular Product.
That means that basically, we would need to keep a reference to the Product in the OrderLine, but this would never be used by any method inside the entity. We would only use this information for reporting purposes, when querying the database; thus it would not be possible to "break" anything inside the Store aggregate because of this internal reference:
class OrderLine {
// ...
public function __construct(Product $product, $quantity) {
$this->productName = $product->getName();
$this->basePrice = $product->getPrice();
$this->quantity = $quantity;
// store this information, but don't use it in any method
$this->product = $product;
}
}
Does this simple requirement dictates that Product becomes an aggregate root? That would also cascade to the ProductOption becoming an aggregate root, as Product has a reference to it, thus resulting in two aggregates which have no meaning outside a Store, and will not need any Repository; looks weird to me.
Any comment is welcome!
Even though it is for 'reporting only' there is still a business / domain meaning there. I think that your design is good. Although I would not handle the new requirement by storing OrderLine -> Product reference. I would do something similar to what you already doing with product name and price. You just need to store some sort of product identifier (SKU?) in the order line. This identifier/SKU can later be used in a query. SKU can be a combination of Store and Product natural keys:
class Sku {
private String _storeNumber;
private String _someProductIdUniqueWithinStore;
}
class OrderLine {
private Money _price;
private int _quantity;
private String _productName;
private Sku _productSku;
}
This way you don't violate any aggregate rules and the product and stores can be safely deleted without affecting existing or archived orders. And you can still have your 'Orders with ProductX from StoreY'.
Update: Regarding your concern about foreign key. In my opinion foreign key is just a mechanism that enforces long-living Domain relationships at the database level. Since you don't have a domain relationship you don't need the enforcement mechanism as well.
In this case you need the information for reporting which has nothing to do with the aggregate root.
So the most suitable place for it would be a service (could be a domain service if it is related to business or better to application service like querying service which query the required data and return them as DTOs customizable for presentation or consumer.
I suggest you create a statistics services which query the required data using read only repositories (or preferable Finders) which returns DTOs instead of corrupting the domain with query models.
Check this
There is Campaign Entity and for that, I have CampaignRepository which have this functions
public IList FindAll();
public Campaign FindByCampaignNumber(string number);
But now i want this criterias -:
Find campaigns that are created today.
Find campaigns that are created in this month
Find top 5 latest campaigns.
Find campaigns that are created in this year.
So for all these campaigns filters,
Do i create separate function for each of them in repository ?
and implement like this way.
Getall campaigns and then filter required campaigns, but i do not want all campaigns. While searching in google i find this solution's
1: http://russelleast.wordpress.com/2008/09/20/implementing-the-repository-and-finder-patterns/
Is there any method i can avoid multiple functions or do i go ahead and create seperate functions for each of this filter ?
Have you considered implementing Specification pattern in your application? Maybe it looks like an overkill, but it may prove useful if your app will have some complex user filter options.
class CampaignSpecification
{
public CampaignSpecification Number(string number);
public CampaignSpecification DateBetween(DateTime from, date to);
public CampaignSpecification Year(DateTime year);
} //I have omitted all the AND/OR stuff it can be easily implemented with any SQL like query language
Here is an example how loading from the repository may look like
var campaignList = CampaignRepository.load(
new CampaignSpec()
.Number("2")
.Year(DateTime.Now);
Also I'd like to add that it depends much on what kind of data access solution you are using, it makes implementing easier when you know what kind of API you will be using(Criteria API, SQL or whatever) so you can tweak your Specification interface to make its implementation simpler.
UPDATE: if you are implementing specifications in .NET using linq and nHibernate please check out http://linqspecs.codeplex.com/
I would go with creating two Specifications: TopCampaignSpec and CampaingCreatedSpec.
var spec = CampaignCreatedSpec.ThisYear();
var campaigns = CampaignsRepository.FindSatisfying(spec);
CampaingCreatedSpec can also be replaced with more generic DateRange class if you need this functionality elsewhere:
var thisYear = DateRange.ThisYear();
var campaigns = CampaignsRepository.FindByDateRange(spec);
I also highly recommend staying away from 'generic' repositories and entities. Please read this
From DDD perspective it does not matter whether data access code is implemented as SQL/HQL/ICriteria or even web service call. This code belongs to repository implementation (data access layer). This is just a sample:
public IList<Campaign> FindByDateRange(CampaignCreatedSpec spec) {
ICriteria c = _nhibernateSession.CreateCriteria(typeof(Campaign));
c.Add(Restrictions.Between("_creationDate", spec.StartDate, spec.EndDate));
return c.List<Campaign>();
}
Here is how I would do this:
class Campaigns{
IEnumerable<Campaign> All(){...}
IEnumerable<Campaign> ByNumber(int number){...}
IEnumerable<Campaign> CreatedToday(){...}
IEnumerable<Campaign> CreatedThisMonth(){...}
IEnumerable<Campaign> CreatedThisYear(){...}
IEnumerable<Campaign> Latest5(){...}
private IQueryable<Campaign> GetSomething(Something something){
//used by public methods to dry out repository
}
}
Reasoning is simple - it matters by what You are interested to look for campaigns (that knowledge is part of Your domain). If we explicitly state functions to reflect that, we will always know it.
Is it appropriate to add all this methods in campaign repository ?
I don't see anything wrong with that.
Arnis i want some code, how u implementing Created today function in domain itself, Are you injecting repository here in this function ? Thanks for your cooperation
I wouldn't implement CreatedToday function in my domain. It would sit in repository and repository implementations should not be concern of domain. If You mean how I would use Campaign repository and if it should be used from domain - no, it should not be used from within of domain. If You mean if I would inject repository inside of repository - You are listening too much of xzibit.
You should be able to do all of the above with the following repository method:
List<Campaign> findCampaigns(Date fromCreationDate, Date toCreationDate, int offset, Integer limit) {
if (fromCreationDate != null) add criteria...
if (toCreationDate != null) add criteria...
if (limit != null) add limit...
}
This is how I do it and it works very well.